def make_function(self, fnargs, nbargs_before, mrdtable): if self._function is not None: return self._function name = self.get_function_name() self.compress_typechecks(mrdtable) checklines = self.generate_typechecks(fnargs[nbargs_before:]) if not checklines: body = self.body else: checklines.append(self.body) body = '\n '.join(checklines) source = 'def %s(%s):\n %s\n' % (name, ', '.join(fnargs), body) if 0: # for debugging the generated mm sources f = open('/tmp/mm-source/%s' % name, 'a') for possiblename in self.possiblenames: print >> f, '#', for part in possiblename: print >> f, getattr(part, '__name__', part), print >> f print >> f print >> f, source f.close() exec compile2(source) in self.miniglobals self._function = self.miniglobals[name] return self._function
def make_fastfunc(unwrap_spec, func): unwrap_info = UnwrapSpec_FastFunc_Unwrap() unwrap_info.apply_over(unwrap_spec) narg = unwrap_info.n args = ['space'] + unwrap_info.args if args == unwrap_info.unwrap: fastfunc = func else: # try to avoid excessive bloat if func.__module__ == 'pypy.interpreter.astcompiler.ast': raise FastFuncNotSupported if (not func.__module__.startswith('pypy.module.__builtin__') and not func.__module__.startswith('pypy.module.sys') and not func.__module__.startswith('pypy.module.math')): if not func.__name__.startswith('descr'): raise FastFuncNotSupported d = {} unwrap_info.miniglobals['func'] = func source = """if 1: def fastfunc_%s_%d(%s): return func(%s) \n""" % (func.__name__, narg, ', '.join(args), ', '.join(unwrap_info.unwrap)) exec compile2(source) in unwrap_info.miniglobals, d fastfunc = d['fastfunc_%s_%d' % (func.__name__, narg)] return narg, fastfunc
def make_objclass_getter(func, cls, cache={}): if hasattr(func, "im_func"): assert not cls or cls is func.im_class cls = func.im_class if not cls: return unknown_objclass_getter, cls try: return cache[cls] except KeyError: pass miniglobals = {} if isinstance(cls, str): assert cls.startswith("<"), "pythontype typecheck should begin with <" cls_name = cls[1:] typeexpr = "space.w_%s" % cls_name else: miniglobals["cls"] = cls typeexpr = "space.gettypeobject(cls.typedef)" source = """if 1: def objclass_getter(space): return %s \n""" % ( typeexpr, ) exec compile2(source) in miniglobals res = miniglobals["objclass_getter"], cls cache[cls] = res return res
def make_fastfunc(unwrap_spec, func): unwrap_info = UnwrapSpec_FastFunc_Unwrap() unwrap_info.apply_over(unwrap_spec) narg = unwrap_info.n args = ['space'] + unwrap_info.args if args == unwrap_info.unwrap: fastfunc = func else: # try to avoid excessive bloat mod = func.__module__ if mod is None: mod = "" if mod == 'pypy.interpreter.astcompiler.ast': raise FastFuncNotSupported if (not mod.startswith('pypy.module.__builtin__') and not mod.startswith('pypy.module.sys') and not mod.startswith('pypy.module.math')): if not func.__name__.startswith('descr'): raise FastFuncNotSupported d = {} unwrap_info.miniglobals['func'] = func source = """if 1: def fastfunc_%s_%d(%s): return func(%s) \n""" % (func.__name__, narg, ', '.join(args), ', '.join(unwrap_info.unwrap)) exec compile2(source) in unwrap_info.miniglobals, d fastfunc = d['fastfunc_%s_%d' % (func.__name__, narg)] return narg, fastfunc
def _make_unwrap_activation_class(self, unwrap_spec, cache={}): try: key = tuple(unwrap_spec) activation_factory_cls, run_args = cache[key] assert run_args == self.run_args, ( "unexpected: same spec, different run_args") return activation_factory_cls except KeyError: parts = [] for el in unwrap_spec: if isinstance(el, tuple): parts.append(''.join([getattr(subel, '__name__', subel) for subel in el])) else: parts.append(getattr(el, '__name__', el)) label = '_'.join(parts) #print label d = {} source = """if 1: def _run_UWS_%s(self, space, scope_w): return self.behavior(%s) \n""" % (label, ', '.join(self.run_args)) exec compile2(source) in self.miniglobals, d d['_run'] = d['_run_UWS_%s' % label] del d['_run_UWS_%s' % label] activation_cls = type("BuiltinActivation_UwS_%s" % label, (BuiltinActivation,), d) cache[key] = activation_cls, self.run_args return activation_cls
def _make_unwrap_activation_class(self, unwrap_spec, cache={}): try: key = tuple(unwrap_spec) activation_factory_cls, run_args = cache[key] assert run_args == self.run_args, ( "unexpected: same spec, different run_args") return activation_factory_cls except KeyError: parts = [] for el in unwrap_spec: if isinstance(el, tuple): parts.append(''.join([getattr(subel, '__name__', subel) for subel in el])) else: parts.append(getattr(el, '__name__', el)) label = '_'.join(parts) #print label d = {} source = """if 1: def _run(self, space, scope_w): return self.behavior(%s) \n""" % (', '.join(self.run_args),) exec compile2(source) in self.miniglobals, d activation_cls = type("BuiltinActivation_UwS_%s" % label, (BuiltinActivation,), d) activation_cls._immutable_ = True cache[key] = activation_cls, self.run_args return activation_cls
def setup(): for name in (ObjSpace.ConstantTable + ObjSpace.ExceptionTable + [ 'int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', 'basestring', 'object' ]): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # for (name, _, arity, _) in ObjSpace.MethodTable: if name == 'type': continue args = ['w_%d' % i for i in range(arity)] params = args[:] d = {'is_root': is_root, 'w_some_obj': w_some_obj} if name in ('get', ): params[-1] += '=None' exec compile2("""\ def meth(self, %s): %s return w_some_obj() """ % (', '.join(params), '; '.join( ['is_root(%s)' % arg for arg in args]))) in d meth = func_with_new_name(d['meth'], name) setattr(FakeObjSpace, name, meth) # for name in ObjSpace.IrregularOpTable: assert hasattr(FakeObjSpace, name) # missing?
def setup(): for name in (ObjSpace.ConstantTable + ObjSpace.ExceptionTable + ['int', 'str', 'float', 'long', 'tuple', 'list', 'dict', 'unicode', 'complex', 'slice', 'bool', 'basestring', 'object']): setattr(FakeObjSpace, 'w_' + name, w_some_obj()) FakeObjSpace.w_type = w_some_type() # for (name, _, arity, _) in ObjSpace.MethodTable: if name == 'type': continue args = ['w_%d' % i for i in range(arity)] params = args[:] d = {'is_root': is_root, 'w_some_obj': w_some_obj} if name in ('get',): params[-1] += '=None' exec compile2("""\ def meth(self, %s): %s return w_some_obj() """ % (', '.join(params), '; '.join(['is_root(%s)' % arg for arg in args]))) in d meth = func_with_new_name(d['meth'], name) setattr(FakeObjSpace, name, meth) # for name in ObjSpace.IrregularOpTable: assert hasattr(FakeObjSpace, name) # missing?
def generate_function(sig, opcodes): consolidate(opcodes) lines = [] has_orbyte = False for op in opcodes: if isinstance(op, str): if has_orbyte: nextbyte = ord(op[0]) if nextbyte: lines.append('orbyte |= %d' % nextbyte) lines.append('builder.writechr(orbyte)') has_orbyte = False op = op[1:] if op: if len(op) > 1: lines.append('builder.write(constlistofchars(%r))' % (op,)) else: lines.append('builder.writechr(%d)' % (ord(op),)) else: has_orbyte = op.eval(lines, has_orbyte) assert not has_orbyte, "malformed bytecode" if not lines: lines.append('pass') args = ', '.join(['builder'] + ['arg%d'%i for i in range(1, len(sig)+1)]) lines.insert(0, 'def encode(%s):' % args) source = '\n '.join(lines) + '\n' miniglobals = { 'packimm32': packimm32, 'packimm8': packimm8, 'packimm16': packimm16, 'constlistofchars': constlistofchars, } exec compile2(source) in miniglobals return miniglobals['encode']
def make_func(name, desc): sig = [] fieldvalues = [] for field in desc.fields: if field in desc.specializations: fieldvalues.append((field, desc.specializations[field])) else: sig.append(field.name) fieldvalues.append((field, field.name)) if isinstance(desc, IDupDesc): for destfield, srcfield in desc.dupfields.iteritems(): fieldvalues.append((destfield, srcfield.name)) body = ['v = r_uint(0)'] assert 'v' not in sig # that wouldn't be funny #body.append('print %r'%name + ', ' + ', '.join(["'%s:', %s"%(s, s) for s in sig])) for field, value in fieldvalues: if field.name == 'spr': body.append('spr = (%s&31) << 5 | (%s >> 5 & 31)'%(value, value)) value = 'spr' body.append('v |= (%3s & r_uint(%#05x)) << %d'%(value, field.mask, (32 - field.right - 1))) body.append('self.emit(v)') src = 'def %s(self, %s):\n %s'%(name, ', '.join(sig), '\n '.join(body)) d = {'r_uint':r_uint} #print src exec compile2(src) in d return d[name]
def generate_function(sig, opcodes): consolidate(opcodes) lines = [] has_orbyte = False for op in opcodes: if isinstance(op, str): if has_orbyte: nextbyte = ord(op[0]) if nextbyte: lines.append('orbyte |= %d' % nextbyte) lines.append('builder.write(chr(orbyte))') has_orbyte = False op = op[1:] if op: lines.append('builder.write(%r)' % (op,)) else: has_orbyte = op.eval(lines, has_orbyte) assert not has_orbyte, "malformed bytecode" if not lines: lines.append('pass') args = ', '.join(['builder'] + ['arg%d'%i for i in range(1, len(sig)+1)]) lines.insert(0, 'def encode(%s):' % args) source = '\n '.join(lines) + '\n' miniglobals = { 'packimm32': packimm32, 'packimm8': packimm8, 'packimm16': packimm16, } exec compile2(source) in miniglobals return miniglobals['encode']
def make_objclass_getter(func, cls, cache={}): if hasattr(func, 'im_func'): assert not cls or cls is func.im_class cls = func.im_class if not cls: return unknown_objclass_getter, cls try: return cache[cls] except KeyError: pass miniglobals = {} if isinstance(cls, str): assert cls.startswith('<'), "pythontype typecheck should begin with <" cls_name = cls[1:] typeexpr = "space.w_%s" % cls_name else: miniglobals['cls'] = cls typeexpr = "space.gettypeobject(cls.typedef)" source = """if 1: def objclass_getter(space): return %s \n""" % (typeexpr, ) exec compile2(source) in miniglobals res = miniglobals['objclass_getter'], cls cache[cls] = res return res
def make_function(self, fnargs, nbargs_before, mrdtable): if self._function is not None: return self._function name = self.get_function_name() self.compress_typechecks(mrdtable) checklines = self.generate_typechecks(mrdtable, fnargs[nbargs_before:]) if not checklines: body = self.body else: checklines.append(self.body) body = '\n '.join(checklines) source = 'def %s(%s):\n %s\n' % (name, ', '.join(fnargs), body) self.debug_dump(source) exec compile2(source) in self.miniglobals self._function = self.miniglobals[name] return self._function
def _make_objclass_getter(cls): if not cls: return unknown_objclass_getter, cls miniglobals = {} if isinstance(cls, str): assert cls.startswith('<'),"pythontype typecheck should begin with <" cls_name = cls[1:] typeexpr = "space.w_%s" % cls_name else: miniglobals['cls'] = cls typeexpr = "space.gettypeobject(cls.typedef)" source = """if 1: def objclass_getter(space): return %s \n""" % (typeexpr,) exec compile2(source) in miniglobals res = miniglobals['objclass_getter'], cls return res
def inplace_add(x, y): x += y return x def inplace_sub(x, y): x -= y return x def inplace_mul(x, y): x *= y return x exec compile2(""" def inplace_truediv(x, y): x /= y return x """, flags=__future__.CO_FUTURE_DIVISION, dont_inherit=1) # makes an INPLACE_TRUE_DIVIDE def inplace_floordiv(x, y): x //= y return x exec compile2(""" def inplace_div(x, y): x /= y return x """, flags=0, dont_inherit=1) # makes an INPLACE_DIVIDE def inplace_mod(x, y):
typename = space.type(w_obj).getname(space) raise operationerrfmt(space.w_TypeError, "unsupported operand type for %(targetname)s(): '%%s'", typename) w_result = space.get_and_call_function(w_impl, w_obj) if %(checker)s: return w_result typename = space.type(w_result).getname(space) msg = "%(specialname)s returned non-%(targetname)s (type '%%s')" raise operationerrfmt(space.w_TypeError, msg, typename) assert not hasattr(DescrOperation, %(targetname)r) DescrOperation.%(targetname)s = %(targetname)s del %(targetname)s \n""" % locals() exec compile2(source) for targetname, specialname in [('str', '__str__'), ('repr', '__repr__'), ('oct', '__oct__'), ('hex', '__hex__')]: source = """if 1: def %(targetname)s(space, w_obj): w_impl = space.lookup(w_obj, %(specialname)r) if w_impl is None: typename = space.type(w_obj).getname(space) raise operationerrfmt(space.w_TypeError, "unsupported operand type for %(targetname)s(): '%%s'", typename) w_result = space.get_and_call_function(w_impl, w_obj) if space.is_true(space.isinstance(w_result, space.w_str)):
def make_perform_trampoline(prefix, exprargs, expr, miniglobals, multimethod, selfindex=0, allow_NotImplemented_results=False): """NOT_RPYTHON""" # mess to figure out how to put a gateway around executing expr argnames = ['_%d'%(i+1) for i in range(multimethod.arity)] explicit_argnames = multimethod.extras.get('argnames', []) argnames[len(argnames)-len(explicit_argnames):] = explicit_argnames solid_arglist = ['w_'+name for name in argnames] wrapper_arglist = solid_arglist[:] if multimethod.extras.get('varargs_w', False): wrapper_arglist.append('args_w') if multimethod.extras.get('w_varargs', False): wrapper_arglist.append('w_args') if multimethod.extras.get('keywords', False): raise Exception, "no longer supported, use __args__" if multimethod.extras.get('general__args__', False): wrapper_arglist.append('__args__') wrapper_arglist += multimethod.extras.get('extra_args', ()) miniglobals.update({ 'OperationError': OperationError, 'typeerrormsg': typeerrormsg}) app_defaults = multimethod.extras.get('defaults', ()) i = len(argnames) - len(app_defaults) wrapper_signature = wrapper_arglist[:] for app_default in app_defaults: name = wrapper_signature[i] wrapper_signature[i] = '%s=%s' % (name, name) miniglobals[name] = app_default i += 1 wrapper_signature.insert(0, wrapper_signature.pop(selfindex)) wrapper_sig = ', '.join(wrapper_signature) src = [] dest = [] for wrapper_arg,expr_arg in zip(['space']+wrapper_arglist, exprargs): if wrapper_arg != expr_arg: src.append(wrapper_arg) dest.append(expr_arg) renaming = ', '.join(dest) +" = "+', '.join(src) # add a call to resolve_target to give the thunk space a chance to replace # the thing with something else offset = len(multimethod.argnames_before) renaming += "; %s = space.resolve_target(%s)" % ( exprargs[selfindex+offset], exprargs[selfindex+offset]) if allow_NotImplemented_results and (len(multimethod.specialnames) > 1 or multimethod.name.startswith('inplace_')): # turn FailedToImplement into NotImplemented code = """def %s_perform_call(space, %s): %s try: return %s except FailedToImplement, e: if e.w_type is not None: raise OperationError(e.w_type, e.w_value) else: return space.w_NotImplemented """ % (prefix, wrapper_sig, renaming, expr) else: # turn FailedToImplement into nice TypeErrors code = """def %s_perform_call(space, %s): %s try: w_res = %s except FailedToImplement, e: if e.w_type is not None: raise OperationError(e.w_type, e.w_value) else: raise OperationError(space.w_TypeError, typeerrormsg(space, %r, [%s])) if w_res is None: w_res = space.w_None return w_res """ % (prefix, wrapper_sig, renaming, expr, multimethod.operatorsymbol, ', '.join(solid_arglist)) exec compile2(code, '', 'exec') in miniglobals return miniglobals["%s_perform_call" % prefix]
def inplace_sub(x, y): x -= y return x def inplace_mul(x, y): x *= y return x exec compile2(""" def inplace_truediv(x, y): x /= y return x """, flags=__future__.CO_FUTURE_DIVISION, dont_inherit=1) # makes an INPLACE_TRUE_DIVIDE def inplace_floordiv(x, y): x //= y return x exec compile2(""" def inplace_div(x, y): x /= y return x
def make_perform_trampoline(prefix, exprargs, expr, miniglobals, multimethod, selfindex=0, allow_NotImplemented_results=False): """NOT_RPYTHON""" # mess to figure out how to put a gateway around executing expr argnames = ['_%d' % (i + 1) for i in range(multimethod.arity)] explicit_argnames = multimethod.extras.get('argnames', []) argnames[len(argnames) - len(explicit_argnames):] = explicit_argnames solid_arglist = ['w_' + name for name in argnames] wrapper_arglist = solid_arglist[:] if multimethod.extras.get('varargs_w', False): wrapper_arglist.append('args_w') if multimethod.extras.get('w_varargs', False): wrapper_arglist.append('w_args') if multimethod.extras.get('keywords', False): raise Exception, "no longer supported, use __args__" if multimethod.extras.get('general__args__', False): wrapper_arglist.append('__args__') wrapper_arglist += multimethod.extras.get('extra_args', ()) miniglobals.update({ 'OperationError': OperationError, 'typeerrormsg': typeerrormsg }) app_defaults = multimethod.extras.get('defaults', ()) i = len(argnames) - len(app_defaults) wrapper_signature = wrapper_arglist[:] for app_default in app_defaults: name = wrapper_signature[i] wrapper_signature[i] = '%s=%s' % (name, name) miniglobals[name] = app_default i += 1 wrapper_signature.insert(0, wrapper_signature.pop(selfindex)) wrapper_sig = ', '.join(wrapper_signature) src = [] dest = [] for wrapper_arg, expr_arg in zip(['space'] + wrapper_arglist, exprargs): if wrapper_arg != expr_arg: src.append(wrapper_arg) dest.append(expr_arg) renaming = ', '.join(dest) + " = " + ', '.join(src) if allow_NotImplemented_results and ( len(multimethod.specialnames) > 1 or multimethod.name.startswith('inplace_')): # turn FailedToImplement into NotImplemented code = """def %s_perform_call(space, %s): %s try: return %s except FailedToImplement, e: if e.w_type is not None: raise OperationError(e.w_type, e.w_value) else: return space.w_NotImplemented """ % (prefix, wrapper_sig, renaming, expr) else: # turn FailedToImplement into nice TypeErrors code = """def %s_perform_call(space, %s): %s try: w_res = %s except FailedToImplement, e: if e.w_type is not None: raise OperationError(e.w_type, e.w_value) else: raise OperationError(space.w_TypeError, typeerrormsg(space, %r, [%s])) if w_res is None: w_res = space.w_None return w_res """ % (prefix, wrapper_sig, renaming, expr, multimethod.operatorsymbol, ', '.join(solid_arglist)) exec compile2(code, '', 'exec') in miniglobals return miniglobals["%s_perform_call" % prefix]
def build_function(self, target, funcname, func_selfarg_index, things_to_call): # support for inventing names for the entries in things_to_call # which are real function objects instead of strings miniglobals = { 'FailedToImplement': FailedToImplement, '__name__': __name__ } def invent_name(obj): if isinstance(obj, str): return obj name = obj.__name__ n = 1 while name in miniglobals: n += 1 name = '%s%d' % (obj.__name__, n) miniglobals[name] = obj return name funcargs = ['arg%d' % i for i in range(self.multimethod.arity)] bodylines = [] for conversion, call, call_selfarg_index in things_to_call: callargs = funcargs[:] if conversion is not None: to_convert = func_selfarg_index convert_callargs = (self.multimethod.argnames_before + [callargs[to_convert]]) callargs[to_convert] = '%s(%s)' % (invent_name(conversion), ', '.join(convert_callargs)) callname = invent_name(call) if call_selfarg_index is not None: # fallback on root_class self.build_function(self.multimethod.root_class, callname, call_selfarg_index, []) callname = '%s.%s' % (callargs.pop(call_selfarg_index), callname) callargs = (self.multimethod.argnames_before + callargs + self.multimethod.argnames_after) bodylines.append('return %s(%s)' % (callname, ', '.join(callargs))) fallback = False if not bodylines: miniglobals['raiseFailedToImplement'] = raiseFailedToImplement bodylines = ['return raiseFailedToImplement()'] fallback = True # NB. make sure that there is only one fallback function object, # i.e. the key used in the mmfunccache below is always the same # for all functions with the same name and an empty bodylines. # protect all lines apart from the last one by a try:except: for i in range(len(bodylines) - 2, -1, -1): bodylines[i:i + 1] = [ 'try:', ' ' + bodylines[i], 'except FailedToImplement:', ' pass' ] if func_selfarg_index is not None: selfargs = [funcargs.pop(func_selfarg_index)] else: selfargs = [] funcargs = (selfargs + self.multimethod.argnames_before + funcargs + self.multimethod.argnames_after) if target is None and not self.baked_perform_call: return funcargs, bodylines[0][len('return ' ):], miniglobals, fallback # indent mode bodylines = [' ' + line for line in bodylines] bodylines.insert(0, 'def %s(%s):' % (funcname, ', '.join(funcargs))) bodylines.append('') source = '\n'.join(bodylines) # XXX find a better place (or way) to avoid duplicate functions l = miniglobals.items() l.sort() l = tuple(l) key = (source, l) try: func = self.mmfunccache[key] except KeyError: exec compile2(source) in miniglobals func = miniglobals[funcname] self.mmfunccache[key] = func #else: # print "avoided duplicate function", func self.to_install.append((target, funcname, func, source, fallback)) return func
def build_function(self, target, funcname, func_selfarg_index, things_to_call): # support for inventing names for the entries in things_to_call # which are real function objects instead of strings miniglobals = {'FailedToImplement': FailedToImplement, '__name__': __name__} def invent_name(obj): if isinstance(obj, str): return obj name = obj.__name__ n = 1 while name in miniglobals: n += 1 name = '%s%d' % (obj.__name__, n) miniglobals[name] = obj return name funcargs = ['arg%d' % i for i in range(self.multimethod.arity)] bodylines = [] for conversion, call, call_selfarg_index in things_to_call: callargs = funcargs[:] if conversion is not None: to_convert = func_selfarg_index convert_callargs = (self.multimethod.argnames_before + [callargs[to_convert]]) callargs[to_convert] = '%s(%s)' % ( invent_name(conversion), ', '.join(convert_callargs)) callname = invent_name(call) if call_selfarg_index is not None: # fallback on root_class self.build_function(self.multimethod.root_class, callname, call_selfarg_index, []) callname = '%s.%s' % (callargs.pop(call_selfarg_index), callname) callargs = (self.multimethod.argnames_before + callargs + self.multimethod.argnames_after) bodylines.append('return %s(%s)' % (callname, ', '.join(callargs))) fallback = False if not bodylines: miniglobals['raiseFailedToImplement'] = raiseFailedToImplement bodylines = ['return raiseFailedToImplement()'] fallback = True # NB. make sure that there is only one fallback function object, # i.e. the key used in the mmfunccache below is always the same # for all functions with the same name and an empty bodylines. # protect all lines apart from the last one by a try:except: for i in range(len(bodylines)-2, -1, -1): bodylines[i:i+1] = ['try:', ' ' + bodylines[i], 'except FailedToImplement:', ' pass'] if func_selfarg_index is not None: selfargs = [funcargs.pop(func_selfarg_index)] else: selfargs = [] funcargs = (selfargs + self.multimethod.argnames_before + funcargs + self.multimethod.argnames_after) if target is None and not self.baked_perform_call: return funcargs, bodylines[0][len('return '):], miniglobals, fallback # indent mode bodylines = [' ' + line for line in bodylines] bodylines.insert(0, 'def %s(%s):' % (funcname, ', '.join(funcargs))) bodylines.append('') source = '\n'.join(bodylines) # XXX find a better place (or way) to avoid duplicate functions l = miniglobals.items() l.sort() l = tuple(l) key = (source, l) try: func = self.mmfunccache[key] except KeyError: exec compile2(source) in miniglobals func = miniglobals[funcname] self.mmfunccache[key] = func #else: # print "avoided duplicate function", func self.to_install.append((target, funcname, func, source, fallback)) return func
def make_perform_trampoline( prefix, exprargs, expr, miniglobals, multimethod, selfindex=0, allow_NotImplemented_results=False ): """NOT_RPYTHON""" # mess to figure out how to put a gateway around executing expr argnames = ["_%d" % (i + 1) for i in range(multimethod.arity)] explicit_argnames = multimethod.extras.get("argnames", []) argnames[len(argnames) - len(explicit_argnames) :] = explicit_argnames solid_arglist = ["w_" + name for name in argnames] wrapper_arglist = solid_arglist[:] if multimethod.extras.get("varargs_w", False): wrapper_arglist.append("args_w") if multimethod.extras.get("w_varargs", False): wrapper_arglist.append("w_args") if multimethod.extras.get("keywords", False): raise Exception, "no longer supported, use __args__" if multimethod.extras.get("general__args__", False): wrapper_arglist.append("__args__") wrapper_arglist += multimethod.extras.get("extra_args", ()) miniglobals.update({"OperationError": OperationError, "typeerrormsg": typeerrormsg}) app_defaults = multimethod.extras.get("defaults", ()) i = len(argnames) - len(app_defaults) wrapper_signature = wrapper_arglist[:] for app_default in app_defaults: name = wrapper_signature[i] wrapper_signature[i] = "%s=%s" % (name, name) miniglobals[name] = app_default i += 1 wrapper_signature.insert(0, wrapper_signature.pop(selfindex)) wrapper_sig = ", ".join(wrapper_signature) src = [] dest = [] for wrapper_arg, expr_arg in zip(["space"] + wrapper_arglist, exprargs): if wrapper_arg != expr_arg: src.append(wrapper_arg) dest.append(expr_arg) renaming = ", ".join(dest) + " = " + ", ".join(src) if allow_NotImplemented_results and (len(multimethod.specialnames) > 1 or multimethod.name.startswith("inplace_")): # turn FailedToImplement into NotImplemented code = """def %s_perform_call(space, %s): %s try: return %s except FailedToImplement, e: if e.w_type is not None: raise OperationError(e.w_type, e.w_value) else: return space.w_NotImplemented """ % ( prefix, wrapper_sig, renaming, expr, ) else: # turn FailedToImplement into nice TypeErrors code = """def %s_perform_call(space, %s): %s try: w_res = %s except FailedToImplement, e: if e.w_type is not None: raise OperationError(e.w_type, e.w_value) else: raise OperationError(space.w_TypeError, typeerrormsg(space, %r, [%s])) if w_res is None: w_res = space.w_None return w_res """ % ( prefix, wrapper_sig, renaming, expr, multimethod.operatorsymbol, ", ".join(solid_arglist), ) exec compile2(code, "", "exec") in miniglobals return miniglobals["%s_perform_call" % prefix]
typename = space.type(w_obj).getname(space) raise operationerrfmt(space.w_TypeError, "unsupported operand type for %(targetname)s(): '%%s'", typename) w_result = space.get_and_call_function(w_impl, w_obj) if %(checker)s: return w_result typename = space.type(w_result).getname(space) msg = "%(specialname)s returned non-%(targetname)s (type '%%s')" raise operationerrfmt(space.w_TypeError, msg, typename) assert not hasattr(DescrOperation, %(targetname)r) DescrOperation.%(targetname)s = %(targetname)s del %(targetname)s \n""" % locals() exec compile2(source) for targetname, specialname in [ ('str', '__str__'), ('repr', '__repr__'), ('oct', '__oct__'), ('hex', '__hex__')]: source = """if 1: def %(targetname)s(space, w_obj): w_impl = space.lookup(w_obj, %(specialname)r) if w_impl is None: typename = space.type(w_obj).getname(space) raise operationerrfmt(space.w_TypeError, "unsupported operand type for %(targetname)s(): '%%s'", typename)