예제 #1
0
파일: enum.py 프로젝트: goto40/mdsd
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")
예제 #2
0
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")
예제 #3
0
파일: struct.py 프로젝트: goto40/mdsd
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")
예제 #4
0
파일: struct.py 프로젝트: goto40/mdsd
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")
예제 #5
0
파일: struct.py 프로젝트: goto40/mdsd
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))