diff options
| -rw-r--r-- | lparser.c | 84 |
1 files changed, 39 insertions, 45 deletions
| @@ -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 | */ |
| 252 | static void markupval (FuncState *fs, int level) { | 252 | static 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 | ||
| 414 | static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { | 414 | static 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 | ||
| 427 | static void leaveblock (FuncState *fs) { | 427 | static 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 | ||
| 467 | static void open_func (LexState *ls, FuncState *fs) { | 474 | static 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 | */ |
| 531 | static void open_mainfunc (LexState *ls, FuncState *fs) { | 539 | static 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 | ||
| 540 | static 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 | |||
| 556 | Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 548 | Proto *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 | ||
| 756 | static void body (LexState *ls, expdesc *e, int needself, int line) { | 749 | static 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 | ||
| 1427 | static int funcname (LexState *ls, expdesc *v) { | 1421 | static 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 | ||
| 1441 | static void funcstat (LexState *ls, int line) { | 1435 | static 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 | } |
