new way to use vararg' parameters (with ...')

This commit is contained in:
Roberto Ierusalimschy
2004-05-31 15:51:50 -03:00
parent 47eda6ebd8
commit 616438fe9a
13 changed files with 192 additions and 106 deletions

View File

@@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 2.3 2004/03/26 14:02:41 roberto Exp roberto $
** $Id: lparser.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -27,6 +27,8 @@
#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m)
@@ -272,11 +274,11 @@ static TString *singlevar (LexState *ls, expdesc *var, int base) {
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
FuncState *fs = ls->fs;
int extra = nvars - nexps;
if (e->k == VCALL) {
if (hasmultret(e->k)) {
extra++; /* includes call itself */
if (extra <= 0) extra = 0;
else luaK_reserveregs(fs, extra-1);
luaK_setcallreturns(fs, e, extra); /* call provides the difference */
if (extra < 0) extra = 0;
luaK_setreturns(fs, e, extra); /* last exp. provides the difference */
if (extra > 1) luaK_reserveregs(fs, extra-1);
}
else {
if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */
@@ -392,6 +394,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
lexstate.nestlevel = 0;
luaX_setinput(L, &lexstate, z, luaS_new(L, name));
open_func(&lexstate, &funcstate);
funcstate.f->is_vararg = NEWSTYLEVARARG;
next(&lexstate); /* read first token */
chunk(&lexstate);
check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
@@ -481,8 +484,8 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) {
static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
if (cc->tostore == 0) return;
if (cc->v.k == VCALL) {
luaK_setcallreturns(fs, &cc->v, LUA_MULTRET);
if (hasmultret(cc->v.k)) {
luaK_setmultret(fs, &cc->v);
luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1);
cc->na--; /* do not count last expression (unknown number of elements) */
}
@@ -558,12 +561,8 @@ static void parlist (LexState *ls) {
if (ls->t.token != ')') { /* is `parlist' not empty? */
do {
switch (ls->t.token) {
case TK_NAME: { /* param -> NAME [ `=' `...' ] */
case TK_NAME: { /* param -> NAME */
new_localvar(ls, str_checkname(ls), nparams++);
if (testnext(ls, '=')) {
check(ls, TK_DOTS);
f->is_vararg = 1;
}
break;
}
case TK_DOTS: { /* param -> `...' */
@@ -629,7 +628,7 @@ static void funcargs (LexState *ls, expdesc *f) {
args.k = VVOID;
else {
explist1(ls, &args);
luaK_setcallreturns(fs, &args, LUA_MULTRET);
luaK_setmultret(fs, &args);
}
check_match(ls, ')', '(', line);
break;
@@ -650,7 +649,7 @@ static void funcargs (LexState *ls, expdesc *f) {
}
lua_assert(f->k == VNONRELOC);
base = f->info; /* base register for call */
if (args.k == VCALL)
if (hasmultret(args.k))
nparams = LUA_MULTRET; /* open call */
else {
if (args.k != VVOID)
@@ -739,43 +738,47 @@ static void simpleexp (LexState *ls, expdesc *v) {
switch (ls->t.token) {
case TK_NUMBER: {
init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r));
next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_STRING: {
codestring(ls, v, ls->t.seminfo.ts);
next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_NIL: {
init_exp(v, VNIL, 0);
next(ls);
break;
}
case TK_TRUE: {
init_exp(v, VTRUE, 0);
next(ls);
break;
}
case TK_FALSE: {
init_exp(v, VFALSE, 0);
next(ls);
break;
}
case TK_DOTS: { /* vararg */
FuncState *fs = ls->fs;
check_condition(ls, fs->f->is_vararg,
"cannot use `...' outside a vararg function");
fs->f->is_vararg = NEWSTYLEVARARG;
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
break;
}
case '{': { /* constructor */
constructor(ls, v);
break;
return;
}
case TK_FUNCTION: {
next(ls);
body(ls, v, 0, ls->linenumber);
break;
return;
}
default: {
primaryexp(ls, v);
break;
return;
}
}
next(ls);
}
@@ -952,7 +955,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
ls->fs->freereg -= nexps - nvars; /* remove extra values */
}
else {
luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */
luaK_setoneret(ls->fs, &e); /* close last expression */
luaK_storevar(ls->fs, &lh->v, &e);
return; /* avoid default */
}
@@ -1236,9 +1239,8 @@ static void exprstat (LexState *ls) {
FuncState *fs = ls->fs;
struct LHS_assign v;
primaryexp(ls, &v.v);
if (v.v.k == VCALL) { /* stat -> func */
luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */
}
if (v.v.k == VCALL) /* stat -> func */
SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
else { /* stat -> assignment */
v.prev = NULL;
assignment(ls, &v, 1);
@@ -1256,9 +1258,9 @@ static void retstat (LexState *ls) {
first = nret = 0; /* return no values */
else {
nret = explist1(ls, &e); /* optional return values */
if (e.k == VCALL) {
luaK_setcallreturns(fs, &e, LUA_MULTRET);
if (nret == 1) { /* tail call? */
if (hasmultret(e.k)) {
luaK_setmultret(fs, &e);
if (e.k == VCALL && nret == 1) { /* tail call? */
SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
}