diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 97 |
1 files changed, 52 insertions, 45 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.125 2012/01/23 23:05:18 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.126 2012/04/20 19:20:05 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 | */ |
@@ -493,21 +493,30 @@ static void leaveblock (FuncState *fs) { | |||
493 | 493 | ||
494 | 494 | ||
495 | /* | 495 | /* |
496 | ** adds prototype being created into its parent list of prototypes | 496 | ** adds a new prototype into list of prototypes |
497 | ** and codes instruction to create new closure | ||
498 | */ | 497 | */ |
499 | static void codeclosure (LexState *ls, Proto *clp, expdesc *v) { | 498 | static Proto *addprototype (LexState *ls) { |
500 | FuncState *fs = ls->fs->prev; | 499 | Proto *clp; |
501 | Proto *f = fs->f; /* prototype of function creating new closure */ | 500 | lua_State *L = ls->L; |
501 | FuncState *fs = ls->fs; | ||
502 | Proto *f = fs->f; /* prototype of current function */ | ||
502 | if (fs->np >= f->sizep) { | 503 | if (fs->np >= f->sizep) { |
503 | int oldsize = f->sizep; | 504 | int oldsize = f->sizep; |
504 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, | 505 | luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); |
505 | MAXARG_Bx, "functions"); | ||
506 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; | 506 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; |
507 | } | 507 | } |
508 | f->p[fs->np++] = clp; | 508 | f->p[fs->np++] = clp = luaF_newproto(L); |
509 | luaC_objbarrier(ls->L, f, clp); | 509 | luaC_objbarrier(L, f, clp); |
510 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); | 510 | return clp; |
511 | } | ||
512 | |||
513 | |||
514 | /* | ||
515 | ** codes instruction to create new closure in parent function | ||
516 | */ | ||
517 | static void codeclosure (LexState *ls, expdesc *v) { | ||
518 | FuncState *fs = ls->fs->prev; | ||
519 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); | ||
511 | luaK_exp2nextreg(fs, v); /* fix it at stack top (for GC) */ | 520 | luaK_exp2nextreg(fs, v); /* fix it at stack top (for GC) */ |
512 | } | 521 | } |
513 | 522 | ||
@@ -529,13 +538,9 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { | |||
529 | fs->nactvar = 0; | 538 | fs->nactvar = 0; |
530 | fs->firstlocal = ls->dyd->actvar.n; | 539 | fs->firstlocal = ls->dyd->actvar.n; |
531 | fs->bl = NULL; | 540 | fs->bl = NULL; |
532 | f = luaF_newproto(L); | 541 | f = fs->f; |
533 | fs->f = f; | ||
534 | f->source = ls->source; | 542 | f->source = ls->source; |
535 | f->maxstacksize = 2; /* registers 0/1 are always valid */ | 543 | f->maxstacksize = 2; /* registers 0/1 are always valid */ |
536 | /* anchor prototype (to avoid being collected) */ | ||
537 | setptvalue2s(L, L->top, f); | ||
538 | incr_top(L); | ||
539 | fs->h = luaH_new(L); | 544 | fs->h = luaH_new(L); |
540 | /* anchor table of constants (to avoid being collected) */ | 545 | /* anchor table of constants (to avoid being collected) */ |
541 | sethvalue2s(L, L->top, fs->h); | 546 | sethvalue2s(L, L->top, fs->h); |
@@ -568,20 +573,6 @@ static void close_func (LexState *ls) { | |||
568 | anchor_token(ls); | 573 | anchor_token(ls); |
569 | L->top--; /* pop table of constants */ | 574 | L->top--; /* pop table of constants */ |
570 | luaC_checkGC(L); | 575 | luaC_checkGC(L); |
571 | L->top--; /* pop prototype (after possible collection) */ | ||
572 | } | ||
573 | |||
574 | |||
575 | /* | ||
576 | ** opens the main function, which is a regular vararg function with an | ||
577 | ** upvalue named LUA_ENV | ||
578 | */ | ||
579 | static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) { | ||
580 | expdesc v; | ||
581 | open_func(ls, fs, bl); | ||
582 | fs->f->is_vararg = 1; /* main function is always vararg */ | ||
583 | init_exp(&v, VLOCAL, 0); | ||
584 | newupvalue(fs, ls->envn, &v); /* create environment upvalue */ | ||
585 | } | 576 | } |
586 | 577 | ||
587 | 578 | ||
@@ -795,8 +786,9 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) { | |||
795 | /* body -> `(' parlist `)' block END */ | 786 | /* body -> `(' parlist `)' block END */ |
796 | FuncState new_fs; | 787 | FuncState new_fs; |
797 | BlockCnt bl; | 788 | BlockCnt bl; |
798 | open_func(ls, &new_fs, &bl); | 789 | new_fs.f = addprototype(ls); |
799 | new_fs.f->linedefined = line; | 790 | new_fs.f->linedefined = line; |
791 | open_func(ls, &new_fs, &bl); | ||
800 | checknext(ls, '('); | 792 | checknext(ls, '('); |
801 | if (ismethod) { | 793 | if (ismethod) { |
802 | new_localvarliteral(ls, "self"); /* create 'self' parameter */ | 794 | new_localvarliteral(ls, "self"); /* create 'self' parameter */ |
@@ -807,7 +799,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) { | |||
807 | statlist(ls); | 799 | statlist(ls); |
808 | new_fs.f->lastlinedefined = ls->linenumber; | 800 | new_fs.f->lastlinedefined = ls->linenumber; |
809 | check_match(ls, TK_END, TK_FUNCTION, line); | 801 | check_match(ls, TK_END, TK_FUNCTION, line); |
810 | codeclosure(ls, new_fs.f, e); | 802 | codeclosure(ls, e); |
811 | close_func(ls); | 803 | close_func(ls); |
812 | } | 804 | } |
813 | 805 | ||
@@ -1596,27 +1588,42 @@ static void statement (LexState *ls) { | |||
1596 | /* }====================================================================== */ | 1588 | /* }====================================================================== */ |
1597 | 1589 | ||
1598 | 1590 | ||
1599 | Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 1591 | /* |
1600 | Dyndata *dyd, const char *name, int firstchar) { | 1592 | ** compiles the main function, which is a regular vararg function with an |
1593 | ** upvalue named LUA_ENV | ||
1594 | */ | ||
1595 | static void mainfunc (LexState *ls, FuncState *fs) { | ||
1596 | BlockCnt bl; | ||
1597 | expdesc v; | ||
1598 | open_func(ls, fs, &bl); | ||
1599 | fs->f->is_vararg = 1; /* main function is always vararg */ | ||
1600 | init_exp(&v, VLOCAL, 0); /* create and... */ | ||
1601 | newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ | ||
1602 | luaX_next(ls); /* read first token */ | ||
1603 | statlist(ls); /* parse main body */ | ||
1604 | check(ls, TK_EOS); | ||
1605 | close_func(ls); | ||
1606 | } | ||
1607 | |||
1608 | |||
1609 | Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | ||
1610 | Dyndata *dyd, const char *name, int firstchar) { | ||
1601 | LexState lexstate; | 1611 | LexState lexstate; |
1602 | FuncState funcstate; | 1612 | FuncState funcstate; |
1603 | BlockCnt bl; | 1613 | Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ |
1604 | TString *tname = luaS_new(L, name); | 1614 | /* anchor closure (to avoid being collected) */ |
1605 | setsvalue2s(L, L->top, tname); /* push name to protect it */ | 1615 | setclLvalue(L, L->top, cl); |
1606 | incr_top(L); | 1616 | incr_top(L); |
1617 | funcstate.f = cl->l.p = luaF_newproto(L); | ||
1618 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ | ||
1607 | lexstate.buff = buff; | 1619 | lexstate.buff = buff; |
1608 | lexstate.dyd = dyd; | 1620 | lexstate.dyd = dyd; |
1609 | dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; | 1621 | dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; |
1610 | luaX_setinput(L, &lexstate, z, tname, firstchar); | 1622 | luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); |
1611 | open_mainfunc(&lexstate, &funcstate, &bl); | 1623 | mainfunc(&lexstate, &funcstate); |
1612 | luaX_next(&lexstate); /* read first token */ | ||
1613 | statlist(&lexstate); /* main body */ | ||
1614 | check(&lexstate, TK_EOS); | ||
1615 | close_func(&lexstate); | ||
1616 | L->top--; /* pop name */ | ||
1617 | lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); | 1624 | lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); |
1618 | /* all scopes should be correctly finished */ | 1625 | /* all scopes should be correctly finished */ |
1619 | lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); | 1626 | lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); |
1620 | return funcstate.f; | 1627 | return cl; /* it's on the stack too */ |
1621 | } | 1628 | } |
1622 | 1629 | ||