[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