Author: leo
Date: Wed Jan 18 08:45:45 2006
New Revision: 11244
Modified:
trunk/src/inter_call.c
trunk/t/op/calling.t
Log:
Calling conventions 6 - named, a first attempt
* first try of passing named, mainly to show how not to do it
* test
* don't try to fetch args, if there are none
Modified: trunk/src/inter_call.c
==============================================================================
--- trunk/src/inter_call.c (original)
+++ trunk/src/inter_call.c Wed Jan 18 08:45:45 2006
@@ -375,6 +375,8 @@ Parrot_fetch_arg(Interp *interpreter, st
if (st->dest.mode & CALL_STATE_NEXT_ARG) {
next_arg(interpreter, &st->dest);
}
+ if (!st->src.n)
+ return 0;
if (st->src.mode & CALL_STATE_NEXT_ARG) {
if (!next_arg(interpreter, &st->src))
return 0;
@@ -393,6 +395,11 @@ Parrot_fetch_arg(Interp *interpreter, st
/* advance src - get next arg */
return Parrot_fetch_arg(interpreter, st);
}
+ if (st->src.sig & PARROT_ARG_NAME) {
+ fetch_arg(interpreter, st);
+ st->name = UVal_str(st->val);
+ next_arg(interpreter, &st->src);
+ }
return fetch_arg(interpreter, st);
}
@@ -540,10 +547,58 @@ clone_key_arg(Interp *interpreter, struc
}
}
+static int
+locate_name(Interp *interpreter, struct call_state *st)
+{
+ int i, start, idx;
+ INTVAL sig;
+ STRING *param;
+
+ if (st->dest.mode & CALL_STATE_SIG)
+ real_exception(interpreter, NULL, E_ValueError,
+ "Can't call C function with named arguments");
+ if (st->first_named >= 0)
+ start = st->first_named;
+ else
+ start = 0;
+ for (i = start; i < st->dest.n; ++i) {
+ sig = VTABLE_get_integer_keyed_int(interpreter,
+ st->dest.u.op.signature, i);
+ if (!(sig & PARROT_ARG_NAME))
+ continue;
+ if (st->first_named < 0)
+ st->first_named = i;
+ idx = st->dest.u.op.pc[i];
+ param = st->dest.ctx->constants[idx]->u.string;
+ if (st->name == param ||
+ 0 == string_equal(interpreter, st->name, param)) {
+ st->dest.sig = VTABLE_get_integer_keyed_int(interpreter,
+ st->dest.u.op.signature, i + 1);
+ st->dest.i = i + 1;
+ idx = st->dest.u.op.pc[i + 1];
+ return idx;
+ }
+ }
+ real_exception(interpreter, NULL, E_ValueError,
+ "Named param '%Ss' not found", st->name);
+ return 0;
+}
+
int
Parrot_convert_arg(Interp *interpreter, struct call_state *st)
{
again:
+ if (st->src.i >= st->src.n && (st->dest.mode & CALL_STATE_NAMED)) {
+ st->dest.i = st->dest.n; /* XXX that's plain wrong */
+ return 0;
+ }
+ if (st->dest.sig & PARROT_ARG_NAME) {
+ st->dest.mode |= CALL_STATE_NAMED;
+ locate_name(interpreter, st);
+ }
+ else if (st->dest.mode & CALL_STATE_NAMED)
+ locate_name(interpreter, st);
+
if (st->dest.sig & PARROT_ARG_OPTIONAL) {
if (st->src.i < st->src.n) {
++st->opt_so_far;
@@ -634,7 +689,8 @@ Parrot_store_arg(Interp *interpreter, st
CTX_REG_PMC(st->dest.ctx, idx) = UVal_pmc(st->val);
break;
}
- st->dest.mode |= CALL_STATE_NEXT_ARG;
+ if (!(st->dest.mode & CALL_STATE_NAMED))
+ st->dest.mode |= CALL_STATE_NEXT_ARG;
return 1;
}
@@ -646,6 +702,7 @@ init_call_stats(struct call_state *st)
st->optionals = 0;
st->params = 0;
st->name = NULL;
+ st->first_named = -1;
}
/*
Modified: trunk/t/op/calling.t
==============================================================================
--- trunk/t/op/calling.t (original)
+++ trunk/t/op/calling.t Wed Jan 18 08:45:45 2006
@@ -1625,7 +1625,25 @@ CODE
17
OUTPUT
+output_is(<<'CODE', <<'OUTPUT', "named - 1");
+.pcc_sub main:
+ set_args "(0x80, 0, 0x80, 0)", "b", 10, "a", 20
+ get_results "()"
+ find_name P1, "foo"
+ invokecc P1
+ print "ok\n"
+ end
+.pcc_sub foo:
+ get_params "(0x80, 0, 0x80, 0)", "a", I0, "b", I1
+ print_item I1
+ print_item I0
+ print_newline
+ returncc
+CODE
+10 20
+ok
+OUTPUT
## remember to change the number of tests :-)
-BEGIN { plan tests => 60; }
+BEGIN { plan tests => 61; }