summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-07 17:00:30 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-07 17:00:30 -0200
commitfd6c1f489862d8ecf7055ca18898fffd006711fa (patch)
tree8993adcebcf891bf32976d86dc7ff5d5023e1e65
parentf0797492875dec5bf7a23b9172809bc92c0c04cd (diff)
downloadlua-fd6c1f489862d8ecf7055ca18898fffd006711fa.tar.gz
lua-fd6c1f489862d8ecf7055ca18898fffd006711fa.tar.bz2
lua-fd6c1f489862d8ecf7055ca18898fffd006711fa.zip
ensures that all local variables are declared inside some block,
opening a new block at 'open_func'
-rw-r--r--lparser.c84
1 files changed, 39 insertions, 45 deletions
diff --git a/lparser.c b/lparser.c
index 63fd577f..ffc3c674 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.98 2011/02/07 12:28:27 roberto Exp roberto $ 2** $Id: lparser.c,v 2.99 2011/02/07 17:14:50 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*/
@@ -46,7 +46,7 @@ typedef struct BlockCnt {
46 int firstgoto; /* index of first pending goto in this block */ 46 int firstgoto; /* index of first pending goto in this block */
47 lu_byte nactvar; /* # active locals outside the block */ 47 lu_byte nactvar; /* # active locals outside the block */
48 lu_byte upval; /* true if some variable in the block is an upvalue */ 48 lu_byte upval; /* true if some variable in the block is an upvalue */
49 lu_byte isbreakable; /* true if `block' is a loop */ 49 lu_byte isloop; /* true if `block' is a loop */
50} BlockCnt; 50} BlockCnt;
51 51
52 52
@@ -251,8 +251,8 @@ static int searchvar (FuncState *fs, TString *n) {
251*/ 251*/
252static void markupval (FuncState *fs, int level) { 252static void markupval (FuncState *fs, int level) {
253 BlockCnt *bl = fs->bl; 253 BlockCnt *bl = fs->bl;
254 while (bl && bl->nactvar > level) bl = bl->previous; 254 while (bl->nactvar > level) bl = bl->previous;
255 if (bl) bl->upval = 1; 255 bl->upval = 1;
256} 256}
257 257
258 258
@@ -411,9 +411,9 @@ static void movegotosout (FuncState *fs, BlockCnt *bl) {
411} 411}
412 412
413 413
414static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { 414static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
415 bl->breaklist = NO_JUMP; 415 bl->breaklist = NO_JUMP;
416 bl->isbreakable = isbreakable; 416 bl->isloop = isloop;
417 bl->nactvar = fs->nactvar; 417 bl->nactvar = fs->nactvar;
418 bl->firstlabel = fs->ls->dyd->label.n; 418 bl->firstlabel = fs->ls->dyd->label.n;
419 bl->firstgoto = fs->ls->dyd->gt.n; 419 bl->firstgoto = fs->ls->dyd->gt.n;
@@ -426,18 +426,25 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
426 426
427static void leaveblock (FuncState *fs) { 427static void leaveblock (FuncState *fs) {
428 BlockCnt *bl = fs->bl; 428 BlockCnt *bl = fs->bl;
429 LexState *ls = fs->ls;
429 fs->bl = bl->previous; 430 fs->bl = bl->previous;
430 removevars(fs, bl->nactvar); 431 removevars(fs, bl->nactvar);
431 fs->ls->dyd->label.n = bl->firstlabel; /* remove local labels */ 432 ls->dyd->label.n = bl->firstlabel; /* remove local labels */
432 movegotosout(fs, bl); 433 if (bl->previous) /* inner block? */
433 if (bl->upval) { 434 movegotosout(fs, bl); /* update pending gotos to outer block */
435 else if (bl->firstgoto < ls->dyd->gt.n) { /* check pending gotos */
436 Labeldesc *gt = &ls->dyd->gt.arr[bl->firstgoto];
437 const char *msg = luaO_pushfstring(ls->L,
438 "label " LUA_QS " (<goto> at line %d) undefined",
439 getstr(gt->name), gt->line);
440 luaX_syntaxerror(ls, msg);
441 }
442 if (bl->previous && bl->upval) {
434 /* create a 'jump to here' to close upvalues */ 443 /* create a 'jump to here' to close upvalues */
435 int j = luaK_jump(fs); 444 int j = luaK_jump(fs);
436 luaK_patchclose(fs, j, bl->nactvar); 445 luaK_patchclose(fs, j, bl->nactvar);
437 luaK_patchtohere(fs, j); 446 luaK_patchtohere(fs, j);
438 } 447 }
439 /* a block either controls scope or breaks (never both) */
440 lua_assert(!bl->isbreakable || !bl->upval);
441 lua_assert(bl->nactvar == fs->nactvar); 448 lua_assert(bl->nactvar == fs->nactvar);
442 fs->freereg = fs->nactvar; /* free registers */ 449 fs->freereg = fs->nactvar; /* free registers */
443 luaK_patchtohere(fs, bl->breaklist); 450 luaK_patchtohere(fs, bl->breaklist);
@@ -464,7 +471,7 @@ static void codeclosure (LexState *ls, Proto *clp, expdesc *v) {
464} 471}
465 472
466 473
467static void open_func (LexState *ls, FuncState *fs) { 474static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
468 lua_State *L = ls->L; 475 lua_State *L = ls->L;
469 Proto *f; 476 Proto *f;
470 fs->prev = ls->fs; /* linked list of funcstates */ 477 fs->prev = ls->fs; /* linked list of funcstates */
@@ -493,6 +500,7 @@ static void open_func (LexState *ls, FuncState *fs) {
493 /* anchor table of constants (to avoid being collected) */ 500 /* anchor table of constants (to avoid being collected) */
494 sethvalue2s(L, L->top, fs->h); 501 sethvalue2s(L, L->top, fs->h);
495 incr_top(L); 502 incr_top(L);
503 enterblock(fs, bl, 0);
496} 504}
497 505
498 506
@@ -501,7 +509,7 @@ static void close_func (LexState *ls) {
501 FuncState *fs = ls->fs; 509 FuncState *fs = ls->fs;
502 Proto *f = fs->f; 510 Proto *f = fs->f;
503 luaK_ret(fs, 0, 0); /* final return */ 511 luaK_ret(fs, 0, 0); /* final return */
504 removevars(fs, 0); 512 leaveblock(fs);
505 luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); 513 luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
506 f->sizecode = fs->pc; 514 f->sizecode = fs->pc;
507 luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); 515 luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
@@ -528,35 +536,20 @@ static void close_func (LexState *ls) {
528** opens the main function, which is a regular vararg function with an 536** opens the main function, which is a regular vararg function with an
529** upvalue named LUA_ENV 537** upvalue named LUA_ENV
530*/ 538*/
531static void open_mainfunc (LexState *ls, FuncState *fs) { 539static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) {
532 expdesc v; 540 expdesc v;
533 open_func(ls, fs); 541 open_func(ls, fs, bl);
534 fs->f->is_vararg = 1; /* main function is always vararg */ 542 fs->f->is_vararg = 1; /* main function is always vararg */
535 init_exp(&v, VLOCAL, 0); 543 init_exp(&v, VLOCAL, 0);
536 newupvalue(fs, ls->envn, &v); /* create environment upvalue */ 544 newupvalue(fs, ls->envn, &v); /* create environment upvalue */
537} 545}
538 546
539 547
540static void mainblock (LexState *ls, FuncState *fs) {
541 BlockCnt bl;
542 enterblock(fs, &bl, 0);
543 statlist(ls); /* read main block */
544 if (bl.firstgoto < ls->dyd->gt.n) { /* check pending gotos */
545 Labeldesc *gt = &ls->dyd->gt.arr[bl.firstgoto];
546 const char *msg = luaO_pushfstring(ls->L,
547 "label " LUA_QS " (<goto> at line %d) undefined",
548 getstr(gt->name), gt->line);
549 luaX_syntaxerror(ls, msg);
550 }
551 bl.upval = 0; /* RETURN will close any pending upvalue */
552 leaveblock(fs);
553}
554
555
556Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 548Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
557 Dyndata *dyd, const char *name) { 549 Dyndata *dyd, const char *name) {
558 LexState lexstate; 550 LexState lexstate;
559 FuncState funcstate; 551 FuncState funcstate;
552 BlockCnt bl;
560 TString *tname = luaS_new(L, name); 553 TString *tname = luaS_new(L, name);
561 setsvalue2s(L, L->top, tname); /* push name to protect it */ 554 setsvalue2s(L, L->top, tname); /* push name to protect it */
562 incr_top(L); 555 incr_top(L);
@@ -564,9 +557,9 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
564 lexstate.dyd = dyd; 557 lexstate.dyd = dyd;
565 dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; 558 dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
566 luaX_setinput(L, &lexstate, z, tname); 559 luaX_setinput(L, &lexstate, z, tname);
567 open_mainfunc(&lexstate, &funcstate); 560 open_mainfunc(&lexstate, &funcstate, &bl);
568 luaX_next(&lexstate); /* read first token */ 561 luaX_next(&lexstate); /* read first token */
569 mainblock(&lexstate, &funcstate); 562 statlist(&lexstate); /* main body */
570 check(&lexstate, TK_EOS); 563 check(&lexstate, TK_EOS);
571 close_func(&lexstate); 564 close_func(&lexstate);
572 L->top--; /* pop name */ 565 L->top--; /* pop name */
@@ -753,19 +746,20 @@ static void parlist (LexState *ls) {
753} 746}
754 747
755 748
756static void body (LexState *ls, expdesc *e, int needself, int line) { 749static void body (LexState *ls, expdesc *e, int ismethod, int line) {
757 /* body -> `(' parlist `)' block END */ 750 /* body -> `(' parlist `)' block END */
758 FuncState new_fs; 751 FuncState new_fs;
759 open_func(ls, &new_fs); 752 BlockCnt bl;
753 open_func(ls, &new_fs, &bl);
760 new_fs.f->linedefined = line; 754 new_fs.f->linedefined = line;
761 checknext(ls, '('); 755 checknext(ls, '(');
762 if (needself) { 756 if (ismethod) {
763 new_localvarliteral(ls, "self"); 757 new_localvarliteral(ls, "self"); /* create 'self' parameter */
764 adjustlocalvars(ls, 1); 758 adjustlocalvars(ls, 1);
765 } 759 }
766 parlist(ls); 760 parlist(ls);
767 checknext(ls, ')'); 761 checknext(ls, ')');
768 mainblock(ls, &new_fs); 762 statlist(ls);
769 new_fs.f->lastlinedefined = ls->linenumber; 763 new_fs.f->lastlinedefined = ls->linenumber;
770 check_match(ls, TK_END, TK_FUNCTION, line); 764 check_match(ls, TK_END, TK_FUNCTION, line);
771 codeclosure(ls, new_fs.f, e); 765 codeclosure(ls, new_fs.f, e);
@@ -1163,7 +1157,7 @@ static void breakstat (LexState *ls) {
1163 FuncState *fs = ls->fs; 1157 FuncState *fs = ls->fs;
1164 BlockCnt *bl = fs->bl; 1158 BlockCnt *bl = fs->bl;
1165 int upval = 0; 1159 int upval = 0;
1166 while (bl && !bl->isbreakable) { 1160 while (bl && !bl->isloop) {
1167 upval |= bl->upval; 1161 upval |= bl->upval;
1168 bl = bl->previous; 1162 bl = bl->previous;
1169 } 1163 }
@@ -1426,25 +1420,25 @@ static void localstat (LexState *ls) {
1426 1420
1427static int funcname (LexState *ls, expdesc *v) { 1421static int funcname (LexState *ls, expdesc *v) {
1428 /* funcname -> NAME {fieldsel} [`:' NAME] */ 1422 /* funcname -> NAME {fieldsel} [`:' NAME] */
1429 int needself = 0; 1423 int ismethod = 0;
1430 singlevar(ls, v); 1424 singlevar(ls, v);
1431 while (ls->t.token == '.') 1425 while (ls->t.token == '.')
1432 fieldsel(ls, v); 1426 fieldsel(ls, v);
1433 if (ls->t.token == ':') { 1427 if (ls->t.token == ':') {
1434 needself = 1; 1428 ismethod = 1;
1435 fieldsel(ls, v); 1429 fieldsel(ls, v);
1436 } 1430 }
1437 return needself; 1431 return ismethod;
1438} 1432}
1439 1433
1440 1434
1441static void funcstat (LexState *ls, int line) { 1435static void funcstat (LexState *ls, int line) {
1442 /* funcstat -> FUNCTION funcname body */ 1436 /* funcstat -> FUNCTION funcname body */
1443 int needself; 1437 int ismethod;
1444 expdesc v, b; 1438 expdesc v, b;
1445 luaX_next(ls); /* skip FUNCTION */ 1439 luaX_next(ls); /* skip FUNCTION */
1446 needself = funcname(ls, &v); 1440 ismethod = funcname(ls, &v);
1447 body(ls, &b, needself, line); 1441 body(ls, &b, ismethod, line);
1448 luaK_storevar(ls->fs, &v, &b); 1442 luaK_storevar(ls->fs, &v, &b);
1449 luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ 1443 luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
1450} 1444}