示例#1
0
def translate_safe_generator_call(builder: IRBuilder, expr: CallExpr,
                                  callee: RefExpr) -> Optional[Value]:
    # Special cases for things that consume iterators where we know we
    # can safely compile a generator into a list.
    if (len(expr.args) > 0 and expr.arg_kinds[0] == ARG_POS
            and isinstance(expr.args[0], GeneratorExpr)):
        if isinstance(callee, MemberExpr):
            return builder.gen_method_call(
                builder.accept(callee.expr), callee.name,
                ([translate_list_comprehension(builder, expr.args[0])] +
                 [builder.accept(arg) for arg in expr.args[1:]]),
                builder.node_type(expr), expr.line, expr.arg_kinds,
                expr.arg_names)
        else:
            if len(expr.args) == 1 and callee.fullname == "builtins.tuple":
                val = sequence_from_generator_preallocate_helper(
                    builder,
                    expr.args[0],
                    empty_op_llbuilder=builder.builder.new_tuple_with_length,
                    set_item_op=new_tuple_set_item_op)
                if val is not None:
                    return val

            return builder.call_refexpr_with_args(
                expr, callee,
                ([translate_list_comprehension(builder, expr.args[0])] +
                 [builder.accept(arg) for arg in expr.args[1:]]))
    return None
def translate_tuple_from_generator_call(
        builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]:
    # Special case for simplest tuple creation from a generator, for example
    #     tuple(f(x) for x in other_list/other_tuple)
    # translate_safe_generator_call() would take care of other cases if this fails.
    if (len(expr.args) == 1
            and expr.arg_kinds[0] == ARG_POS
            and isinstance(expr.args[0], GeneratorExpr)):
        return sequence_from_generator_preallocate_helper(
            builder, expr.args[0],
            empty_op_llbuilder=builder.builder.new_tuple_with_length,
            set_item_op=new_tuple_set_item_op)
    return None
示例#3
0
def translate_list_from_generator_call(
        builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]:
    """Special case for simplest list comprehension.

    For example:
        list(f(x) for x in some_list/some_tuple/some_str)
    'translate_list_comprehension()' would take care of other cases
    if this fails.
    """
    if (len(expr.args) == 1
            and expr.arg_kinds[0] == ARG_POS
            and isinstance(expr.args[0], GeneratorExpr)):
        return sequence_from_generator_preallocate_helper(
            builder, expr.args[0],
            empty_op_llbuilder=builder.builder.new_list_op_with_length,
            set_item_op=new_list_set_item_op)
    return None
示例#4
0
def dict_methods_fast_path(builder: IRBuilder, expr: CallExpr,
                           callee: RefExpr) -> Optional[Value]:
    # Specialize a common case when list() is called on a dictionary view
    # method call, for example foo = list(bar.keys()).
    if not (len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]):
        return None
    arg = expr.args[0]

    # Special case for simplest list comprehension, for example
    #     list(x for x in tmp_list)
    # TODO: The following code should be moved to a new function after
    #       supporting multiple specialize functions
    if not isinstance(callee, MemberExpr) and isinstance(arg, GeneratorExpr):
        val = sequence_from_generator_preallocate_helper(
            builder,
            arg,
            empty_op_llbuilder=builder.builder.new_list_op_with_length,
            set_item_op=new_list_set_item_op)
        if val is not None:
            return val

    if not (isinstance(arg, CallExpr) and not arg.args
            and isinstance(arg.callee, MemberExpr)):
        return None
    base = arg.callee.expr
    attr = arg.callee.name
    rtype = builder.node_type(base)
    if not (is_dict_rprimitive(rtype) and attr in ('keys', 'values', 'items')):
        return None

    obj = builder.accept(base)
    # Note that it is not safe to use fast methods on dict subclasses, so
    # the corresponding helpers in CPy.h fallback to (inlined) generic logic.
    if attr == 'keys':
        return builder.call_c(dict_keys_op, [obj], expr.line)
    elif attr == 'values':
        return builder.call_c(dict_values_op, [obj], expr.line)
    else:
        return builder.call_c(dict_items_op, [obj], expr.line)