Esempio n. 1
0
def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehension) -> Value:
    d = builder.primitive_op(new_dict_op, [], o.line)
    loop_params = list(zip(o.indices, o.sequences, o.condlists))

    def gen_inner_stmts() -> None:
        k = builder.accept(o.key)
        v = builder.accept(o.value)
        builder.primitive_op(dict_set_item_op, [d, k, v], o.line)

    comprehension_helper(builder, loop_params, gen_inner_stmts, o.line)
    return d
Esempio n. 2
0
def transform_set_comprehension(builder: IRBuilder, o: SetComprehension) -> Value:
    gen = o.generator
    set_ops = builder.primitive_op(new_set_op, [], o.line)
    loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))

    def gen_inner_stmts() -> None:
        e = builder.accept(gen.left_expr)
        builder.primitive_op(set_add_op, [set_ops, e], o.line)

    comprehension_helper(builder, loop_params, gen_inner_stmts, o.line)
    return set_ops
Esempio n. 3
0
def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehension) -> Value:
    if any(o.is_async):
        builder.error('async comprehensions are unimplemented', o.line)

    d = builder.call_c(dict_new_op, [], o.line)
    loop_params = list(zip(o.indices, o.sequences, o.condlists))

    def gen_inner_stmts() -> None:
        k = builder.accept(o.key)
        v = builder.accept(o.value)
        builder.call_c(dict_set_item_op, [d, k, v], o.line)

    comprehension_helper(builder, loop_params, gen_inner_stmts, o.line)
    return d
Esempio n. 4
0
def translate_next_call(builder: IRBuilder, expr: CallExpr,
                        callee: RefExpr) -> Optional[Value]:
    """Special case for calling next() on a generator expression, an
    idiom that shows up some in mypy.

    For example, next(x for x in l if x.id == 12, None) will
    generate code that searches l for an element where x.id == 12
    and produce the first such object, or None if no such element
    exists.
    """
    if not (expr.arg_kinds in ([ARG_POS], [ARG_POS, ARG_POS])
            and isinstance(expr.args[0], GeneratorExpr)):
        return None

    gen = expr.args[0]

    retval = Register(builder.node_type(expr))
    default_val = None
    if len(expr.args) > 1:
        default_val = builder.accept(expr.args[1])

    exit_block = BasicBlock()

    def gen_inner_stmts() -> None:
        # next takes the first element of the generator, so if
        # something gets produced, we are done.
        builder.assign(retval, builder.accept(gen.left_expr),
                       gen.left_expr.line)
        builder.goto(exit_block)

    loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))
    comprehension_helper(builder, loop_params, gen_inner_stmts, gen.line)

    # Now we need the case for when nothing got hit. If there was
    # a default value, we produce it, and otherwise we raise
    # StopIteration.
    if default_val:
        builder.assign(retval, default_val, gen.left_expr.line)
        builder.goto(exit_block)
    else:
        builder.add(
            RaiseStandardError(RaiseStandardError.STOP_ITERATION, None,
                               expr.line))
        builder.add(Unreachable())

    builder.activate_block(exit_block)
    return retval
Esempio n. 5
0
def any_all_helper(builder: IRBuilder,
                   gen: GeneratorExpr,
                   initial_value: Callable[[], Value],
                   modify: Callable[[Value], Value],
                   new_value: Callable[[], Value]) -> Value:
    retval = Register(bool_rprimitive)
    builder.assign(retval, initial_value(), -1)
    loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))
    true_block, false_block, exit_block = BasicBlock(), BasicBlock(), BasicBlock()

    def gen_inner_stmts() -> None:
        comparison = modify(builder.accept(gen.left_expr))
        builder.add_bool_branch(comparison, true_block, false_block)
        builder.activate_block(true_block)
        builder.assign(retval, new_value(), -1)
        builder.goto(exit_block)
        builder.activate_block(false_block)

    comprehension_helper(builder, loop_params, gen_inner_stmts, gen.line)
    builder.goto_and_activate(exit_block)

    return retval
Esempio n. 6
0
def translate_sum_call(builder: IRBuilder, expr: CallExpr,
                       callee: RefExpr) -> Optional[Value]:
    # specialized implementation is used if:
    # - only one or two arguments given (if not, sum() has been given invalid arguments)
    # - first argument is a Generator (there is no benefit to optimizing the performance of eg.
    #   sum([1, 2, 3]), so non-Generator Iterables are not handled)
    if not (len(expr.args) in (1, 2) and expr.arg_kinds[0] == ARG_POS
            and isinstance(expr.args[0], GeneratorExpr)):
        return None

    # handle 'start' argument, if given
    if len(expr.args) == 2:
        # ensure call to sum() was properly constructed
        if not expr.arg_kinds[1] in (ARG_POS, ARG_NAMED):
            return None
        start_expr = expr.args[1]
    else:
        start_expr = IntExpr(0)

    gen_expr = expr.args[0]
    target_type = builder.node_type(expr)
    retval = Register(target_type)
    builder.assign(retval,
                   builder.coerce(builder.accept(start_expr), target_type, -1),
                   -1)

    def gen_inner_stmts() -> None:
        call_expr = builder.accept(gen_expr.left_expr)
        builder.assign(retval, builder.binary_op(retval, call_expr, '+', -1),
                       -1)

    loop_params = list(
        zip(gen_expr.indices, gen_expr.sequences, gen_expr.condlists))
    comprehension_helper(builder, loop_params, gen_inner_stmts, gen_expr.line)

    return retval