예제 #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)

    builder.comprehension_helper(loop_params, gen_inner_stmts, o.line)
    return d
예제 #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)

    builder.comprehension_helper(loop_params, gen_inner_stmts, o.line)
    return set_ops
예제 #3
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 = builder.alloc_temp(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))
    builder.comprehension_helper(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
예제 #4
0
def any_all_helper(builder: IRBuilder, gen: GeneratorExpr,
                   initial_value_op: OpDescription, modify: Callable[[Value],
                                                                     Value],
                   new_value_op: OpDescription) -> Value:
    retval = builder.alloc_temp(bool_rprimitive)
    builder.assign(retval, builder.primitive_op(initial_value_op, [], -1), -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, builder.primitive_op(new_value_op, [], -1), -1)
        builder.goto(exit_block)
        builder.activate_block(false_block)

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

    return retval