Ejemplo n.º 1
0
def env_get(env_expr, token_expr, resolve_unique=False, sequential=False):
    """
    Expression for lexical environment get operation.

    :param AbstractExpression env_expr: Expression that will yield the env
        to get the element from.
    :param AbstractExpression token_expr: Expression that will yield the
        token to use as a key on the env.
    :param bool resolve_unique: Wether we want an unique result or not.
        NOTE: For the moment, nothing will be done to ensure that only one
        result is available. The implementation will just take the first
        result.
    :param bool sequential: Whether resolution needs to be sequential or not.
    """

    sub_exprs = [construct(env_expr, LexicalEnvType),
                 construct(token_expr, Token)]

    if sequential:
        # Pass the From parameter if the user wants sequential semantics
        array_expr = 'AST_Envs.Get ({}, Get_Symbol ({}), {})'
        sub_exprs.append(construct(Self, T.root_node))
    else:
        array_expr = 'AST_Envs.Get ({}, Get_Symbol ({}))'

    make_expr = partial(BasicExpr, result_var_name="Env_Get_Result",
                        sub_exprs=sub_exprs)

    if resolve_unique:
        return make_expr("Get ({}, 0)".format(array_expr), EnvElement)
    else:
        EnvElement.array_type().add_to_context()
        return make_expr("Create ({})".format(array_expr),
                         EnvElement.array_type())
Ejemplo n.º 2
0
    def compute_types(self):
        """
        Compute various information related to compiled types, that needs to be
        available for code generation.
        """

        # Get the list of ASTNode types from the Struct metaclass
        from langkit.compiled_types import (
            EnvElement, LexicalEnvType, StructMetaclass
        )

        self.astnode_types = list(StructMetaclass.astnode_types)

        # Here we're skipping Struct because it's not a real type in
        # generated code. We're also putting env_metadata and EnvElement in
        # the beginning and in the right dependency order (the metadata
        # type before the env element type).
        # TODO: Using a dependency order topological sort wouldn't hurt at
        # some point.
        self.struct_types = [
            t for t in StructMetaclass.struct_types
            if t not in [EnvElement, StructMetaclass.env_metadata]
        ]
        self.struct_types.insert(0, EnvElement)

        if StructMetaclass.env_metadata:
            self.struct_types = (
                [StructMetaclass.env_metadata] + self.struct_types
            )

        self.root_grammar_class = StructMetaclass.root_grammar_class
        self.env_metadata = StructMetaclass.env_metadata
        self.env_element = EnvElement

        # The Group lexical environment operation takes an array of lexical
        # envs, so we always need to generate the corresponding array type.
        self.array_types.add(LexicalEnvType.array_type())

        # Likewise for the EnvElement array type: LexicalEnv.get returns it.
        # No need to bind anything if the language specification did not
        # specify any EnvElement, though.
        if self.env_element:
            self.array_types.add(EnvElement.array_type())

        # Sort them in dependency order as required but also then in
        # alphabetical order so that generated declarations are kept in a
        # relatively stable order. This is really useful for debugging
        # purposes.
        keys = {
            cls: cls.hierarchical_name()
            for cls in self.astnode_types
        }
        self.astnode_types.sort(key=lambda cls: keys[cls])

        # Check that the environment hook is bound if the language spec uses
        # it.
        if self.env_hook_subprogram is None:
            for t in self.astnode_types:
                with t.diagnostic_context():
                    check_source_language(
                        t.env_spec is None or not t.env_spec.env_hook_enabled,
                        'Cannot invoke the environment hook if'
                        ' CompileContext.bind_env_hook has not been called'
                    )