Esempio n. 1
0
def add_get_to_callable_class(builder: IRBuilder, fn_info: FuncInfo) -> None:
    """Generate the '__get__' method for a callable class."""
    line = fn_info.fitem.line
    with builder.enter_method(fn_info.callable_class.ir,
                              '__get__',
                              object_rprimitive,
                              fn_info,
                              self_type=object_rprimitive):
        instance = builder.add_argument('instance', object_rprimitive)
        builder.add_argument('owner', object_rprimitive)

        # If accessed through the class, just return the callable
        # object. If accessed through an object, create a new bound
        # instance method object.
        instance_block, class_block = BasicBlock(), BasicBlock()
        comparison = builder.translate_is_op(builder.read(instance),
                                             builder.none_object(), 'is', line)
        builder.add_bool_branch(comparison, class_block, instance_block)

        builder.activate_block(class_block)
        builder.add(Return(builder.self()))

        builder.activate_block(instance_block)
        builder.add(
            Return(
                builder.call_c(
                    method_new_op,
                    [builder.self(), builder.read(instance)], line)))
Esempio n. 2
0
def add_throw_to_generator_class(builder: IRBuilder, fn_info: FuncInfo,
                                 fn_decl: FuncDecl,
                                 sig: FuncSignature) -> None:
    """Generates the 'throw' method for a generator class."""
    builder.enter_method(fn_info.generator_class.ir, 'throw',
                         object_rprimitive, fn_info)
    typ = builder.add_argument('type', object_rprimitive)
    val = builder.add_argument('value', object_rprimitive, ARG_OPT)
    tb = builder.add_argument('traceback', object_rprimitive, ARG_OPT)

    # Because the value and traceback arguments are optional and hence
    # can be NULL if not passed in, we have to assign them Py_None if
    # they are not passed in.
    none_reg = builder.none_object()
    builder.assign_if_null(val, lambda: none_reg, builder.fn_info.fitem.line)
    builder.assign_if_null(tb, lambda: none_reg, builder.fn_info.fitem.line)

    # Call the helper function using the arguments passed in, and return that result.
    result = builder.add(
        Call(fn_decl, [
            builder.self(),
            builder.read(typ),
            builder.read(val),
            builder.read(tb), none_reg
        ], fn_info.fitem.line))
    builder.add(Return(result))
    builder.leave_method()
Esempio n. 3
0
def add_register_method_to_callable_class(builder: IRBuilder,
                                          fn_info: FuncInfo) -> None:
    line = -1
    with builder.enter_method(fn_info.callable_class.ir, 'register',
                              object_rprimitive):
        cls_arg = builder.add_argument('cls', object_rprimitive)
        func_arg = builder.add_argument('func', object_rprimitive,
                                        ArgKind.ARG_OPT)
        ret_val = builder.call_c(register_function,
                                 [builder.self(), cls_arg, func_arg], line)
        builder.add(Return(ret_val, line))
Esempio n. 4
0
def gen_glue_ne_method(builder: IRBuilder, cls: ClassIR, line: int) -> None:
    """Generate a "__ne__" method from a "__eq__" method. """
    builder.enter_method(cls, '__ne__', object_rprimitive)
    rhs_arg = builder.add_argument('rhs', object_rprimitive)

    # If __eq__ returns NotImplemented, then __ne__ should also
    not_implemented_block, regular_block = BasicBlock(), BasicBlock()
    eqval = builder.add(MethodCall(builder.self(), '__eq__', [rhs_arg], line))
    not_implemented = builder.add(LoadAddress(not_implemented_op.type,
                                              not_implemented_op.src, line))
    builder.add(Branch(
        builder.translate_is_op(eqval, not_implemented, 'is', line),
        not_implemented_block,
        regular_block,
        Branch.BOOL))

    builder.activate_block(regular_block)
    retval = builder.coerce(
        builder.unary_op(eqval, 'not', line), object_rprimitive, line
    )
    builder.add(Return(retval))

    builder.activate_block(not_implemented_block)
    builder.add(Return(not_implemented))

    builder.leave_method()
Esempio n. 5
0
def add_send_to_generator_class(builder: IRBuilder, fn_info: FuncInfo,
                                fn_decl: FuncDecl, sig: FuncSignature) -> None:
    """Generates the 'send' method for a generator class."""
    builder.enter_method(fn_info.generator_class.ir, 'send', object_rprimitive,
                         fn_info)
    arg = builder.add_argument('arg', object_rprimitive)
    none_reg = builder.none_object()
    # Call the helper function with error flags set to Py_None, and return that result.
    result = builder.add(
        Call(fn_decl,
             [builder.self(), none_reg, none_reg, none_reg,
              builder.read(arg)], fn_info.fitem.line))
    builder.add(Return(result))
    builder.leave_method()