Ejemplo n.º 1
0
    def get_reference_propositions(self, obj, attr, name_part):
        """
        retrieve a list of reference propositions.
        Args:
            obj: parent
            attr: attribute
            name_part: The name is used to build the list
                (e.g. using a substring-like logic).
        Returns:
            the list of objects representing the proposed references
        """
        from textx.scoping.tools import resolve_model_path
        from textx import textx_isinstance
        obj_list = resolve_model_path(obj, self.path_to_container_object)
        if type(obj_list) is Postponed:
            self.postponed_counter += 1
            return obj_list
        # the referenced element must be a list
        # (else it is a design error in the path passed to
        # the RelativeName object).
        if not isinstance(obj_list, list):
            from textx.exceptions import TextXError
            raise TextXError(
                "expected path to list in the model ({})".format(
                    self.path_to_container_object))
        obj_list = filter(
            lambda x: textx_isinstance(x, attr.cls) and
            x.name.find(name_part) >= 0, obj_list)

        return list(obj_list)
 def custom_scope_redirection(obj):
     from textx import textx_isinstance
     if textx_isinstance(obj, mm["PackageRef"]):
         if obj.ref is None:
             from textx.scoping import Postponed
             return Postponed()
         return [obj.ref]
     else:
         return []
Ejemplo n.º 3
0
        def _find_obj_fqn(p, fqn_name, cls):
            """
            Helper function:
            find a named object based on a qualified name ("."-separated
            names) starting from object p.

            Args:
                p: the container where to start the search
                fqn_name: the "."-separated name

            Returns:
                the object or None
            """

            def find_obj(parent, name):
                if parent is not current_obj and \
                        self.scope_redirection_logic is not None:
                    from textx.scoping import Postponed
                    res = self.scope_redirection_logic(parent)
                    assert res is not None, \
                        "scope_redirection_logic must not return None"
                    if type(res) is Postponed:
                        return res
                    for m in res:
                        return_value = find_obj(m, name)
                        if return_value is not None:
                            return return_value
                for attr in [a for a in parent.__dict__ if
                             not a.startswith('__') and not
                             a.startswith('_tx_') and not
                             callable(getattr(parent, a))]:
                    obj = getattr(parent, attr)
                    if isinstance(obj, (list, tuple)):
                        for innerobj in obj:
                            if hasattr(innerobj, "name") \
                                    and innerobj.name == name:
                                return innerobj
                    else:
                        if hasattr(obj, "name") and obj.name == name:
                            return obj
                return None

            for n in fqn_name.split('.'):
                obj = find_obj(p, n)
                if obj:
                    if type(obj) is Postponed:
                        return obj
                    p = obj
                else:
                    return None

            from textx import textx_isinstance
            if textx_isinstance(obj, cls):
                return p
            else:
                return None
Ejemplo n.º 4
0
def test_textx_isinstace():
    grammar = \
        '''
    Model: a=A;
    A: B;
    B: C;
    C: x=ID;
    '''
    my_meta_model = metamodel_from_str(grammar)
    A = my_meta_model['A']
    B = my_meta_model['B']
    C = my_meta_model['C']
    my_model = my_meta_model.model_from_str("c")
    c = get_children_of_type("C", my_model)
    assert len(c) == 1
    c = c[0]
    assert textx_isinstance(c, C)
    assert textx_isinstance(c, B)
    assert textx_isinstance(c, A)
