Example #1
0
def transform_with(builder: IRBuilder,
                   expr: Expression,
                   target: Optional[Lvalue],
                   body: GenFunc,
                   line: int) -> None:
    # This is basically a straight transcription of the Python code in PEP 343.
    # I don't actually understand why a bunch of it is the way it is.
    # We could probably optimize the case where the manager is compiled by us,
    # but that is not our common case at all, so.
    mgr_v = builder.accept(expr)
    typ = builder.primitive_op(type_op, [mgr_v], line)
    exit_ = builder.maybe_spill(builder.py_get_attr(typ, '__exit__', line))
    value = builder.py_call(
        builder.py_get_attr(typ, '__enter__', line), [mgr_v], line
    )
    mgr = builder.maybe_spill(mgr_v)
    exc = builder.maybe_spill_assignable(builder.primitive_op(true_op, [], -1))

    def try_body() -> None:
        if target:
            builder.assign(builder.get_assignment_target(target), value, line)
        body()

    def except_body() -> None:
        builder.assign(exc, builder.primitive_op(false_op, [], -1), line)
        out_block, reraise_block = BasicBlock(), BasicBlock()
        builder.add_bool_branch(
            builder.py_call(builder.read(exit_),
                            [builder.read(mgr)] + get_sys_exc_info(builder), line),
            out_block,
            reraise_block
        )
        builder.activate_block(reraise_block)
        builder.primitive_op(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
        builder.add(Unreachable())
        builder.activate_block(out_block)

    def finally_body() -> None:
        out_block, exit_block = BasicBlock(), BasicBlock()
        builder.add(
            Branch(builder.read(exc), exit_block, out_block, Branch.BOOL_EXPR)
        )
        builder.activate_block(exit_block)
        none = builder.none_object()
        builder.py_call(
            builder.read(exit_), [builder.read(mgr), none, none, none], line
        )
        builder.goto_and_activate(out_block)

    transform_try_finally_stmt(
        builder,
        lambda: transform_try_except(builder,
                                     try_body,
                                     [(None, None, except_body)],
                                     None,
                                     line),
        finally_body
    )
Example #2
0
def cache_class_attrs(builder: IRBuilder, attrs_to_cache: List[Lvalue], cdef: ClassDef) -> None:
    """Add class attributes to be cached to the global cache"""
    typ = builder.load_native_type_object(cdef.fullname)
    for lval in attrs_to_cache:
        assert isinstance(lval, NameExpr)
        rval = builder.py_get_attr(typ, lval.name, cdef.line)
        builder.init_final_static(lval, rval, cdef.name)
Example #3
0
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
Example #4
0
def transform_super_expr(builder: IRBuilder, o: SuperExpr) -> Value:
    # warning(builder, 'can not optimize super() expression', o.line)
    sup_val = builder.load_module_attr_by_fullname('builtins.super', o.line)
    if o.call.args:
        args = [builder.accept(arg) for arg in o.call.args]
    else:
        assert o.info is not None
        typ = builder.load_native_type_object(o.info.fullname)
        ir = builder.mapper.type_to_ir[o.info]
        iter_env = iter(builder.environment.indexes)
        vself = next(iter_env)  # grab first argument
        if builder.fn_info.is_generator:
            # grab sixth argument (see comment in translate_super_method_call)
            self_targ = list(builder.environment.symtable.values())[6]
            vself = builder.read(self_targ, builder.fn_info.fitem.line)
        elif not ir.is_ext_class:
            vself = next(
                iter_env)  # second argument is self if non_extension class
        args = [typ, vself]
    res = builder.py_call(sup_val, args, o.line)
    return builder.py_get_attr(res, o.name, o.line)