summaryrefslogtreecommitdiff
path: root/src/lparser.c
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2010-01-08 12:00:00 +0000
committerrepogen <>2010-01-08 12:00:00 +0000
commit22912c77c80f8de8f7accd3319c726f7c5349fd3 (patch)
treecaf064ecca31cd2ef1c919c585ee6b3d5e6d25d6 /src/lparser.c
parent300cd56eb905be061aa75bb665549b3b85109bbe (diff)
downloadlua-github-5.2.0-work1.tar.gz
Lua 5.2.0-work15.2.0-work1
Diffstat (limited to 'src/lparser.c')
-rw-r--r--src/lparser.c371
1 files changed, 223 insertions, 148 deletions
diff --git a/src/lparser.c b/src/lparser.c
index 1e2a9a88..cc21f67f 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
+** $Id: lparser.c,v 2.75 2010/01/06 11:48:02 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -27,11 +27,13 @@
-#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
+/* maximum number of local variables per function (must be smaller
+ than 250, due to the bytecode format) */
+#define MAXVARS 200
+
-#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
-#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
/*
@@ -55,6 +57,8 @@ static void expr (LexState *ls, expdesc *v);
static void anchor_token (LexState *ls) {
+ /* last token from outer function must be EOS */
+ lua_assert(ls->fs != NULL || ls->t.token == TK_EOS);
if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
TString *ts = ls->t.seminfo.ts;
luaX_newstring(ls, getstr(ts), ts->tsv.len);
@@ -64,16 +68,23 @@ static void anchor_token (LexState *ls) {
static void error_expected (LexState *ls, int token) {
luaX_syntaxerror(ls,
- luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token)));
+ luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token)));
}
static void errorlimit (FuncState *fs, int limit, const char *what) {
- const char *msg = (fs->f->linedefined == 0) ?
- luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
- luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
- fs->f->linedefined, limit, what);
- luaX_lexerror(fs->ls, msg, 0);
+ const char *msg;
+ const char *where = (fs->f->linedefined == 0) ?
+ "main function" :
+ luaO_pushfstring(fs->L, "function at line %d", fs->f->linedefined);
+ msg = luaO_pushfstring(fs->L, "too many %s (limit is %d) in %s",
+ what, limit, where);
+ luaX_syntaxerror(fs->ls, msg);
+}
+
+
+static void checklimit (FuncState *fs, int v, int l, const char *what) {
+ if (v > l) errorlimit(fs, l, what);
}
@@ -107,7 +118,7 @@ static void check_match (LexState *ls, int what, int who, int where) {
error_expected(ls, what);
else {
luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
- LUA_QS " expected (to close " LUA_QS " at line %d)",
+ "%s expected (to close %s at line %d)",
luaX_token2str(ls, what), luaX_token2str(ls, who), where));
}
}
@@ -135,7 +146,7 @@ static void codestring (LexState *ls, expdesc *e, TString *s) {
}
-static void checkname(LexState *ls, expdesc *e) {
+static void checkname (LexState *ls, expdesc *e) {
codestring(ls, e, str_checkname(ls));
}
@@ -145,7 +156,7 @@ static int registerlocalvar (LexState *ls, TString *varname) {
Proto *f = fs->f;
int oldsize = f->sizelocvars;
luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
- LocVar, SHRT_MAX, "too many local variables");
+ LocVar, SHRT_MAX, "local variables");
while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
f->locvars[fs->nlocvars].varname = varname;
luaC_objbarrier(ls->L, f, varname);
@@ -153,14 +164,30 @@ static int registerlocalvar (LexState *ls, TString *varname) {
}
-#define new_localvarliteral(ls,v,n) \
- new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
+static void new_localvar (LexState *ls, TString *name) {
+ FuncState *fs = ls->fs;
+ Varlist *vl = ls->varl;
+ int reg = registerlocalvar(ls, name);
+ checklimit(fs, vl->nactvar + 1 - fs->firstlocal,
+ MAXVARS, "local variables");
+ luaM_growvector(ls->L, vl->actvar, vl->nactvar + 1,
+ vl->actvarsize, vardesc, MAX_INT, "local variables");
+ vl->actvar[vl->nactvar++].idx = cast(unsigned short, reg);
+}
+
+
+static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) {
+ new_localvar(ls, luaX_newstring(ls, name, sz));
+}
+#define new_localvarliteral(ls,v) \
+ new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1)
-static void new_localvar (LexState *ls, TString *name, int n) {
- FuncState *fs = ls->fs;
- luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
- fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
+
+static LocVar *getlocvar (FuncState *fs, int i) {
+ int idx = fs->ls->varl->actvar[fs->firstlocal + i].idx;
+ lua_assert(idx < fs->nlocvars);
+ return &fs->f->locvars[idx];
}
@@ -168,15 +195,15 @@ static void adjustlocalvars (LexState *ls, int nvars) {
FuncState *fs = ls->fs;
fs->nactvar = cast_byte(fs->nactvar + nvars);
for (; nvars; nvars--) {
- getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
+ getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc;
}
}
-static void removevars (LexState *ls, int tolevel) {
- FuncState *fs = ls->fs;
+static void removevars (FuncState *fs, int tolevel) {
+ fs->ls->varl->nactvar -= (fs->nactvar - tolevel);
while (fs->nactvar > tolevel)
- getlocvar(fs, --fs->nactvar).endpc = fs->pc;
+ getlocvar(fs, --fs->nactvar)->endpc = fs->pc;
}
@@ -184,30 +211,31 @@ static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
int i;
Proto *f = fs->f;
int oldsize = f->sizeupvalues;
- for (i=0; i<f->nups; i++) {
- if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
- lua_assert(f->upvalues[i] == name);
+ int instk = (v->k == VLOCAL);
+ lua_assert(instk || v->k == VUPVAL);
+ for (i=0; i<fs->nups; i++) {
+ if (f->upvalues[i].instack == instk && f->upvalues[i].idx == v->u.s.info) {
+ lua_assert(f->upvalues[i].name == name);
return i;
}
}
/* new one */
- luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues");
- luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
- TString *, MAX_INT, "");
- while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
- f->upvalues[f->nups] = name;
+ checklimit(fs, fs->nups + 1, UCHAR_MAX, "upvalues");
+ luaM_growvector(fs->L, f->upvalues, fs->nups, f->sizeupvalues,
+ Upvaldesc, UCHAR_MAX, "upvalues");
+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL;
+ f->upvalues[fs->nups].name = name;
luaC_objbarrier(fs->L, f, name);
- lua_assert(v->k == VLOCAL || v->k == VUPVAL);
- fs->upvalues[f->nups].k = cast_byte(v->k);
- fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
- return f->nups++;
+ f->upvalues[fs->nups].instack = cast_byte(instk);
+ f->upvalues[fs->nups].idx = cast_byte(v->u.s.info);
+ return fs->nups++;
}
static int searchvar (FuncState *fs, TString *n) {
int i;
for (i=fs->nactvar-1; i >= 0; i--) {
- if (n == getlocvar(fs, i).varname)
+ if (n == getlocvar(fs, i)->varname)
return i;
}
return -1; /* not found */
@@ -222,10 +250,8 @@ static void markupval (FuncState *fs, int level) {
static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
- if (fs == NULL) { /* no more levels? */
- init_exp(var, VGLOBAL, NO_REG); /* default is global variable */
- return VGLOBAL;
- }
+ if (fs == NULL) /* no more levels? */
+ return VGLOBAL; /* default is global variable */
else {
int v = searchvar(fs, n); /* look up at current level */
if (v >= 0) {
@@ -248,8 +274,16 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
static void singlevar (LexState *ls, expdesc *var) {
TString *varname = str_checkname(ls);
FuncState *fs = ls->fs;
- if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
- var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL) {
+ if (fs->envreg == NO_REG) /* regular global? */
+ init_exp(var, VGLOBAL, luaK_stringK(fs, varname));
+ else { /* "globals" are in current lexical environment */
+ expdesc key;
+ init_exp(var, VLOCAL, fs->envreg); /* current environment */
+ codestring(ls, &key, varname); /* key is variable name */
+ luaK_indexed(fs, var, &key); /* env[varname] */
+ }
+ }
}
@@ -274,12 +308,13 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
static void enterlevel (LexState *ls) {
- if (++ls->L->nCcalls > LUAI_MAXCCALLS)
- luaX_lexerror(ls, "chunk has too many syntax levels", 0);
+ global_State *g = G(ls->L);
+ ++g->nCcalls;
+ checklimit(ls->fs, g->nCcalls, LUAI_MAXCCALLS, "syntax levels");
}
-#define leavelevel(ls) ((ls)->L->nCcalls--)
+#define leavelevel(ls) (G((ls)->L)->nCcalls--)
static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
@@ -296,7 +331,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
static void leaveblock (FuncState *fs) {
BlockCnt *bl = fs->bl;
fs->bl = bl->previous;
- removevars(fs->ls, bl->nactvar);
+ removevars(fs, bl->nactvar);
if (bl->upval)
luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
/* a block either controls scope or breaks (never both) */
@@ -307,49 +342,51 @@ static void leaveblock (FuncState *fs) {
}
-static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
- FuncState *fs = ls->fs;
- Proto *f = fs->f;
+static void pushclosure (LexState *ls, Proto *clp, expdesc *v) {
+ FuncState *fs = ls->fs->prev;
+ Proto *f = fs->f; /* prototype of function creating new closure */
int oldsize = f->sizep;
- int i;
luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
- MAXARG_Bx, "constant table overflow");
+ MAXARG_Bx, "functions");
while (oldsize < f->sizep) f->p[oldsize++] = NULL;
- f->p[fs->np++] = func->f;
- luaC_objbarrier(ls->L, f, func->f);
+ f->p[fs->np++] = clp;
+ /* initial environment for new function is current lexical environment */
+ clp->envreg = fs->envreg;
+ luaC_objbarrier(ls->L, f, clp);
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
- for (i=0; i<func->f->nups; i++) {
- OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
- luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
- }
}
static void open_func (LexState *ls, FuncState *fs) {
lua_State *L = ls->L;
- Proto *f = luaF_newproto(L);
- fs->f = f;
+ Proto *f;
fs->prev = ls->fs; /* linked list of funcstates */
fs->ls = ls;
fs->L = L;
ls->fs = fs;
fs->pc = 0;
- fs->lasttarget = -1;
+ fs->lasttarget = 0;
fs->jpc = NO_JUMP;
fs->freereg = 0;
fs->nk = 0;
fs->np = 0;
+ fs->nups = 0;
fs->nlocvars = 0;
fs->nactvar = 0;
+ fs->firstlocal = ls->varl->nactvar;
+ fs->envreg = NO_REG;
fs->bl = NULL;
+ f = luaF_newproto(L);
+ fs->f = f;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
- fs->h = luaH_new(L, 0, 0);
- /* anchor table of constants and prototype (to avoid being collected) */
- sethvalue2s(L, L->top, fs->h);
- incr_top(L);
+ /* anchor prototype (to avoid being collected) */
setptvalue2s(L, L->top, f);
incr_top(L);
+ fs->h = luaH_new(L);
+ /* anchor table of constants (to avoid being collected) */
+ sethvalue2s(L, L->top, fs->h);
+ incr_top(L);
}
@@ -357,7 +394,7 @@ static void close_func (LexState *ls) {
lua_State *L = ls->L;
FuncState *fs = ls->fs;
Proto *f = fs->f;
- removevars(ls, 0);
+ removevars(fs, 0);
luaK_ret(fs, 0, 0); /* final return */
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
f->sizecode = fs->pc;
@@ -369,30 +406,37 @@ static void close_func (LexState *ls) {
f->sizep = fs->np;
luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
f->sizelocvars = fs->nlocvars;
- luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
- f->sizeupvalues = f->nups;
- lua_assert(luaG_checkcode(f));
+ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
+ f->sizeupvalues = fs->nups;
lua_assert(fs->bl == NULL);
ls->fs = fs->prev;
- L->top -= 2; /* remove table and prototype from the stack */
- /* last token read was anchored in defunct function; must reanchor it */
- if (fs) anchor_token(ls);
+ /* last token read was anchored in defunct function; must re-anchor it */
+ anchor_token(ls);
+ L->top--; /* pop table of constants */
+ luaC_checkGC(L);
+ L->top--; /* pop prototype (after possible collection) */
}
-Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Varlist *varl,
+ const char *name) {
struct LexState lexstate;
struct FuncState funcstate;
+ TString *tname = luaS_new(L, name);
+ setsvalue2s(L, L->top, tname); /* push name to protect it */
+ incr_top(L);
lexstate.buff = buff;
- luaX_setinput(L, &lexstate, z, luaS_new(L, name));
+ lexstate.varl = varl;
+ luaX_setinput(L, &lexstate, z, tname);
open_func(&lexstate, &funcstate);
- funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */
+ funcstate.f->is_vararg = 1; /* main function is always vararg */
luaX_next(&lexstate); /* read first token */
chunk(&lexstate);
check(&lexstate, TK_EOS);
close_func(&lexstate);
+ L->top--; /* pop name */
lua_assert(funcstate.prev == NULL);
- lua_assert(funcstate.f->nups == 0);
+ lua_assert(funcstate.nups == 0);
lua_assert(lexstate.fs == NULL);
return funcstate.f;
}
@@ -404,8 +448,8 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
/*============================================================*/
-static void field (LexState *ls, expdesc *v) {
- /* field -> ['.' | ':'] NAME */
+static void fieldsel (LexState *ls, expdesc *v) {
+ /* fieldsel -> ['.' | ':'] NAME */
FuncState *fs = ls->fs;
expdesc key;
luaK_exp2anyreg(fs, v);
@@ -447,7 +491,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
expdesc key, val;
int rkkey;
if (ls->t.token == TK_NAME) {
- luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
+ checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
checkname(ls, &key);
}
else /* ls->t.token == '[' */
@@ -488,15 +532,39 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
static void listfield (LexState *ls, struct ConsControl *cc) {
+ /* listfield -> exp */
expr(ls, &cc->v);
- luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
+ checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
cc->na++;
cc->tostore++;
}
+static void field (LexState *ls, struct ConsControl *cc) {
+ /* field -> listfield | recfield */
+ switch(ls->t.token) {
+ case TK_NAME: { /* may be 'listfield' or 'recfield' */
+ if (luaX_lookahead(ls) != '=') /* expression? */
+ listfield(ls, cc);
+ else
+ recfield(ls, cc);
+ break;
+ }
+ case '[': {
+ recfield(ls, cc);
+ break;
+ }
+ default: {
+ listfield(ls, cc);
+ break;
+ }
+ }
+}
+
+
static void constructor (LexState *ls, expdesc *t) {
- /* constructor -> ?? */
+ /* constructor -> '{' [ field { sep field } [sep] ] '}'
+ sep -> ',' | ';' */
FuncState *fs = ls->fs;
int line = ls->linenumber;
int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
@@ -511,24 +579,7 @@ static void constructor (LexState *ls, expdesc *t) {
lua_assert(cc.v.k == VVOID || cc.tostore > 0);
if (ls->t.token == '}') break;
closelistfield(fs, &cc);
- switch(ls->t.token) {
- case TK_NAME: { /* may be listfields or recfields */
- luaX_lookahead(ls);
- if (ls->lookahead.token != '=') /* expression? */
- listfield(ls, &cc);
- else
- recfield(ls, &cc);
- break;
- }
- case '[': { /* constructor_item -> recfield */
- recfield(ls, &cc);
- break;
- }
- default: { /* constructor_part -> listfield */
- listfield(ls, &cc);
- break;
- }
- }
+ field(ls, &cc);
} while (testnext(ls, ',') || testnext(ls, ';'));
check_match(ls, '}', '{', line);
lastlistfield(fs, &cc);
@@ -550,17 +601,13 @@ static void parlist (LexState *ls) {
do {
switch (ls->t.token) {
case TK_NAME: { /* param -> NAME */
- new_localvar(ls, str_checkname(ls), nparams++);
+ new_localvar(ls, str_checkname(ls));
+ nparams++;
break;
}
case TK_DOTS: { /* param -> `...' */
luaX_next(ls);
-#if defined(LUA_COMPAT_VARARG)
- /* use `arg' as default name */
- new_localvarliteral(ls, "arg", nparams++);
- f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
-#endif
- f->is_vararg |= VARARG_ISVARARG;
+ f->is_vararg = 1;
break;
}
default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
@@ -568,7 +615,7 @@ static void parlist (LexState *ls) {
} while (!f->is_vararg && testnext(ls, ','));
}
adjustlocalvars(ls, nparams);
- f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
+ f->numparams = cast_byte(fs->nactvar);
luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
}
@@ -580,7 +627,7 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
new_fs.f->linedefined = line;
checknext(ls, '(');
if (needself) {
- new_localvarliteral(ls, "self", 0);
+ new_localvarliteral(ls, "self");
adjustlocalvars(ls, 1);
}
parlist(ls);
@@ -588,8 +635,8 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
chunk(ls);
new_fs.f->lastlinedefined = ls->linenumber;
check_match(ls, TK_END, TK_FUNCTION, line);
+ pushclosure(ls, new_fs.f, e);
close_func(ls);
- pushclosure(ls, &new_fs, e);
}
@@ -694,8 +741,8 @@ static void primaryexp (LexState *ls, expdesc *v) {
prefixexp(ls, v);
for (;;) {
switch (ls->t.token) {
- case '.': { /* field */
- field(ls, v);
+ case '.': { /* fieldsel */
+ fieldsel(ls, v);
break;
}
case '[': { /* `[' exp1 `]' */
@@ -725,7 +772,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
static void simpleexp (LexState *ls, expdesc *v) {
- /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
+ /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
constructor | FUNCTION body | primaryexp */
switch (ls->t.token) {
case TK_NUMBER: {
@@ -753,7 +800,6 @@ static void simpleexp (LexState *ls, expdesc *v) {
FuncState *fs = ls->fs;
check_condition(ls, fs->f->is_vararg,
"cannot use " LUA_QL("...") " outside a vararg function");
- fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
break;
}
@@ -811,11 +857,11 @@ static const struct {
lu_byte left; /* left priority for each binary operator */
lu_byte right; /* right priority */
} priority[] = { /* ORDER OPR */
- {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */
- {10, 9}, {5, 4}, /* power and concat (right associative) */
- {3, 3}, {3, 3}, /* equality and inequality */
- {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */
- {2, 2}, {1, 1} /* logical (and/or) */
+ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */
+ {10, 9}, {5, 4}, /* ^, .. (right associative) */
+ {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */
+ {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */
+ {2, 2}, {1, 1} /* and, or */
};
#define UNARY_PRIORITY 8 /* priority for unary operators */
@@ -938,8 +984,8 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
primaryexp(ls, &nv.v);
if (nv.v.k == VLOCAL)
check_conflict(ls, lh, &nv.v);
- luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
- "variables in assignment");
+ checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls,
+ "variable names");
assignment(ls, &nv, nvars+1);
}
else { /* assignment -> `=' explist1 */
@@ -1000,7 +1046,7 @@ static void whilestat (LexState *ls, int line) {
enterblock(fs, &bl, 1);
checknext(ls, TK_DO);
block(ls);
- luaK_patchlist(fs, luaK_jump(fs), whileinit);
+ luaK_jumpto(fs, whileinit);
check_match(ls, TK_END, TK_WHILE, line);
leaveblock(fs);
luaK_patchtohere(fs, condexit); /* false conditions finish the loop */
@@ -1021,13 +1067,13 @@ static void repeatstat (LexState *ls, int line) {
condexit = cond(ls); /* read condition (inside scope block) */
if (!bl2.upval) { /* no upvalues? */
leaveblock(fs); /* finish scope */
- luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */
+ luaK_patchlist(fs, condexit, repeat_init); /* close the loop */
}
else { /* complete semantics when there are upvalues */
breakstat(ls); /* if condition then break */
luaK_patchtohere(ls->fs, condexit); /* else... */
leaveblock(fs); /* finish scope... */
- luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */
+ luaK_jumpto(fs, repeat_init); /* and repeat */
}
leaveblock(fs); /* finish loop */
}
@@ -1035,11 +1081,12 @@ static void repeatstat (LexState *ls, int line) {
static int exp1 (LexState *ls) {
expdesc e;
- int k;
+ int reg;
expr(ls, &e);
- k = e.k;
luaK_exp2nextreg(ls->fs, &e);
- return k;
+ lua_assert(e.k == VNONRELOC);
+ reg = e.u.s.info;
+ return reg;
}
@@ -1057,10 +1104,15 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
block(ls);
leaveblock(fs); /* end of scope for declared variables */
luaK_patchtohere(fs, prep);
- endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
- luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
- luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */
- luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
+ if (isnum) /* numeric for? */
+ endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
+ else { /* generic for */
+ luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
+ luaK_fixline(fs, line);
+ endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP);
+ }
+ luaK_patchlist(fs, endfor, prep + 1);
+ luaK_fixline(fs, line);
}
@@ -1068,10 +1120,10 @@ static void fornum (LexState *ls, TString *varname, int line) {
/* fornum -> NAME = exp1,exp1[,exp1] forbody */
FuncState *fs = ls->fs;
int base = fs->freereg;
- new_localvarliteral(ls, "(for index)", 0);
- new_localvarliteral(ls, "(for limit)", 1);
- new_localvarliteral(ls, "(for step)", 2);
- new_localvar(ls, varname, 3);
+ new_localvarliteral(ls, "(for index)");
+ new_localvarliteral(ls, "(for limit)");
+ new_localvarliteral(ls, "(for step)");
+ new_localvar(ls, varname);
checknext(ls, '=');
exp1(ls); /* initial value */
checknext(ls, ',');
@@ -1079,7 +1131,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
if (testnext(ls, ','))
exp1(ls); /* optional step */
else { /* default step = 1 */
- luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
+ luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1));
luaK_reserveregs(fs, 1);
}
forbody(ls, base, line, 1, 1);
@@ -1090,17 +1142,19 @@ static void forlist (LexState *ls, TString *indexname) {
/* forlist -> NAME {,NAME} IN explist1 forbody */
FuncState *fs = ls->fs;
expdesc e;
- int nvars = 0;
+ int nvars = 4; /* gen, state, control, plus at least one declared var */
int line;
int base = fs->freereg;
/* create control variables */
- new_localvarliteral(ls, "(for generator)", nvars++);
- new_localvarliteral(ls, "(for state)", nvars++);
- new_localvarliteral(ls, "(for control)", nvars++);
+ new_localvarliteral(ls, "(for generator)");
+ new_localvarliteral(ls, "(for state)");
+ new_localvarliteral(ls, "(for control)");
/* create declared variables */
- new_localvar(ls, indexname, nvars++);
- while (testnext(ls, ','))
- new_localvar(ls, str_checkname(ls), nvars++);
+ new_localvar(ls, indexname);
+ while (testnext(ls, ',')) {
+ new_localvar(ls, str_checkname(ls));
+ nvars++;
+ }
checknext(ls, TK_IN);
line = ls->linenumber;
adjust_assign(ls, 3, explist1(ls, &e), &e);
@@ -1165,14 +1219,12 @@ static void ifstat (LexState *ls, int line) {
static void localfunc (LexState *ls) {
expdesc v, b;
FuncState *fs = ls->fs;
- new_localvar(ls, str_checkname(ls), 0);
+ new_localvar(ls, str_checkname(ls));
init_exp(&v, VLOCAL, fs->freereg);
luaK_reserveregs(fs, 1);
adjustlocalvars(ls, 1);
body(ls, &b, 0, ls->linenumber);
luaK_storevar(fs, &v, &b);
- /* debug information will only see the variable after this point! */
- getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
}
@@ -1182,7 +1234,8 @@ static void localstat (LexState *ls) {
int nexps;
expdesc e;
do {
- new_localvar(ls, str_checkname(ls), nvars++);
+ new_localvar(ls, str_checkname(ls));
+ nvars++;
} while (testnext(ls, ','));
if (testnext(ls, '='))
nexps = explist1(ls, &e);
@@ -1196,14 +1249,14 @@ static void localstat (LexState *ls) {
static int funcname (LexState *ls, expdesc *v) {
- /* funcname -> NAME {field} [`:' NAME] */
+ /* funcname -> NAME {fieldsel} [`:' NAME] */
int needself = 0;
singlevar(ls, v);
while (ls->t.token == '.')
- field(ls, v);
+ fieldsel(ls, v);
if (ls->t.token == ':') {
needself = 1;
- field(ls, v);
+ fieldsel(ls, v);
}
return needself;
}
@@ -1221,6 +1274,24 @@ static void funcstat (LexState *ls, int line) {
}
+static void instat (LexState *ls, int line) {
+ /* instat -> IN exp DO block END */
+ FuncState *fs = ls->fs;
+ int oldenv = fs->envreg; /* save current environment */
+ BlockCnt bl;
+ luaX_next(ls); /* skip IN */
+ enterblock(fs, &bl, 0); /* scope for environment variable */
+ new_localvarliteral(ls, "(environment)");
+ fs->envreg = exp1(ls); /* new environment */
+ adjustlocalvars(ls, 1);
+ checknext(ls, TK_DO);
+ block(ls);
+ leaveblock(fs);
+ check_match(ls, TK_END, TK_IN, line);
+ fs->envreg = oldenv; /* restore outer environment */
+}
+
+
static void exprstat (LexState *ls) {
/* stat -> func | assignment */
FuncState *fs = ls->fs;
@@ -1285,6 +1356,10 @@ static int statement (LexState *ls) {
check_match(ls, TK_END, TK_DO, line);
return 0;
}
+ case TK_IN: {
+ instat(ls, line);
+ return 0;
+ }
case TK_FOR: { /* stat -> forstat */
forstat(ls, line);
return 0;