Ejemplo n.º 5
0
    def get_reference_propositions(self, obj, attr, name_part):
        """
        retrieve a list of reference propositions.
        Args:
            obj: parent
            attr: attribute
            name_part: The name is used to build the list
                (e.g. using a substring-like logic).
        Returns:
            the list of objects representing the proposed references
        """
        from textx.scoping.tools import resolve_model_path
        from textx import textx_isinstance
        # find all all "connected" objects
        # (e.g. find all classes: the most derived
        # class, its base, the base of its base, etc.)
        from textx.scoping.tools import get_list_of_concatenated_objects
        def_obj = resolve_model_path(obj, self.path_to_definition_object)
        def_objs = get_list_of_concatenated_objects(
            def_obj, self.path_to_extension)
        # for all containing classes, collect all
        # objects to be looked up (e.g. methods)
        obj_list = []
        for def_obj in def_objs:
            if type(def_obj) is Postponed:
                self.postponed_counter += 1
                return def_obj

            tmp_list = resolve_model_path(def_obj, self.path_to_target)
            assert tmp_list is not None
            # expected to point to  alist
            if not isinstance(tmp_list, list):
                from textx.exceptions import TextXError
                raise TextXError(
                    "expected path to list in the model ({})".format(
                        self.path_to_target))
            tmp_list = list(filter(
                lambda x: textx_isinstance(x, attr.cls) and
                x.name.find(name_part) >= 0, tmp_list))
            obj_list = obj_list + tmp_list

        return list(obj_list)
    def ref_scope(refItem, attr, attr_ref):
        from textx.scoping.tools import get_named_obj_in_list
        from textx.scoping import Postponed
        from textx import textx_isinstance
        reference = refItem.parent
        if reference is None:
            return Postponed()
        index = reference.refs.index(refItem)
        assert (index >= 0)

        base = reference.instance if index == 0 \
            else reference.refs[index - 1].valref
        if base is None or base.type is None:
            return Postponed()
        x = get_named_obj_in_list(base.type.vals, attr_ref.obj_name)

        if index == len(reference.refs)-1:
            if not textx_isinstance(x, attr.cls):
                print(x)
                return None
        return x
Ejemplo n.º 7
0
def _assert_attr_used_in_formula_must_have_a_max_and_default_value(f, d):
    mm = get_metamodel(d)
    all_refs = list(
        map(lambda x: x.ref._tx_path, get_children_of_type("AttrRef", f)))
    # _tx_apth is a list of references to the final variable (e.g. header.n
    # yields [header,n].
    if len(all_refs) > 0:
        all_refs = reduce(lambda a, b: a + b, all_refs)  # merge all ref lists
    all_refs = filter(
        lambda x: textx_isinstance(x, mm["ScalarAttribute"]) and x.has_rawtype(
        ),
        all_refs,
    )
    for r in all_refs:
        textx_assert(
            has_property(r, "maxValue"),
            d,
            f"attribute {r.name} used in dim formula must have a 'maxValue'",
        )
        textx_assert(
            has_property(r, "defaultValue"),
            d,
            f"attribute {r.name} used in dim formula must have a 'defaultValue'",
        )
Ejemplo n.º 8
0
    def __call__(self, obj, attr, obj_ref):
        """
        the default scope provider

        Args:
            obj: unused (used for multi_metamodel_support)
            attr: unused
            obj_ref: the cross reference to be resolved

        Returns:
            the resolved reference or None
        """
        from textx.const import RULE_COMMON, RULE_ABSTRACT
        from textx.model import ObjCrossRef
        from textx.scoping.tools import get_parser

        if obj_ref is None:
            return None  # an error! (see model.py: resolve_refs (TODO check)

        assert type(obj_ref) is ObjCrossRef, type(obj_ref)

        if get_parser(obj).debug:
            get_parser(obj).dprint("Resolving obj crossref: {}:{}"
                                   .format(obj_ref.cls, obj_ref.obj_name))

        def _inner_resolve_link_rule_ref(cls, obj_name):
            """
            Depth-first resolving of link rule reference.
            """
            if cls._tx_type is RULE_ABSTRACT:
                for inherited in cls._tx_inh_by:
                    result = _inner_resolve_link_rule_ref(inherited,
                                                          obj_name)
                    if result:
                        return result
            elif cls._tx_type == RULE_COMMON:
                # TODO make this code exchangable
                # allow to know the current attribute (model location for
                # namespace) and to navigate through the whole model...
                # OR (with another scope provider) to make custom lookups in
                # the model
                #
                # Scopeprovider
                # - needs: .current reference (in the model)
                #          .the model (?)
                # - provides: the resolved object or None
                if id(cls) in get_parser(obj)._instances:
                    objs = get_parser(obj)._instances[id(cls)]
                    return objs.get(obj_name)

        if self.multi_metamodel_support:
            from textx import get_model, get_children
            from textx import textx_isinstance
            result_lst = get_children(
                lambda x:
                hasattr(x, "name") and x.name == obj_ref.obj_name
                and textx_isinstance(x, obj_ref.cls), get_model(obj))
            if len(result_lst) == 1:
                result = result_lst[0]
            elif len(result_lst) > 1:
                line, col = get_parser(obj).pos_to_linecol(obj_ref.position)
                raise TextXSemanticError(
                    "name {} is not unique.".format(obj_ref.obj_name),
                    line=line, col=col, filename=get_model(obj)._tx_filename)
            else:
                result = None
        else:
            result = _inner_resolve_link_rule_ref(obj_ref.cls,
                                                  obj_ref.obj_name)
        if result:
            return result

        return None  # error handled outside
