예제 #1
0
파일: genclass.py 프로젝트: proa14/mypy
def setup_non_ext_dict(builder: IRBuilder,
                       cdef: ClassDef,
                       metaclass: Value,
                       bases: Value) -> Value:
    """
    Initialize the class dictionary for a non-extension class. This class dictionary
    is passed to the metaclass constructor.
    """

    # Check if the metaclass defines a __prepare__ method, and if so, call it.
    has_prepare = builder.primitive_op(py_hasattr_op,
                                    [metaclass,
                                    builder.load_static_unicode('__prepare__')], cdef.line)

    non_ext_dict = builder.alloc_temp(dict_rprimitive)

    true_block, false_block, exit_block, = BasicBlock(), BasicBlock(), BasicBlock()
    builder.add_bool_branch(has_prepare, true_block, false_block)

    builder.activate_block(true_block)
    cls_name = builder.load_static_unicode(cdef.name)
    prepare_meth = builder.py_get_attr(metaclass, '__prepare__', cdef.line)
    prepare_dict = builder.py_call(prepare_meth, [cls_name, bases], cdef.line)
    builder.assign(non_ext_dict, prepare_dict, cdef.line)
    builder.goto(exit_block)

    builder.activate_block(false_block)
    builder.assign(non_ext_dict, builder.primitive_op(new_dict_op, [], cdef.line), cdef.line)
    builder.goto(exit_block)
    builder.activate_block(exit_block)

    return non_ext_dict
예제 #2
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
예제 #3
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
예제 #4
0
def transform_conditional_expr(builder: IRBuilder,
                               expr: ConditionalExpr) -> Value:
    if_body, else_body, next = BasicBlock(), BasicBlock(), BasicBlock()

    builder.process_conditional(expr.cond, if_body, else_body)
    expr_type = builder.node_type(expr)
    # Having actual Phi nodes would be really nice here!
    target = builder.alloc_temp(expr_type)

    builder.activate_block(if_body)
    true_value = builder.accept(expr.if_expr)
    true_value = builder.coerce(true_value, expr_type, expr.line)
    builder.add(Assign(target, true_value))
    builder.goto(next)

    builder.activate_block(else_body)
    false_value = builder.accept(expr.else_expr)
    false_value = builder.coerce(false_value, expr_type, expr.line)
    builder.add(Assign(target, false_value))
    builder.goto(next)

    builder.activate_block(next)

    return target
예제 #5
0
def try_finally_entry_blocks(builder: IRBuilder,
                             err_handler: BasicBlock,
                             return_entry: BasicBlock,
                             main_entry: BasicBlock,
                             finally_block: BasicBlock,
                             ret_reg: Optional[Register]) -> Value:
    old_exc = builder.alloc_temp(exc_rtuple)

    # Entry block for non-exceptional flow
    builder.activate_block(main_entry)
    if ret_reg:
        builder.add(
            Assign(
                ret_reg,
                builder.add(LoadErrorValue(builder.ret_types[-1]))
            )
        )
    builder.goto(return_entry)

    builder.activate_block(return_entry)
    builder.add(Assign(old_exc, builder.add(LoadErrorValue(exc_rtuple))))
    builder.goto(finally_block)

    # Entry block for errors
    builder.activate_block(err_handler)
    if ret_reg:
        builder.add(
            Assign(
                ret_reg,
                builder.add(LoadErrorValue(builder.ret_types[-1]))
            )
        )
    builder.add(Assign(old_exc, builder.primitive_op(error_catch_op, [], -1)))
    builder.goto(finally_block)

    return old_exc