[pypy-svn] r5309 - in pypy/trunk/src/pypy: interpreter interpreter/test objspace objspace/std

arigo at codespeak.net arigo at codespeak.net
Fri Jun 25 18:25:39 CEST 2004


Author: arigo
Date: Fri Jun 25 18:25:37 2004
New Revision: 5309

Modified:
   pypy/trunk/src/pypy/interpreter/argument.py
   pypy/trunk/src/pypy/interpreter/function.py
   pypy/trunk/src/pypy/interpreter/gateway.py
   pypy/trunk/src/pypy/interpreter/module.py
   pypy/trunk/src/pypy/interpreter/test/test_function.py
   pypy/trunk/src/pypy/interpreter/test/test_gateway.py
   pypy/trunk/src/pypy/objspace/descroperation.py
   pypy/trunk/src/pypy/objspace/std/dicttype.py
   pypy/trunk/src/pypy/objspace/std/listtype.py
   pypy/trunk/src/pypy/objspace/std/objecttype.py
   pypy/trunk/src/pypy/objspace/trivial.py
Log:
Gateway cleanups: trying to remove interpreter-level ** arguments.

Now interp2app(f) no longer accepts interp-level functions with **.
Instead, the signature of f should either end with a * argument, or with an 
argument called __args__ (hum).  In the latter case, the app-level version of 
f appears to have a * and a ** argument, and the interp-level version will get 
all that nicely collected in an pypy.interpreter.argument.Arguments instance.

Hum, the goal was to solve the problem in the failing test, but it still 
fails.  See mail to pypy-dev "fun with functions".



Modified: pypy/trunk/src/pypy/interpreter/argument.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/argument.py	(original)
+++ pypy/trunk/src/pypy/interpreter/argument.py	Fri Jun 25 18:25:37 2004
@@ -15,6 +15,8 @@
     ###  Construction  ###
 
     def __init__(self, space, args_w=[], kwds_w={}):
+        assert isinstance(args_w, list)  # I keep forgetting the 'space'
+        assert isinstance(kwds_w, dict)  # argument so hopefully this helps
         self.space = space
         self.args_w = args_w
         self.kwds_w = kwds_w

Modified: pypy/trunk/src/pypy/interpreter/function.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/function.py	(original)
+++ pypy/trunk/src/pypy/interpreter/function.py	Fri Jun 25 18:25:37 2004
@@ -32,6 +32,9 @@
         frame.setfastscope(scope_w)
         return frame.run()
 
+    def interplevel_call(self, *args_w):
+        return self.call_args(Arguments(self.space, list(args_w)))
+
     def getdict(self):
         return self.w_func_dict
 
@@ -51,10 +54,8 @@
         else:
             return wrap(Method(space, wrap(self), None, w_cls))
 
-    def descr_function_call(self, *args_w, **kwds_w):
-        # XXX the Gateway interface should not use interp-level */**
-        # XXX arguments -- conflict with 'self'!
-        return self.call_args(Arguments(self.space, list(args_w), kwds_w))
+    def descr_function_call(self, __args__):
+        return self.call_args(__args__)
 
     def fget_func_defaults(space, w_self):
         self = space.unwrap(w_self)
@@ -103,9 +104,11 @@
                                      self.space.wrap(msg))
         return self.space.call_args(self.w_function, args)
 
