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)))
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()
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))
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()
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()