Esempio n. 1
0
    def actual_c_type(
            self, typ: Union[TypeOrPlaceholder,
                             ct.TypeRepo.Defer]) -> TypeOrPlaceholder:
        """
        Return the C type used to encode ``typ`` values.

        In the C/OCaml binding layer, some types are encoded as other types.
        For instance: all entities are exposed as the root entity type.

        :param typ: Type to encode in the C/OCaml binding layer.
        """
        # DummyAnalysisContextType is a placeholder, not a real CompiledType
        if isinstance(typ, DummyAnalysisContextType):
            return typ

        if typ.is_entity_type:
            # Expose all entity types as the root entity type
            result = T.entity
        elif typ.is_array_type:
            element_type = self.actual_c_type(typ.element_type)
            assert isinstance(element_type, ct.CompiledType)
            result = element_type.array
        else:
            result = typ

        # Make sure we get a CompiledType instance
        return resolve_type(result)
Esempio n. 2
0
    def do_prepare(self):
        self.matchers = []

        for i, match_fn in enumerate(self.matchers_functions):
            argspec = inspect.getargspec(match_fn)
            check_source_language(
                len(argspec.args) == 1 and not argspec.varargs
                and not argspec.keywords
                and (not argspec.defaults or len(argspec.defaults) < 2),
                'Invalid matcher lambda')

            if argspec.defaults:
                match_type = resolve_type(argspec.defaults[0])

                check_source_language(
                    match_type.is_ast_node or match_type.is_entity_type,
                    'Invalid matching type: {}'.format(match_type.dsl_name))
            else:
                match_type = None

            match_var = AbstractVariable(names.Name('Match_{}'.format(i)),
                                         type=match_type,
                                         create_local=True,
                                         source_name=names.Name.from_lower(
                                             argspec.args[0]))
            self.matchers.append((match_type, match_var, match_fn(match_var)))
Esempio n. 3
0
        def compute_internal(p, toplevel=True):
            # Skip parsers create nodes out of thin air in reaction to a
            # parsing error, so unparser logics must ignore them.
            if isinstance(p, Skip):
                pass

            elif isinstance(p, Opt) and p._booleanize:
                qual_type = resolve_type(p._booleanize)
                for alt_type in qual_type._alternatives:
                    append(alt_type, p)
                toplevel = False

            elif isinstance(p, (List, _Transform)):
                append(p.type, p)
                toplevel = False

            elif isinstance(p, (Null, Or)):
                pass

            elif isinstance(p, _Extract):
                assert isinstance(p.parser, _Row)
                subparsers = p.parser.parsers

                # Reject information loss at the top level. As a special case,
                # allow that top-level "p" parses a node followed by a
                # termination token.
                check_source_language(
                    not self.context.generate_unparser or not toplevel
                    or (len(p.parser.parsers) == 2
                        and isinstance(subparsers[1], _Token)
                        and subparsers[1]._val == LexerToken.Termination),
                    'Top-level information loss prevents unparsers generation')

            for c in p.children:
                compute_internal(c, toplevel)
Esempio n. 4
0
    def do_prepare(self):
        self.matchers = []

        for i, match_fn in enumerate(self.matchers_functions):
            argspec = inspect.getargspec(match_fn)
            check_source_language(
                len(argspec.args) == 1 and
                not argspec.varargs and
                not argspec.keywords and
                (not argspec.defaults or len(argspec.defaults) < 2),
                'Invalid matcher lambda'
            )

            if argspec.defaults:
                match_type = resolve_type(argspec.defaults[0])
                check_source_language(
                    issubclass(match_type, ASTNode) and
                    match_type != ASTNode,
                    'Invalid matching type: {}'.format(
                        match_type.name().camel
                    )
                )
            else:
                match_type = None

            match_var = AbstractVariable(
                names.Name('Match_{}'.format(i)),
                type=match_type,
                create_local=True
            )
            self.matchers.append((match_type, match_var, match_fn(match_var)))
Esempio n. 5
0
def type_name(type):
    from langkit.compiled_types import ASTNodeType, resolve_type

    type = resolve_type(type)

    def bases(typ):
        t = typ.base
        while t is not None:
            yield t
            t = t.base

    if isinstance(type, ASTNodeType):
        if (type.is_list_type
                and not any(t.is_generic_list_type for t in bases(type.base))):
            return "ASTList[{}]".format(type_name(type.element_type))
        else:
            return type.raw_name.camel
    elif type.is_array_type:
        return "Array[{}]".format(type_name(type.element_type))
    elif type.is_entity_type:
        return type_name(type.element_type)
    elif type.is_struct_type:
        return type.api_name.camel
    elif type.is_ast_node:
        return "{}.node".format(type.name.camel)
    elif type.name.camel == 'Integer':
        return 'Int'
    elif type.name.camel == 'Boolean':
        return 'Bool'
    elif type.name.camel == 'SymbolType':
        return 'Symbol'
    elif type.name.camel == 'BigIntegerType':
        return 'BigInt'
    else:
        return type.name.camel
Esempio n. 6
0
    def do_prepare(self):
        self.dest_type = resolve_type(self.dest_type)

        check_source_language(
            self.dest_type.matches(ASTNode)
            or self.dest_type.matches(T.root_node.env_el()),
            "One can only cast to an ASTNode subtype or to an env_element"
        )
Esempio n. 7
0
    def do_prepare(self):
        self.struct_type = resolve_type(self.struct_type)

        check_source_language(issubclass(self.struct_type, Struct), (
            "Invalid type, expected struct type, got {}".format(
                self.struct_type.name().camel
            )
        ))
