1# Copyright (c) 2024 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14require 'delegate'
15require 'ostruct'
16
17module Enums
18  class EnumData < SimpleDelegator
19    def type
20      raise 'Unsupported enum kind' unless %w[simple flags].include?(kind)
21
22      kind == 'simple' ? 'int' : 'unsigned'
23    end
24
25    def flags
26      dig(:flags) || []
27    end
28
29    def flag_unions
30      res = {}
31      dig(:flag_unions)&.each { |union| res[union.name] = union.flags }
32      res
33    end
34
35    def namespace
36      dig(:namespace)
37    end
38
39    def parent_class_name
40      dig(:parent_class_name)
41    end
42
43    def name_to_upper_snake
44      dig(:name)&.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
45                        &.gsub(/([a-z\d])([A-Z])/, '\1_\2')
46                        &.upcase
47    end
48  end
49
50  @enums = {}
51
52  def enums
53    @enums
54  end
55
56  def wrap_data(data)
57    return unless data
58
59    data.enums&.each do |enum|
60      @enums[enum.name] = EnumData.new(enum)
61    end
62
63    node_type_enum_flags = []
64    scope_type_enum_flags = []
65    data.macros&.each do |macros|
66      case macros.name
67      when 'AST_NODE_MAPPING'
68        node_type_enum_flags.concat(macros.values&.map { |x| x[0] })
69      when 'AST_NODE_REINTERPRET_MAPPING'
70        node_type_enum_flags.concat(macros.values&.map { |x| x[0..1] }&.flatten)
71      when 'SCOPE_TYPES'
72        scope_type_enum_flags.concat(macros.values&.map { |x| x[0] })
73      end
74    end
75    data.varbinder&.macros&.each do |macros|
76      case macros.name
77      when 'SCOPE_TYPES'
78        scope_type_enum_flags.concat(macros.values&.map { |x| x[0] })
79      end
80    end
81
82    return if node_type_enum_flags.empty?
83
84    @enums['AstNodeType'] = EnumData.new(OpenStruct.new({ 'kind' => 'simple', 'flags' => node_type_enum_flags,
85                                                          'namespace' => 'ir', 'name' => 'AstNodeType' }))
86
87    return if scope_type_enum_flags.empty?
88
89    @enums['ScopeType'] = EnumData.new(OpenStruct.new({ 'kind' => 'simple', 'flags' => scope_type_enum_flags,
90                                                        'namespace' => 'varbinder', 'name' => 'ScopeType' }))
91  end
92
93  module_function :wrap_data, :enums
94end
95
96def Gen.on_require(data)
97  Enums.wrap_data(data)
98end
99