Exemplo n.º 1
0
def direct_env(env: AbstractExpression,
               or_current: bool = False) -> AbstractExpression:
    """
    Return an ``DesignatedEnv`` struct to mean a direct environment value.

    :param or_current: If True, return ``current_env()`` when ``env`` evaluates
        to ``No(T.LexicalEnv)``. Otherwise, return the empty env direct
        environment instead, which is equivalent to ``no_env()``.
    """
    if or_current:
        return cast(Any, env).then(
            lambda non_null_env:
            T.DesignatedEnv.new(
                kind=T.DesignatedEnvKind.resolve_value("direct_env"),
                env_name=No(T.Symbol),
                direct_env=non_null_env,
            ),
            default_val=current_env(),
        )
    else:
        return T.DesignatedEnv.new(
            kind=T.DesignatedEnvKind.resolve_value("direct_env"),
            env_name=No(T.Symbol),
            direct_env=env,
        )
Exemplo n.º 2
0
def named_env(name: AbstractExpression,
              or_current: bool = False) -> AbstractExpression:
    """
    Return an ``DesignatedEnv`` struct to mean a named env.

    :param or_current: If True, return ``current_env()`` when ``name``
        evaluates to ``No(T.Symbol)``. Otherwise, return the named env for the
        null symbol instead, which is equivalent to ``no_env()``.
    """
    if or_current:
        return cast(Any, name).then(
            lambda non_null_name:
            T.DesignatedEnv.new(
                kind=T.DesignatedEnvKind.resolve_value("named_env"),
                env_name=non_null_name,
                direct_env=No(T.LexicalEnv),
            ),
            default_val=current_env(),
        )
    else:
        return T.DesignatedEnv.new(
            kind=T.DesignatedEnvKind.resolve_value("named_env"),
            env_name=name,
            direct_env=No(T.LexicalEnv),
        )
Exemplo n.º 3
0
def current_env() -> AbstractExpression:
    """
    Return an ``DesignatedEnv`` struct to mean the current environment.
    """
    return T.DesignatedEnv.new(
        kind=T.DesignatedEnvKind.resolve_value("current_env"),
        env_name=No(T.Symbol),
        direct_env=No(T.LexicalEnv),
    )
Exemplo n.º 4
0
def no_env() -> AbstractExpression:
    """
    Return a ``DesignatedEnv`` struct to mean no destination environment.
    """
    return T.DesignatedEnv.new(
        kind=T.DesignatedEnvKind.resolve_value("none"),
        env_name=No(T.Symbol),
        direct_env=No(T.LexicalEnv),
    )
Exemplo n.º 5
0
    def construct(self):
        # Accept as a prefix:
        #
        #   * any pointer, since it can be checked against "null";
        #   * any StructType, since structs are nullable;
        #   * any LexicalEnvType, which has EmptyEnv as a null value.
        expr = construct(
            self.expr, lambda cls:
            (cls.is_ptr or cls.is_struct_type or cls.is_lexical_env_type),
            'Invalid prefix type for .then: {expr_type}')
        self.var_expr.set_type(expr.type)

        # Create a then-expr specific scope to restrict the span of the "then"
        # variable in the debugger.
        with PropertyDef.get_scope().new_child() as then_scope:
            then_scope.add(self.var_expr.local_var)
            then_expr = construct(self.then_expr)
            var_expr = construct(self.var_expr)
        then_expr = BindingScope(then_expr, [var_expr], scope=then_scope)

        # Affect default value to the fallback expression
        if self.default_val is None:
            check_source_language(
                then_expr.type.null_allowed or then_expr.type is T.BoolType,
                "Then expression should have a default value provided,"
                " in cases where the provided function's return type (here"
                " {}) does not have a default null value".format(
                    then_expr.type.dsl_name))
            default_expr = construct(No(then_expr.type))
        else:
            default_expr = construct(self.default_val, then_expr.type)

        return Then.Expr(expr, construct(self.var_expr), then_expr,
                         default_expr, then_scope)