Ejemplo n.º 9
0
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))
Ejemplo n.º 10
0
 def _is(x, rule):
     return textx_isinstance(x, calc_mm[rule])
 def __call__(self, obj, attr, obj_ref):
     if textx_isinstance(obj.parent, self.meta["Start"]):
         return self.pStart(obj, attr, obj_ref)
     else:
         return self.pEvent1(obj, attr, obj_ref)
Ejemplo n.º 12
0
def is_applicable_for(parent, definition):
    mm = get_metamodel(parent)
    appl = definition.applicable_for

    if len(appl) == 0:
        #  not apply ATTRTYPE properties for structs
        if (textx_isinstance(parent, mm["Struct"])
                or textx_isinstance(parent, mm["EnumEntry"])
                or textx_isinstance(parent, mm["VariantMapping"]) or
            (hasattr(parent, "type")
             and textx_isinstance(parent.type, mm["Struct"]))
            ) and definition.internaltype == "ATTRTYPE":
            raise Exception(
                "ATTRTYPE only applicable for rawtype/enum scalar/array attributes"
            )
        return True

    attr = parent
    assert (textx_isinstance(attr, mm["Attribute"])
            or textx_isinstance(attr, mm["VariantMapping"])
            or textx_isinstance(attr, mm["EnumEntry"])
            or textx_isinstance(attr, mm["Struct"]))
    if "array" in appl or "scalar" in appl:
        if "struct_definition" not in appl and textx_isinstance(
                attr, mm["Struct"]):
            return False
        elif "array" not in appl and textx_isinstance(attr,
                                                      mm["ArrayAttribute"]):
            return False
        elif "scalar" not in appl and (
                textx_isinstance(attr, mm["ScalarAttribute"])
                or textx_isinstance(attr, mm["VariantMapping"])):
            return False
    appl = list(filter(lambda x: x not in ["scalar", "array"], appl))
    if len(appl) == 0:
        return True
    if textx_isinstance(attr, mm["Struct"]) and "struct_definition" in appl:
        return True
    if textx_isinstance(attr, mm["VariantAttribute"]) and "variant" in appl:
        return True
    if textx_isinstance(attr, mm["EnumEntry"]) and "enum_value" in appl:
        return True
    if textx_isinstance(attr, mm["VariantMapping"]):
        if "struct" in appl:
            return True
        else:
            return False
    if textx_isinstance(attr, mm["ArrayAttribute"]) or textx_isinstance(
            attr, mm["ScalarAttribute"]):
        if textx_isinstance(attr.type, mm["Enum"]) and "enum" in appl:
            return True
        if textx_isinstance(attr.type, mm["Struct"]) and "struct" in appl:
            return True
        if textx_isinstance(attr.type, mm["RawType"]):
            rt_appl = list(
                filter(
                    lambda x: textx_isinstance(x, mm["ApplicableForRawType"]),
                    appl))
            if len(rt_appl) == 0:
                return False

            allowed = list(
                reduce(lambda x, y: x.extend(y),
                       map(lambda x: x.concrete_types, rt_appl)))
            if len(allowed) == 0:
                return True  # all rawtypes allowed
            elif attr.type in allowed:
                return True
    return False
