def collection_get(self: AbstractExpression, collection: AbstractExpression, index: AbstractExpression, or_null: bool) -> ResolvedExpression: """ Get the `index`\\ -th element from `collection`. Indexes are 0-based. As in Python, `index` can be negative, to retrieve elements in reverse order. For instance, ``expr.at(-1)`` will return the last element. :param or_null: If true, the expression will return null if the index is not valid for the collection. If False, it will raise an exception. """ # index yields a 0-based index and all the Get primitives expect 0-based # indexes, so there is no need to fiddle indexes here. index_expr = construct(index, T.Int) coll_expr = construct(collection) as_entity = coll_expr.type.is_entity_type if as_entity: saved_coll_expr, coll_expr, entity_info = ( coll_expr.destructure_entity() ) check_source_language( coll_expr.type.is_collection, '.at prefix must be a collection: got {} instead'.format( coll_expr.type.dsl_name ) ) # We process null list nodes as empty lists, so insert a null check before # getting the collection item only if asked to raise an exception. if not or_null: if coll_expr.type.is_ast_node: coll_expr = NullCheckExpr(coll_expr) elif coll_expr.type.is_entity_type: coll_expr = NullCheckExpr(coll_expr, implicit_deref=True) coll_expr, element_type = canonicalize_list(coll_expr, to_root_list=True) or_null_expr = construct(or_null) result: ResolvedExpression = CallExpr( 'Get_Result', 'Get', element_type, [coll_expr, index_expr, or_null_expr] ) if as_entity: result = SequenceExpr(saved_coll_expr, make_as_entity(result, entity_info)) result.abstract_expr = self return result
def parents_access_constructor( prefix: ResolvedExpression, node_data: AbstractNodeData, args: List[Optional[ResolvedExpression]], abstract_expr: Optional[AbstractExpression] = None ) -> ResolvedExpression: """ Return an access to the "fields" parents, whether called on a node or an entity. .. todo:: Implement rebindings shedding. """ # We expect exactly one argument: with_self. If not provided, use the # default value. assert len(args) == 1 with_self: ResolvedExpression = (args[0] or construct( node_data.natural_arguments[0].abstract_default_value)) cons_args = [with_self] return build_field_access( prefix, 'parents', cons_args, lambda: CallExpr( 'Node_Parents', 'Parents', T.root_node.array, [cast(ResolvedExpression, NullCheckExpr(prefix))] + cons_args, abstract_expr=abstract_expr, ), abstract_expr=abstract_expr, )
def construct_non_null_rebindings(rebindings): """ Construct `rebindings` to be an environment rebindings value and wrap it in a non-null check. :param AbstractExpression rebindings: Rebindings-returning expression to process. :rtype: ResolvedExpression """ return NullCheckExpr(construct(rebindings, T.EnvRebindings))
def analysis_unit_root(self, unit): """ Return `unit`'s root AST node. :param ResolvedExpression unit: Expression that yields the analysis unit for which we want to extract the root AST node. """ unit_expr = NullCheckExpr(construct(unit, T.AnalysisUnitType)) return FieldAccessExpr(unit_expr, 'AST_Root', T.root_node, do_explicit_incref=False, abstract_expr=self)
def collection_get(self, collection, index, or_null): """ Get the `index`\ -th element from `collection`. Indexes are 0-based. As in Python, `index` can be negative, to retrieve elements in reverse order. For instance, ``expr.at(-1)`` will return the last element. :param bool or_null: If true, the expression will return null if the index is not valid for the collection. If False, it will raise an exception. """ # index yields a 0-based index and all the Get primitives expect 0-based # indexes, so there is no need to fiddle indexes here. index_expr = construct(index, T.LongType) coll_expr = construct(collection) as_entity = coll_expr.type.is_entity_type if as_entity: saved_coll_expr, coll_expr, entity_info = ( coll_expr.destructure_entity()) check_source_language( coll_expr.type.is_collection, '.at prefix must be a collection: got {} instead'.format( coll_expr.type.dsl_name)) if coll_expr.type.is_ast_node: coll_expr = NullCheckExpr(coll_expr) elif coll_expr.type.is_entity_type: coll_expr = NullCheckExpr(coll_expr, implicit_deref=True) or_null = construct(or_null) result = CallExpr('Get_Result', 'Get', coll_expr.type.element_type, [coll_expr, index_expr, or_null]) if as_entity: result = SequenceExpr(saved_coll_expr, make_as_entity(result, entity_info)) result.abstract_expr = self return result
def children(self, node): """ Return `node`'s children in the AST. This works on both bare nodes and entities. """ node_expr = construct(node) check_source_language( node_expr.type.is_ast_node or node_expr.type.is_entity_type, 'Invalid prefix for "children": got {} but AST node or entity' ' expected'.format(node_expr.type.dsl_name)) return build_field_access( node_expr, 'children', [], lambda: CallExpr('Node_Children', 'Children', T.root_node.array, [NullCheckExpr(node_expr)], abstract_expr=self), abstract_expr=self, )