summaryrefslogtreecommitdiffstats
path: root/lua/lparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'lua/lparser.c')
-rw-r--r--lua/lparser.c153
1 files changed, 84 insertions, 69 deletions
diff --git a/lua/lparser.c b/lua/lparser.c
index 4d68936..b3eb3ca 100644
--- a/lua/lparser.c
+++ b/lua/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.124 2011/12/02 13:23:56 roberto Exp $
+** $Id: lparser.c,v 2.128 2012/05/20 14:51:23 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -222,7 +222,7 @@ static int searchupvalue (FuncState *fs, TString *name) {
int i;
Upvaldesc *up = fs->f->upvalues;
for (i = 0; i < fs->nups; i++) {
- if (eqstr(up[i].name, name)) return i;
+ if (luaS_eqstr(up[i].name, name)) return i;
}
return -1; /* not found */
}
@@ -246,7 +246,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
static int searchvar (FuncState *fs, TString *n) {
int i;
for (i=fs->nactvar-1; i >= 0; i--) {
- if (eqstr(n, getlocvar(fs, i)->varname))
+ if (luaS_eqstr(n, getlocvar(fs, i)->varname))
return i;
}
return -1; /* not found */
@@ -342,7 +342,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
FuncState *fs = ls->fs;
Labellist *gl = &ls->dyd->gt;
Labeldesc *gt = &gl->arr[g];
- lua_assert(eqstr(gt->name, label->name));
+ lua_assert(luaS_eqstr(gt->name, label->name));
if (gt->nactvar < label->nactvar) {
TString *vname = getlocvar(fs, gt->nactvar)->varname;
const char *msg = luaO_pushfstring(ls->L,
@@ -369,7 +369,7 @@ static int findlabel (LexState *ls, int g) {
/* check labels in current block for a match */
for (i = bl->firstlabel; i < dyd->label.n; i++) {
Labeldesc *lb = &dyd->label.arr[i];
- if (eqstr(lb->name, gt->name)) { /* correct label? */
+ if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */
if (gt->nactvar > lb->nactvar &&
(bl->upval || dyd->label.n > bl->firstlabel))
luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
@@ -403,7 +403,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
Labellist *gl = &ls->dyd->gt;
int i = ls->fs->bl->firstgoto;
while (i < gl->n) {
- if (eqstr(gl->arr[i].name, lb->name))
+ if (luaS_eqstr(gl->arr[i].name, lb->name))
closegoto(ls, i, lb);
else
i++;
@@ -461,7 +461,7 @@ static void breaklabel (LexState *ls) {
** message when label name is a reserved word (which can only be 'break')
*/
static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
- const char *msg = (gt->name->tsv.reserved > 0)
+ const char *msg = isreserved(gt->name)
? "<%s> at line %d not inside a loop"
: "no visible label " LUA_QS " for <goto> at line %d";
msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
@@ -493,21 +493,30 @@ static void leaveblock (FuncState *fs) {
/*
-** adds prototype being created into its parent list of prototypes
-** and codes instruction to create new closure
+** adds a new prototype into list of prototypes
*/
-static void codeclosure (LexState *ls, Proto *clp, expdesc *v) {
- FuncState *fs = ls->fs->prev;
- Proto *f = fs->f; /* prototype of function creating new closure */
+static Proto *addprototype (LexState *ls) {
+ Proto *clp;
+ lua_State *L = ls->L;
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f; /* prototype of current function */
if (fs->np >= f->sizep) {
int oldsize = f->sizep;
- luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
- MAXARG_Bx, "functions");
+ luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
while (oldsize < f->sizep) f->p[oldsize++] = NULL;
}
- f->p[fs->np++] = clp;
- luaC_objbarrier(ls->L, f, clp);
- init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
+ f->p[fs->np++] = clp = luaF_newproto(L);
+ luaC_objbarrier(L, f, clp);
+ return clp;
+}
+
+
+/*
+** codes instruction to create new closure in parent function
+*/
+static void codeclosure (LexState *ls, expdesc *v) {
+ FuncState *fs = ls->fs->prev;
+ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
luaK_exp2nextreg(fs, v); /* fix it at stack top (for GC) */
}
@@ -529,13 +538,9 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
fs->nactvar = 0;
fs->firstlocal = ls->dyd->actvar.n;
fs->bl = NULL;
- f = luaF_newproto(L);
- fs->f = f;
+ f = fs->f;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
- /* 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);
@@ -568,20 +573,6 @@ static void close_func (LexState *ls) {
anchor_token(ls);
L->top--; /* pop table of constants */
luaC_checkGC(L);
- L->top--; /* pop prototype (after possible collection) */
-}
-
-
-/*
-** opens the main function, which is a regular vararg function with an
-** upvalue named LUA_ENV
-*/
-static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) {
- expdesc v;
- open_func(ls, fs, bl);
- fs->f->is_vararg = 1; /* main function is always vararg */
- init_exp(&v, VLOCAL, 0);
- newupvalue(fs, ls->envn, &v); /* create environment upvalue */
}
@@ -795,8 +786,9 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
/* body -> `(' parlist `)' block END */
FuncState new_fs;
BlockCnt bl;
- open_func(ls, &new_fs, &bl);
+ new_fs.f = addprototype(ls);
new_fs.f->linedefined = line;
+ open_func(ls, &new_fs, &bl);
checknext(ls, '(');
if (ismethod) {
new_localvarliteral(ls, "self"); /* create 'self' parameter */
@@ -807,7 +799,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
statlist(ls);
new_fs.f->lastlinedefined = ls->linenumber;
check_match(ls, TK_END, TK_FUNCTION, line);
- codeclosure(ls, new_fs.f, e);
+ codeclosure(ls, e);
close_func(ls);
}
@@ -879,8 +871,8 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
*/
-static void prefixexp (LexState *ls, expdesc *v) {
- /* prefixexp -> NAME | '(' expr ')' */
+static void primaryexp (LexState *ls, expdesc *v) {
+ /* primaryexp -> NAME | '(' expr ')' */
switch (ls->t.token) {
case '(': {
int line = ls->linenumber;
@@ -901,12 +893,12 @@ static void prefixexp (LexState *ls, expdesc *v) {
}
-static void primaryexp (LexState *ls, expdesc *v) {
- /* primaryexp ->
- prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
+static void suffixedexp (LexState *ls, expdesc *v) {
+ /* suffixedexp ->
+ primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
FuncState *fs = ls->fs;
int line = ls->linenumber;
- prefixexp(ls, v);
+ primaryexp(ls, v);
for (;;) {
switch (ls->t.token) {
case '.': { /* fieldsel */
@@ -941,7 +933,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
static void simpleexp (LexState *ls, expdesc *v) {
/* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
- constructor | FUNCTION body | primaryexp */
+ constructor | FUNCTION body | suffixedexp */
switch (ls->t.token) {
case TK_NUMBER: {
init_exp(v, VKNUM, 0);
@@ -981,7 +973,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
return;
}
default: {
- primaryexp(ls, v);
+ suffixedexp(ls, v);
return;
}
}
@@ -1141,10 +1133,10 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
expdesc e;
check_condition(ls, vkisvar(lh->v.k), "syntax error");
- if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
+ if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */
struct LHS_assign nv;
nv.prev = lh;
- primaryexp(ls, &nv.v);
+ suffixedexp(ls, &nv.v);
if (nv.v.k != VINDEXED)
check_conflict(ls, lh, &nv.v);
checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
@@ -1200,7 +1192,7 @@ static void gotostat (LexState *ls, int pc) {
static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
int i;
for (i = fs->bl->firstlabel; i < ll->n; i++) {
- if (eqstr(label, ll->arr[i].name)) {
+ if (luaS_eqstr(label, ll->arr[i].name)) {
const char *msg = luaO_pushfstring(fs->ls->L,
"label " LUA_QS " already defined on line %d",
getstr(label), ll->arr[i].line);
@@ -1210,6 +1202,13 @@ static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
}
+/* skip no-op statements */
+static void skipnoopstat (LexState *ls) {
+ while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
+ statement(ls);
+}
+
+
static void labelstat (LexState *ls, TString *label, int line) {
/* label -> '::' NAME '::' */
FuncState *fs = ls->fs;
@@ -1219,9 +1218,7 @@ static void labelstat (LexState *ls, TString *label, int line) {
checknext(ls, TK_DBCOLON); /* skip double colon */
/* create new entry for this label */
l = newlabelentry(ls, ll, label, line, fs->pc);
- /* skip other no-op statements */
- while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
- statement(ls);
+ skipnoopstat(ls); /* skip other no-op statements */
if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
/* assume that locals are already out of scope */
ll->arr[l].nactvar = fs->bl->nactvar;
@@ -1384,6 +1381,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
gotostat(ls, v.t); /* handle goto/break */
+ skipnoopstat(ls); /* skip other no-op statements */
if (block_follow(ls, 0)) { /* 'goto' is the entire block? */
leaveblock(fs);
return; /* and that is it */
@@ -1480,13 +1478,15 @@ static void exprstat (LexState *ls) {
/* stat -> func | assignment */
FuncState *fs = ls->fs;
struct LHS_assign v;
- primaryexp(ls, &v.v);
- if (v.v.k == VCALL) /* stat -> func */
- SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
- else { /* stat -> assignment */
+ suffixedexp(ls, &v.v);
+ if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
v.prev = NULL;
assignment(ls, &v, 1);
}
+ else { /* stat -> func */
+ check_condition(ls, v.v.k == VCALL, "syntax error");
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
+ }
}
@@ -1594,27 +1594,42 @@ static void statement (LexState *ls) {
/* }====================================================================== */
-Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar) {
+/*
+** compiles the main function, which is a regular vararg function with an
+** upvalue named LUA_ENV
+*/
+static void mainfunc (LexState *ls, FuncState *fs) {
+ BlockCnt bl;
+ expdesc v;
+ open_func(ls, fs, &bl);
+ fs->f->is_vararg = 1; /* main function is always vararg */
+ init_exp(&v, VLOCAL, 0); /* create and... */
+ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */
+ luaX_next(ls); /* read first token */
+ statlist(ls); /* parse main body */
+ check(ls, TK_EOS);
+ close_func(ls);
+}
+
+
+Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ Dyndata *dyd, const char *name, int firstchar) {
LexState lexstate;
FuncState funcstate;
- BlockCnt bl;
- TString *tname = luaS_new(L, name);
- setsvalue2s(L, L->top, tname); /* push name to protect it */
+ Closure *cl = luaF_newLclosure(L, 1); /* create main closure */
+ /* anchor closure (to avoid being collected) */
+ setclLvalue(L, L->top, cl);
incr_top(L);
+ funcstate.f = cl->l.p = luaF_newproto(L);
+ funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
lexstate.buff = buff;
lexstate.dyd = dyd;
dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
- luaX_setinput(L, &lexstate, z, tname, firstchar);
- open_mainfunc(&lexstate, &funcstate, &bl);
- luaX_next(&lexstate); /* read first token */
- statlist(&lexstate); /* main body */
- check(&lexstate, TK_EOS);
- close_func(&lexstate);
- L->top--; /* pop name */
+ luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar);
+ mainfunc(&lexstate, &funcstate);
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
/* all scopes should be correctly finished */
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
- return funcstate.f;
+ return cl; /* it's on the stack too */
}