From 3cadc37f470df50deb5c920b028125b8bb6c316b Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 8 May 2012 10:53:33 -0300 Subject: no more 'Proto' objects on the stack. Protos are anchored on outer Protos or on a Closure, which must be created before the Proto. --- lparser.c | 97 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 45 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index ed1b3081..84bc5f25 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.125 2012/01/23 23:05:18 roberto Exp roberto $ +** $Id: lparser.c,v 2.126 2012/04/20 19:20:05 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -493,21 +493,30 @@ static void leaveblock (FuncState *fs) { /* -** adds prototype being created into its parent list of prototypes -** and codes instruction to create new closure +** adds a new prototype into list of prototypes */ -static void codeclosure (LexState *ls, Proto *clp, expdesc *v) { - FuncState *fs = ls->fs->prev; - Proto *f = fs->f; /* prototype of function creating new closure */ +static Proto *addprototype (LexState *ls) { + Proto *clp; + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; /* prototype of current function */ if (fs->np >= f->sizep) { int oldsize = f->sizep; - luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, - MAXARG_Bx, "functions"); + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); while (oldsize < f->sizep) f->p[oldsize++] = NULL; } - f->p[fs->np++] = clp; - luaC_objbarrier(ls->L, f, clp); - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + f->p[fs->np++] = clp = luaF_newproto(L); + luaC_objbarrier(L, f, clp); + return clp; +} + + +/* +** codes instruction to create new closure in parent function +*/ +static void codeclosure (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs->prev; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); luaK_exp2nextreg(fs, v); /* fix it at stack top (for GC) */ } @@ -529,13 +538,9 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { fs->nactvar = 0; fs->firstlocal = ls->dyd->actvar.n; fs->bl = NULL; - f = luaF_newproto(L); - fs->f = f; + f = fs->f; f->source = ls->source; f->maxstacksize = 2; /* registers 0/1 are always valid */ - /* anchor prototype (to avoid being collected) */ - setptvalue2s(L, L->top, f); - incr_top(L); fs->h = luaH_new(L); /* anchor table of constants (to avoid being collected) */ sethvalue2s(L, L->top, fs->h); @@ -568,20 +573,6 @@ static void close_func (LexState *ls) { anchor_token(ls); L->top--; /* pop table of constants */ luaC_checkGC(L); - L->top--; /* pop prototype (after possible collection) */ -} - - -/* -** opens the main function, which is a regular vararg function with an -** upvalue named LUA_ENV -*/ -static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) { - expdesc v; - open_func(ls, fs, bl); - fs->f->is_vararg = 1; /* main function is always vararg */ - init_exp(&v, VLOCAL, 0); - newupvalue(fs, ls->envn, &v); /* create environment upvalue */ } @@ -795,8 +786,9 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) { /* body -> `(' parlist `)' block END */ FuncState new_fs; BlockCnt bl; - open_func(ls, &new_fs, &bl); + new_fs.f = addprototype(ls); new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); checknext(ls, '('); if (ismethod) { new_localvarliteral(ls, "self"); /* create 'self' parameter */ @@ -807,7 +799,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) { statlist(ls); new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); - codeclosure(ls, new_fs.f, e); + codeclosure(ls, e); close_func(ls); } @@ -1596,27 +1588,42 @@ static void statement (LexState *ls) { /* }====================================================================== */ -Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar) { +/* +** compiles the main function, which is a regular vararg function with an +** upvalue named LUA_ENV +*/ +static void mainfunc (LexState *ls, FuncState *fs) { + BlockCnt bl; + expdesc v; + open_func(ls, fs, &bl); + fs->f->is_vararg = 1; /* main function is always vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + luaX_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); +} + + +Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar) { LexState lexstate; FuncState funcstate; - BlockCnt bl; - TString *tname = luaS_new(L, name); - setsvalue2s(L, L->top, tname); /* push name to protect it */ + Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ + /* anchor closure (to avoid being collected) */ + setclLvalue(L, L->top, cl); incr_top(L); + funcstate.f = cl->l.p = luaF_newproto(L); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ lexstate.buff = buff; lexstate.dyd = dyd; dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; - luaX_setinput(L, &lexstate, z, tname, firstchar); - open_mainfunc(&lexstate, &funcstate, &bl); - luaX_next(&lexstate); /* read first token */ - statlist(&lexstate); /* main body */ - check(&lexstate, TK_EOS); - close_func(&lexstate); - L->top--; /* pop name */ + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); + mainfunc(&lexstate, &funcstate); lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); /* all scopes should be correctly finished */ lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - return funcstate.f; + return cl; /* it's on the stack too */ } -- cgit v1.2.3-55-g6feb