Ejemplo n.º 13
0
    def resolve_one_step(self):
        """
        Resolves model references.
        """
        metamodel = self.parser.metamodel

        current_crossrefs = self.parser._crossrefs
        # print("DEBUG: Current crossrefs #: {}".
        #      format(len(current_crossrefs)))
        new_crossrefs = []
        self.delayed_crossrefs = []
        resolved_crossref_count = 0

        # -------------------------
        # start of resolve-loop
        # -------------------------
        default_scope = DefaultScopeProvider()
        for obj, attr, crossref in current_crossrefs:
            if (get_model(obj) == self.model):
                attr_value = getattr(obj, attr.name)
                attr_refs = [
                    obj.__class__.__name__ + "." + attr.name, "*." + attr.name,
                    obj.__class__.__name__ + ".*", "*.*"
                ]
                if crossref.scope_provider is not None:
                    resolved = crossref.scope_provider(obj, attr, crossref)
                else:
                    for attr_ref in attr_refs:
                        if attr_ref in metamodel.scope_providers:
                            if self.parser.debug:
                                self.parser.dprint(
                                    " FOUND {}".format(attr_ref))
                            resolved = metamodel.scope_providers[attr_ref](
                                obj, attr, crossref)
                            break
                    else:
                        resolved = default_scope(obj, attr, crossref)

                # Collect cross-references for textx-tools
                if resolved is not None and not type(resolved) is Postponed:
                    if metamodel.textx_tools_support:
                        self.pos_crossref_list.append(
                            RefRulePosition(
                                name=crossref.obj_name,
                                ref_pos_start=crossref.position,
                                ref_pos_end=crossref.position +
                                len(resolved.name),
                                def_pos_start=resolved._tx_position,
                                def_pos_end=resolved._tx_position_end))

                if resolved is None:
                    # As a fall-back search builtins if given
                    if metamodel.builtins:
                        if crossref.obj_name in metamodel.builtins:
                            from textx import textx_isinstance
                            if textx_isinstance(
                                    metamodel.builtins[crossref.obj_name],
                                    crossref.cls):
                                resolved = metamodel.builtins[
                                    crossref.obj_name]

                if resolved is None:
                    line, col = self.parser.pos_to_linecol(crossref.position)
                    raise TextXSemanticError(
                        message='Unknown object "{}" of class "{}"'.format(
                            crossref.obj_name, crossref.cls.__name__),
                        line=line,
                        col=col,
                        err_type=UNKNOWN_OBJ_ERROR,
                        expected_obj_cls=crossref.cls,
                        filename=self.model._tx_filename)

                if type(resolved) is Postponed:
                    self.delayed_crossrefs.append((obj, attr, crossref))
                    new_crossrefs.append((obj, attr, crossref))
                else:
                    resolved_crossref_count += 1
                    if attr.mult in [MULT_ONEORMORE, MULT_ZEROORMORE]:
                        attr_value.append(resolved)
                    else:
                        setattr(obj, attr.name, resolved)
            else:  # crossref not in model
                new_crossrefs.append((obj, attr, crossref))
        # -------------------------
        # end of resolve-loop
        # -------------------------
        # store cross-refs from other models in the parser list (for later
        # processing)
        self.parser._crossrefs = new_crossrefs
        # print("DEBUG: Next crossrefs #: {}".format(len(new_crossrefs)))
        return (resolved_crossref_count, self.delayed_crossrefs)
def test_metamodel_provider_advanced_test3_global():
    """
    Advanced test for ExtRelativeName and PlainNameGlobalRepo.

    Here we have a global model repository shared between
    different meta models.

    The meta models interact (refer to each other, different directions).
    """
    #################################
    # META MODEL DEF
    #################################
    this_folder = dirname(abspath(__file__))

    def get_meta_model(global_repo, grammar_file_name):
        mm = metamodel_from_file(join(this_folder, grammar_file_name),
                                 debug=False, classes=[Cls, Obj])
        mm.register_scope_providers({
            "*.*": global_repo,
        })
        return mm

    global_repo_provider = scoping_providers.PlainNameGlobalRepo()
    global_repo_provider.register_models(
        join(this_folder, "metamodel_provider3", "circular", "*.a"))
    global_repo_provider.register_models(
        join(this_folder, "metamodel_provider3", "circular", "*.b"))
    global_repo_provider.register_models(
        join(this_folder, "metamodel_provider3", "circular", "*.c"))

    a_mm = get_meta_model(
        global_repo_provider, join(this_folder,
                                   "metamodel_provider3", "A.tx"))
    b_mm = get_meta_model(
        global_repo_provider, join(this_folder,
                                   "metamodel_provider3", "B.tx"))
    c_mm = get_meta_model(
        global_repo_provider, join(this_folder,
                                   "metamodel_provider3", "C.tx"))

    clear_language_registrations()
    register_language(
        'a-dsl',
        pattern='*.a',
        description='Test Lang A',
        metamodel=a_mm)
    register_language(
        'b-dsl',
        pattern='*.b',
        description='Test Lang B',
        metamodel=b_mm)
    register_language(
        'c-dsl',
        pattern='*.c',
        description='Test Lang C',
        metamodel=c_mm)

    #################################
    # MODEL PARSING
    #################################

    model_repo = global_repo_provider.load_models_in_model_repo().all_models

    #################################
    # TEST MODEL
    #################################

    def get_all(model_repo, what):
        lst = []
        for m in model_repo.filename_to_model.values():
            lst = lst + get_children_of_type(what, m)
        return lst

    lst = get_all(model_repo, "Obj")
    # print(lst)
    assert len(lst) == 3

    # check some references to be resolved (!=None)
    for a in lst:
        assert a.ref

    # check meta classes
    assert a_mm["Cls"]._tx_fqn == b_mm["Cls"]._tx_fqn

    # more checks
    from textx import textx_isinstance
    for a in lst:
        assert textx_isinstance(a, a_mm["Obj"])
        assert textx_isinstance(a, b_mm["Obj"])
        assert textx_isinstance(a, c_mm["Obj"])

    #################################
    # END
    #################################
    clear_language_registrations()
