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 pypy.interpreter.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 build(cache, func): space = cache.space # make a built-in function assert isinstance(func.code, BuiltinCode) # XXX bltin = func.code._bltin unwrap_spec = func.code._unwrap_spec from pypy.interpreter import pycode argnames, varargname, kwargname = pycode.cpython_code_signature( bltin.func_code) orig_sig = Signature(bltin, argnames, varargname, kwargname) tramp = UnwrapSpec_Trampoline(orig_sig) tramp.miniglobals = { '___space': space, '___W_Object': CPyObjSpace.W_Object, '___bltin': bltin, '___OperationError': OperationError, '___reraise': reraise, } tramp.apply_over(unwrap_spec) sourcelines = ['def trampoline(%s):' % (', '.join(tramp.inputargs),)] # this description is to aid viewing in graphviewer sourcelines.append(' "wrapper for fn: %s"' % func.name) for line in tramp.wrappings: sourcelines.append(' ' + line) sourcelines.append(' try:') sourcelines.append(' w_result = ___bltin(%s)' % ( ', '.join(tramp.passedargs),)) sourcelines.append(' except ___OperationError, e:') sourcelines.append(' ___reraise(e)') # the following line is not reached, unless we are translated # in which case it makes the function return (PyObject*)NULL. sourcelines.append(' w_result = ___W_Object()') sourcelines.append(' else:') # # convert None to Py_None sourcelines.append(' if w_result is None:') sourcelines.append(' return None') sourcelines.append(' return w_result.value') sourcelines.append('') miniglobals = tramp.miniglobals exec py.code.Source('\n'.join(sourcelines)).compile() in miniglobals trampoline = miniglobals['trampoline'] trampoline = func_with_new_name(trampoline, func.name) trampoline.nb_args = len(tramp.inputargs) trampoline.star_arg = tramp.star_arg trampoline.allow_someobjects = True # annotator hint trampoline._annspecialcase_ = "specialize:all_someobjects" if func.defs_w: trampoline.func_defaults = tuple([space.unwrap(w_x) for w_x in func.defs_w]) w_result = W_Object(trampoline) space.wrap_cache[id(w_result)] = w_result, func, follow_annotations return w_result
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: 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 _make_descr_typecheck_wrapper(tag, func, extraargs, cls, use_closure): # - 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 a string, XXX unused? 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) from pypy.interpreter import pycode sig = pycode.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 _make_descr_typecheck_wrapper(tag, func, extraargs, cls, use_closure): # - 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 a string, XXX unused? 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, Wrappable) 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) from pypy.interpreter import pycode argnames, _, _ = pycode.cpython_code_signature(func.func_code) 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, argtypes, restype, callable, error=_NOT_SPECIFIED, c_name=None): self.argtypes = argtypes self.restype = restype self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype)) self.callable = callable if error is not _NOT_SPECIFIED: self.error_value = error self.c_name = c_name # extract the signature from the (CPython-level) code object from pypy.interpreter import pycode argnames, varargname, kwargname = pycode.cpython_code_signature(callable.func_code) assert argnames[0] == 'space' self.argnames = argnames[1:] assert len(self.argnames) == len(self.argtypes)
def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED, c_name=None): self.argtypes = argtypes self.restype = restype self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype)) self.callable = callable if error is not _NOT_SPECIFIED: self.error_value = error self.c_name = c_name # extract the signature from the (CPython-level) code object from pypy.interpreter import pycode argnames, varargname, kwargname = pycode.cpython_code_signature(callable.func_code) assert argnames[0] == 'space' self.argnames = argnames[1:] assert len(self.argnames) == len(self.argtypes)
def build_flow(self, func, constargs={}): """ """ if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'): raise Exception, "%r is tagged as NOT_RPYTHON" % (func, ) code = func.func_code if code.co_flags & 32: # generator raise TypeError("%r is a generator" % (func, )) code = PyCode._from_code(self, code) if func.func_closure is None: closure = None else: closure = [ extract_cell_content(c, name, func) for c, name in zip( func.func_closure, func.func_code.co_freevars) ] # CallableFactory.pycall may add class_ to functions that are methods name = func.func_name class_ = getattr(func, 'class_', None) if class_ is not None: name = '%s.%s' % (class_.__name__, name) for c in "<>&!": name = name.replace(c, '_') ec = flowcontext.FlowExecutionContext(self, code, func.func_globals, constargs, closure, name) graph = ec.graph graph.func = func # attach a signature and defaults to the graph # so that it becomes even more interchangeable with the function # itself graph.signature = cpython_code_signature(code) graph.defaults = func.func_defaults or () self.setup_executioncontext(ec) from pypy.tool.error import FlowingError, format_global_error try: ec.build_flow() except FlowingError, a: # attach additional source info to AnnotatorError _, _, tb = sys.exc_info() e = FlowingError( format_global_error(ec.graph, ec.crnt_offset, str(a))) raise FlowingError, e, tb
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: 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 build_flow(self, func, constargs={}, tweak_for_generator=True): """ """ if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'): raise Exception, "%r is tagged as NOT_RPYTHON" % (func, ) code = func.func_code is_generator = bool(code.co_flags & CO_GENERATOR) code = PyCode._from_code(self, code) if func.func_closure is None: cl = None else: cl = [extract_cell_content(c) for c in func.func_closure] # CallableFactory.pycall may add class_ to functions that are methods name = func.func_name class_ = getattr(func, 'class_', None) if class_ is not None: name = '%s.%s' % (class_.__name__, name) for c in "<>&!": name = name.replace(c, '_') class outerfunc: # hack closure = cl ec = flowcontext.FlowExecutionContext(self, code, func.func_globals, constargs, outerfunc, name, is_generator) graph = ec.graph graph.func = func # attach a signature and defaults to the graph # so that it becomes even more interchangeable with the function # itself graph.signature = cpython_code_signature(code) graph.defaults = func.func_defaults or () self.setup_executioncontext(ec) try: ec.build_flow() except error.FlowingError, a: # attach additional source info to AnnotatorError _, _, tb = sys.exc_info() formated = error.format_global_error(ec.graph, ec.crnt_offset, str(a)) e = error.FlowingError(formated) raise error.FlowingError, e, tb
def build_flow(self, func, constargs={}): """ """ if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'): raise Exception, "%r is tagged as NOT_RPYTHON" % (func,) code = func.func_code if code.co_flags & 32: # generator raise TypeError("%r is a generator" % (func,)) code = PyCode._from_code(self, code) if func.func_closure is None: closure = None else: closure = [extract_cell_content(c, name, func) for c, name in zip(func.func_closure, func.func_code.co_freevars)] # CallableFactory.pycall may add class_ to functions that are methods name = func.func_name class_ = getattr(func, 'class_', None) if class_ is not None: name = '%s.%s' % (class_.__name__, name) for c in "<>&!": name = name.replace(c, '_') ec = flowcontext.FlowExecutionContext(self, code, func.func_globals, constargs, closure, name) graph = ec.graph graph.func = func # attach a signature and defaults to the graph # so that it becomes even more interchangeable with the function # itself graph.signature = cpython_code_signature(code) graph.defaults = func.func_defaults or () self.setup_executioncontext(ec) from pypy.tool.error import FlowingError, format_global_error try: ec.build_flow() except FlowingError, a: # attach additional source info to AnnotatorError _, _, tb = sys.exc_info() e = FlowingError(format_global_error(ec.graph, ec.crnt_offset, str(a))) raise FlowingError, e, tb
def build_flow(self, func, constargs={}, tweak_for_generator=True): """ """ if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'): raise Exception, "%r is tagged as NOT_RPYTHON" % (func,) code = func.func_code is_generator = bool(code.co_flags & CO_GENERATOR) code = PyCode._from_code(self, code) if func.func_closure is None: cl = None else: cl = [extract_cell_content(c) for c in func.func_closure] # CallableFactory.pycall may add class_ to functions that are methods name = func.func_name class_ = getattr(func, 'class_', None) if class_ is not None: name = '%s.%s' % (class_.__name__, name) for c in "<>&!": name = name.replace(c, '_') class outerfunc: # hack closure = cl ec = flowcontext.FlowExecutionContext(self, code, func.func_globals, constargs, outerfunc, name, is_generator) graph = ec.graph graph.func = func # attach a signature and defaults to the graph # so that it becomes even more interchangeable with the function # itself graph.signature = cpython_code_signature(code) graph.defaults = func.func_defaults or () self.setup_executioncontext(ec) try: ec.build_flow() except error.FlowingError, a: # attach additional source info to AnnotatorError _, _, tb = sys.exc_info() formated = error.format_global_error(ec.graph, ec.crnt_offset, str(a)) e = error.FlowingError(formated) raise error.FlowingError, e, tb
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 pypy.interpreter.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 __init__(self, func, unwrap_spec=None, self_type=None, descrmismatch=None, doc=None): # '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__ 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 from pypy.interpreter import pycode sig = pycode.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") orig_sig = SignatureBuilder(func, argnames, varargname, kwargname) app_sig = SignatureBuilder(func) UnwrapSpec_Check(orig_sig).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 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)
def __init__(self, func, unwrap_spec=None, self_type=None, descrmismatch=None): "NOT_RPYTHON" # 'implfunc' is the interpreter-level function. # Note that this uses a lot of (construction-time) introspection. Code.__init__(self, func.__name__) self.docstring = func.__doc__ 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 from pypy.interpreter import pycode argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code) 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") orig_sig = SignatureBuilder(func, argnames, varargname, kwargname) app_sig = SignatureBuilder(func) UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, app_sig) self.sig = argnames, varargname, kwargname = app_sig.signature() 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 else: self.__class__ = globals()['BuiltinCode%d' % arity] setattr(self, 'fastfunc_%d' % arity, fastfunc)
def __init__(self, func, unwrap_spec = None, self_type = None, descrmismatch=None): "NOT_RPYTHON" # 'implfunc' is the interpreter-level function. # Note that this uses a lot of (construction-time) introspection. eval.Code.__init__(self, func.__name__) self.docstring = func.__doc__ # 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 # baseobjspace.Wrappable subclasses imply interp_w and a typecheck # argument.Arguments is for a final rest arguments Arguments object # 'args_w' for unpacktuple 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 from pypy.interpreter import pycode argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code) if unwrap_spec is None: unwrap_spec = getattr(func,'unwrap_spec',None) if unwrap_spec is None: unwrap_spec = [ObjSpace]+ [W_Root] * (len(argnames)-1) if self_type: unwrap_spec = ['self'] + unwrap_spec[1:] 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, Wrappable) unwrap_spec[0] = ('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") orig_sig = Signature(func, argnames, varargname, kwargname) app_sig = Signature(func) UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, app_sig #to populate ) self.sig = argnames, varargname, kwargname = app_sig.signature() 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 else: self.__class__ = globals()['BuiltinCode%d' % arity] setattr(self, 'fastfunc_%d' % arity, fastfunc)