From 616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 31 May 2004 15:51:50 -0300 Subject: new way to use `vararg' parameters (with `...') --- lparser.c | 60 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index d9f6cbd4..06fd8951 100644 --- a/lparser.c +++ b/lparser.c @@ -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), " 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); } -- cgit v1.2.3-55-g6feb