[pypy-commit] cffi cffi-1.0: Function types

arigo noreply at buildbot.pypy.org
Fri Apr 10 18:45:03 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1687:db54ee477ad5
Date: 2015-04-10 18:45 +0200
http://bitbucket.org/cffi/cffi/changeset/db54ee477ad5/

Log:	Function types

diff --git a/new/parse_c_type.c b/new/parse_c_type.c
--- a/new/parse_c_type.c
+++ b/new/parse_c_type.c
@@ -77,6 +77,22 @@
     return *p;
 }
 
+static int number_of_commas(token_t *tok)
+{
+    const char *p = tok->p;
+    int result = 0;
+    int nesting = 0;
+    while (1) {
+        switch (*p++) {
+        case ',': result++; break;
+        case '(': nesting++; break;
+        case ')': if ((--nesting) < 0) return result; break;
+        case 0:   return result;
+        default:  break;
+        }
+    }
+}
+
 static void next_token(token_t *tok)
 {
     const char *p = tok->p + tok->size;
@@ -237,43 +253,47 @@
             result = _CFFI_OP(_CFFI_GETOP(0), x);
         }
         else {
-            abort();
-#if 0
             /* function type */
-            ds = alloc_ds(tok, 2);
-            if (ds == NULL)
-                return;
-            ds[0] = TOK_OPEN_PAREN;
-            ds[1] = 0;
+            int arg_total, base_index, arg_next, has_ellipsis=0;
+
             if (tok->kind == TOK_VOID && get_following_char(tok) == ')') {
                 next_token(tok);
             }
+
+            /* (over-)estimate 'arg_total'.  May return 1 when it is really 0 */
+            arg_total = number_of_commas(tok) + 1;
+
+            *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index);
+            p_current = tok->output + tok->output_index;
+
+            base_index = write_ds(tok, _CFFI_OP(_CFFI_OP_FUNCTION, 0));
+            if (base_index < 0)
+                return -1;
+            /* reserve (arg_total + 1) slots for the arguments and the
+               final FUNCTION_END */
+            for (arg_next = 0; arg_next <= arg_total; arg_next++)
+                if (write_ds(tok, _CFFI_OP(0, 0)) < 0)
+                    return -1;
+
+            arg_next = base_index + 1;
+
             if (tok->kind != TOK_CLOSE_PAREN) {
                 while (1) {
                     if (tok->kind == TOK_DOTDOTDOT) {
-                        ds[0] = TOK_DOTDOTDOT;
+                        has_ellipsis = 1;
                         next_token(tok);
                         break;
                     }
-                    intptr_t *ds_type = alloc_ds(tok, 2);
-                    if (ds_type == NULL)
-                        return;
-                    assert(ds_type == ds + 2 + 2 * ds[1]);
-                    assert(2 * sizeof(intptr_t) >= sizeof(_crx_qual_type));
-                    parse_complete(tok, (_crx_qual_type *)ds_type);
-                    ds[1]++;
+                    int arg = parse_complete(tok);
+                    assert(arg_next - base_index <= arg_total);
+                    tok->output[arg_next++] = _CFFI_OP(_CFFI_OP_NOOP, arg);
                     if (tok->kind != TOK_COMMA)
                         break;
                     next_token(tok);
                 }
             }
-            intptr_t *ds_next = alloc_ds(tok, 1);
-            if (ds_next == NULL)
-                return;
-            assert(ds_next == ds + 2 + 2 * ds[1]);
-            *ds_next = *jump_slot;
-            *jump_slot = -(ds - tok->all_delay_slots);
-#endif
+            tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END,
+                                             has_ellipsis);
         }
 
         if (tok->kind != TOK_CLOSE_PAREN)
diff --git a/new/test_parse_c_type.py b/new/test_parse_c_type.py
--- a/new/test_parse_c_type.py
+++ b/new/test_parse_c_type.py
@@ -52,6 +52,8 @@
 Array = make_getter('ARRAY')
 OpenArray = make_getter('OPEN_ARRAY')
 NoOp = make_getter('NOOP')
+Func = make_getter('FUNCTION')
+FuncEnd = make_getter('FUNCTION_END')
 
 
 def test_simple():
@@ -101,3 +103,25 @@
                                     Pointer(0), Pointer(1),
                                     NoOp(6), Pointer(3), '->', Pointer(4),
                                     OpenArray(2)]
+
+def test_simple_function():
+    assert parse("int()") == [Prim(lib._CFFI_PRIM_INT),
+                              '->', Func(0), FuncEnd(0), 0]
+    assert parse("int(int)") == [Prim(lib._CFFI_PRIM_INT),
+                                 '->', Func(0), NoOp(4), FuncEnd(0),
+                                 Prim(lib._CFFI_PRIM_INT)]
+    assert parse("int(long, char)") == [
+                                 Prim(lib._CFFI_PRIM_INT),
+                                 '->', Func(0), NoOp(5), NoOp(6), FuncEnd(0),
+                                 Prim(lib._CFFI_PRIM_LONG),
+                                 Prim(lib._CFFI_PRIM_CHAR)]
+    assert parse("int(int*)") == [Prim(lib._CFFI_PRIM_INT),
+                                  '->', Func(0), NoOp(5), FuncEnd(0),
+                                  Prim(lib._CFFI_PRIM_INT),
+                                  Pointer(4)]
+    assert parse("int*(void)") == [Prim(lib._CFFI_PRIM_INT),
+                                   Pointer(0),
+                                   '->', Func(1), FuncEnd(0), 0]
+    assert parse("int(int, ...)") == [Prim(lib._CFFI_PRIM_INT),
+                                      '->', Func(0), NoOp(5), FuncEnd(1), 0,
+                                      Prim(lib._CFFI_PRIM_INT)]


More information about the pypy-commit mailing list