SuObject* copyCallStack() { static Value qqq = new SuString("???"); SuObject* calls = new SuObject; if (! tls().proc || ! tls().proc->fp) return calls; for (Frame* f = tls().proc->fp; f > tls().proc->frames; --f) { SuObject* call = new SuObject; SuObject* vars = new SuObject; if (f->fn) { call->put("fn", f->fn); int i = 0, n = 0; TRY(i = f->fn->source(f->ip - f->fn->code - 1, &n)); call->put("src_i", i); call->put("src_n", n); for (i = 0; i < f->fn->nlocals; ++i) if (f->local[i]) { Value value = qqq; TRY(value = f->local[i]); TRY(vars->put(symbol(f->fn->locals[i]), value)); } if (f->self) vars->put("this", f->self); } else if (f->prim) { TRY(call->put("fn", f->prim)); } call->put("locals", vars); calls->add(call); } return calls; }
void Func::args(short nargs, short nargnames, short* argnames, int each) { Value* args = GETSP() - nargs + 1; short unamed = nargs - nargnames - (each == -1 ? 0 : 1); short i, j; if (!rest && unamed > nparams) except("too many arguments to " << this); verify(!rest || nparams == 1); // rest must be only param verify(each == -1 || nargs == 1); // each must be only arg if (nparams > nargs) // expand stack (before filling it) SETSP(GETSP() + nparams - nargs); if (each != -1 && rest) { args[0] = args[0].object()->slice(each); } else if (rest) { // put args into object SuObject* ob = new SuObject(); // un-named for (i = 0; i < unamed; ++i) ob->add(args[i]); // named for (j = 0; i < nargs; ++i, ++j) ob->put(symbol(argnames[j]), args[i]); args[0] = ob; } else if (each != -1) { SuObject* ob = args[0].object(); if (ob->vecsize() > nparams + each) except("too many arguments to " << this << " vecsize " << ob->vecsize() << " each " << each << " nparams " << nparams); // un-named members for (i = 0; i < nparams; ++i) args[i] = ob->get(i + each); // named members verify(locals); for (i = 0; i < nparams; ++i) if (Value x = ob->get(symbol(locals[i]))) args[i] = x; } else if (nargnames > 0) { // shuffle named args to match params const int maxargnames = 100; Value tmp[maxargnames]; // move named args aside verify(nargnames < maxargnames); for (i = 0; i < nargnames; ++i) tmp[i] = args[unamed + i]; // initialized remaining params for (i = unamed; i < nparams; ++i) args[i] = Value(); // fill in params with named args verify(locals); for (i = 0; i < nparams; ++i) for (j = 0; j < nargnames; ++j) if (locals[i] == argnames[j]) args[i] = tmp[j]; } else { // initialized remaining params for (i = unamed; i < nparams; ++i) args[i] = Value(); } // fill in dynamic implicits if (flags) { for (i = 0; i < nparams; ++i) if (!args[i] && (flags[i] & DYN)) { int sn = ::symnum(CATSTRA("_", symstr(locals[i]))); args[i] = dynamic(sn); } } // fill in defaults if (ndefaults > 0) { verify(literals); for (j = nparams - ndefaults, i = 0; i < ndefaults; ++i, ++j) if (!args[j]) args[j] = literals[i]; } if (nargs > nparams) // shrink stack (after processing args) SETSP(GETSP() + nparams - nargs); // check that all parameters now have values verify(locals); for (i = 0; i < nparams; ++i) if (!args[i]) except("missing argument(s) to " << this); }