// expand @args void argseach(short& nargs, short& nargnames, short*& argnames, int& each) { if (each < 0) return; verify(nargs == 1); verify(nargnames == 0); SuObject* ob = POP().object(); int i = 0; nargs = 0; int vs = ob->vecsize(); argnames = new short[ob->mapsize()]; for (auto iter = ob->begin(); iter != ob->end(); ++iter, ++i) { if (i < each) continue; if (i >= vs) // named members argnames[nargnames++] = (*iter).first.symnum(); PUSH((*iter).second); ++nargs; } each = -1; }
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); }