-    def descr_method_call(self, *args_w, **kwds_w):
-        # XXX same as descr_function_call()
-        return self.call_args(Arguments(self.space, list(args_w), kwds_w))
+    def interplevel_call(self, *args_w):
+        return self.call_args(Arguments(self.space, list(args_w)))
+
+    def descr_method_call(self, __args__):
+        return self.call_args(__args__)
 
 class StaticMethod(Wrappable):
     """A static method.  Note that there is one class staticmethod at

Modified: pypy/trunk/src/pypy/interpreter/gateway.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/gateway.py	(original)
+++ pypy/trunk/src/pypy/interpreter/gateway.py	Fri Jun 25 18:25:37 2004
@@ -14,6 +14,7 @@
 from pypy.interpreter import eval, pycode
 from pypy.interpreter.function import Function, Method
 from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.argument import Arguments
 
 
 class BuiltinCode(eval.Code):
@@ -34,7 +35,8 @@
         # Currently we enforce the following signature tricks:
         #  * the first arg must be either 'self' or 'space'
         #  * 'w_' prefixes for the rest
-        #  * '_w' suffixes on * and **
+        #  * '_w' suffix for the optional '*' argument
+        #  * alternatively a final '__args__' means an Arguments()
         # Not exactly a clean approach XXX.
         argnames, varargname, kwargname = tmp.signature()
         argnames = list(argnames)
@@ -47,22 +49,31 @@
         self.spacearg = spacearg
         if spacearg:
             del argnames[0]
-        for i in range(ismethod, len(argnames)):
-            a = argnames[i]
-            assert a.startswith('w_'), (
-                "argument %s of built-in function %r should start with 'w_'" %
-                (a, func))
-            argnames[i] = a[2:]
-        if varargname is not None:
+
+        assert kwargname is None, (
+            "built-in function %r should not take a ** argument" % func)
+
+        self.generalargs = argnames[-1:] == ['__args__']
+        self.starargs = varargname is not None
+        assert not (self.generalargs and self.starargs), (
+            "built-in function %r has both __args__ and a * argument" % func)
+        if self.generalargs:
+            del argnames[-1]
+            varargname = "args"
+            kwargname = "keywords"
+        elif self.starargs:
             assert varargname.endswith('_w'), (
                 "argument *%s of built-in function %r should end in '_w'" %
                 (varargname, func))
             varargname = varargname[:-2]
-        if kwargname is not None:
-            assert kwargname.endswith('_w'), (
-                "argument **%s of built-in function %r should end in '_w'" %
-                (kwargname, func))
-            kwargname = kwargname[:-2]
+
+        for i in range(ismethod, len(argnames)):
+            a = argnames[i]
+            assert a.startswith('w_'), (
+                "argument %s of built-in function %r should "
+                "start with 'w_'" % (a, func))
+            argnames[i] = a[2:]
+
         self.sig = argnames, varargname, kwargname
 
     def create_frame(self, space, w_globals, closure=None):
@@ -79,34 +90,19 @@
     # via the interface defined in eval.Frame.
 
     def run(self):
-        argarray = self.fastlocals_w
+        argarray = list(self.fastlocals_w)
+        if self.code.generalargs:
+            w_kwds = argarray.pop()
+            w_args = argarray.pop()
+            argarray.append(Arguments.frompacked(self.space, w_args, w_kwds))
+        elif self.code.starargs:
+            w_args = argarray.pop()
+            argarray += self.space.unpacktuple(w_args)
         if self.code.ismethod:
-            argarray = [self.space.unwrap(argarray[0])] + argarray[1:]
+            argarray[0] = self.space.unwrap(argarray[0])
         if self.code.spacearg:
-            argarray = [self.space] + argarray
-        return call_with_prepared_arguments(self.space, self.code.func,
-                                            argarray)
-
-
-def call_with_prepared_arguments(space, function, argarray):
-    """Call the given function. 'argarray' is a correctly pre-formatted
-    list of values for the formal parameters, including one for * and one
-    for **."""
-    # XXX there is no clean way to do this in Python,
-    # we have to hack back an arguments tuple and keywords dict.
-    # This algorithm is put in its own well-isolated function so that
-    # you don't need to look at it :-)
-    keywords = {}
-    co = function.func_code
-    if co.co_flags & 8:  # CO_VARKEYWORDS
-        w_kwds = argarray[-1]
-        for w_key in space.unpackiterable(w_kwds):
-            keywords[space.unwrap(w_key)] = space.getitem(w_kwds, w_key)
-        argarray = argarray[:-1]
-    if co.co_flags & 4:  # CO_VARARGS
-        w_varargs = argarray[-1]
-        argarray = argarray[:-1] + space.unpacktuple(w_varargs)
-    return function(*argarray, **keywords)
+            argarray.insert(0, self.space)
+        return self.code.func(*argarray)
 
 
 class Gateway(Wrappable):
@@ -203,18 +199,18 @@
     def getdefaults(self, space):
         return [space.wrap(val) for val in self.staticdefs]
 
-    def __call__(self, space, *args_w, **kwds_w):
+    def __call__(self, space, *args_w):
         # to call the Gateway as a non-method, 'space' must be explicitely
         # supplied. We build the Function object and call it.
         fn = self.get_function(space)
-        return fn.descr_function_call(*args_w, **kwds_w)
+        return fn.interplevel_call(*args_w)
 
     def __get__(self, obj, cls=None):
         if obj is None:
             return self
         else:
             method = self.get_method(obj)
-            return method.descr_method_call
+            return method.interplevel_call
 
 class interp2app(Gateway):
     """Build a Gateway that calls 'f' at interp-level."""

Modified: pypy/trunk/src/pypy/interpreter/module.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/module.py	(original)
+++ pypy/trunk/src/pypy/interpreter/module.py	Fri Jun 25 18:25:37 2004
@@ -21,7 +21,7 @@
     def setdict(self, w_dict):
         self.w_dict = w_dict
 
-    def descr_module__new__(space, w_subtype, *args_w, **kwds_w):
+    def descr_module__new__(space, w_subtype, __args__):
         module = space.allocate_instance(Module, w_subtype)
         module.__init__(space, space.wrap('?'))
         return space.wrap(module)

Modified: pypy/trunk/src/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/test/test_function.py	(original)
+++ pypy/trunk/src/pypy/interpreter/test/test_function.py	Fri Jun 25 18:25:37 2004
@@ -148,7 +148,7 @@
         space = self.space
         w_meth = self.fn.descr_function_get(space.wrap(5), space.type(space.wrap(5)))
         meth = space.unwrap(w_meth)
-        w_result = meth.descr_method_call(space.wrap(42))
+        w_result = meth.interplevel_call(space.wrap(42))
         self.assertEquals(space.unwrap(w_result), 42)
 
     def test_fail_call(self):
@@ -156,7 +156,7 @@
         w_meth = self.fn.descr_function_get(space.wrap(5), space.type(space.wrap(5)))
         meth = space.unwrap(w_meth)
         self.assertRaises_w(self.space.w_TypeError,
-                            meth.descr_method_call,
+                            meth.interplevel_call,
                             space.wrap("spam"), space.wrap("egg"))
 
 if __name__ == '__main__':

Modified: pypy/trunk/src/pypy/interpreter/test/test_gateway.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/test/test_gateway.py	(original)
+++ pypy/trunk/src/pypy/interpreter/test/test_gateway.py	Fri Jun 25 18:25:37 2004
@@ -9,27 +9,50 @@
         self.space = testit.objspace()
 
     def test_signature(self):
-        def c(space, w_x, w_y, *args_w, **kw_w):
+        def c(space, w_x, w_y, *hello_w):
             pass
         code = gateway.BuiltinCode(c)
-        self.assertEqual(code.signature(), (['x', 'y'], 'args', 'kw'))
+        self.assertEqual(code.signature(), (['x', 'y'], 'hello', None))
         def d(self, w_boo):
             pass
         code = gateway.BuiltinCode(d)
         self.assertEqual(code.signature(), (['self', 'boo'], None, None))
+        def e(space, w_x, w_y, __args__):
+            pass
+        code = gateway.BuiltinCode(e)
+        self.assertEqual(code.signature(), (['x', 'y'], 'args', 'keywords'))
 
     def test_call(self):
-        def c(space, w_x, w_y, *args_w, **kw_w):
+        def c(space, w_x, w_y, *hello_w):
+            u = space.unwrap
+            w = space.wrap
+            self.assertEquals(len(hello_w), 2)
+            self.assertEquals(u(hello_w[0]), 0)
+            self.assertEquals(u(hello_w[1]), True)
+            return w((u(w_x) - u(w_y) + len(hello_w)))
+        code = gateway.BuiltinCode(c)
+        w = self.space.wrap
+        w_dict = self.space.newdict([
+            (w('x'), w(123)),
+            (w('y'), w(23)),
+            (w('hello'), self.space.newtuple([w(0), w(True)])),
+            ])
+        w_result = code.exec_code(self.space, w_dict, w_dict)
+        self.assertEqual_w(w_result, w(102))
+
+    def test_call_args(self):
+        def c(space, w_x, w_y, __args__):
             u = space.unwrap
             w = space.wrap
-            return w((u(w_x) - u(w_y) + len(args_w)) * u(kw_w['boo']))
+            return w((u(w_x) - u(w_y) + len(__args__.args_w))
+                     * u(__args__.kwds_w['boo']))
         code = gateway.BuiltinCode(c)
         w = self.space.wrap
         w_dict = self.space.newdict([
             (w('x'), w(123)),
             (w('y'), w(23)),
             (w('args'), self.space.newtuple([w(0), w(True)])),
-            (w('kw'), self.space.newdict([(w('boo'), w(10))])),
+            (w('keywords'), self.space.newdict([(w('boo'), w(10))])),
             ])
         w_result = code.exec_code(self.space, w_dict, w_dict)
         self.assertEqual_w(w_result, w(1020))

Modified: pypy/trunk/src/pypy/objspace/descroperation.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/descroperation.py	(original)
+++ pypy/trunk/src/pypy/objspace/descroperation.py	Fri Jun 25 18:25:37 2004
@@ -48,7 +48,7 @@
                     raise
         raise OperationError(space.w_AttributeError,w_name)
 
-    def descr__init__(space, w_obj, *args_w, **kwds_w):
+    def descr__init__(space, w_obj, __args__):
         pass   # XXX some strange checking maybe
 
 class DescrOperation:

Modified: pypy/trunk/src/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/dicttype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/dicttype.py	Fri Jun 25 18:25:37 2004
@@ -93,7 +93,7 @@
 
 # ____________________________________________________________
 
-def descr__new__(space, w_dicttype, *args_w, **kwds_w):
+def descr__new__(space, w_dicttype, __args__):
     from pypy.objspace.std.dictobject import W_DictObject
     w_obj = space.allocate_instance(W_DictObject, w_dicttype)
     w_obj.__init__(space, [])

Modified: pypy/trunk/src/pypy/objspace/std/listtype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/listtype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/listtype.py	Fri Jun 25 18:25:37 2004
@@ -13,7 +13,7 @@
 
 # ____________________________________________________________
 
-def descr__new__(space, w_listtype, *args_w, **kwds_w):
+def descr__new__(space, w_listtype, __args__):
     from pypy.objspace.std.listobject import W_ListObject
     w_obj = space.allocate_instance(W_ListObject, w_listtype)
     w_obj.__init__(space, [])

Modified: pypy/trunk/src/pypy/objspace/std/objecttype.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/objecttype.py	(original)
+++ pypy/trunk/src/pypy/objspace/std/objecttype.py	Fri Jun 25 18:25:37 2004
@@ -21,19 +21,19 @@
 def descr__class__(space, w_obj):
     return space.type(w_obj)
 
-def descr__new__(space, w_type, *args_w, **kwds_w):
+def descr__new__(space, w_type, __args__):
     from pypy.objspace.std.objectobject import W_ObjectObject
     # don't allow arguments if the default object.__init__() is about
     # to be called
     w_parentinit, w_ignored = w_type.lookup_where('__init__')
-    if w_parentinit is space.w_object and (args_w or kwds_w):
+    if w_parentinit is space.w_object and (__args__.args_w or __args__.kwds_w):
         raise OperationError(space.w_TypeError,
                              space.wrap("default __new__ takes no parameters"))
     w_obj = space.allocate_instance(W_ObjectObject, w_type)
     w_obj.__init__(space)
     return w_obj
 
-def descr__init__(space, *args_w, **kwds_w):
+def descr__init__(space, __args__):
     pass
 
 # ____________________________________________________________

Modified: pypy/trunk/src/pypy/objspace/trivial.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/trivial.py	(original)
+++ pypy/trunk/src/pypy/objspace/trivial.py	Fri Jun 25 18:25:37 2004
@@ -182,10 +182,10 @@
             for descrname, descr in typedef.rawdict.items():
                 if isinstance(descr, interp2app):
                     def make_stuff(descr=descr, descrname=descrname, space=self):
-                        def stuff(w_obj, *args, **kwds):
+                        def stuff(w_obj, *args):
                             fn = descr.get_function(space)
                             try:
-                                return fn.descr_function_call(w_obj, *args, **kwds)
+                                return fn.interplevel_call(w_obj, *args)
                             except OperationError, e:
                                 if not hasattr(e.w_type, 'originalex'):
                                     raise # XXX



More information about the Pypy-commit mailing list