Esempio n. 1
0
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
Esempio n. 2
0
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,
    )
Esempio n. 3
0
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))
Esempio n. 4
0
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)
Esempio n. 5
0
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
Esempio n. 6
0
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,
    )