[pypy-commit] creflect default: Stop trying to be clever and reject overloaded functions. Change

arigo noreply at buildbot.pypy.org
Thu Dec 18 23:38:27 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r201:83606604d6cd
Date: 2014-12-18 17:34 +0000
http://bitbucket.org/cffi/creflect/changeset/83606604d6cd/

Log:	Stop trying to be clever and reject overloaded functions. Change
	the tests to use one possible workaround instead.

diff --git a/creflect/codegen.py b/creflect/codegen.py
--- a/creflect/codegen.py
+++ b/creflect/codegen.py
@@ -65,7 +65,6 @@
     outerblock = CodeBlock(parent=None)
     outerblock.writeline('#include "creflect.h"')
     outerblock.crx_func_name = crx_func_name
-    outerblock.func_names_seen = set()
 
     funcblock = CodeBlock(outerblock)
 
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -348,7 +348,7 @@
     def shadow_global_var(self, top_level_block, fnname):
         if self.ellipsis:
             return fnname
-        shadowname = _unique_name(top_level_block, '%s__d%s_%s', fnname)
+        shadowname = _unique_name(top_level_block, '%s__d_%s', fnname)
         wrline = top_level_block.writeline
         args = [arg.get_c_name('a%d' % i) for i, arg in enumerate(self.args)]
         decl = '%s(%s)' % (shadowname, ', '.join(args) or 'void')
@@ -365,7 +365,7 @@
         # a special-case for global function declarations
         assert not self.ellipsis
         toplevel = block.crx_top_level
-        crx_func_name = _unique_name(toplevel, '%s__c%s_%s', fnname)
+        crx_func_name = _unique_name(toplevel, '%s__c_%s', fnname)
         wrline = toplevel.writeline
         wrline('static void %s(void *args[], void *result) {' % (
             crx_func_name,))
@@ -379,13 +379,7 @@
 
 
 def _unique_name(toplevel, pattern, fnname):
-    result = pattern % (toplevel.crx_func_name, '', fnname)
-    n = 0
-    while result in toplevel.func_names_seen:
-        n += 1
-        result = pattern % (toplevel.crx_func_name, n, fnname)
-    toplevel.func_names_seen.add(result)
-    return result
+    return pattern % (toplevel.crx_func_name, fnname)
 
 
 class PointerType(BaseType):
diff --git a/creflect/test/codegen/func-006.c b/creflect/test/codegen/func-006.c
--- a/creflect/test/codegen/func-006.c
+++ b/creflect/test/codegen/func-006.c
@@ -1,30 +1,32 @@
-/* Multiple declarations of a function with the same name:
-   a way to work around "..." in signatures */
+/* A manual way to work around "..." in signatures */
 
-int f(int);
-int f(int, long);
+int f_1(int);
+int f_2(int, long);
 
 # ____________________________________________________________
 # drop
 
+#define f_1  f
+#define f_2  f
+
 int f(int a, ...) { return 42 * a; }
 
 # ____________________________________________________________
 
