[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