summaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-06-16 13:36:39 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-06-16 13:36:39 -0300
commitfdede8541965a58be39178528d31cdb397010b94 (patch)
treefbc2ed2dfe6941bededbdc50823dbd0c022574a2 /lparser.c
parentbeab626061a29bd957ae297bd5993cb5b4e15f22 (diff)
downloadlua-fdede8541965a58be39178528d31cdb397010b94.tar.gz
lua-fdede8541965a58be39178528d31cdb397010b94.tar.bz2
lua-fdede8541965a58be39178528d31cdb397010b94.zip
label names must be unique inside a function
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/lparser.c b/lparser.c
index 64c3ccce..c02e4b84 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.108 2011/04/18 19:48:24 roberto Exp roberto $ 2** $Id: lparser.c,v 2.109 2011/05/02 17:33:01 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -367,7 +367,7 @@ static int findlabel (LexState *ls, int g) {
367 /* check labels in current block for a match */ 367 /* check labels in current block for a match */
368 for (i = bl->firstlabel; i < dyd->label.n; i++) { 368 for (i = bl->firstlabel; i < dyd->label.n; i++) {
369 Labeldesc *lb = &dyd->label.arr[i]; 369 Labeldesc *lb = &dyd->label.arr[i];
370 if (eqstr(lb->name, gt->name)) { /* correct label? */ 370 if (eqstr(lb->name, gt->name) && lb->pc != -1) { /* correct label? */
371 if (gt->nactvar > lb->nactvar && 371 if (gt->nactvar > lb->nactvar &&
372 (bl->upval || dyd->label.n > bl->firstlabel)) 372 (bl->upval || dyd->label.n > bl->firstlabel))
373 luaK_patchclose(ls->fs, gt->pc, lb->nactvar); 373 luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
@@ -411,7 +411,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
411/* 411/*
412** "export" pending gotos to outer level, to check them against 412** "export" pending gotos to outer level, to check them against
413** outer labels; if the block being exited has upvalues, and 413** outer labels; if the block being exited has upvalues, and
414** the goto exists the scope of any variable (which can be the 414** the goto exits the scope of any variable (which can be the
415** upvalue), close those variables being exited. 415** upvalue), close those variables being exited.
416*/ 416*/
417static void movegotosout (FuncState *fs, BlockCnt *bl) { 417static void movegotosout (FuncState *fs, BlockCnt *bl) {
@@ -460,12 +460,18 @@ static void breaklabel (LexState *ls) {
460static void undefgoto (LexState *ls, Labeldesc *gt) { 460static void undefgoto (LexState *ls, Labeldesc *gt) {
461 const char *msg = (gt->name->tsv.reserved > 0) 461 const char *msg = (gt->name->tsv.reserved > 0)
462 ? "<%s> at line %d not inside a loop" 462 ? "<%s> at line %d not inside a loop"
463 : "label " LUA_QS " (<goto> at line %d) undefined"; 463 : "no visible label " LUA_QS " for <goto> at line %d";
464 msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); 464 msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
465 semerror(ls, msg); 465 semerror(ls, msg);
466} 466}
467 467
468 468
469static void invalidatelabels (Labellist *ll, int level) {
470 for (; level < ll->n; level++)
471 ll->arr[level].pc = -1; /* mark label as out of scope */
472}
473
474
469static void leaveblock (FuncState *fs) { 475static void leaveblock (FuncState *fs) {
470 BlockCnt *bl = fs->bl; 476 BlockCnt *bl = fs->bl;
471 LexState *ls = fs->ls; 477 LexState *ls = fs->ls;
@@ -481,7 +487,7 @@ static void leaveblock (FuncState *fs) {
481 removevars(fs, bl->nactvar); 487 removevars(fs, bl->nactvar);
482 lua_assert(bl->nactvar == fs->nactvar); 488 lua_assert(bl->nactvar == fs->nactvar);
483 fs->freereg = fs->nactvar; /* free registers */ 489 fs->freereg = fs->nactvar; /* free registers */
484 ls->dyd->label.n = bl->firstlabel; /* remove local labels */ 490 invalidatelabels(&ls->dyd->label, bl->firstlabel); /* remove local labels */
485 if (bl->previous) /* inner block? */ 491 if (bl->previous) /* inner block? */
486 movegotosout(fs, bl); /* update pending gotos to outer block */ 492 movegotosout(fs, bl); /* update pending gotos to outer block */
487 else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ 493 else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */
@@ -526,6 +532,7 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
526 fs->nlocvars = 0; 532 fs->nlocvars = 0;
527 fs->nactvar = 0; 533 fs->nactvar = 0;
528 fs->firstlocal = ls->dyd->actvar.n; 534 fs->firstlocal = ls->dyd->actvar.n;
535 fs->firstlabel = ls->dyd->label.n;
529 fs->bl = NULL; 536 fs->bl = NULL;
530 f = luaF_newproto(L); 537 f = luaF_newproto(L);
531 fs->f = f; 538 fs->f = f;
@@ -548,6 +555,7 @@ static void close_func (LexState *ls) {
548 Proto *f = fs->f; 555 Proto *f = fs->f;
549 luaK_ret(fs, 0, 0); /* final return */ 556 luaK_ret(fs, 0, 0); /* final return */
550 leaveblock(fs); 557 leaveblock(fs);
558 ls->dyd->label.n = fs->firstlabel; /* remove labels */
551 luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); 559 luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
552 f->sizecode = fs->pc; 560 f->sizecode = fs->pc;
553 luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); 561 luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
@@ -1185,13 +1193,11 @@ static void gotostat (LexState *ls, TString *label, int line) {
1185} 1193}
1186 1194
1187 1195
1188static void labelstat (LexState *ls, TString *label, int line) { 1196/* check for repeated labels on the same function */
1189 /* label -> '@' NAME ':' */ 1197static void checkrepeated (LexState *ls, FuncState *fs, Labellist *ll,
1190 FuncState *fs = ls->fs; 1198 TString *label) {
1191 Labellist *ll = &ls->dyd->label; 1199 int i;
1192 int l, i; /* index of new label being created */ 1200 for (i = fs->firstlabel; i < ll->n; i++) {
1193 /* check for repeated labels on the same block */
1194 for (i = ls->fs->bl->firstlabel; i < ll->n; i++) {
1195 if (eqstr(label, ll->arr[i].name)) { 1201 if (eqstr(label, ll->arr[i].name)) {
1196 const char *msg = luaO_pushfstring(ls->L, 1202 const char *msg = luaO_pushfstring(ls->L,
1197 "label " LUA_QS " already defined on line %d", 1203 "label " LUA_QS " already defined on line %d",
@@ -1199,6 +1205,15 @@ static void labelstat (LexState *ls, TString *label, int line) {
1199 semerror(ls, msg); 1205 semerror(ls, msg);
1200 } 1206 }
1201 } 1207 }
1208}
1209
1210
1211static void labelstat (LexState *ls, TString *label, int line) {
1212 /* label -> '@' NAME ':' */
1213 FuncState *fs = ls->fs;
1214 Labellist *ll = &ls->dyd->label;
1215 int l; /* index of new label being created */
1216 checkrepeated(ls, fs, ll, label); /* check for repeated labels */
1202 checknext(ls, ':'); /* skip colon */ 1217 checknext(ls, ':'); /* skip colon */
1203 /* create new entry for this label */ 1218 /* create new entry for this label */
1204 l = newlabelentry(ls, ll, label, line, fs->pc); 1219 l = newlabelentry(ls, ll, label, line, fs->pc);