From 8332d5c8a5059b85da1adaa3f0197d0f57afae81 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 27 Aug 2003 18:01:44 -0300 Subject: parser fully reentrant(!) --- lparser.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 1eb56401..633a5693 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.215 2003/07/29 18:51:00 roberto Exp roberto $ +** $Id: lparser.c,v 1.216 2003/08/25 19:51:54 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -13,6 +13,7 @@ #include "lcode.h" #include "ldebug.h" +#include "ldo.h" #include "lfunc.h" #include "llex.h" #include "lmem.h" @@ -71,6 +72,14 @@ static void lookahead (LexState *ls) { } +static void anchor_token (LexState *ls) { + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + TString *ts = ls->t.seminfo.ts; + luaX_newstring(ls, getstr(ts), ts->tsv.len); + } +} + + static void error_expected (LexState *ls, int token) { luaX_syntaxerror(ls, luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token))); @@ -138,9 +147,11 @@ static void checkname(LexState *ls, expdesc *e) { static int luaI_registerlocalvar (LexState *ls, TString *varname) { FuncState *fs = ls->fs; Proto *f = fs->f; + int oldsize = f->sizelocvars; luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, LocVar, USHRT_MAX, "too many local variables"); - f->locvars[fs->nlocvars].varname = varname; + while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; /* write barrier */ return fs->nlocvars++; } @@ -170,24 +181,27 @@ static void removevars (LexState *ls, int tolevel) { static void new_localvarstr (LexState *ls, const char *name, int n) { - new_localvar(ls, luaS_new(ls->L, name), n); + TString *ts = luaX_newstring(ls, name, strlen(name)); + new_localvar(ls, ts, n); } static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { int i; Proto *f = fs->f; + int oldsize = f->sizeupvalues; for (i=0; inups; i++) { if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { - lua_assert(fs->f->upvalues[i] == name); + lua_assert(f->upvalues[i] == name); return i; } } /* new one */ luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues"); - luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues, + luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, TString *, MAX_INT, ""); - fs->f->upvalues[f->nups] = name; + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; + f->upvalues[f->nups] = name; /* write barrier */ lua_assert(v->k == VLOCAL || v->k == VUPVAL); fs->upvalues[f->nups].k = cast(lu_byte, v->k); fs->upvalues[f->nups].info = cast(lu_byte, v->info); @@ -290,10 +304,12 @@ static void leaveblock (FuncState *fs) { static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { FuncState *fs = ls->fs; Proto *f = fs->f; + int oldsize = f->sizep; int i; luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "constant table overflow"); - f->p[fs->np++] = func->f; + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + f->p[fs->np++] = func->f; /* write barrier */ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); for (i=0; if->nups; i++) { OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; @@ -303,24 +319,30 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { static void open_func (LexState *ls, FuncState *fs) { + lua_State *L = ls->L; Proto *f = luaF_newproto(ls->L); fs->f = f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; - fs->L = ls->L; + fs->L = L; ls->fs = fs; fs->pc = 0; fs->lasttarget = 0; fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; - fs->h = luaH_new(ls->L, 0, 0); fs->np = 0; fs->nlocvars = 0; fs->nactvar = 0; fs->bl = NULL; f->source = ls->source; f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L, 0, 0); + /* anchor table of constants and prototype (to avoid being collected) */ + sethvalue2s(L->top, fs->h); + incr_top(L); + setptvalue2s(L->top, f); + incr_top(L); } @@ -345,6 +367,9 @@ static void close_func (LexState *ls) { lua_assert(luaG_checkcode(f)); lua_assert(fs->bl == NULL); ls->fs = fs->prev; + L->top -= 2; /* remove table and prototype from the stack */ + /* last token read was anchored in defunct function; must reanchor it */ + if (fs) anchor_token(ls); } @@ -362,6 +387,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { lua_assert(funcstate.prev == NULL); lua_assert(funcstate.f->nups == 0); lua_assert(lexstate.nestlevel == 0); + lua_assert(lexstate.fs == NULL); return funcstate.f; } @@ -530,7 +556,7 @@ static void parlist (LexState *ls) { case TK_DOTS: { /* param -> `...' */ next(ls); /* use `arg' as default name */ - new_localvar(ls, luaS_new(ls->L, "arg"), nparams++); + new_localvarstr(ls, "arg", nparams++); f->is_vararg = 1; break; } -- cgit v1.2.3-55-g6feb