[pypy-svn] r7884 - in pypy/trunk/src/pypy/translator: . test

arigo at codespeak.net arigo at codespeak.net
Thu Dec 16 15:20:45 CET 2004


Author: arigo
Date: Thu Dec 16 15:20:45 2004
New Revision: 7884

Modified:
   pypy/trunk/src/pypy/translator/genc.h
   pypy/trunk/src/pypy/translator/genc.py
   pypy/trunk/src/pypy/translator/test/test_ctrans.py
Log:
- supports keyword arguments in the functions created by genc.py.
- some clean-up of a workaround for a C preprocessor limitation.



Modified: pypy/trunk/src/pypy/translator/genc.h
==============================================================================
--- pypy/trunk/src/pypy/translator/genc.h	(original)
+++ pypy/trunk/src/pypy/translator/genc.h	Thu Dec 16 15:20:45 2004
@@ -199,6 +199,11 @@
 
 #if defined(USE_CALL_TRACE)
 
+#define TRACE_CALL       __f, __tstate,
+#define TRACE_ARGS       PyFrameObject *__f, PyThreadState *__tstate,
+#define TRACE_CALL_VOID  __f, __tstate
+#define TRACE_ARGS_VOID  PyFrameObject *__f, PyThreadState *__tstate
+
 #define FAIL(err) { __f->f_lineno = __f->f_code->co_firstlineno = __LINE__; goto err; }
 
 #define FUNCTION_HEAD(signature, self, args, names, file, line) \
@@ -215,6 +220,11 @@
 
 #else /* !defined(USE_CALL_TRACE) */
 
+#define TRACE_CALL       /* nothing */
+#define TRACE_ARGS       /* nothing */
+#define TRACE_CALL_VOID  /* nothing */
+#define TRACE_ARGS_VOID  void
+
 #define FAIL(err) { goto err; }
 
 #define FUNCTION_HEAD(signature, self, args, names, file, line)

Modified: pypy/trunk/src/pypy/translator/genc.py
==============================================================================
--- pypy/trunk/src/pypy/translator/genc.py	(original)
+++ pypy/trunk/src/pypy/translator/genc.py	Thu Dec 16 15:20:45 2004
@@ -38,8 +38,6 @@
 
 class GenC:
     MODNAMES = {}
-    # XXX - I don't know how to make a macro do this.. so..
-    USE_CALL_TRACE = True
 
     def __init__(self, f, translator, modname=None, f2=None, f2name=None):
         self.f = f
@@ -454,8 +452,6 @@
             'entrypoint': self.nameof(self.translator.functions[0]),
             }
         # header
-        if self.USE_CALL_TRACE:
-            print >> f, '#define USE_CALL_TRACE'
         print >> f, self.C_HEADER
 
         # function implementations
@@ -510,9 +506,9 @@
         self.gen_global_declarations()
 
         # print header
-        name = self.nameof(func)
-        assert name.startswith('gfunc_')
-        f_name = 'f_' + name[6:]
+        cname = self.nameof(func)
+        assert cname.startswith('gfunc_')
+        f_name = 'f_' + cname[6:]
 
         # collect all the local variables
         graph = self.translator.getflowgraph(func)
@@ -540,22 +536,31 @@
         fast_set = dict(zip(fast_args, fast_args))
 
         declare_fast_args = [('PyObject *' + a) for a in fast_args]
-        if self.USE_CALL_TRACE:
-            declare_fast_args[:0] = ['PyFrameObject *__f', 'PyThreadState *__tstate']
+        if declare_fast_args:
+            declare_fast_args = 'TRACE_ARGS ' + ', '.join(declare_fast_args)
+        else:
+            declare_fast_args = 'TRACE_ARGS_VOID'
+        fast_function_header = ('static PyObject *\n'
+                                '%s(%s)' % (fast_name, declare_fast_args))
 
-        print >> f, 'static PyObject *'
-        print >> f, '%s(%s);' % (fast_name, ', '.join(declare_fast_args))
+        print >> f, fast_function_header + ';'  # forward
         print >> f
 
         print >> f, 'static PyObject *'