Ejemplo n.º 15
0
def get_property(attr, prop_name):
    def get_value(res, internaltype):
        if internaltype == "STRING":
            textx_assert(res.textValue is not None, attr,
                         prop_name + " must be a STRING")
            return res.textValue.x
        elif internaltype == "INT":
            textx_assert(res.numberValue is not None, attr,
                         prop_name + " must be an NUMBER/INT")
        elif internaltype == "UINT":
            textx_assert(res.numberValue is not None, attr,
                         prop_name + " must be an NUMBER/UINT")
        elif internaltype == "BOOL":
            textx_assert(
                res.numberValue is not None,
                attr,
                prop_name + " must be an NUMBER/BOOL as int",
            )
        elif internaltype == "FLOAT":
            textx_assert(res.numberValue is not None, attr,
                         prop_name + " must be an NUMBER")
            assert res.numberValue is not None
        elif internaltype == "ENUM":
            textx_assert(res.numberValue is not None, attr,
                         prop_name + " must be an ENUM")
            assert res.numberValue is not None
        else:
            return None
        return compute_formula_for_internaltype(res.numberValue.x,
                                                internaltype, prop_name)

    res = list(
        filter(lambda x: x.definition.name == prop_name, attr.properties))
    if len(res) == 0:
        return None
    else:
        mm = get_metamodel(attr)
        textx_assert(len(res) == 1, attr, prop_name + " must be unique")
        res = res[0]
        internaltype = res.definition.internaltype
        if internaltype == "ATTRTYPE":
            textx_assert(
                not textx_isinstance(attr, mm["VariantAttribute"]),
                attr,
                prop_name + " not supported for variants",
            )
            correct_instance = textx_isinstance(
                attr.type, mm["RawType"]) or textx_isinstance(
                    attr.type, mm["Enum"])
            textx_assert(
                correct_instance,
                attr,
                prop_name + " only applicable for rawtypes/enums",
            )
            internaltype = attr.type.internaltype
        value = get_value(res, internaltype)
        textx_assert(
            value is not None,
            attr,
            prop_name + " could not be interpreted (unexpected)",
        )
        return value
Ejemplo n.º 16
0
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")
Ejemplo n.º 17
0
 def _is(x, rule):
     return textx_isinstance(x, calc_mm[rule])
