[pypy-svn] rev 818 - in pypy/trunk/src/pypy/interpreter: . test
mwh at codespeak.net
mwh at codespeak.net
Tue Jun 17 17:24:31 CEST 2003
Author: mwh
Date: Tue Jun 17 17:24:30 2003
New Revision: 818
Modified:
pypy/trunk/src/pypy/interpreter/extmodule.py
pypy/trunk/src/pypy/interpreter/pycode.py
pypy/trunk/src/pypy/interpreter/test/test_extmodule.py
Log:
support for varadic and varkeywordic (sic) builtin functions
i have a feeling i may be being overly clever again in
extmodule.py, feel free to quibble (OTOH, it works & has
tests)
Modified: pypy/trunk/src/pypy/interpreter/extmodule.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/extmodule.py (original)
+++ pypy/trunk/src/pypy/interpreter/extmodule.py Tue Jun 17 17:24:30 2003
@@ -14,6 +14,8 @@
return self.data
+# a little excercise in OOP, Python 2.2-style:
+
class PyBuiltinCode(pycode.PyBaseCode):
"""The code object implementing a built-in (interpreter-level) hook."""
@@ -23,8 +25,6 @@
co = func.func_code
self.co_name = func.__name__
self.co_flags = co.co_flags
- # extract argument names from 'co',
- # removing 'self' and the 'w_' prefixes
if boundmethod:
assert co.co_varnames[0] == "self"
start = 1
@@ -36,18 +36,72 @@
argnames.append(argname[2:])
self.co_varnames = tuple(argnames)
self.co_argcount = co.co_argcount - start
+ self.next_arg = self.co_argcount + start
- def eval_code(self, space, w_globals, w_locals):
- # this isn't quite complete: varargs and kwargs are missing
+ def prepare_args(self, space, w_locals):
args = []
- for argname in self.co_varnames:
+ for argname in self.co_varnames[:self.co_argcount]:
w_arg = space.getitem(w_locals, space.wrap(argname))
args.append(w_arg)
- w_ret = self.func(*args)
- return w_ret
+ return args
+
+ def eval_code(self, space, w_globals, w_locals):
+ args = self.prepare_args(space, w_locals)
+ return self.func(*args)
+
+
+class PyBuiltinVarCode(PyBuiltinCode):
+
+ def __init__(self, func, boundmethod=False):
+ super(PyBuiltinVarCode, self).__init__(func, boundmethod)
+ self.vararg_name = func.func_code.co_varnames[self.next_arg]
+ self.co_varnames += (self.vararg_name,)
+ assert self.vararg_name.endswith('_w'), "%s, arg %d: %s"%(
+ func.func_name, self.co_argcount + 1, self.vararg_name)
+ self.next_arg += 1
+
+ def prepare_args(self, space, w_locals):
+ args = super(PyBuiltinVarCode, self).prepare_args(space, w_locals)
+ w_args = space.getitem(w_locals, space.wrap(self.vararg_name))
+ args.extend(space.unpackiterable(w_args))
+ return args
+
+
+class PyBuiltinKwCode(PyBuiltinCode):
+ def __init__(self, func, boundmethod=False):
+ super(PyBuiltinKwCode, self).__init__(func, boundmethod)
+ self.kwarg_name = func.func_code.co_varnames[self.next_arg]
+ self.co_varnames += (self.kwarg_name,)
+ assert self.kwarg_name.endswith('_w'), "%s, arg %d: %s"%(
+ func.func_name, self.co_argcount + 1, self.kwarg_name)
+ self.next_arg += 1
+
+ def eval_code(self, space, w_globals, w_locals):
+ args = self.prepare_args(space, w_locals)
+ w_kws = space.getitem(w_locals, space.wrap(self.kwarg_name))
+ kws = {}
+ for w_key in space.unpackiterable(w_kws):
+ kws[space.unwrap(w_key)] = space.getitem(w_kws, w_key)
+
+ return self.func(*args, **kws)
+
+
+class PyBuiltinVarKwCode(PyBuiltinKwCode, PyBuiltinVarCode):
+ pass
+
def make_builtin_func(space, func, boundmethod=False):
- code = PyBuiltinCode(func, boundmethod)
+ if func.func_code.co_flags & pycode.CO_VARARGS:
+ if func.func_code.co_flags & pycode.CO_VARKEYWORDS:
+ code_cls = PyBuiltinVarKwCode
+ else:
+ code_cls = PyBuiltinVarCode
+ else:
+ if func.func_code.co_flags & pycode.CO_VARKEYWORDS:
+ code_cls = PyBuiltinKwCode
+ else:
+ code_cls = PyBuiltinCode
+ code = code_cls(func, boundmethod)
w_defaults = space.wrap(func.func_defaults)
w_function = space.newfunction(code, space.w_None, w_defaults)
return w_function
Modified: pypy/trunk/src/pypy/interpreter/pycode.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pycode.py (original)
+++ pypy/trunk/src/pypy/interpreter/pycode.py Tue Jun 17 17:24:30 2003
@@ -25,7 +25,7 @@
CO_VARKEYWORDS = 0x0008
-class PyBaseCode:
+class PyBaseCode(object):
def __init__(self):
self.co_name = ""
self.co_flags = 0
Modified: pypy/trunk/src/pypy/interpreter/test/test_extmodule.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/test/test_extmodule.py (original)
+++ pypy/trunk/src/pypy/interpreter/test/test_extmodule.py Tue Jun 17 17:24:30 2003
@@ -98,7 +98,34 @@
self.assertEqual_w(w_res, w(65))
w_res = space.call_function(builtin_f, w_input, w(100))
self.assertEqual_w(w_res, w(142))
-
+
+ def test_varargs(self):
+ s = self.space
+ w = s.wrap
+ def f(w_first, *args_w):
+ w_r = w_first
+ for w_i in args_w:
+ w_r = s.add(w_r, w_i)
+ return w_r
+ builtin_f = extmodule.make_builtin_func(s, f)
+ self.assertEqual_w(s.call_function(builtin_f, w(1)), w(1))
+ self.assertEqual_w(s.call_function(builtin_f, w(1), w(2), w(3)), w(6))
+
+ def test_kwargs(self):
+ s = self.space
+ w = s.wrap
+ def f(**kws_w):
+ return s.add(kws_w['a'], kws_w['b'])
+ builtin_f = extmodule.make_builtin_func(s, f)
+ self.assertEqual_w(s.call_function(builtin_f, a=w(1), b=w(2)), w(3))
+
+ def test_varkwargs(self):
+ s = self.space
+ w = s.wrap
+ def f(*args_w, **kws_w):
+ return s.add(args_w[0], kws_w['a'])
+ builtin_f = extmodule.make_builtin_func(s, f)
+ self.assertEqual_w(s.call_function(builtin_f, w(2), a=w(1)), w(3))
if __name__ == '__main__':
testsupport.main()
More information about the Pypy-commit
mailing list