-static void testfunc_006__c_f(void *args[], void *result) {
-    *(int *)result = f(*(int *)args[0]);
+static void testfunc_006__c_f_1(void *args[], void *result) {
+    *(int *)result = f_1(*(int *)args[0]);
 }
 
-static int testfunc_006__d_f(int a0) {
-    return f(a0);
+static int testfunc_006__d_f_1(int a0) {
+    return f_1(a0);
 }
 
-static void testfunc_006__c1_f(void *args[], void *result) {
-    *(int *)result = f(*(int *)args[0], *(long *)args[1]);
+static void testfunc_006__c_f_2(void *args[], void *result) {
+    *(int *)result = f_2(*(int *)args[0], *(long *)args[1]);
 }
 
-static int testfunc_006__d1_f(int a0, long a1) {
-    return f(a0, a1);
+static int testfunc_006__d_f_2(int a0, long a1) {
+    return f_2(a0, a1);
 }
 
 void testfunc_006(_crx_builder_t *cb)
@@ -36,8 +38,8 @@
         t1 = cb->get_signed_type(cb, sizeof(int), "int");
         a1[0].type = t1;
         a1[0].qualifiers = 0;
-        cb->define_func(cb, "f", t1, a1, 1, &testfunc_006__c_f, &testfunc_006__d_f);
-#expect FUNC f: int -> int
+        cb->define_func(cb, "f_1", t1, a1, 1, &testfunc_006__c_f_1, &testfunc_006__d_f_1);
+#expect FUNC f_1: int -> int
     }
     {
         t2 = cb->get_signed_type(cb, sizeof(long), "long");
@@ -45,7 +47,7 @@
         a2[0].qualifiers = 0;
         a2[1].type = t2;
         a2[1].qualifiers = 0;
-        cb->define_func(cb, "f", t1, a2, 2, &testfunc_006__c1_f, &testfunc_006__d1_f);
-#expect FUNC f: int -> long -> int
+        cb->define_func(cb, "f_2", t1, a2, 2, &testfunc_006__c_f_2, &testfunc_006__d_f_2);
+#expect FUNC f_2: int -> long -> int
     }
 }
diff --git a/zeffir/builder.c b/zeffir/builder.c
--- a/zeffir/builder.c
+++ b/zeffir/builder.c
@@ -828,10 +828,10 @@
 
     PyObject *l_dict = ((zeffir_builder_t *)cb)->l_dict;
     PyObject *l_libname_obj = ((zeffir_builder_t *)cb)->lib->l_libname_obj;
-    PyObject *x = PyDict_GetItemString(l_dict, name);
+    PyObject *x;
 
     assert(trampl != NULL);
-    x = make_builtin_func(l_libname_obj, name, ret, args, nargs, trampl, x);
+    x = make_builtin_func(l_libname_obj, name, ret, args, nargs, trampl);
     if (x == NULL)
         return;
 
diff --git a/zeffir/cfunc.c b/zeffir/cfunc.c
--- a/zeffir/cfunc.c
+++ b/zeffir/cfunc.c
@@ -1,5 +1,5 @@
 
-typedef struct ZefFuncSupportObject_s {
+typedef struct {
     PyObject_HEAD
 
     /* note that 'zfs_trampl' is either a '_crx_trampoline0_fn' or a
@@ -9,7 +9,6 @@
     int                 zfs_nargs;
     int                 zfs_dotdotdot;
     void               *zfs_trampl;
-    struct ZefFuncSupportObject_s *zfs_overloaded_next;
     PyMethodDef         zfs_md;
     size_t              zfs_size_args;
     CTypeDescrObject   *zfs_ret;
@@ -25,15 +24,6 @@
     for (i = zfs->zfs_nargs - 1; i >= 0; i--)
         Py_DECREF(zfs->zfs_args[i]);
     Py_DECREF(zfs->zfs_ret);
-
-    /* avoid long chain of recursive calls to zef_func_support_dealloc */
-    while (zfs->zfs_overloaded_next != NULL) {
-        ZefFuncSupportObject *zfs2 = zfs->zfs_overloaded_next;
-        zfs->zfs_overloaded_next = zfs2->zfs_overloaded_next;
-        zfs2->zfs_overloaded_next = NULL;
-        Py_DECREF(zfs2);
-    }
-
     PyObject_Del(zfs);
 }
 
@@ -134,27 +124,10 @@
         if (PyErr_Occurred())
             return NULL;
 
-        if (zfs->zfs_overloaded_next == NULL) {
-            PyErr_Format(PyExc_TypeError,
-                         "'%s' expected %d arguments, but got %zd",
-                         funcname, nargs, actualnargs);
-            return NULL;
-        }
-
-        /* XXX right now, pick the first overloaded function with the
-           correct number of arguments.  Later we'll need to pick the
-           right one based on the provided argument types. */
-        zfs = zfs->zfs_overloaded_next;
-        while (zfs->zfs_nargs != actualnargs) {
-            zfs = zfs->zfs_overloaded_next;
-            if (zfs == NULL) {
-                PyErr_Format(PyExc_TypeError,
-                             "'%s': no version with %zd arguments found",
-                             funcname, actualnargs);
-                return NULL;
-            }
-        }
-        nargs = zfs->zfs_nargs;
+        PyErr_Format(PyExc_TypeError,
+                     "'%s' expected %d arguments, but got %zd",
+                     funcname, nargs, actualnargs);
+        return NULL;
     }
 
     void *llargs[nargs];
@@ -283,7 +256,6 @@
 
     memset(&zfs->zfs_md, 0, sizeof(PyMethodDef));
     zfs->zfs_trampl = NULL;
-    zfs->zfs_overloaded_next = NULL;
     zfs->zfs_nargs = nargs;
     zfs->zfs_dotdotdot = dotdotdot;
     zfs->zfs_ret = ret;
@@ -316,8 +288,7 @@
 static PyObject *make_builtin_func(PyObject *libname_obj,
                                    const char *funcname, _crx_type_t *ret,
                                    _crx_qual_type args[], int nargs,
-                                   _crx_trampoline0_fn trampl,
-                                   PyObject *overloaded)
+                                   _crx_trampoline0_fn trampl)
 {
     char *p;
     ZefFuncSupportObject *zfs;
@@ -334,27 +305,11 @@
     zfs->zfs_md.ml_flags = METH_VARARGS;
     /*zfs->zfs_md.ml_doc = ... */
 
-    if (overloaded != NULL && PyCFunction_Check(overloaded) &&
-            PyCFunction_GET_FUNCTION(overloaded) == &zfs_call) {
-
-        /* attach 'zfs' to the end of the chain of zfs_overloaded_next */
-        PyObject *oself = PyCFunction_GET_SELF(overloaded);
-        ZefFuncSupportObject *zfs1 = (ZefFuncSupportObject *)oself;
-
-        while (zfs1->zfs_overloaded_next != NULL) {
-            zfs1 = zfs1->zfs_overloaded_next;
-        }
-        zfs1->zfs_overloaded_next = zfs;
-        Py_INCREF(overloaded);
-        return overloaded;
-    }
-    else {
-        /* make a new PyCFunction */
-        PyObject *res = PyCFunction_NewEx(&zfs->zfs_md, (PyObject *)zfs,
-                                          libname_obj);
-        Py_DECREF(zfs);
-        return res;
-    }
+    /* make a new PyCFunction */
+    PyObject *res = PyCFunction_NewEx(&zfs->zfs_md, (PyObject *)zfs,
+                                      libname_obj);
+    Py_DECREF(zfs);
+    return res;
 }
 
 static PyObject *cfunctype_getargs(CTypeDescrObject *ct)
diff --git a/zeffir/test/function.crx b/zeffir/test/function.crx
--- a/zeffir/test/function.crx
+++ b/zeffir/test/function.crx
@@ -36,6 +36,12 @@
     return result;
 }
 