Ejemplo n.º 18
0
def test_rrel_basic_lookup():
    """
    This is a basic test for the find function:
    we use a model with some structure
    and query this structure with RREL expressions.
    """
    #################################
    # META MODEL DEF
    #################################

    my_metamodel = metamodel_from_str(metamodel_str)

    #################################
    # MODEL PARSING
    #################################

    my_model = my_metamodel.model_from_str(modeltext)

    #################################
    # TEST
    #################################

    P2 = find(my_model, "P2", "packages")
    assert P2.name == "P2"
    Part2 = find(my_model, "P2.Part2", "packages.classes")
    assert Part2.name == "Part2"
    rec = find(my_model, "P2.Part2.rec", "packages.classes.attributes")
    rec_with_fixed_name = find(my_model, "P2.rec",
                               "packages.'Part2'~classes.attributes")
    assert rec_with_fixed_name is rec
    assert rec.name == "rec"
    assert rec.parent == Part2

    P2 = find(my_model, "P2", "(packages)")
    assert P2.name == "P2"

    from textx import get_model
    assert get_model(my_model) is my_model

    P2 = find(my_model, "P2", "packages*")
    assert P2.name == "P2"
    Part2 = find(my_model, "P2.Part2", "packages*.classes")
    assert Part2.name == "Part2"
    rec = find(my_model, "P2.Part2.rec", "packages*.classes.attributes")
    assert rec.name == "rec"
    assert rec.parent == Part2

    Part2_tst = find(rec, "", "..")
    assert Part2_tst is Part2

    P2_from_inner_node = find(rec, "P2", "(packages)")
    assert P2_from_inner_node is P2

    P2_tst = find(rec, "", "parent(Package)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "...")
    assert P2_tst is P2

    P2_tst = find(rec, "", ".(..).(..)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "(..).(..)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "...(.).(.)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "..(.).(..)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "..((.)*)*.(..)")
    assert P2_tst is P2

    none = find(my_model, "", "..")
    assert none is None

    m = find(my_model, "", ".")  # '.' references the current element
    assert m is my_model

    inner = find(my_model, "inner", "~packages.~packages.~classes.attributes")
    assert inner.name == "inner"

    package_Inner = find(inner, "Inner", "parent(OBJECT)*.packages")
    assert textx_isinstance(package_Inner, my_metamodel["Package"])
    assert not textx_isinstance(package_Inner, my_metamodel["Class"])

    assert None is find(inner, "P2", "parent(Class)*.packages")

    # expensive version of a "Plain Name" scope provider:
    inner = find(my_model, "inner", "~packages*.~classes.attributes")
    assert inner.name == "inner"

    rec2 = find(my_model, "P2.Part2.rec",
                "other1,other2,packages*.classes.attributes")
    assert rec2 is rec

    rec2 = find(my_model, "P2.Part2.rec",
                "other1,packages*.classes.attributes,other2")
    assert rec2 is rec

    rec2 = find(my_model,
                "P2::Part2::rec",
                "other1,packages*.classes.attributes,other2",
                split_string="::")
    assert rec2 is rec

    rec2 = find(my_model, "P2.Part2.rec", "other1,other2,other3")
    assert rec2 is None

    rec2 = find(my_model, "P2.Part2.rec", "(packages,classes,attributes)*")
    assert rec2 is rec

    rec2 = find(my_model, "P2.Part2.rec",
                "(packages,(classes,attributes)*)*.attributes")
    assert rec2 is rec

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*")
    assert rec2.name == "rec"

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["OBJECT"])
    assert rec2.name == "rec"

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["Attribute"])
    assert rec2 is rec

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["Package"])
    assert rec2 is None

    rec2 = find(my_model, "rec", "(~packages,classes,attributes,~classes)*",
                my_metamodel["Class"])
    assert rec2.name == "rec"
    assert rec2 is not rec  # it is the class...

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["Class"])
    assert rec2.name == "rec"
    assert rec2 is not rec  # it is the class...

    t = find(my_model, "", ".")
    assert t is my_model

    t = find(my_model, "", "(.)")
    assert t is my_model

    t = find(my_model, "", "(.)*")
    assert t is my_model

    t = find(my_model, "", "(.)*.no_existent")  # inifite recursion stopper
    assert t is None

    rec2 = find(my_model, "rec",
                "(.)*.(~packages,~classes,attributes,classes)*",
                my_metamodel["Class"])
    assert rec2.name == "rec"
    assert rec2 is not rec  # it is the class...

    # Here, we test the start_from_root/start_locally logic:
    P2t = find(rec, "P2", "(.)*.packages")
    assert P2t is None
    P2t = find(rec, "P2", "(.,not_existent_but_root)*.packages")
    assert P2t is P2
    rect = find(rec, "rec", "(~packages)*.(..).attributes")
    assert rect is None
    rect = find(rec, "rec", "(.,~packages)*.(..).attributes")
    assert rect is rec
