[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