def generate_cpp_enum(f, e): """ :param f: outut file obj :param e: enum obj """ f.write(get_open_namespace_for_obj(e)) f.write("enum class {} : {} {{\n".format(e.name, fqn(e.type))) for ee in e.enum_entries: comma = "" if ee == e.enum_entries[-1] else "," f.write(" {} = {}{}\n".format(ee.name, ee.value.render_formula(), comma)) f.write("};\n") f.write(f"inline std::ostream& operator<<(std::ostream& o, const {e.name}& v) {{\n") f.write(" switch(v) {\n") for ee in e.enum_entries: f.write(f' case {e.name}::{ee.name}: o << "{ee.name}"; break;\n') f.write(' default: o << "???";\n') f.write(" }\n") f.write(" return o;\n") f.write("}\n") f.write(f"inline std::istream& operator>>(std::istream& i, {e.name}& ret) {{\n") f.write(" std::string txt;\n") f.write(" i >> txt;\n") elseif = "if" for ee in e.enum_entries: f.write(f' {elseif}(txt == "{ee.name}") {{ ret = {e.name}::{ee.name}; }}\n') elseif = "else if" f.write( f' else {{ throw std::runtime_error(std::string("unknown {e.name}: ")+txt); }}\n' ) f.write(" return i;\n") f.write("}\n") f.write("} // close namespace\n")
def generate_cpp_constants(f, cs): f.write(get_open_namespace_for_obj(cs)) f.write("struct {} {{\n".format(cs.name)) for c in cs.constant_entries: f.write(" static constexpr {} {} = {};\n".format( fqn(c.type), c.name, c.value.render_formula())) f.write("}}; //{}\n\n".format(cs.name)) f.write("}\n")
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(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_variant(): f.write(" // -- variant {}\n".format(a.name)) f.write(" union {\n") for m in a.mappings: f.write(f" {get_cpp_return_type(m.type)} {m.the_name};\n") f.write(" }} {} // depends on {}\n".format( a.name, a.variant_selector.render_formula())) else: value_type = get_cpp_return_type(a.type) if a.is_container(): f.write(" // -- container {} {}\n".format(value_type, a.name)) f.write(" // not represented.") elif a.has_fixpoint() and a.is_scalar(): f.write(" // -- fixpoint scalar {} {}\n".format( value_type, a.name)) f.write(" double {}; \n".format(a.name)) elif a.has_fixpoint() and a.is_array(): f.write(" // -- fixpoint array {} {}\n".format( value_type, a.name)) f.write(" double {}{}; \n".format(a.name, get_max_dims(a))) elif a.is_scalar(): f.write(" // -- scalar {} {}\n".format(value_type, a.name)) f.write(" {} {}; \n".format(value_type, a.name)) elif a.is_array(): f.write(" // -- array {} {}\n".format(value_type, a.name)) f.write(" {} {}{}; \n".format(value_type, a.name, get_max_dims(a))) f.write("}\n") # ---------------------------------------- f.write("} // close namespace\n")
def _get_ctor_param_type(a): mm = get_metamodel(a) if a.is_embedded(): if textx.textx_isinstance(a, mm["ScalarAttribute"]): return get_cpp_return_type(a.type) elif textx.textx_isinstance(a, mm["ArrayAttribute"]): return f"std::array<{get_cpp_return_type(a.type)},{a.compute_formula()}>" if textx.textx_isinstance(a, mm["ScalarAttribute"]): return fqn(a.type) elif textx.textx_isinstance(a, mm["ArrayAttribute"]): if a.has_fixed_size(): return f"std::array<{fqn(a.type)},{a.compute_formula()}>" else: return f"std::vector<{fqn(a.type)}>" elif textx.textx_isinstance(a, mm["VariantAttribute"]): return f"std::variant<{get_variant_types(a)}>" else: raise Exception("unexpected type")
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))