new way to use vararg' parameters (with ...')
This commit is contained in:
60
lparser.c
60
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), "<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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user