コード例 #1
0
        def construct_operand(op):
            from langkit.expressions import Cast, New
            expr = construct(op)

            check_source_language(

                expr.type == LogicVarType
                or expr.type.matches(T.root_node)
                or expr.type.matches(T.root_node.env_el()),

                "Operands to a logic bind operator should be either "
                "a logic variable or an ASTNode, got {}".format(expr.type)
            )

            if expr.type.matches(T.root_node.env_el()):
                if expr.type is not T.root_node.env_el():
                    expr = Cast.Expr(expr, T.root_node.env_el())
            elif expr.type.matches(T.root_node):
                # Cast the ast node type if necessary
                if expr.type is not T.root_node:
                    expr = Cast.Expr(expr, T.root_node)

                # If the expression is a root node, implicitly construct an
                # env_element from it.
                expr = New.StructExpr(T.root_node.env_el(), {
                    Name('El'): expr,
                    Name('MD'): LiteralExpr('<>', None),
                    Name('Parents_Bindings'): LiteralExpr('null', None)
                })

            return expr
コード例 #2
0
    def construct(self):
        # Resolve the converter property, make sure it has an acceptable
        # signature and generate a functor for it.
        self.conv_prop = self._resolve_property("Bind's conv_prop",
                                                self.conv_prop, 1)

        # Left operand must be a logic variable. Make sure the resulting
        # equation will work on a clean logic variable.
        lhs = self._construct_logic_var(self.from_expr)

        # Second one can be either a logic variable or an entity (or an AST
        # node that is promoted to an entity).
        rhs = construct(self.to_expr)

        if rhs.type.matches(T.LogicVar):
            # The second operand is a logic variable: this is a Propagate or a
            # Unify equation depending on whether we have a conversion
            # property.

            # For this operand too, make sure it will work on a clean logic
            # variable.
            rhs = ResetLogicVar(rhs)

            return (
                PropagateExpr(lhs, [rhs], self.conv_prop, abstract_expr=self)
                if self.conv_prop else UnifyExpr(lhs, rhs, abstract_expr=self))

        else:
            # The second operand is a value: this is an Assign equation

            if rhs.type.matches(T.root_node):
                from langkit.expressions import make_as_entity
                rhs = make_as_entity(rhs)
            else:
                check_source_language(
                    rhs.type.matches(T.root_node.entity)
                    or rhs.type.matches(T.LogicVar),
                    "Right operand must be either a logic variable or an"
                    f" entity, got {rhs.type.dsl_name}")

            # Because of Ada OOP typing rules, for code generation to work
            # properly, make sure the type of `rhs` is the root node entity.
            if rhs.type is not T.root_node.entity:
                from langkit.expressions import Cast
                rhs = Cast.Expr(rhs, T.root_node.entity)

            return AssignExpr(lhs, rhs, self.conv_prop, abstract_expr=self)
コード例 #3
0
ファイル: logic.py プロジェクト: danielmercier/langkit
    def construct(self):
        from langkit.compile_context import get_context
        self.resolve_props()

        get_context().do_generate_logic_binder(self.conv_prop, self.eq_prop)

        # We have to wait for the construct pass for the following checks
        # because they rely on type information, which is not supposed to be
        # computed before this pass.
        if self.conv_prop:
            check_multiple([
                (self.conv_prop.type.matches(T.root_node.entity),
                 'Bind property must return a subtype of {}'.format(
                     T.root_node.entity.dsl_name)),
                (self.conv_prop.struct.matches(T.root_node),
                 'Bind property must belong to a subtype of {}'.format(
                     T.root_node.dsl_name)),
            ])

            DynamicVariable.check_call_bindings(self.conv_prop,
                                                "In Bind's conv_prop {prop}")

        # Those checks are run in construct, because we need the eq_prop to be
        # prepared already, which is not certain in do_prepare (order
        # dependent).

        if self.eq_prop:
            args = self.eq_prop.natural_arguments
            check_multiple([
                (self.eq_prop.type == T.Bool,
                 'Equality property must return boolean'),
                (self.eq_prop.struct.matches(T.root_node),
                 'Equality property must belong to a subtype of {}'.format(
                     T.root_node.dsl_name)),
                (len(args) == 1,
                 'Equality property: expected 1 argument, got {}'.format(
                     len(args))),
            ])

            other_type = args[0].type
            check_source_language(
                other_type.is_entity_type,
                "First arg of equality property should be an entity type")
            check_source_language(
                other_type.element_type == self.eq_prop.struct,
                "Self and first argument should be of the same type")

            DynamicVariable.check_call_bindings(self.eq_prop,
                                                "In Bind's eq_prop {prop}")

        cprop_uid = (self.conv_prop.uid if self.conv_prop else "Default")
        eprop_uid = (self.eq_prop.uid if self.eq_prop else "Default")

        if self.conv_prop:
            pred_func = Bind.Expr.dynamic_vars_to_holder(
                self.conv_prop, 'Logic_Converter_{}'.format(cprop_uid))
        else:
            pred_func = untyped_literal_expr('No_Logic_Converter_Default')

        # Left operand must be a logic variable. Make sure the resulting
        # equation will work on a clean logic variable.
        lhs = ResetLogicVar(construct(self.from_expr, T.LogicVar))

        # Second one can be either a logic variable or an entity (or an AST
        # node that is promoted to an entity).
        rhs = construct(self.to_expr)

        if rhs.type.matches(T.LogicVar):
            # For this operand too, make sure it will work on a clean logic
            # variable.
            rhs = ResetLogicVar(rhs)
        elif rhs.type.matches(T.root_node):
            from langkit.expressions import make_as_entity
            rhs = make_as_entity(rhs)
        else:
            check_source_language(
                rhs.type.matches(T.root_node.entity),
                'Right operand must be either a logic variable or an entity,'
                ' got {}'.format(rhs.type.dsl_name))

        # Because of Ada OOP typing rules, for code generation to work
        # properly, make sure the type of `rhs` is the root node entity.
        if (rhs.type.matches(T.root_node.entity)
                and rhs.type is not T.root_node.entity):
            from langkit.expressions import Cast
            rhs = Cast.Expr(rhs, T.root_node.entity)

        return Bind.Expr(self.conv_prop,
                         self.eq_prop,
                         cprop_uid,
                         eprop_uid,
                         lhs,
                         rhs,
                         pred_func,
                         abstract_expr=self)