[pypy-svn] r50895 - in pypy/dist/pypy: config interpreter objspace objspace/test

cfbolz at codespeak.net cfbolz at codespeak.net
Tue Jan 22 23:36:51 CET 2008


Author: cfbolz
Date: Tue Jan 22 23:36:50 2008
New Revision: 50895

Modified:
   pypy/dist/pypy/config/pypyoption.py
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/objspace/reflective.py
   pypy/dist/pypy/objspace/test/test_reflective.py
Log:
expose the space.call_args method to the reflective object space. This needed a
config option which allows to disable the speed hacks in the calling code that
is normally there.


Modified: pypy/dist/pypy/config/pypyoption.py
==============================================================================
--- pypy/dist/pypy/config/pypyoption.py	(original)
+++ pypy/dist/pypy/config/pypyoption.py	Tue Jan 22 23:36:50 2008
@@ -46,6 +46,9 @@
     ChoiceOption("name", "Object Space name",
                  ["std", "flow", "thunk", "dump", "taint", "reflective"],
                  "std",
+                 requires={"reflective":
+                               [("objspace.disable_call_speedhacks", True)]
+                          },
                  cmdline='--objspace -o'),
 
     ChoiceOption("parser", "which parser to use for app-level code",
@@ -108,6 +111,10 @@
                "Honor the __builtins__ key of a module dictionary",
                default=False),
 