+#define sum_ints_0  sum_ints
+#define sum_ints_1  sum_ints
+#define sum_ints_2  sum_ints
+#define sum_ints_3  sum_ints
+#define sum_ints_4  sum_ints
+
 
 // CREFLECT: start
 
@@ -43,10 +49,10 @@
 int add_from_array(int array[], int count);
 void returning_nothing(char *);
 void cant_call_dotdotdot(int x, ...);
-int sum_ints(int);
-int sum_ints(int, int);
-int sum_ints(int, int, int);
-int sum_ints(int, int, int, int);
-int sum_ints(int, int, int, int, int);
+int sum_ints_0(int);
+int sum_ints_1(int, int);
+int sum_ints_2(int, int, int);
+int sum_ints_3(int, int, int, int);
+int sum_ints_4(int, int, int, int, int);
 
 // CREFLECT: end
diff --git a/zeffir/test/test_function.py b/zeffir/test/test_function.py
--- a/zeffir/test/test_function.py
+++ b/zeffir/test/test_function.py
@@ -52,8 +52,19 @@
 
 def test_overloaded_function():
     ffi, lib = support.compile_and_open('function')
-    assert lib.sum_ints(0) == 0
-    assert lib.sum_ints(1, 10) == 10
-    assert lib.sum_ints(2, 20, 30) == 50
-    assert lib.sum_ints(3, 40, 50, 60) == 150
-    assert lib.sum_ints(4, 70, 80, 90, 100) == 340
+    assert lib.sum_ints_0(0) == 0
+    assert lib.sum_ints_1(1, 10) == 10
+    assert lib.sum_ints_2(2, 20, 30) == 50
+    assert lib.sum_ints_3(3, 40, 50, 60) == 150
+    assert lib.sum_ints_4(4, 70, 80, 90, 100) == 340
+    #
+    # or, this can be done in pure Python with some code like that:
+    _sum_ints = [lib.sum_ints_0, lib.sum_ints_1, lib.sum_ints_2,
+                lib.sum_ints_3, lib.sum_ints_4]
+    def sum_ints(*args):
+        return _sum_ints[len(args)](len(args), *args)
+    assert sum_ints() == 0
+    assert sum_ints(10) == 10
+    assert sum_ints(20, 30) == 50
+    assert sum_ints(40, 50, 60) == 150
+    assert sum_ints(70, 80, 90, 100) == 340


More information about the pypy-commit mailing list