Ejemplo n.º 19
0
    def __call__(self, obj, attr, obj_ref):
        """
        the default scope provider

        Args:
            obj: unused (used for multi_metamodel_support)
            attr: unused
            obj_ref: the cross reference to be resolved

        Returns:
            the resolved reference or None
        """
        from textx.const import RULE_COMMON, RULE_ABSTRACT
        from textx.model import ObjCrossRef
        from textx.scoping.tools import get_parser

        if obj_ref is None:
            return None  # an error! (see model.py: resolve_refs (TODO check)

        assert type(obj_ref) is ObjCrossRef, type(obj_ref)

        if get_parser(obj).debug:
            get_parser(obj).dprint("Resolving obj crossref: {}:{}"
                                   .format(obj_ref.cls, obj_ref.obj_name))

        def _inner_resolve_link_rule_ref(cls, obj_name):
            """
            Depth-first resolving of link rule reference.
            """
            if cls._tx_type is RULE_ABSTRACT:
                for inherited in cls._tx_inh_by:
                    result = _inner_resolve_link_rule_ref(inherited,
                                                          obj_name)
                    if result:
                        return result
            elif cls._tx_type == RULE_COMMON:
                # TODO make this code exchangable
                # allow to know the current attribute (model location for
                # namespace) and to navigate through the whole model...
                # OR (with another scope provider) to make custom lookups in
                # the model
                #
                # Scopeprovider
                # - needs: .current reference (in the model)
                #          .the model (?)
                # - provides: the resolved object or None
                if id(cls) in get_parser(obj)._instances:
                    objs = get_parser(obj)._instances[id(cls)]
                    return objs.get(obj_name)

        if self.multi_metamodel_support:
            from textx import get_model, get_children
            from textx import textx_isinstance
            result_lst = get_children(
                lambda x:
                _hasattr(x, "name") and _getattr(x, "name") == obj_ref.obj_name
                and textx_isinstance(x, obj_ref.cls), get_model(obj))
            if len(result_lst) == 1:
                result = result_lst[0]
            elif len(result_lst) > 1:
                line, col = get_parser(obj).pos_to_linecol(obj_ref.position)
                raise TextXSemanticError(
                    "name {} is not unique.".format(obj_ref.obj_name),
                    line=line, col=col, filename=get_model(obj)._tx_filename)
            else:
                result = None
        else:
            result = _inner_resolve_link_rule_ref(obj_ref.cls,
                                                  obj_ref.obj_name)
        if result:
            return result

        return None  # error handled outside
def test_metamodel_provider_advanced_test3_global_single_metamodel():
    """
    simplified test with only one meta model
    """
    #################################
    # META MODEL DEF
    #################################
    this_folder = dirname(abspath(__file__))

    def get_meta_model(global_repo, grammar_file_name):
        mm = metamodel_from_file(join(this_folder, grammar_file_name),
                                 debug=False, classes=[Cls, Obj])
        mm.register_scope_providers({
            "*.*": global_repo,
        })
        return mm

    global_repo_provider = scoping_providers.PlainNameGlobalRepo()
    global_repo_provider.register_models(
        join(this_folder, "metamodel_provider3", "single", "*.a"))

    a_mm = get_meta_model(
        global_repo_provider, join(this_folder,
                                   "metamodel_provider3", "A.tx"))

    clear_language_registrations()
    register_language(
        'a-dsl',
        pattern='*.a',
        description='Test Lang A',
        metamodel=a_mm)

    #################################
    # MODEL PARSING
    #################################

    model_repo = global_repo_provider.load_models_in_model_repo().all_models

    #################################
    # TEST MODEL
    #################################

    def get_all(model_repo, what):
        lst = []
        for m in model_repo.filename_to_model.values():
            lst = lst + get_children_of_type(what, m)
        return lst

    lst = get_all(model_repo, "Obj")
    # print(lst)
    assert len(lst) == 3

    # check some references to be resolved (!=None)
    for a in lst:
        assert a.ref

    # check meta classes
    assert a_mm["Cls"]._tx_fqn == a_mm["Cls"]._tx_fqn

    # more checks
    from textx import textx_isinstance
    for a in lst:
        assert textx_isinstance(a, a_mm["Obj"])
        assert textx_isinstance(a, a_mm["Obj"])
        assert textx_isinstance(a, a_mm["Obj"])

    #################################
    # END
    #################################
    clear_language_registrations()