Esempio n. 8
0
    def from_parser(node, parser):
        """
        Given a parser that creates a specific type of parse node, return the
        corresponding unparser. Emit a user diagnostic if this transformation
        cannot be made.

        :param ASTNodeType node: Parse node that `parser` emits.
        :param Parser parser: Parser for which we want to create an unparser.
        :rtype: NodeUnparser
        """
        assert not node.abstract and not node.synthetic, (
            'Invalid unparser request for {}'.format(node.dsl_name))
        parser = unwrap(parser)

        with parser.diagnostic_context:
            if node.is_token_node:
                return NodeUnparser._from_token_node_parser(node, parser)

            if isinstance(parser, _Transform):
                return NodeUnparser._from_transform_parser(node, parser)

            if isinstance(parser, List):
                check_source_language(
                    isinstance(parser.parser,
                               (Defer, List, Null, Or, _Transform)),
                    'Unparsers generation require list parsers to directly'
                    ' build nodes for each list item')
                return ListNodeUnparser(node,
                                        TokenUnparser.from_parser(parser.sep))

            if isinstance(parser, Opt):
                if parser._booleanize:
                    # This is a special parser: when the subparser succeeds,
                    # the "present" alternative is created to hold its result,
                    # otherwise the "absent" alternative is created (and no
                    # token are consumed).
                    #
                    # So in both cases, we create an unparser, but we emit
                    # tokens only for the "present" alternative.
                    result = RegularNodeUnparser(node)
                    qual_type = resolve_type(parser._booleanize)
                    if node is qual_type._alternatives_map['Present']:
                        NodeUnparser._emit_to_token_sequence(
                            parser.parser, result.pre_tokens)
                    return result

                else:
                    return NodeUnparser.from_parser(node, parser.parser)

            if isinstance(parser, Null):
                return NullNodeUnparser(node)

            check_source_language(
                False,
                'Unsupported parser for unparsers generation: {}'.format(
                    parser))
Esempio n. 9
0
    def do_prepare(self):
        self.struct_type = resolve_type(self.struct_type)

        check_source_language(
            self.struct_type.is_base_struct_type,
            'Invalid type, expected struct type or AST node, got {}'.format(
                self.struct_type.dsl_name))
        check_source_language(
            not self.struct_type.is_ast_node or self.struct_type.synthetic,
            'Synthetized AST nodes must be annotated as synthetic')
Esempio n. 10
0
    def construct(self):
        """
        Construct a resolved expression that is the result of testing the kind
        of a node.

        :rtype: IsAExpr
        """
        expr = construct(self.expr)
        astnodes = [resolve_type(a) for a in self.astnodes]
        for a in astnodes:
            check_source_language(
                issubclass(a, ASTNode),
                "Expected ASTNode subclass, got {}".format(a)
            )
            check_source_language(a.matches(expr.type), (
                'When testing the dynamic subtype of an AST node, the type to'
                ' check must be a subclass of the value static type.'
            ))
        return IsA.Expr(expr, astnodes)
Esempio n. 11
0
    def construct(self):
        """
        Construct a resolved expression that is the result of testing the kind
        of a node.

        :rtype: IsAExpr
        """
        expr = construct(self.expr)
        astnodes = [resolve_type(a) for a in self.astnodes]
        for a in astnodes:
            check_source_language(
                issubclass(a, ASTNode) or a.is_env_element_type,
                "Expected ASTNode subclass or env_element, got {}".format(a)
            )
            check_source_language(a.matches(expr.type), (
                'When testing the dynamic subtype of an AST node, the type to'
                ' check must be a subclass of the value static type.'
            ))
        return IsA.Expr(expr, astnodes)
Esempio n. 12
0
    def actual_c_type(self, typ):
        """
        Return the C type used to encode ``typ`` values.

        In the C/OCaml binding layer, some types are encoded as other types.
        For instance: all entities are exposed as the root entity type.

        :param CompiledType typ: Type to encode in the C/OCaml binding layer.
        :rtype: CompiledType
        """
        # AnalysisContextType is a placeholder, not a real CompiledType
        if isinstance(typ, self.AnalysisContextType):
            return typ

        if typ.is_entity_type:
            # Expose all entity types as the root entity type
            result = T.entity
        elif typ.is_array_type:
            result = self.actual_c_type(typ.element_type).array
        else:
            result = typ

        # Make sure we get a CompiledType instance
        return resolve_type(result)
Esempio n. 13
0
 def _enum_value_resolver(cls, enum_type_name, value_name):
     return cls(lambda: resolve_type(getattr(T, enum_type_name)).
                resolve_value(value_name))
Esempio n. 14
0
 def __repr__(self):
     return '<IsA {}>'.format(', '.join(
         resolve_type(n).name.camel for n in self.astnodes))
Esempio n. 15
0
 def resolve(astnode):
     t = resolve_type(astnode)
     return t.entity if as_entity and t.is_ast_node else t
Esempio n. 16
0
    def do_prepare(self):
        self.dest_type = resolve_type(self.dest_type)

        check_source_language(
            self.dest_type.is_ast_node or self.dest_type.is_entity_type,
            "One can only cast to an ASTNode subtype or to an entity")
Esempio n. 17
0
 def __repr__(self):
     return '<New {}>'.format(resolve_type(self.struct_type).name.camel)
Esempio n. 18
0
 def __repr__(self):
     return '<Cast to {}>'.format(resolve_type(self.dest_type).name.camel)
Esempio n. 19
0
 def do_prepare(self):
     self.astnode = resolve_type(self.astnode)
     check_source_language(self.astnode.matches(ASTNode), (
         "One can only cast to an ASTNode subtype"
     ))
Esempio n. 20
0
 def node_name(node: Union[CompiledType, TypeRepo.Defer]) -> str:
     return get_node_name(ctx, resolve_type(node))
Esempio n. 21
0
 def node_name(node):
     return get_node_name(ctx, resolve_type(node))