• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2024-2025 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 all_flags_with_value
30      res = {}
31      dig(:flags)&.each_with_index do |flag, index|
32        if type == 'int'
33          res[flag] = index
34        else
35          res[flag] = 1 << (index - 1)
36        end
37      end
38
39      dig(:flag_unions)&.each do |union|
40        res[union.name] = union.flags.reduce(0) { |result, key| result | res[key] }
41      end
42      res
43    end
44
45    def flag_unions
46      res = {}
47      dig(:flag_unions)&.each { |union| res[union.name] = union.flags }
48      res
49    end
50
51    def namespace
52      if Enums.change_namespace.include?(dig(:namespace))
53        return Enums.change_namespace[dig(:namespace)]
54      else
55        return dig(:namespace)
56      end
57    end
58
59    def parent_class_name
60      dig(:parent_class_name)
61    end
62
63    def name_to_upper_snake
64      dig(:name)&.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
65                        &.gsub(/([a-z\d])([A-Z])/, '\1_\2')
66                        &.upcase
67    end
68  end
69
70  def get_astnodetype_value(class_name)
71    enums['AstNodeType'].all_flags_with_value[class_name]
72  end
73
74  @enums = {}
75  @change_namespace = {
76    'ast_verifier' => 'compiler::ast_verifier', 'verifier_invariants' => 'util::gen::verifier_invariants'
77  }
78
79  attr_reader :change_namespace
80  attr_reader :enums
81
82  def wrap_data(data)
83    return unless data
84
85    data.enums&.each do |enum|
86      @enums[enum.name] = EnumData.new(enum)
87    end
88
89    node_type_enum_flags = []
90    scope_type_enum_flags = []
91    decl_type_enum_flags = ['NONE']
92    data.macros&.each do |macros|
93      case macros.name
94      when 'AST_NODE_MAPPING'
95        node_type_enum_flags.concat(macros.values.map { |x| x[0] })
96      when 'AST_NODE_REINTERPRET_MAPPING'
97        node_type_enum_flags.concat(macros.values.flat_map { |x| x[0..1] })
98      when 'SCOPE_TYPES'
99        scope_type_enum_flags.concat(macros.values.map { |x| x[0] })
100      end
101    end
102    data.varbinder&.macros&.each do |macros|
103      case macros.name
104      when 'SCOPE_TYPES'
105        scope_type_enum_flags.concat(macros.values.map { |x| x[0] })
106      when 'DECLARATION_KINDS'
107        decl_type_enum_flags.concat(macros.values.map { |x| x[0] })
108      end
109    end
110
111    unless node_type_enum_flags.empty?
112      @enums['AstNodeType'] = EnumData.new(OpenStruct.new({ 'kind' => 'simple', 'flags' => node_type_enum_flags,
113                                                            'namespace' => 'ir', 'name' => 'AstNodeType' }))
114    end
115
116    unless scope_type_enum_flags.empty?
117      @enums['ScopeType'] = EnumData.new(OpenStruct.new({ 'kind' => 'simple', 'flags' => scope_type_enum_flags,
118                                                          'namespace' => 'varbinder', 'name' => 'ScopeType' }))
119    end
120
121    return if decl_type_enum_flags.empty? || decl_type_enum_flags == ['NONE']
122
123    @enums['DeclType'] = EnumData.new(OpenStruct.new({ 'kind' => 'simple', 'flags' => decl_type_enum_flags,
124                                                       'namespace' => 'varbinder', 'name' => 'DeclType' }))
125  end
126
127  module_function :wrap_data, :enums, :change_namespace, :get_astnodetype_value
128end
129
130def Gen.on_require(data)
131  Enums.wrap_data(data)
132end
133