Exemplo n.º 6
0
def new_env_assoc(key, val, dest_env=None, metadata=None):
    """
    Create a new env assoc, providing basic defaults when fields are not
    specified.

    :param AbstractExpression key: The symbol for which to associate a value.
    :param AbstractExpression val: The node to associate to the key.
    :param AbstractExpression dest_env: The environment in which to insert the
        mapping. If this expression evaluates to the empty environment, the
        mapping will be added to the initial env, e.g. the currently bound env
        or whatever was specified using the set_initial_env construct.
    :param AbstractExpression metadata: Additional metadata to associate to the
        node.
    """
    return T.env_assoc.new(
        key=key,
        val=val,
        dest_env=No(T.LexicalEnv) if dest_env is None else dest_env,
        metadata=No(T.defer_env_md) if metadata is None else metadata)
Exemplo n.º 7
0
    def construct(self):
        # Add var_expr to the scope for this Then expression
        PropertyDef.get_scope().add(self.var_expr.local_var)

        # Accept as a prefix:
        # * any pointer, since it can be checked against "null";
        # * any Struct, since its "Is_Null" field can be checked.
        expr = construct(self.expr,
                         lambda cls: cls.is_ptr or issubclass(cls, Struct))
        self.var_expr.set_type(expr.type)

        then_expr = construct(self.then_expr)

        # Affect default value to the fallback expression. For the moment,
        # only booleans and structs are handled.
        if self.default_val is None:
            if then_expr.type.matches(BoolType):
                default_expr = construct(False)
            elif issubclass(then_expr.type, Struct):
                default_expr = construct(
                    No(
                        # Because we're doing issubclass instead of isinstance,
                        # PyCharm do not understand that then_exp.type is a Struct,
                        # so the following is necessary not to have warnings.
                        assert_type(then_expr.type, Struct)))
            elif then_expr.type.matches(LexicalEnvType):
                default_expr = construct(EmptyEnv)
            elif then_expr.type.matches(Symbol):
                default_expr = LiteralExpr(Symbol.nullexpr(), Symbol)
            else:
                # The following is not actually used but PyCharm's typer
                # requires it.
                default_expr = None

                check_source_language(
                    False,
                    "Then expression should have a default value provided, "
                    "in cases where the provided function's return type is "
                    "not Bool, here {}".format(then_expr.type.name().camel))
        else:
            default_expr = construct(self.default_val, then_expr.type)

        return Then.Expr(expr, construct(self.var_expr), then_expr,
                         default_expr)
Exemplo n.º 8
0
def new_env_assoc(key, value, dest_env=None, metadata=None):
    """
    Create a new env assoc, providing basic defaults when fields are not
    specified.

    :param AbstractExpression key: The symbol for which to associate a value.
    :param AbstractExpression value: The node to associate to the key.
    :param AbstractExpression dest_env: The environment in which to insert the
        mapping (a DesignatedEnv struct value). If left to None, use the
        current environment.
    :param AbstractExpression metadata: Additional metadata to associate to the
        node.
    """
    return T.env_assoc.new(
        key=key,
        value=value,
        dest_env=current_env() if dest_env is None else dest_env,
        metadata=No(T.defer_env_md) if metadata is None else metadata
    )
Exemplo n.º 9
0
def env_group(self, env_array, with_md=None):
    """
    Return a new lexical environment that logically groups together multiple
    environments. `env_array` must be an array that contains the environments
    to be grouped. If it is empty, the empty environment is returned.

    If provided, `with_md` must be a metadata structure: it will be made the
    default metadata for this lexical environment.

    :type env_array: AbstractExpression
    :type with_md: AbstractExpression
    """
    from langkit.expressions import No

    if not with_md:
        with_md = No(T.env_md)

    return CallExpr('Group_Env', 'Group', T.LexicalEnv,
                    [construct(env_array, T.LexicalEnv.array),
                     construct(with_md, T.env_md)],
                    abstract_expr=self)