-        print >> f, '%s(PyObject* self, PyObject* args)' % (f_name,)
+        print >> f, '%s(PyObject* self, PyObject* args, PyObject* kwds)' % (
+            f_name,)
         print >> f, '{'
         print >> f, '\tFUNCTION_HEAD(%s, %s, args, %s, __FILE__, __LINE__ - 2)' % (
-            c_string('%s(%s)' % (name, ', '.join(name_of_defaults))),
-            name,
+            c_string('%s(%s)' % (cname, ', '.join(name_of_defaults))),
+            cname,
             '(%s)' % (', '.join(map(c_string, name_of_defaults) + ['NULL']),),
         )
 
+        kwlist = ['"%s"' % name for name in
+                      func.func_code.co_varnames[:func.func_code.co_argcount]]
+        kwlist.append('0')
+        print >> f, '\tstatic char* kwlist[] = {%s};' % (', '.join(kwlist),)
+
         if fast_args:
             print >> f, '\tPyObject *%s;' % (', *'.join(fast_args))
         print >> f
@@ -586,24 +591,27 @@
             print >> f, '\t%s = %s;' % (
                 positional_args[min_number_of_args+i],
                 name_of_defaults[i])
-        lst = ['args',
-               '"%s"' % func.__name__,
-               '%d' % min_number_of_args,
-               '%d' % len(positional_args),
+        fmt = 'O'*min_number_of_args
+        if min_number_of_args < len(positional_args):
+            fmt += '|' + 'O'*(len(positional_args)-min_number_of_args)
+        lst = ['args', 'kwds',
+               '"%s:%s"' % (fmt, func.__name__),
+               'kwlist',
                ]
         lst += ['&' + a.name for a in positional_args]
-        print >> f, '\tif (!PyArg_UnpackTuple(%s))' % ', '.join(lst),
+        print >> f, '\tif (!PyArg_ParseTupleAndKeywords(%s))' % ', '.join(lst),
         print >> f, tail
 
         call_fast_args = list(fast_args)
-        if self.USE_CALL_TRACE:
-            call_fast_args[:0] = ['__f', '__tstate']
-        print >> f, '\treturn %s(%s);' % (fast_name, ', '.join(call_fast_args))
+        if call_fast_args:
+            call_fast_args = 'TRACE_CALL ' + ', '.join(call_fast_args)
+        else:
+            call_fast_args = 'TRACE_CALL_VOID'
+        print >> f, '\treturn %s(%s);' % (fast_name, call_fast_args)
         print >> f, '}'
         print >> f
 
-        print >> f, 'static PyObject *'
-        print >> f, '%s(%s)' % (fast_name, ', '.join(declare_fast_args))
+        print >> f, fast_function_header
         print >> f, '{'
 
         fast_locals = [arg for arg in localnames if arg not in fast_set]
@@ -630,8 +638,9 @@
         print >> f, '}'
 
         # print the PyMethodDef
-        print >> f, 'static PyMethodDef ml_%s = { "%s", %s, METH_VARARGS };' % (
-            name, func.__name__, f_name)
+        print >> f, ('static PyMethodDef ml_%s = {\n'
+            '    "%s", (PyCFunction)%s, METH_VARARGS|METH_KEYWORDS };' % (
+            cname, func.__name__, f_name))
         print >> f
 
         if not self.translator.frozen:

Modified: pypy/trunk/src/pypy/translator/test/test_ctrans.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/test_ctrans.py	(original)
+++ pypy/trunk/src/pypy/translator/test/test_ctrans.py	Thu Dec 16 15:20:45 2004
@@ -152,7 +152,7 @@
         self.assertRaises(TypeError, call_with_star, [4,7,12,63])
         self.assertRaises(TypeError, call_with_star, 521)
 
-    def XXX_test_call_with_keyword(self):
+    def test_call_with_keyword(self):
         call_with_keyword = self.build_cfunc(snippet.call_with_keyword)
         self.assertEquals(call_with_keyword(100), 82)
 



More information about the Pypy-commit mailing list