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)
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)))
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)
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)))
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
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" )
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 ) ))
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))
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')
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)
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)
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)
def _enum_value_resolver(cls, enum_type_name, value_name): return cls(lambda: resolve_type(getattr(T, enum_type_name)). resolve_value(value_name))
def __repr__(self): return '<IsA {}>'.format(', '.join( resolve_type(n).name.camel for n in self.astnodes))
def resolve(astnode): t = resolve_type(astnode) return t.entity if as_entity and t.is_ast_node else t
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")
def __repr__(self): return '<New {}>'.format(resolve_type(self.struct_type).name.camel)
def __repr__(self): return '<Cast to {}>'.format(resolve_type(self.dest_type).name.camel)
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" ))
def node_name(node: Union[CompiledType, TypeRepo.Defer]) -> str: return get_node_name(ctx, resolve_type(node))
def node_name(node): return get_node_name(ctx, resolve_type(node))