def __init__(self, bookkeeper, pyobj=None, name=None, signature=None, defaults=None, specializer=None): super(FunctionDesc, self).__init__(bookkeeper, pyobj) if name is None: name = pyobj.func_name if signature is None: if hasattr(pyobj, '_generator_next_method_of_'): from rpython.flowspace.argument import Signature signature = Signature(['entry']) # haaaaaack defaults = () else: signature = cpython_code_signature(pyobj.func_code) if defaults is None: defaults = pyobj.func_defaults self.name = name self.signature = signature self.defaults = defaults or () # 'specializer' is a function with the following signature: # specializer(funcdesc, args_s) => graph # or => s_result (overridden/memo cases) self.specializer = specializer self._cache = {} # convenience for the specializer
def newfuncdesc(self, pyfunc): name = pyfunc.__name__ if hasattr(pyfunc, '_generator_next_method_of_'): from rpython.flowspace.argument import Signature signature = Signature(['entry']) # haaaaaack defaults = () else: signature = cpython_code_signature(pyfunc.func_code) defaults = pyfunc.func_defaults # get the specializer based on the tag of the 'pyobj' # (if any), according to the current policy tag = getattr(pyfunc, '_annspecialcase_', None) specializer = self.annotator.policy.get_specializer(tag) if specializer is memo: return description.MemoDesc(self, pyfunc, name, signature, defaults, specializer) return description.FunctionDesc(self, pyfunc, name, signature, defaults, specializer)
def newfuncdesc(self, pyfunc): name = pyfunc.__name__ if hasattr(pyfunc, '_generator_next_method_of_'): from rpython.flowspace.argument import Signature signature = Signature(['entry']) # haaaaaack defaults = () else: signature = cpython_code_signature(pyfunc.__code__) defaults = pyfunc.__defaults__ # get the specializer based on the tag of the 'pyobj' # (if any), according to the current policy tag = getattr(pyfunc, '_annspecialcase_', None) specializer = self.annotator.policy.get_specializer(tag) if specializer is memo: return description.MemoDesc(self, pyfunc, name, signature, defaults, specializer) return description.FunctionDesc(self, pyfunc, name, signature, defaults, specializer)
def _make_descr_typecheck_wrapper(tag, func, extraargs, cls, use_closure): from rpython.flowspace.bytecode import cpython_code_signature # - if cls is None, the wrapped object is passed to the function # - if cls is a class, an unwrapped instance is passed if cls is None and use_closure: return func if hasattr(func, 'im_func'): assert func.im_class is cls func = func.im_func miniglobals = {func.__name__: func, 'OperationError': OperationError} if cls is None: source = """ def descr_typecheck_%(name)s(closure, space, obj, %(extra)s): return %(name)s(%(args)s, %(extra)s) """ else: cls_name = cls.__name__ assert issubclass(cls, W_Root) source = """ def descr_typecheck_%(name)s(closure, space, w_obj, %(extra)s): obj = space.descr_self_interp_w(%(cls_name)s, w_obj) return %(name)s(%(args)s, %(extra)s) """ miniglobals[cls_name] = cls name = func.__name__ extra = ', '.join(extraargs) sig = cpython_code_signature(func.func_code) argnames = sig.argnames if use_closure: if argnames[1] == 'space': args = "closure, space, obj" else: args = "closure, obj, space" else: if argnames[0] == 'space': args = "space, obj" else: args = "obj, space" source = py.code.Source(source % locals()) exec source.compile() in miniglobals return miniglobals['descr_typecheck_%s' % func.__name__]
def __init__(self, func, unwrap_spec=None, self_type=None, descrmismatch=None, doc=None): from rpython.rlib import rutf8 from rpython.flowspace.bytecode import cpython_code_signature # 'implfunc' is the interpreter-level function. # Note that this uses a lot of (construction-time) introspection. Code.__init__(self, func.__name__) self.docstring = doc or func.__doc__ if self.docstring: # check that it's utf-8 rutf8.check_utf8(self.docstring, False) self.identifier = "%s-%s-%s" % (func.__module__, func.__name__, getattr(self_type, '__name__', '*')) # unwrap_spec can be passed to interp2app or # attached as an attribute to the function. # It is a list of types or singleton objects: # baseobjspace.ObjSpace is used to specify the space argument # baseobjspace.W_Root is for wrapped arguments to keep wrapped # argument.Arguments is for a final rest arguments Arguments object # 'args_w' for fixedview applied to rest arguments # 'w_args' for rest arguments passed as wrapped tuple # str,int,float: unwrap argument as such type # (function, cls) use function to check/unwrap argument of type cls # First extract the signature from the (CPython-level) code object sig = cpython_code_signature(func.func_code) argnames = sig.argnames varargname = sig.varargname kwargname = sig.kwargname self._argnames = argnames if unwrap_spec is None: unwrap_spec = build_unwrap_spec(func, argnames, self_type) if self_type: assert unwrap_spec[ 0] == 'self', "self_type without 'self' spec element" unwrap_spec = list(unwrap_spec) if descrmismatch is not None: assert issubclass(self_type, W_Root) unwrap_spec[0] = ('INTERNAL:self', self_type) self.descrmismatch_op = descrmismatch self.descr_reqcls = self_type else: unwrap_spec[0] = self_type else: assert descrmismatch is None, ( "descrmismatch without a self-type specified") app_sig = SignatureBuilder(func) UnwrapSpec_Check(func, argnames).apply_over(unwrap_spec, app_sig) self.sig = app_sig.signature() argnames = self.sig.argnames varargname = self.sig.varargname self.minargs = len(argnames) if varargname: self.maxargs = sys.maxint else: self.maxargs = self.minargs self.activation = UnwrapSpec_EmitRun.make_activation(unwrap_spec, func) self._bltin = func self._unwrap_spec = unwrap_spec # speed hack if 0 <= len(unwrap_spec) <= 5: try: arity, fastfunc = UnwrapSpec_FastFunc_Unwrap.make_fastfunc( unwrap_spec, func) except FastFuncNotSupported: if unwrap_spec == [ObjSpace, Arguments]: self.__class__ = BuiltinCodePassThroughArguments0 self.func__args__ = func elif unwrap_spec == [ObjSpace, W_Root, Arguments]: self.__class__ = BuiltinCodePassThroughArguments1 self.func__args__ = func elif unwrap_spec == [self_type, ObjSpace, Arguments]: self.__class__ = BuiltinCodePassThroughArguments1 self.descr_reqcls = self_type miniglobals = {'func': func, 'self_type': self_type} d = {} source = """if 1: def _call(space, w_obj, args): self = space.descr_self_interp_w(self_type, w_obj) return func(self, space, args) \n""" exec compile2(source) in miniglobals, d self.func__args__ = d['_call'] else: self.__class__ = globals()['BuiltinCode%d' % arity] setattr(self, 'fastfunc_%d' % arity, fastfunc)