def generate_py_for_enum(enum_obj, output_file): mm = get_metamodel(enum_obj) if obj_is_newer_than_file(enum_obj, output_file): with open(output_file, "w") as f: f.write(f"""# generated code # for enum f{enum_obj.name} import numpy as np from enum import Enum """) for r in get_referenced_elements_of_enum(enum_obj): f.write("import {}\n".format(module_name(r))) f.write("\n") f.write("meta = {\n") for ev in enum_obj.enum_entries: pdefs = get_all_possible_properties(ev) pdefs = sorted(pdefs.keys()) f.write(f" '{ev.name}':{{") output_properties(f, ev, pdefs) f.write("},\n") f.write("}\n") f.write(f"class {enum_obj.name}(Enum):\n") t = fqn(enum_obj.type) for ev in enum_obj.enum_entries: v = ev.value.render_formula(**fp(enum_obj)) f.write(f" {ev.name} = {t}({v})\n") f.write(" def __repr__(self):\n") f.write(" return self.name\n") f.write(" def __str__(self):\n") f.write(" return self.name\n")
def test_property2(): text = r""" package example.one (property_set example.one.ProjExt) property_set ProjExt { property optional myprop1: STRING property applicable for rawtype, enum myprop2: ATTRTYPE } struct A { scalar x: built_in.int32 (.description="a", .myprop2=1) } """ mm = metamodel_for_language("item") assert mm is not None model = mm.model_from_str(text) assert model is not None items = get_children_of_type("Struct", model) assert len(items) == 1 pdefs = get_all_possible_properties(items[0].attributes[0]) assert len(pdefs) >= 7 assert "minValue" in pdefs assert "maxValue" in pdefs assert "defaultValue" in pdefs assert "description" in pdefs assert "myprop1" in pdefs assert "myprop2" in pdefs pdefs["myprop1"].internaltype == "STRING" pdefs["myprop2"].internaltype == "ATTRTYPE" pdefs = get_all_possible_mandatory_properties(items[0].attributes[0]) assert len(pdefs) == 1 assert "myprop2" in pdefs
def test_property1(): text = r""" package example struct Point { scalar x : built_in.float (.minValue=0.1, .defaultValue=1, .maxValue=1e5) scalar y : built_in.float (.defaultValue=0x0aB, .description="Hello") } struct Polygon { scalar n : built_in.uint32 (.defaultValue=16, .maxValue=1000) array points : Point[n] } """ mm = metamodel_for_language("item") assert mm is not None model = mm.model_from_str(text) assert model is not None items = get_children_of_type("Struct", model) assert len(items) == 2 Point = items[0] assert Point.name == "Point" assert len(Point.attributes[0].properties) == 3 assert len(Point.attributes[1].properties) == 2 assert Point.attributes[1].properties[0].definition.name == "defaultValue" assert Point.attributes[1].properties[0].numberValue.x.compute_formula( ) == 0xAB assert Point.attributes[1].properties[1].textValue.x == "Hello" assert get_property(Point.attributes[1], "defaultValue") == 0xAB assert get_property(Point.attributes[1], "description") == "Hello" assert has_property(Point.attributes[1], "defaultValue") assert has_property(Point.attributes[1], "description") assert not has_property(Point.attributes[1], "minValue") assert not has_property(Point.attributes[1], "maxValue") pdefs = get_all_possible_properties( Point, filter_applicable_to_model_object=False) assert len(pdefs) >= 6
def generate_cpp_struct(f, i): """ :param f: output file obj :param i: item to be generated (the struct) """ mm = textx.get_metamodel(i) f.write("//---------------------------\n") f.write("#ifdef SWIG\n") f.write("%shared_ptr({});\n".format(fqn(i))) f.write( "%template(MDSD_StructFunctions_{}) mdsd::StructFunctions<{}>;\n".format( i.name, fqn(i) ) ) f.write("%template(MDSD_Struct_{}) mdsd::Struct<{}>;\n".format(i.name, fqn(i))) f.write( "%template(MDSD_StructWrapper_{}) mdsd::StructWrapper<{}>;\n".format( i.name, fqn(i) ) ) for a in i.attributes: if textx.textx_isinstance(a, mm["ArrayAttribute"]): if a.has_fixed_size(): f.write(define_swig_array(a.type, a.compute_formula(), mm)) else: f.write(define_swig_vector(a.type, mm)) f.write("#endif\n") f.write("//---------------------------\n") f.write(get_open_namespace_for_obj(i)) f.write("struct {} {{\n".format(i.name)) for c in i.constant_entries: f.write( " static constexpr {} {} = {};\n".format( fqn(c.type), c.name, c.value.render_formula() ) ) for a in i.attributes: if a.is_embedded(): value_type = get_cpp_return_type(a.type) if textx.textx_isinstance(a, mm["ScalarAttribute"]): f.write(" inline {} {}() const;\n".format(value_type, a.name)) else: f.write( " inline {} {}(size_t idx) const;\n".format(value_type, a.name) ) if textx.textx_isinstance(a, mm["ScalarAttribute"]): f.write(" inline void {}({} val);\n".format(a.name, value_type)) else: f.write( " inline void {}(size_t idx, {} val);\n".format(a.name, value_type) ) continue if textx.textx_isinstance(a, mm["ScalarAttribute"]): f.write(" {} {} = {{}};\n".format(fqn(a.type), a.name)) elif textx.textx_isinstance(a, mm["ArrayAttribute"]): if a.has_fixed_size(): f.write( " std::array<{},{}> {} = {{}};\n".format( fqn(a.type), a.compute_formula(), a.name ) ) else: f.write(" std::vector<{}> {} = {{}};\n".format(fqn(a.type), a.name)) elif textx.textx_isinstance(a, mm["VariantAttribute"]): f.write( " std::variant<{}> {} = {{}};\n".format(get_variant_types(a), a.name) ) else: raise Exception("unexpected type") f.write( " mdsd::StructWrapper<{0}> _GET_WRAPPER() {{ return mdsd::StructWrapper<{0}>{{this}}; }}\n".format( i.name ) ) f.write("\n#ifndef SWIG\n") f.write(" struct META {\n") # ---------------------------------------- f.write( " template<class STRUCT,class VISITOR, class ...T> // enable accept for this struct: \n" ) f.write(" static void __accept_varargs(VISITOR &&v, T&... s) {\n") for a in i.attributes: f.write(" v.template visit<{}::META::{}>(s...);\n".format(i.name, a.name)) f.write(" }\n") # ---------------------------------------- f.write(" static constexpr const char* __name() ") f.write('{{ return "{}"; }}\n'.format(i.name)) f.write(f" static constexpr bool __is_dynamic = {tf(is_dynamic(i))};\n") f.write(" // META substructs:\n") for a in i.attributes: if a.is_variant(): for m in a.mappings: pdefs = get_all_possible_properties(m) pdefs = sorted(pdefs.keys()) f.write(" struct {} {{\n".format(meta_name_of_variant_mapping(m))) f.write(" using STRUCT={};\n".format(i.name)) f.write(" static constexpr const char* __name() ") f.write('{{ return "{}"; }}\n'.format(a.name)) f.write(" static constexpr bool __is_variant_entry = true;\n") f.write(" static constexpr bool __is_scalar = true;\n") f.write(" static constexpr bool __is_variant = false;\n") f.write(" static constexpr bool __is_array = false;\n") f.write(" static constexpr bool __is_enumtype = false;\n") f.write(" static constexpr bool __is_rawtype = false;\n") f.write(" static constexpr bool __is_struct = true;\n") f.write(" static constexpr bool __is_container = false;\n") insert_normal_meta_info(f, pdefs, m) f.write(" };\n") for a in i.attributes: f.write(" struct {} {{\n".format(a.name)) f.write(" using STRUCT={};\n".format(i.name)) f.write(" static constexpr const char* __name() ") f.write('{{ return "{}"; }}\n'.format(a.name)) f.write(" static constexpr bool __is_variant_entry = false;\n") if not textx.textx_isinstance(a, mm["VariantAttribute"]): f.write(f" using __type = {fqn(a.type)};") f.write(f" static constexpr bool __is_dynamic = {tf(is_dynamic(a))};\n") if hasattr(a, "type") and a.type.name == "char": f.write(" static constexpr bool __has_char_content = true;\n") else: f.write(" static constexpr bool __has_char_content = false;\n") if a.if_attr is None: f.write(" static constexpr bool __has_if_restriction = false;\n") f.write( " static constexpr bool __if_restriction(const STRUCT &) { return true; }\n\n" ) else: f.write(" static constexpr bool __has_if_restriction = true;\n") f.write( " static constexpr bool __if_restriction(const STRUCT &s) {{ return {}; }}\n\n".format( a.if_attr.predicate.render_formula(prefix="s.") ) ) if not (a.is_embedded()): if ( textx.textx_isinstance(a, mm["ArrayAttribute"]) and a.type.name == "char" ): f.write( " static constexpr auto __get_ref(STRUCT &s) {{ return mdsd::String(s.{}); }}\n".format( a.name ) ) f.write( " static constexpr const auto __get_ref(const STRUCT &s)" " {{ return mdsd::String(s.{}); }}\n".format(a.name) ) else: f.write( " static constexpr auto& __get_ref(STRUCT &s) {{ return s.{}; }}\n".format( a.name ) ) f.write( " static constexpr const auto& __get_ref(const STRUCT &s) {{ return s.{}; }}\n".format( a.name ) ) else: f.write( " static constexpr auto& __get_ref_of_container(STRUCT &s) {{ return s.{}; }}\n".format( get_container(a).name ) ) f.write( " static constexpr const auto& __get_ref_of_container(const STRUCT &s)" " {{ return s.{}; }}\n".format(get_container(a).name) ) if textx.textx_isinstance(a, mm["ArrayAttribute"]): f.write( " static constexpr auto __get_ref(STRUCT &s) {{ return mdsd::makeArrayRef<{}>(\n".format( fqn(a.type) ) ) f.write( " [&s](size_t idx){{ return s.{}(idx); }},\n".format( a.name ) ) f.write( " [&s](size_t idx, {} x){{ return s.{}(idx, x); }},\n".format( fqn(a.type), a.name ) ) f.write(" {}\n".format(a.compute_formula())) f.write(" ); }\n") f.write( " static constexpr auto __get_ref(const STRUCT &s)" " {{ return mdsd::makeCArrayRef<{}>(\n".format(fqn(a.type)) ) f.write( " [&s](size_t idx){{ return s.{}(idx); }},\n".format( a.name ) ) f.write(" {}\n".format(a.compute_formula())) f.write(" ); }\n") else: f.write( " static constexpr auto __get_ref(STRUCT &s) {{ return mdsd::makeRef<{}>(\n".format( fqn(a.type) ) ) f.write(" [&s](){{ return s.{}(); }},\n".format(a.name)) f.write( " [&s]({} x){{ return s.{}(x); }}\n".format( fqn(a.type), a.name ) ) f.write(" ); }\n") f.write( " static constexpr auto __get_ref(const STRUCT &s) {{ return mdsd::makeCRef<{}>(\n".format( fqn(a.type) ) ) f.write(" [&s](){{ return s.{}(); }}\n".format(a.name)) f.write(" ); }\n") pdefs = get_all_possible_properties(a) pdefs = sorted(pdefs.keys()) if "fixpointLsbValue" in pdefs: if has_fixpoint(a): f.write(" static constexpr bool __is_fixpoint = true;\n") f.write( f" static constexpr double __fixpointLsbValue = {get_fixpoint_LSB_value(a)};\n" ) f.write( f" static constexpr double __fixpointOffsetValue = {get_fixpoint_offset_value(a)};\n" ) f.write( f" template<class FLOAT=double> static constexpr {fqn(a.type)} __float2integral(FLOAT f) " f"{{ return static_cast<{fqn(a.type)}>(std::llround((f-__fixpointOffsetValue)" f"/__fixpointLsbValue)); }}\n" ) f.write( f" template<class FLOAT=double> static constexpr FLOAT __integral2float({fqn(a.type)} i) " f"{{ return static_cast<FLOAT>(i)*__fixpointLsbValue+__fixpointOffsetValue; }}\n" ) else: f.write(" static constexpr bool __is_fixpoint = false;\n") else: f.write(" static constexpr bool __is_fixpoint = false;\n") insert_normal_meta_info(f, pdefs, a) if textx.textx_isinstance(a, mm["VariantAttribute"]): f.write( " template<class S, class F> // S may also be const\n" ) f.write( " static void __call_function_on_concrete_variant_type(S &s, F f) {\n" ) f.write( " switch(s.{}) {{\n".format(a.variant_selector.render_formula()) ) for m in a.mappings: f.write(" case {}: ".format(m.id)) assert not textx.textx_isinstance(m.type, mm["RawType"]) f.write( "f.template operator()<STRUCT::META::{}>(std::get<{}>(s.{})); break;\n".format( meta_name_of_variant_mapping(m), fqn(m.type), a.name ) ) f.write(' default: throw std::runtime_error("(unexpected id)");\n') f.write(" }\n") f.write(" }\n") f.write(" template<class S> // S may also be const\n") f.write( " static void __init_variant_type_if_type_is_not_matching(S &s) {\n" ) f.write( " switch(s.{}) {{\n".format(a.variant_selector.render_formula()) ) for m in a.mappings: f.write(" case {}: ".format(m.id)) f.write( "if (not std::holds_alternative<{}>(s.{})) {{ s.{}={}{{}}; }} break;\n".format( fqn(m.type), a.name, a.name, fqn(m.type), ) ) f.write(' default: throw std::runtime_error("unexpected id");\n') f.write(" }\n") f.write(" }\n") f.write(" static constexpr bool __is_scalar = true;\n") f.write(" static constexpr bool __is_variant = true;\n") f.write(" static constexpr bool __is_array = false;\n") f.write(" static constexpr bool __is_enumtype = false;\n") f.write(" static constexpr bool __is_rawtype = false;\n") f.write(" static constexpr bool __is_struct = true;\n") f.write( " static constexpr bool __is_container = {};\n".format( tf(a.is_container()) ) ) f.write( " static constexpr bool __is_embedded = {};\n".format( tf(a.is_embedded()) ) ) elif textx.textx_isinstance(a, mm["ScalarAttribute"]): f.write(" static constexpr bool __is_scalar = true;\n") f.write(" static constexpr bool __is_variant = false;\n") f.write(" static constexpr bool __is_array = false;\n") if textx.textx_isinstance(a.type, mm["Enum"]): f.write(" static constexpr bool __is_enumtype = true;\n") else: f.write(" static constexpr bool __is_enumtype = false;\n") if textx.textx_isinstance(a.type, mm["RawType"]): f.write(" static constexpr bool __is_rawtype = true;\n") else: f.write(" static constexpr bool __is_rawtype = false;\n") if textx.textx_isinstance(a.type, mm["Struct"]): f.write(" static constexpr bool __is_struct = true;\n") else: f.write(" static constexpr bool __is_struct = false;\n") f.write( " static constexpr bool __is_container = {};\n".format( tf(a.is_container()) ) ) f.write( " static constexpr bool __is_embedded = {};\n".format( tf(a.is_embedded()) ) ) if a.is_embedded(): start_end_bit = get_start_end_bit(a) f.write( " static constexpr size_t __embedded_bits = {};\n".format( get_bits(a.type) ) ) f.write( " static constexpr size_t __embedded_start_bit = {};\n".format( start_end_bit[0] ) ) f.write( " static constexpr size_t __embedded_end_bit = {};\n".format( start_end_bit[1] ) ) elif textx.textx_isinstance(a, mm["ArrayAttribute"]): f.write(" static constexpr bool __is_scalar = false;\n") f.write(" static constexpr bool __is_variant = false;\n") f.write(" static constexpr bool __is_array = true;\n") if a.has_fixed_size(): f.write(" static constexpr bool __is_dynamic_array = false;\n") else: f.write(" static constexpr bool __is_dynamic_array = true;\n") f.write( " static constexpr size_t __get_dim([[maybe_unused]] const {} &{}) {{ return {};}}\n".format( i.name, "s" if not a.has_fixed_size() else "", a.render_formula(prefix="s."), ) ) txt = f" static constexpr size_t __get_dim([[maybe_unused]] const {i.name}" txt += f"&{'s' if not a.has_fixed_size() else ''}, size_t _idx) {{\n" txt += " switch(_idx) {\n" for idx in range(len(a.dims)): txt += f" case {idx}: return {a.dims[idx].dim.render_formula(prefix='s.')};\n" txt += ' default: throw std::runtime_error("unexpected dimension");\n' txt += " }\n" txt += " }\n" f.write(txt) if textx.textx_isinstance(a.type, mm["Enum"]): f.write(" static constexpr bool __is_enumtype = true;\n") else: f.write(" static constexpr bool __is_enumtype = false;\n") if textx.textx_isinstance(a.type, mm["RawType"]): f.write(" static constexpr bool __is_rawtype = true;\n") else: f.write(" static constexpr bool __is_rawtype = false;\n") if textx.textx_isinstance(a.type, mm["Struct"]): f.write(" static constexpr bool __is_struct = true;\n") else: f.write(" static constexpr bool __is_struct = false;\n") f.write( " static constexpr bool __is_container = {};\n".format( tf(a.is_container()) ) ) f.write( " static constexpr bool __is_embedded = {};\n".format( tf(a.is_embedded()) ) ) if a.is_embedded(): start_end_bit = get_start_end_bit(a) f.write( " static constexpr size_t __embedded_bits = {};\n".format( get_bits(a.type) ) ) f.write( " static constexpr size_t __embedded_start_bit = {};\n".format( start_end_bit[0] ) ) f.write( " static constexpr size_t __embedded_end_bit = {};\n".format( start_end_bit[1] ) ) else: raise Exception("unexpected type constellation") f.write(" }}; // meta struct {}\n".format(a.name)) f.write(" }; //struct META\n\n") f.write("#endif // #ifndef SWIG\n\n") f.write(f" {i.name}() {{\n") f.write(" mdsd::init_default_values(*this);\n") f.write(" }\n") if _extra_init_required(i): f.write(f" {i.name}({_get_ctor_params(i)}) {{\n") f.write(f" {_get_ctor_body(i)};\n") f.write(" }\n") f.write( " static std::shared_ptr<{}> item_create() {{ return std::make_shared<{}>(); }}\n".format( i.name, i.name ) ) f.write("}}; //struct {}\n".format(i.name)) for a in i.attributes: if a.is_embedded(): value_type = get_cpp_return_type(a.type) signed_info = get_signed_or_unsigned(a.type) container_name = get_container(a).name if textx.textx_isinstance(a, mm["ScalarAttribute"]): f.write( " inline {} {}::{}() const {{\n".format(value_type, i.name, a.name) ) f.write( f" return mdsd::read_{signed_info}_from_container<{value_type}>({container_name}," f" META::{a.name}::__embedded_start_bit, META::{a.name}::__embedded_end_bit);\n" ) f.write(" }\n") else: f.write( " inline {} {}::{}(size_t idx) const {{\n".format( value_type, i.name, a.name ) ) f.write( f" return mdsd::read_{signed_info}_from_container<{value_type}>({container_name}," f" META::{a.name}::__embedded_start_bit-idx*META::{a.name}::__embedded_bits," f" META::{a.name}::__embedded_start_bit+1-(idx+1)*META::{a.name}::__embedded_bits);\n" ) f.write(" }\n") if textx.textx_isinstance(a, mm["ScalarAttribute"]): f.write( " inline void {}::{}({} val) {{\n".format( i.name, a.name, value_type ) ) f.write( f" {container_name} = mdsd::write_to_container({container_name}," f" META::{a.name}::__embedded_start_bit, META::{a.name}::__embedded_end_bit, val);\n" ) f.write(" }\n") else: f.write( " inline void {}::{}(size_t idx, {} val) {{\n".format( i.name, a.name, value_type ) ) f.write( f" {container_name} = mdsd::write_to_container({container_name}," f" META::{a.name}::__embedded_start_bit-idx*META::{a.name}::__embedded_bits," f" META::{a.name}::__embedded_start_bit+1-(idx+1)*META::{a.name}::__embedded_bits, val);\n" ) f.write(" }\n") f.write("#ifndef SWIG\n") # ---------------------------------------- f.write( "template<class VISITOR, class STRUCT> // enable accept for this struct: \n" ) f.write( "std::enable_if_t<std::is_same_v<std::remove_const_t<STRUCT>,{}>> accept(VISITOR &&v, STRUCT &s) {{\n".format( i.name ) ) f.write(" STRUCT::META::template __accept_varargs<STRUCT>(v, s);\n") f.write("}\n") # ---------------------------------------- f.write("#endif // #ifndef SWIG\n") f.write("} // close namespace\n") f.write("// swig helper:\n") for a in i.attributes: if textx.textx_isinstance(a, mm["VariantAttribute"]): f.write(define_swig_variant_access(i, a))
def generate_py_for_struct(struct_obj, output_file): mm = get_metamodel(struct_obj) if obj_is_newer_than_file(struct_obj, output_file): with open(output_file, "w") as f: f.write("""# generated code from dataclasses import dataclass, field import numpy as np import mdsd.item_support as support from mdsd.item.init_values import init_default_values from mdsd.common import get_embedded_from_uint, ArrayLike from mdsd.common import set_embedded_in_uint from mdsd.common import ArrayLike, str2array, array2str from mdsd.common import int2float_fixpoint_value, float2int_fixpoint_value, FixpointArrayLike from typing import Sequence, Union from functools import reduce """) for r in get_referenced_elements_of_struct(struct_obj): f.write("import {}\n".format(module_name(r))) f.write("\n") i = struct_obj for c in i.constant_entries: f.write( f"{c.name} = {fqn(c.type)}({c.value.render_formula(**fp(i))})\n" ) f.write("\n@dataclass(eq=False)\n") f.write("class {}:\n".format(i.name)) for a in i.attributes: if a.is_embedded(): rawtype = a.type if textx_isinstance(a.type, mm["Enum"]): rawtype = a.type.type if textx_isinstance(a, mm["ScalarAttribute"]): # SCALAR EMBEDDED # -------------------------------------------------------------- start_end_bit = get_start_end_bit(a) c = get_container(a) f.write(f" @property\n") f.write(f" def {a.name}(self):\n") f.write( f" ret = get_embedded_from_uint({fqn(rawtype)}, self.{c.name},[{start_end_bit[0]},{start_end_bit[1]}])\n" ) if textx_isinstance(a.type, mm["Enum"]): f.write(f" ret = {fqn(a.type)}(ret)\n") f.write(f" return ret\n") f.write(f"\n") f.write(f" @{a.name}.setter\n") f.write(f" def {a.name}(self, v):\n") if textx_isinstance(a.type, mm["Enum"]): f.write(f" v = v.value\n") f.write( f" assert isinstance(v, {fqn(rawtype)})\n") f.write( f" self.{c.name} = set_embedded_in_uint(v, self.{c.name},[{start_end_bit[0]},{start_end_bit[1]}])\n" ) f.write(f"\n") # -------------------------------------------------------------- elif textx_isinstance(a, mm["ArrayAttribute"]): # ARRAY EMBEDDED # -------------------------------------------------------------- start_end_bit = get_start_end_bit(a) c = get_container(a) f.write(f" @property\n") f.write(f" def {a.name}(self):\n") f.write(f" def getter(idx):\n") f.write(f" assert idx >= 0\n") f.write( f" assert idx < reduce(lambda a, b: a * b, {i.name}._meta['{a.name}']['_get_dim_nd'](self))\n" ) f.write( f" ret = get_embedded_from_uint({fqn(rawtype)}, self.{c.name},[{start_end_bit[0]}-idx*{rawtype.bits},{start_end_bit[0]}+1-(idx+1)*{rawtype.bits}])\n" ) if textx_isinstance(a.type, mm["Enum"]): f.write(f" ret = {fqn(a.type)}(ret)\n") f.write(f" return ret\n") f.write(f" def setter(idx, v):\n") f.write(f" assert idx >= 0\n") f.write( f" assert idx < reduce(lambda a, b: a * b, {i.name}._meta['{a.name}']['_get_dim_nd'](self))\n" ) f.write( f" assert isinstance(v, {fqn(a.type)})\n" ) if textx_isinstance(a.type, mm["Enum"]): f.write(f" v = v.value\n") f.write( f" self.{c.name} = set_embedded_in_uint(v, self.{c.name},[{start_end_bit[0]}-idx*{rawtype.bits},{start_end_bit[0]}+1-(idx+1)*{rawtype.bits}])\n" ) f.write( f" return ArrayLike( getter=getter, setter=setter, mytype={fqn(a.type)}, shape={i.name}._meta['{a.name}']['_get_dim_nd'](self) )\n" ) f.write(f"\n") f.write(f" @{a.name}.setter\n") f.write(f" def {a.name}(self, v):\n") f.write(f" self.{a.name}.copy_from(v)\n") f.write(f"\n") # -------------------------------------------------------------- pass else: raise Exception("unexpected type") else: # not embedded if textx_isinstance(a, mm["ScalarAttribute"]): if textx_isinstance(a.type, mm["RawType"]): f.write(" {} : {}={}()\n".format( a.name, fqn(a.type), fqn(a.type))) else: if textx_isinstance(a.type, mm["Enum"]): f.write(" {} : {} = {}.{}\n".format( a.name, fqn(a.type), fqn(a.type), a.type.enum_entries[0].name, )) else: f.write( " {} : {}= field( default_factory=lambda: {}() )\n" .format(a.name, fqn(a.type), fqn(a.type))) if hasattr(a, "type") and a.type.name == "char": f.write(f" @property\n") f.write(f" def {a.name}_as_str(self):\n") f.write(f" return chr(self.{a.name})\n") f.write(f"\n") f.write(f" @{a.name}_as_str.setter\n") f.write(f" def {a.name}_as_str(self, v):\n") f.write( f" self.{a.name} = np.uint8(ord(v))\n") f.write(f"\n") elif textx_isinstance(a, mm["ArrayAttribute"]): if textx_isinstance(a.type, mm["RawType"]): f.write(" {} : np.ndarray=None\n".format( a.name)) else: f.write(" {} : Sequence[{}]=None\n".format( a.name, fqn(a.type))) if hasattr(a, "type") and a.type.name == "char": f.write(f" @property\n") f.write(f" def {a.name}_as_str(self):\n") f.write( f" return array2str(self.{a.name})\n") f.write(f"\n") f.write(f" @{a.name}_as_str.setter\n") f.write(f" def {a.name}_as_str(self, v):\n") f.write( f" self.{a.name} = str2array(v, len(self.{a.name}))\n" ) f.write(f"\n") elif textx_isinstance(a, mm["VariantAttribute"]): f.write(" {} : Union[{}]=None\n".format( a.name, get_variant_types(a))) else: raise Exception("unexpected type") pdefs = get_all_possible_properties(a) pdefs = sorted(pdefs.keys()) if "fixpointLsbValue" in pdefs: if textx_isinstance(a, mm["ScalarAttribute"]): if has_fixpoint(a): f.write(f" @property\n") f.write( f" def {'item_fixpoint_'+a.name}(self):\n") f.write( f" return int2float_fixpoint_value(self, '{a.name}', self.{a.name})\n" ) f.write(f" @{'item_fixpoint_'+a.name}.setter\n") f.write( f" def {'item_fixpoint_'+a.name}(self, v):\n" ) f.write( f" self.{a.name} = float2int_fixpoint_value(self, '{a.name}', v)\n" ) elif textx_isinstance(a, mm["ArrayAttribute"]): if has_fixpoint(a): f.write(f" @property\n") f.write( f" def {'item_fixpoint_'+a.name}(self):\n") f.write( f" return FixpointArrayLike(self, '{a.name}')\n" ) f.write(f" @{'item_fixpoint_'+a.name}.setter\n") f.write( f" def {'item_fixpoint_'+a.name}(self, v):\n" ) f.write( f" self.{a.name} = float2int_fixpoint_value(self, '{a.name}', v)\n" ) f.write("\n def __post_init__(self):\n") f.write(" init_default_values(self)\n") f.write(f""" def __setattr__(self, attribute, value): if not attribute in self._meta: raise Exception("Illegal field {{}} in {{}}".format(attribute,self.__class__.__name__)) else: if len(self._meta[attribute])==0: super({i.name}, self).__setattr__(attribute, value) elif self._meta[attribute]["_is_embedded"]: super({i.name}, self).__setattr__(attribute, value) elif value is None: self.__dict__[attribute] = value elif self._meta[attribute]["_is_variant"]: if isinstance(value, self._meta[attribute]["_get_type"]()): self.__dict__[attribute] = value else: raise Exception("Illegal value of type {{}} for field {{}}".format(value.__class__.__name__,attribute)) elif self._meta[attribute]["_is_scalar"]: if isinstance(value, self._meta[attribute]["_get_type"]()): self.__dict__[attribute] = value elif self._meta[attribute]["_is_rawtype"]: self.__dict__[attribute] = self._meta[attribute]["_get_type"]()(value) else: raise Exception("Illegal value of type {{}} for field {{}}".format(value.__class__.__name__,attribute)) else: self.__dict__[attribute] = np.array(value, dtype=self._meta[attribute]["_get_type"]()) """) f.write("\n _meta_order = [\n") for a in i.attributes: f.write(f" '{a.name}',\n") f.write("\n ]\n") f.write("\n _meta = {\n") for a in i.attributes: pdefs = get_all_possible_properties(a) pdefs = sorted(pdefs.keys()) if "fixpointLsbValue" in pdefs: if has_fixpoint(a): f.write(' "item_fixpoint_{}": {{}},'.format( a.name)) if hasattr(a, "type") and a.type.name == "char": f.write(f' "{a.name}_as_str": {{}},\n') if a.is_variant(): for m in a.mappings: m_pdefs = get_all_possible_properties(m) m_pdefs = sorted(m_pdefs.keys()) f.write(f' "{meta_name_for_mapping(m)}": ') f.write("{") output_properties(f, m, m_pdefs) f.write("},\n") f.write(' "{}": {{ '.format(a.name)) f.write('"_name":"{}",'.format(a.name)) if a.if_attr is None: f.write('"_has_if_restriction":False,') f.write('"_if_restriction":lambda _: True,') else: f.write('"_has_if_restriction":True,') f.write('"_if_restriction":lambda s:{},'.format( a.if_attr.predicate.render_formula(prefix="s."))) if textx_isinstance(a, mm["VariantAttribute"]): f.write('"_get_type_for": lambda s: {}[s.{}], '.format( get_variant_type_map(a), a.variant_selector.render_formula(**fp(struct_obj)), )) f.write('"_get_meta_for": lambda s: {}[s.{}], '.format( get_variant_meta_map(struct_obj, a), a.variant_selector.render_formula(**fp(struct_obj)), )) f.write('"_is_scalar":True,') f.write('"_is_variant":True,') f.write('"_is_array":False,') f.write('"_is_rawtype":False,') f.write('"_is_enum":False,') f.write('"_is_struct":True,') f.write('"_is_embedded":False,') f.write('"_get_type": lambda: ({}), '.format( get_variant_types(a))) elif textx_isinstance(a, mm["ScalarAttribute"]): f.write(f'"_is_container":{a.is_container()},') f.write('"_is_scalar":True,') f.write('"_is_variant":False,') f.write('"_is_array":False,') if textx_isinstance(a.type, mm["RawType"]): f.write('"_is_rawtype":True,') else: f.write('"_is_rawtype":False,') if textx_isinstance(a.type, mm["Struct"]): f.write('"_is_struct":True,') else: f.write('"_is_struct":False,') if textx_isinstance(a.type, mm["Enum"]): f.write('"_is_enum":True,') else: f.write('"_is_enum":False,') f.write(f'"_is_embedded":{tf(a.is_embedded())},') f.write('"_get_type": lambda: {}, '.format(fqn(a.type))) if textx_isinstance(a.type, mm["Enum"]): f.write('"_get_underlying_type": lambda: {}, '.format( fqn(a.type.type))) if hasattr(a, "type") and a.type.name == "char": f.write('"_has_char_content":True,') else: f.write('"_has_char_content":False,') elif textx_isinstance(a, mm["ArrayAttribute"]): f.write('"_is_scalar":False,') f.write('"_is_variant":False,') f.write('"_is_array":True,') if a.has_fixed_size(): f.write('"_is_dynamic_array":False,') else: f.write('"_is_dynamic_array":True,') f.write('"_get_dim":lambda x:({}),'.format( a.render_formula(prefix="x.", **fp(struct_obj)))) f.write('"_get_dim_nd":lambda x:({},),'.format( a.render_formula_comma_separated(prefix="x.", **fp(struct_obj)))) if textx_isinstance(a.type, mm["RawType"]): f.write('"_is_rawtype":True,') else: f.write('"_is_rawtype":False,') if textx_isinstance(a.type, mm["Struct"]): f.write('"_is_struct":True,') else: f.write('"_is_struct":False,') if textx_isinstance(a.type, mm["Enum"]): f.write('"_is_enum":True,') else: f.write('"_is_enum":False,') f.write(f'"_is_embedded":{tf(a.is_embedded())},') f.write('"_get_type": lambda: {}, '.format(fqn(a.type))) if textx_isinstance(a.type, mm["Enum"]): f.write('"_get_underlying_type": lambda: {}, '.format( fqn(a.type.type))) if hasattr(a, "type") and a.type.name == "char": f.write('"_has_char_content":True,') else: f.write('"_has_char_content":False,') else: raise Exception("unexpected type constellation") pdefs = get_all_possible_properties(a) pdefs = sorted(pdefs.keys()) if "fixpointLsbValue" in pdefs: if has_fixpoint(a): f.write(f'"_is_fixpoint":True,') f.write( f'"_fixpointLsbValue": {get_fixpoint_LSB_value(a)},' ) f.write( f'"_fixpointOffsetValue": {get_fixpoint_offset_value(a)},' ) else: f.write(f'"_is_fixpoint":False,') else: f.write(f'"_is_fixpoint":False,') output_properties(f, a, pdefs) f.write("},\n") f.write(" } # end of _meta\n") f.write(" _meta_struct={\n") for up in get_all_unique_properties(i): f.write( f" 'item_get_unique_{up[0].name}':lambda i:i.{'.'.join(map(lambda x:x.name, up[1]))},\n" ) f.write( f" 'item_set_unique_{up[0].name}':lambda i,v:setattr({'.'.join(['i']+list(map(lambda x: x.name, up[1][:-1])))}, '{up[1][-1].name}',v),\n" ) f.write(" } # end of _meta_struct\n")
def check_Struct(s): mm = get_metamodel(s) # check mandatory properties in attributes mandatory_prop_defs = get_all_possible_mandatory_properties(s) attr_prop_defs = map(lambda p: p.definition, s.properties) for d in mandatory_prop_defs.values(): textx_assert(d in attr_prop_defs, s, f"missing mandatory property '{d.name}'") # check if max count of properties are not violated ("... to ... times per message) def get_all_properties_of_struct(s): lst = [] for a in s.attributes: lst = lst + a.properties if textx_isinstance(a, mm["ScalarAttribute"]) and textx_isinstance( a.type, mm["Struct"]): do_break = get_property(a, "is_payload") # None or bool if do_break is None or not do_break: lst = lst + get_all_properties_of_struct(a.type) return lst properties = get_all_properties_of_struct(s) properties_per_def = {} for p in properties: if p.definition not in properties_per_def: properties_per_def[p.definition] = [p] else: properties_per_def[p.definition].append(p) property_defs = get_all_possible_properties( s, filter_applicable_to_model_object=False).values() for d in property_defs: if d.numberOfPropRestriction is not None: n = len(properties_per_def.get(d, [])) textx_assert( n >= d.numberOfPropRestriction.min, s, f'need at least {d.numberOfPropRestriction.min} of property "{d.name}"', ) textx_assert( n <= d.numberOfPropRestriction.max, s, f'not more than {d.numberOfPropRestriction.max} of property "{d.name}" allowed', ) # unique names: all_attribute_names = list(map(lambda x: x.name, s.attributes)) all_attribute_names_unique = set(all_attribute_names) if len(all_attribute_names) != len(all_attribute_names_unique): idx = 0 while len(all_attribute_names) > 0: first = all_attribute_names[0] del all_attribute_names[0] textx_assert( first in all_attribute_names_unique, s.attributes[idx], f"attribute name {first} is not unique", ) all_attribute_names_unique.remove(first) idx += 1 check_Constants(s)