1b1994897Sopenharmony_ci# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2b1994897Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 3b1994897Sopenharmony_ci# you may not use this file except in compliance with the License. 4b1994897Sopenharmony_ci# You may obtain a copy of the License at 5b1994897Sopenharmony_ci# 6b1994897Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 7b1994897Sopenharmony_ci# 8b1994897Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 9b1994897Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 10b1994897Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11b1994897Sopenharmony_ci# See the License for the specific language governing permissions and 12b1994897Sopenharmony_ci# limitations under the License. 13b1994897Sopenharmony_ci 14b1994897Sopenharmony_cirequire 'ostruct' 15b1994897Sopenharmony_cirequire 'delegate' 16b1994897Sopenharmony_ci 17b1994897Sopenharmony_ciclass Attritute < SimpleDelegator 18b1994897Sopenharmony_ci def getter_name 19b1994897Sopenharmony_ci r = name.capitalize 20b1994897Sopenharmony_ci type == 'bool' ? 'Is' + r : 'Get' + r 21b1994897Sopenharmony_ci end 22b1994897Sopenharmony_ci 23b1994897Sopenharmony_ci def setter_name 24b1994897Sopenharmony_ci 'Set' + name.capitalize 25b1994897Sopenharmony_ci end 26b1994897Sopenharmony_ci 27b1994897Sopenharmony_ci def bool? 28b1994897Sopenharmony_ci type == 'bool' 29b1994897Sopenharmony_ci end 30b1994897Sopenharmony_ci 31b1994897Sopenharmony_ci def enum? 32b1994897Sopenharmony_ci type == 'enum' 33b1994897Sopenharmony_ci end 34b1994897Sopenharmony_ci 35b1994897Sopenharmony_ci def size? 36b1994897Sopenharmony_ci type == 'size' 37b1994897Sopenharmony_ci end 38b1994897Sopenharmony_ci 39b1994897Sopenharmony_ci def multiple? 40b1994897Sopenharmony_ci !bool? && multiple 41b1994897Sopenharmony_ci end 42b1994897Sopenharmony_ci 43b1994897Sopenharmony_ci def applicable_to?(item_type) 44b1994897Sopenharmony_ci applicable_to.include?(item_type) 45b1994897Sopenharmony_ci end 46b1994897Sopenharmony_ci 47b1994897Sopenharmony_ci def set_flags? 48b1994897Sopenharmony_ci (defined? flags) && flags.any? || enum? && values.any? { |v| v.flags && v.flags.any? } 49b1994897Sopenharmony_ci end 50b1994897Sopenharmony_ciend 51b1994897Sopenharmony_ci 52b1994897Sopenharmony_cimodule Metadata 53b1994897Sopenharmony_ci module_function 54b1994897Sopenharmony_ci 55b1994897Sopenharmony_ci def attributes 56b1994897Sopenharmony_ci @data.attributes.map do |op| 57b1994897Sopenharmony_ci Attritute.new(op) 58b1994897Sopenharmony_ci end 59b1994897Sopenharmony_ci end 60b1994897Sopenharmony_ci 61b1994897Sopenharmony_ci def language 62b1994897Sopenharmony_ci @data.language || '' 63b1994897Sopenharmony_ci end 64b1994897Sopenharmony_ci 65b1994897Sopenharmony_ci def extends_default? 66b1994897Sopenharmony_ci !language.empty? 67b1994897Sopenharmony_ci end 68b1994897Sopenharmony_ci 69b1994897Sopenharmony_ci def item_types 70b1994897Sopenharmony_ci ['record', 'field', 'function', 'param'] 71b1994897Sopenharmony_ci end 72b1994897Sopenharmony_ci 73b1994897Sopenharmony_ci def wrap_data(data) 74b1994897Sopenharmony_ci @data = data 75b1994897Sopenharmony_ci end 76b1994897Sopenharmony_ciend 77b1994897Sopenharmony_ci 78b1994897Sopenharmony_cidef Gen.on_require(data) 79b1994897Sopenharmony_ci Metadata.wrap_data(data) 80b1994897Sopenharmony_ciend 81b1994897Sopenharmony_ci 82b1994897Sopenharmony_cimodule MetadataGen 83b1994897Sopenharmony_ci module_function 84b1994897Sopenharmony_ci 85b1994897Sopenharmony_ci def attribute_name(attribute) 86b1994897Sopenharmony_ci return attribute.name if Metadata.language.empty? 87b1994897Sopenharmony_ci "#{Metadata.language.downcase}.#{attribute.name}" 88b1994897Sopenharmony_ci end 89b1994897Sopenharmony_ci 90b1994897Sopenharmony_ci def class_name(item_type) 91b1994897Sopenharmony_ci item_type.capitalize + 'Metadata' 92b1994897Sopenharmony_ci end 93b1994897Sopenharmony_ci 94b1994897Sopenharmony_ci def validate_body(item_type, is_bool) 95b1994897Sopenharmony_ci attributes = Metadata::attributes.select { |a| a.applicable_to?(item_type) && a.bool? == is_bool } 96b1994897Sopenharmony_ci body = [] 97b1994897Sopenharmony_ci indent = ' ' * 4 98b1994897Sopenharmony_ci 99b1994897Sopenharmony_ci attributes.each do |a| 100b1994897Sopenharmony_ci body << "#{indent}if (attribute == \"#{attribute_name(a)}\") {" 101b1994897Sopenharmony_ci 102b1994897Sopenharmony_ci unless a.multiple? 103b1994897Sopenharmony_ci body << "#{indent * 2}if (HasAttribute(attribute)) {" 104b1994897Sopenharmony_ci body << "#{indent * 3}return Error(\"Attribute '#{attribute_name(a)}' already defined\"," 105b1994897Sopenharmony_ci body << "#{indent * 3} Error::Type::MULTIPLE_ATTRIBUTE);" 106b1994897Sopenharmony_ci body << "#{indent * 2}}" 107b1994897Sopenharmony_ci end 108b1994897Sopenharmony_ci 109b1994897Sopenharmony_ci if a.enum? 110b1994897Sopenharmony_ci a.values.each do |v| 111b1994897Sopenharmony_ci body << "#{indent * 2}if (value == \"#{v.value}\") {" 112b1994897Sopenharmony_ci body << "#{indent * 3}return {};" 113b1994897Sopenharmony_ci body << "#{indent * 2}}" 114b1994897Sopenharmony_ci body << "" 115b1994897Sopenharmony_ci end 116b1994897Sopenharmony_ci 117b1994897Sopenharmony_ci body << "#{indent * 2}return Error(std::string(\"Attribute '#{attribute_name(a)}' have incorrect value '\").append(value) +" 118b1994897Sopenharmony_ci body << "#{indent * 2} R\"('. Should be one of #{a.values.map(&:value)})\", Error::Type::INVALID_VALUE);" 119b1994897Sopenharmony_ci elsif a.size? 120b1994897Sopenharmony_ci body << "#{indent * 2}return ValidateSize(value);" 121b1994897Sopenharmony_ci else 122b1994897Sopenharmony_ci body << "#{indent * 2}return {};" 123b1994897Sopenharmony_ci end 124b1994897Sopenharmony_ci 125b1994897Sopenharmony_ci body << "#{indent}}" 126b1994897Sopenharmony_ci body << "" 127b1994897Sopenharmony_ci end 128b1994897Sopenharmony_ci 129b1994897Sopenharmony_ci Metadata::attributes.select { |a| a.applicable_to?(item_type) && a.bool? != is_bool }.each do |a| 130b1994897Sopenharmony_ci body << "#{indent}if (attribute == \"#{attribute_name(a)}\") {" 131b1994897Sopenharmony_ci body << "#{indent * 2}return Error(\"Attribute '#{attribute_name(a)}' #{is_bool ? "must" : "must not"} have a value\"," 132b1994897Sopenharmony_ci body << "#{indent * 2} #{is_bool ? "Error::Type::MISSING_VALUE" : "Error::Type::UNEXPECTED_VALUE"});" 133b1994897Sopenharmony_ci body << "#{indent}}" 134b1994897Sopenharmony_ci body << "" 135b1994897Sopenharmony_ci end 136b1994897Sopenharmony_ci 137b1994897Sopenharmony_ci if Metadata::extends_default? 138b1994897Sopenharmony_ci args = ['attribute'] 139b1994897Sopenharmony_ci args << 'value' unless is_bool 140b1994897Sopenharmony_ci body << "#{indent}return pandasm::#{class_name(item_type)}::Validate(#{args.join(', ')});" 141b1994897Sopenharmony_ci else 142b1994897Sopenharmony_ci body << "#{indent}return Error(std::string(\"Unknown attribute '\").append(attribute) + \"'\"," 143b1994897Sopenharmony_ci body << "#{indent} Error::Type::UNKNOWN_ATTRIBUTE);" 144b1994897Sopenharmony_ci end 145b1994897Sopenharmony_ci 146b1994897Sopenharmony_ci body 147b1994897Sopenharmony_ci end 148b1994897Sopenharmony_ci 149b1994897Sopenharmony_ci def set_flags_body(item_type, is_bool) 150b1994897Sopenharmony_ci attributes = Metadata::attributes.select { |a| a.applicable_to?(item_type) && a.bool? == is_bool && a.set_flags? } 151b1994897Sopenharmony_ci body = [] 152b1994897Sopenharmony_ci indent = ' ' * 4 153b1994897Sopenharmony_ci 154b1994897Sopenharmony_ci attributes.each do |a| 155b1994897Sopenharmony_ci body << "#{indent}if (attribute == \"#{attribute_name(a)}\") {" 156b1994897Sopenharmony_ci 157b1994897Sopenharmony_ci if defined? a.flags 158b1994897Sopenharmony_ci body << "#{indent * 2}SetAccessFlags(GetAccessFlags() | #{a.flags.join(' | ')});" 159b1994897Sopenharmony_ci end 160b1994897Sopenharmony_ci 161b1994897Sopenharmony_ci if a.enum? 162b1994897Sopenharmony_ci a.values.select { |v| v.flags && v.flags.any? }.each do |v| 163b1994897Sopenharmony_ci body << "#{indent * 2}if (value == \"#{v.value}\") {" 164b1994897Sopenharmony_ci body << "#{indent * 3}SetAccessFlags(GetAccessFlags() | #{v.flags.join(' | ')});" 165b1994897Sopenharmony_ci body << "#{indent * 2}}" 166b1994897Sopenharmony_ci body << "" 167b1994897Sopenharmony_ci end 168b1994897Sopenharmony_ci end 169b1994897Sopenharmony_ci 170b1994897Sopenharmony_ci body << "#{indent}}" 171b1994897Sopenharmony_ci end 172b1994897Sopenharmony_ci 173b1994897Sopenharmony_ci if Metadata::extends_default? 174b1994897Sopenharmony_ci args = ['attribute'] 175b1994897Sopenharmony_ci args << 'value' unless is_bool 176b1994897Sopenharmony_ci body << "#{indent}pandasm::#{class_name(item_type)}::SetFlags(#{args.join(', ')});" 177b1994897Sopenharmony_ci end 178b1994897Sopenharmony_ci 179b1994897Sopenharmony_ci body 180b1994897Sopenharmony_ci end 181b1994897Sopenharmony_ci 182b1994897Sopenharmony_ci def remove_flags_body(item_type, is_bool) 183b1994897Sopenharmony_ci attributes = Metadata::attributes.select { |a| a.applicable_to?(item_type) && a.bool? == is_bool && a.set_flags? } 184b1994897Sopenharmony_ci body = [] 185b1994897Sopenharmony_ci indent = ' ' * 4 186b1994897Sopenharmony_ci 187b1994897Sopenharmony_ci attributes.each do |a| 188b1994897Sopenharmony_ci body << "#{indent}if (attribute == \"#{attribute_name(a)}\") {" 189b1994897Sopenharmony_ci 190b1994897Sopenharmony_ci if defined? a.flags 191b1994897Sopenharmony_ci body << "#{indent * 2}if ((GetAccessFlags() & #{a.flags.join(' | ')}) != 0) {" 192b1994897Sopenharmony_ci body << "#{indent * 3}SetAccessFlags(GetAccessFlags() ^ (#{a.flags.join(' | ')}));" 193b1994897Sopenharmony_ci body << "#{indent * 2}}" 194b1994897Sopenharmony_ci end 195b1994897Sopenharmony_ci 196b1994897Sopenharmony_ci if a.enum? 197b1994897Sopenharmony_ci a.values.select { |v| v.flags && v.flags.any? }.each do |v| 198b1994897Sopenharmony_ci body << "#{indent * 2}if (value == \"#{v.value}\") {" 199b1994897Sopenharmony_ci body << "#{indent * 3}if ((GetAccessFlags() & (#{v.flags.join(' | ')})) != 0) {" 200b1994897Sopenharmony_ci body << "#{indent * 4}SetAccessFlags(GetAccessFlags() ^ (#{v.flags.join(' | ')}));" 201b1994897Sopenharmony_ci body << "#{indent * 3}}" 202b1994897Sopenharmony_ci body << "#{indent * 2}}" 203b1994897Sopenharmony_ci end 204b1994897Sopenharmony_ci end 205b1994897Sopenharmony_ci 206b1994897Sopenharmony_ci body << "#{indent}}" 207b1994897Sopenharmony_ci end 208b1994897Sopenharmony_ci 209b1994897Sopenharmony_ci if Metadata::extends_default? 210b1994897Sopenharmony_ci args = ['attribute'] 211b1994897Sopenharmony_ci args << 'value' unless is_bool 212b1994897Sopenharmony_ci body << "#{indent}pandasm::#{class_name(item_type)}::RemoveFlags(#{args.join(', ')});" 213b1994897Sopenharmony_ci end 214b1994897Sopenharmony_ci 215b1994897Sopenharmony_ci body 216b1994897Sopenharmony_ci end 217b1994897Sopenharmony_ci 218b1994897Sopenharmony_ci def arg_list(is_bool) 219b1994897Sopenharmony_ci args = ['const std::string_view &attribute'] 220b1994897Sopenharmony_ci args << 'const std::string_view &value' if !is_bool 221b1994897Sopenharmony_ci args 222b1994897Sopenharmony_ci end 223b1994897Sopenharmony_ci 224b1994897Sopenharmony_ci def add_unused_attribute(arg) 225b1994897Sopenharmony_ci "[[maybe_unused]] #{arg}" 226b1994897Sopenharmony_ci end 227b1994897Sopenharmony_ci 228b1994897Sopenharmony_ci def validate_arg_list(item_type, is_bool) 229b1994897Sopenharmony_ci args = arg_list(is_bool) 230b1994897Sopenharmony_ci return args if Metadata::extends_default? 231b1994897Sopenharmony_ci 232b1994897Sopenharmony_ci attributes = Metadata::attributes.select { |a| a.applicable_to?(item_type) && a.bool? == is_bool } 233b1994897Sopenharmony_ci args[0] = add_unused_attribute(args[0]) if attributes.none? 234b1994897Sopenharmony_ci args[1] = add_unused_attribute(args[1]) if args[1] && attributes.none? { |a| a.enum? } 235b1994897Sopenharmony_ci args 236b1994897Sopenharmony_ci end 237b1994897Sopenharmony_ci 238b1994897Sopenharmony_ci def flags_arg_list(item_type, is_bool) 239b1994897Sopenharmony_ci args = arg_list(is_bool) 240b1994897Sopenharmony_ci return args if Metadata::extends_default? 241b1994897Sopenharmony_ci 242b1994897Sopenharmony_ci attributes = Metadata::attributes.select { |a| a.applicable_to?(item_type) && a.bool? == is_bool && a.set_flags? } 243b1994897Sopenharmony_ci use_value = attributes.any? { |a| a.enum? && a.values.any? { |v| v.flags && v.flags.any? } } 244b1994897Sopenharmony_ci args[0] = add_unused_attribute(args[0]) if attributes.none? 245b1994897Sopenharmony_ci args[1] = add_unused_attribute(args[1]) if args[1] && !use_value 246b1994897Sopenharmony_ci args 247b1994897Sopenharmony_ci end 248b1994897Sopenharmony_ci 249b1994897Sopenharmony_ciend 250