[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