+    BoolOption("disable_call_speedhacks",
+               "make sure that all calls go through space.call_args",
+               default=False),
+
     OptionDescription("std", "Standard Object Space Options", [
         BoolOption("withtproxy", "support transparent proxies",
                    default=True),

Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Tue Jan 22 23:36:50 2008
@@ -661,43 +661,45 @@
         return self.call_args(w_callable, args)
 
     def call_function(self, w_func, *args_w):
-        # XXX start of hack for performance
-        from pypy.interpreter.function import Function, Method
-        if isinstance(w_func, Method):
-            w_inst = w_func.w_instance
-            if w_inst is not None:
-                func = w_func.w_function
-                if isinstance(func, Function):
-                    return func.funccall(w_inst, *args_w)
-            elif args_w and self.is_true(
-                    self.abstract_isinstance(args_w[0], w_func.w_class)):
-                w_func = w_func.w_function
-
-        if isinstance(w_func, Function):
-            return w_func.funccall(*args_w)
-        # XXX end of hack for performance
+        if not self.config.objspace.disable_call_speedhacks:
+            # XXX start of hack for performance
+            from pypy.interpreter.function import Function, Method
+            if isinstance(w_func, Method):
+                w_inst = w_func.w_instance
+                if w_inst is not None:
+                    func = w_func.w_function
+                    if isinstance(func, Function):
+                        return func.funccall(w_inst, *args_w)
+                elif args_w and self.is_true(
+                        self.abstract_isinstance(args_w[0], w_func.w_class)):
+                    w_func = w_func.w_function
+
+            if isinstance(w_func, Function):
+                return w_func.funccall(*args_w)
+            # XXX end of hack for performance
 
         args = Arguments(self, list(args_w))
         return self.call_args(w_func, args)
 
     def call_valuestack(self, w_func, nargs, frame):
-        # XXX start of hack for performance
-        from pypy.interpreter.function import Function, Method
-        hint(w_func.__class__, promote=True)
-        if isinstance(w_func, Method):
-            w_inst = w_func.w_instance
-            if w_inst is not None:
-                func = w_func.w_function
-                if isinstance(func, Function):
-                    return func.funccall_obj_valuestack(w_inst, nargs, frame)
-            elif nargs > 0 and self.is_true(
-                self.abstract_isinstance(frame.peekvalue(nargs-1),   #    :-(
-                                         w_func.w_class)):
-                w_func = w_func.w_function
-
-        if isinstance(w_func, Function):
-            return w_func.funccall_valuestack(nargs, frame)
-        # XXX end of hack for performance
+        if not self.config.objspace.disable_call_speedhacks:
+            # XXX start of hack for performance
+            from pypy.interpreter.function import Function, Method
+            hint(w_func.__class__, promote=True)
+            if isinstance(w_func, Method):
+                w_inst = w_func.w_instance
+                if w_inst is not None:
+                    func = w_func.w_function
+                    if isinstance(func, Function):
+                        return func.funccall_obj_valuestack(w_inst, nargs, frame)
+                elif nargs > 0 and self.is_true(
+                    self.abstract_isinstance(frame.peekvalue(nargs-1),   #    :-(
+                                             w_func.w_class)):
+                    w_func = w_func.w_function
+
+            if isinstance(w_func, Function):
+                return w_func.funccall_valuestack(nargs, frame)
+            # XXX end of hack for performance
 
         args = frame.make_arguments(nargs)
         try:

Modified: pypy/dist/pypy/objspace/reflective.py
==============================================================================
--- pypy/dist/pypy/objspace/reflective.py	(original)
+++ pypy/dist/pypy/objspace/reflective.py	Tue Jan 22 23:36:50 2008
@@ -1,4 +1,5 @@
-from pypy.interpreter import gateway
+from pypy.interpreter import gateway, typedef
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
 from pypy.interpreter.error import OperationError
 from pypy.objspace import std
 from pypy.objspace.std.typeobject import W_TypeObject
@@ -7,23 +8,22 @@
 def set_reflectivespace(space, w_reflectivespace):
     ec = space.getexecutioncontext()
     if space.is_w(w_reflectivespace, space.w_None):
-        ec.w_reflectivespace = None
+        ec.w_rspace = None
     else:
-        ec.w_reflectivespace = w_reflectivespace
+        ec.w_rspace = w_reflectivespace
 app_set_reflectivespace = gateway.interp2app(set_reflectivespace)
 
 def get_reflective_space(space):
     ec = space.getexecutioncontext()
-    if ec.w_reflectivespace is not None:
-        w_rspace = ec.w_reflectivespace
-        ec.w_reflectivespace = None
+    if ec.w_rspace is not None:
+        w_rspace = ec.w_rspace
+        ec.w_rspace = None
         return w_rspace
     return None
 
 def reset_reflective_space(space, w_rspace):
     ec = space.getexecutioncontext()
-    ec.w_reflectivespace = w_rspace
-
+    ec.w_rspace = w_rspace
 
 DontWrapMe = [
     'wrap',
@@ -37,10 +37,10 @@
     'unwrap',
     'is_true',
     'is_w',
-    'call_args',
     'marshal_w',
     ]
 
+
 def proxymaker(space, opname, parentfn):
     if opname in DontWrapMe:
         return None
@@ -66,6 +66,23 @@
             if w_newobj is not None:
                 return w_newobj
             return w_obj
+    elif opname == "call_args":
+        def fn(w_callable, args):
+            w_rspace = get_reflective_space(space)
+            if w_rspace is not None:
+                try:
+                    try:
+                        w_f = space.getattr(w_rspace, space.wrap(opname))
+                    except OperationError, e:
+                        if not e.match(space, space.w_AttributeError):
+                            raise
+                    else:
+                        args = args.prepend(w_callable)
+                        w_args, w_kwargs = args.topacked()
+                        return space.call(w_f, w_args, w_kwargs)
+                finally:
+                    reset_reflective_space(space, w_rspace)
+            return parentfn(w_callable, args)
     elif opname.startswith("new"):
         def fn(*args):
             w_obj = parentfn(*args)
@@ -95,7 +112,7 @@
 class ReflectiveObjSpace(std.Space):
     def createexecutioncontext(self):
         ec = std.Space.createexecutioncontext(self)
-        ec.w_reflectivespace = None
+        ec.w_rspace = None
         return ec
 
 def Space(*args, **kwds):

Modified: pypy/dist/pypy/objspace/test/test_reflective.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_reflective.py	(original)
+++ pypy/dist/pypy/objspace/test/test_reflective.py	Tue Jan 22 23:36:50 2008
@@ -83,3 +83,41 @@
         a = A()
         set_reflectivespace(Space())
         assert a.f() == 2
+
+    def test_autocurry(self):
+        # rather simplified for now
+        from __pypy__ import set_reflectivespace
+        class partial(object):
+            def __init__(self, func, *args, **kwargs):
+                self.func = func
+                self.args = args
+                self.kwargs = kwargs
+            def __call__(self, *args, **kwargs):
+                args = self.args + args
+                for key, value in self.kwargs.iteritems():
+                    if key in kwargs:
+                        raise TypeError("got multiple values for keyword argument %r" % (key, ))
+                    kwargs[key] = value
+                return self.func(*args, **kwargs)
+        import types
+        class Space:
+            def call_args(self, func, *args, **kwargs):
+                print func, args, kwargs
+                if (len(kwargs) != 0 or not 
+                    isinstance(func, types.FunctionType)):
+                    return func(*args, **kwargs)
+                defaults = func.func_defaults
+                if defaults is None:
+                    defaults = ()
+                argcount = func.func_code.co_argcount
+                minargs = argcount - len(defaults)
+                if len(args) >= minargs:
+                    return func(*args, **kwargs)
+                return partial(func, *args, **kwargs)
+        def f(x, y, z):
+            return x + y * z
+        set_reflectivespace(Space())
+        g = f(1, 2)
+        assert g(3) == f(1, 2, 3)
+        # XXX the following does not work, of course:
+        # assert f(4)(6)(7) == f(4, 6, 7)



More information about the Pypy-commit mailing list