Author: leo
Date: Tue Jan 31 04:41:42 2006
New Revision: 11386
Modified:
trunk/src/inter_call.c
Log:
Named arguments - fix :optional [perl #38371]
* the :optional bit of named arguments was ignored, if the arg
was not passed, :opt_flag was undefined
* this is now fixed
* pass PMCNULL instead of NULL for missing optional PMCs
* turn on param count error checking for named
Modified: trunk/src/inter_call.c
==============================================================================
--- trunk/src/inter_call.c (original)
+++ trunk/src/inter_call.c Tue Jan 31 04:41:42 2006
@@ -777,26 +777,57 @@ too_many(Interp *interpreter, struct cal
}
static void
+null_val(int sig, struct call_state *st)
+{
+ switch (sig & PARROT_ARG_TYPE_MASK) {
+ case PARROT_ARG_INTVAL:
+ UVal_int(st->val) = 0; break;
+ case PARROT_ARG_FLOATVAL:
+ UVal_num(st->val) = 0.0; break;
+ case PARROT_ARG_STRING:
+ UVal_str(st->val) = NULL; break;
+ case PARROT_ARG_PMC:
+ UVal_pmc(st->val) = PMCNULL; break;
+ }
+}
+
+static void
check_named(Interp *interpreter, struct call_state *st, const char *action)
{
- int i, n_named, idx;
+ int i, n_named, idx, was_set, n_i;
INTVAL sig;
STRING *param;
n_named = -1;
- st->dest.mode &= ~CALL_STATE_SLURP;
- st->dest.mode |= CALL_STATE_x_NAMED;
+ was_set = n_i = 0;
for (i = st->first_named; i < st->dest.n; ++i) {
- sig = VTABLE_get_integer_keyed_int(interpreter,
+ st->dest.sig = sig = VTABLE_get_integer_keyed_int(interpreter,
st->dest.u.op.signature, i);
- if (!(sig & PARROT_ARG_NAME))
+ if ((sig & PARROT_ARG_NAME)) {
+ if (sig & PARROT_ARG_SLURPY_ARRAY)
+ break;
+ was_set = 0;
+ n_named++;
+ n_i = i;
+ if (st->named_done & (1 << n_named)) {
+ was_set = 1;
+ }
continue;
- if (sig & PARROT_ARG_SLURPY_ARRAY)
- break;
- n_named++;
- if (st->named_done & (1 << n_named))
+ }
+ if (was_set)
+ continue;
+ if (sig & PARROT_ARG_OPTIONAL) {
+ null_val(sig, st);
+ idx = st->dest.u.op.pc[i];
+ store_arg(st, idx);
+ continue;
+ }
+ if (sig & PARROT_ARG_OPT_FLAG) {
+ idx = st->dest.u.op.pc[i];
+ CTX_REG_INT(st->dest.ctx, idx) = 0;
continue;
- idx = st->dest.u.op.pc[i];
+ }
+ idx = st->dest.u.op.pc[n_i];
param = st->dest.ctx->constants[idx]->u.string;
real_exception(interpreter, NULL, E_ValueError,
"too few arguments passed - missing required named arg '%Ss'",
@@ -918,14 +949,13 @@ store_opt:
break;
case CALL_STATE_END_POS_OPT:
++st->optionals;
- UVal_num(st->val) = 0.0; /* XXX assumes all bits 0 */
+ null_val(st->dest.sig, st);
opt_flag = 0;
goto store_opt;
case CALL_STATE_END_NAMED_NAMED|CALL_STATE_OPT:
case CALL_STATE_END_NAMED_NAMED:
case CALL_STATE_END_POS_NAMED:
- if (err_check)
- check_named(interpreter, st, action);
+ check_named(interpreter, st, action);
return;
case CALL_STATE_END_x:
if (err_check)