diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-14 14:36:34 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-14 14:36:34 -0200 |
commit | c0a865fa54b3c692af3783bd9470b8c0537b77b4 (patch) | |
tree | e641cdb906ae94ca80472333c26772102aff2093 /lparser.c | |
parent | 0009ac1f3addb79e3cb4f1f1d12929a975f1f241 (diff) | |
download | lua-c0a865fa54b3c692af3783bd9470b8c0537b77b4.tar.gz lua-c0a865fa54b3c692af3783bd9470b8c0537b77b4.tar.bz2 lua-c0a865fa54b3c692af3783bd9470b8c0537b77b4.zip |
error for repeated label + jumps allowed to labels followed by
'no-op' statements
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 58 |
1 files changed, 34 insertions, 24 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.104 2011/02/10 14:50:41 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.105 2011/02/14 14:59:28 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 | */ |
@@ -339,8 +339,8 @@ static void enterlevel (LexState *ls) { | |||
339 | static void closegoto (LexState *ls, int g, Labeldesc *label) { | 339 | static void closegoto (LexState *ls, int g, Labeldesc *label) { |
340 | int i; | 340 | int i; |
341 | FuncState *fs = ls->fs; | 341 | FuncState *fs = ls->fs; |
342 | Dyndata *dyd = ls->dyd; | 342 | Labellist *gl = &ls->dyd->gt; |
343 | Labeldesc *gt = &dyd->gt.arr[g]; | 343 | Labeldesc *gt = &gl->arr[g]; |
344 | lua_assert(eqstr(gt->name, label->name)); | 344 | lua_assert(eqstr(gt->name, label->name)); |
345 | if (gt->nactvar < label->nactvar) { | 345 | if (gt->nactvar < label->nactvar) { |
346 | const char *msg = luaO_pushfstring(ls->L, | 346 | const char *msg = luaO_pushfstring(ls->L, |
@@ -350,9 +350,9 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) { | |||
350 | } | 350 | } |
351 | luaK_patchlist(fs, gt->pc, label->pc); | 351 | luaK_patchlist(fs, gt->pc, label->pc); |
352 | /* remove goto from pending list */ | 352 | /* remove goto from pending list */ |
353 | for (i = g; i < dyd->gt.n - 1; i++) | 353 | for (i = g; i < gl->n - 1; i++) |
354 | dyd->gt.arr[i] = dyd->gt.arr[i + 1]; | 354 | gl->arr[i] = gl->arr[i + 1]; |
355 | dyd->gt.n--; | 355 | gl->n--; |
356 | } | 356 | } |
357 | 357 | ||
358 | 358 | ||
@@ -397,10 +397,10 @@ static int newlabelentry (LexState *ls, Labellist *l, TString *name, | |||
397 | ** block; solves forward jumps | 397 | ** block; solves forward jumps |
398 | */ | 398 | */ |
399 | static void findgotos (LexState *ls, Labeldesc *lb) { | 399 | static void findgotos (LexState *ls, Labeldesc *lb) { |
400 | Dyndata *dyd = ls->dyd; | 400 | Labellist *gl = &ls->dyd->gt; |
401 | int i = ls->fs->bl->firstgoto; | 401 | int i = ls->fs->bl->firstgoto; |
402 | while (i < dyd->gt.n) { | 402 | while (i < gl->n) { |
403 | if (eqstr(dyd->gt.arr[i].name, lb->name)) | 403 | if (eqstr(gl->arr[i].name, lb->name)) |
404 | closegoto(ls, i, lb); | 404 | closegoto(ls, i, lb); |
405 | else | 405 | else |
406 | i++; | 406 | i++; |
@@ -416,11 +416,11 @@ static void findgotos (LexState *ls, Labeldesc *lb) { | |||
416 | */ | 416 | */ |
417 | static void movegotosout (FuncState *fs, BlockCnt *bl) { | 417 | static void movegotosout (FuncState *fs, BlockCnt *bl) { |
418 | int i = bl->firstgoto; | 418 | int i = bl->firstgoto; |
419 | Dyndata *dyd = fs->ls->dyd; | 419 | Labellist *gl = &fs->ls->dyd->gt; |
420 | /* correct pending gotos to current block and try to close it | 420 | /* correct pending gotos to current block and try to close it |
421 | with visible labels */ | 421 | with visible labels */ |
422 | while (i < dyd->gt.n) { | 422 | while (i < gl->n) { |
423 | Labeldesc *gt = &dyd->gt.arr[i]; | 423 | Labeldesc *gt = &gl->arr[i]; |
424 | if (gt->nactvar > bl->nactvar) { | 424 | if (gt->nactvar > bl->nactvar) { |
425 | if (bl->upval) | 425 | if (bl->upval) |
426 | luaK_patchclose(fs, gt->pc, bl->nactvar); | 426 | luaK_patchclose(fs, gt->pc, bl->nactvar); |
@@ -1185,21 +1185,31 @@ static void gotostat (LexState *ls, TString *label, int line) { | |||
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | 1187 | ||
1188 | static void labelstat (LexState *ls, TString *label) { | 1188 | static void labelstat (LexState *ls, TString *label, int line) { |
1189 | /* label -> '@' NAME ':' */ | 1189 | /* label -> '@' NAME ':' */ |
1190 | FuncState *fs = ls->fs; | 1190 | FuncState *fs = ls->fs; |
1191 | int l; /* index of new label being created */ | 1191 | Labellist *ll = &ls->dyd->label; |
1192 | Labeldesc *lb; | 1192 | int l, i; /* index of new label being created */ |
1193 | checknext(ls, ':'); | 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)) { | ||
1196 | const char *msg = luaO_pushfstring(ls->L, | ||
1197 | "label " LUA_QS " already defined on line %d", | ||
1198 | getstr(label), ll->arr[i].line); | ||
1199 | semerror(ls, msg); | ||
1200 | } | ||
1201 | } | ||
1202 | checknext(ls, ':'); /* skip colon */ | ||
1194 | /* create new entry for this label */ | 1203 | /* create new entry for this label */ |
1195 | l = newlabelentry(ls, &ls->dyd->label, label, 0, fs->pc); | 1204 | l = newlabelentry(ls, ll, label, line, fs->pc); |
1196 | lb = &ls->dyd->label.arr[l]; | 1205 | /* skip other no-op statements */ |
1197 | while (testnext(ls, ';')) ; /* skip trailing semicolons */ | 1206 | while (ls->t.token == ';' || ls->t.token == '@') |
1198 | if (block_follow(ls, 0)) { /* label is last statement in the block? */ | 1207 | statement(ls); |
1208 | if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ | ||
1199 | /* assume that locals are already out of scope */ | 1209 | /* assume that locals are already out of scope */ |
1200 | lb->nactvar = fs->bl->nactvar; | 1210 | ll->arr[l].nactvar = fs->bl->nactvar; |
1201 | } | 1211 | } |
1202 | findgotos(ls, lb); | 1212 | findgotos(ls, &ll->arr[l]); |
1203 | } | 1213 | } |
1204 | 1214 | ||
1205 | 1215 | ||
@@ -1476,7 +1486,7 @@ static void retstat (LexState *ls) { | |||
1476 | } | 1486 | } |
1477 | } | 1487 | } |
1478 | luaK_ret(fs, first, nret); | 1488 | luaK_ret(fs, first, nret); |
1479 | testnext(ls, ';'); /* skip optional semicollon */ | 1489 | testnext(ls, ';'); /* skip optional semicolon */ |
1480 | } | 1490 | } |
1481 | 1491 | ||
1482 | 1492 | ||
@@ -1524,7 +1534,7 @@ static void statement (LexState *ls) { | |||
1524 | } | 1534 | } |
1525 | case '@': { /* stat -> label */ | 1535 | case '@': { /* stat -> label */ |
1526 | luaX_next(ls); /* skip '@' */ | 1536 | luaX_next(ls); /* skip '@' */ |
1527 | labelstat(ls, str_checkname(ls)); | 1537 | labelstat(ls, str_checkname(ls), line); |
1528 | break; | 1538 | break; |
1529 | } | 1539 | } |
1530 | case TK_RETURN: { /* stat -> retstat */ | 1540 | case TK_RETURN: { /* stat -> retstat */ |