some reorganization of dynamic data structures used by the parser

This commit is contained in:
Roberto Ierusalimschy 2011-02-07 15:14:50 -02:00
parent f8d677f94c
commit f079749287
4 changed files with 104 additions and 118 deletions

23
ldo.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 2.90 2010/10/25 19:01:37 roberto Exp roberto $ ** $Id: ldo.c,v 2.91 2011/02/04 17:34:43 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -615,10 +615,8 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
*/ */
struct SParser { /* data to `f_parser' */ struct SParser { /* data to `f_parser' */
ZIO *z; ZIO *z;
Mbuffer buff; /* buffer to be used by the scanner */ Mbuffer buff; /* dynamic structure used by the scanner */
Varlist varl; /* list of local variables (to be used by the parser) */ Dyndata dyd; /* dynamic structures used by the parser */
Gotolist gtl; /* list of pending gotos (") */
Labellist labell; /* list of active labels (") */
const char *name; const char *name;
}; };
@ -630,8 +628,7 @@ static void f_parser (lua_State *L, void *ud) {
int c = luaZ_lookahead(p->z); int c = luaZ_lookahead(p->z);
tf = (c == LUA_SIGNATURE[0]) tf = (c == LUA_SIGNATURE[0])
? luaU_undump(L, p->z, &p->buff, p->name) ? luaU_undump(L, p->z, &p->buff, p->name)
: luaY_parser(L, p->z, &p->buff, &p->varl, : luaY_parser(L, p->z, &p->buff, &p->dyd, p->name);
&p->gtl, &p->labell, p->name);
setptvalue2s(L, L->top, tf); setptvalue2s(L, L->top, tf);
incr_top(L); incr_top(L);
cl = luaF_newLclosure(L, tf); cl = luaF_newLclosure(L, tf);
@ -646,15 +643,15 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
int status; int status;
L->nny++; /* cannot yield during parsing */ L->nny++; /* cannot yield during parsing */
p.z = z; p.name = name; p.z = z; p.name = name;
p.varl.actvar = NULL; p.varl.nactvar = p.varl.actvarsize = 0; p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
p.gtl.gt = NULL; p.gtl.ngt = p.gtl.gtsize = 0; p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
p.labell.label = NULL; p.labell.nlabel = p.labell.labelsize = 0; p.dyd.label.arr = NULL; p.dyd.label.size = 0;
luaZ_initbuffer(L, &p.buff); luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff); luaZ_freebuffer(L, &p.buff);
luaM_freearray(L, p.varl.actvar, p.varl.actvarsize); luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
luaM_freearray(L, p.gtl.gt, p.gtl.gtsize); luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
luaM_freearray(L, p.labell.label, p.labell.labelsize); luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
L->nny--; L->nny--;
return status; return status;
} }

10
llex.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: llex.h,v 1.66 2011/02/02 14:55:17 roberto Exp roberto $ ** $Id: llex.h,v 1.67 2011/02/04 17:34:43 roberto Exp roberto $
** Lexical Analyzer ** Lexical Analyzer
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -48,19 +48,19 @@ typedef struct Token {
} Token; } Token;
/* state of the lexer plus state of the parser when shared by all
functions */
typedef struct LexState { typedef struct LexState {
int current; /* current character (charint) */ int current; /* current character (charint) */
int linenumber; /* input line counter */ int linenumber; /* input line counter */
int lastline; /* line of last token `consumed' */ int lastline; /* line of last token `consumed' */
Token t; /* current token */ Token t; /* current token */
Token lookahead; /* look ahead token */ Token lookahead; /* look ahead token */
struct FuncState *fs; /* `FuncState' is private to the parser */ struct FuncState *fs; /* current function (parser) */
struct lua_State *L; struct lua_State *L;
ZIO *z; /* input stream */ ZIO *z; /* input stream */
Mbuffer *buff; /* buffer for tokens */ Mbuffer *buff; /* buffer for tokens */
struct Varlist *varl; /* list of all active local variables */ struct Dyndata *dyd; /* dynamic structures used by the parser */
struct Gotolist *gtl; /* list of pending gotos */
struct Labellist *labell; /* list of active labels */
TString *source; /* current source name */ TString *source; /* current source name */
TString *envn; /* environment variable name */ TString *envn; /* environment variable name */
char decpoint; /* locale decimal point */ char decpoint; /* locale decimal point */

129
lparser.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 2.97 2011/02/04 17:34:43 roberto Exp roberto $ ** $Id: lparser.c,v 2.98 2011/02/07 12:28:27 roberto Exp roberto $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -42,8 +42,8 @@
typedef struct BlockCnt { typedef struct BlockCnt {
struct BlockCnt *previous; /* chain */ struct BlockCnt *previous; /* chain */
int breaklist; /* list of jumps out of this loop */ int breaklist; /* list of jumps out of this loop */
int firstlabel; /* index (in Labellist) of first label in this block */ int firstlabel; /* index of first label in this block */
int firstgoto; /* index (in Gotolist) of first pending goto in this block */ int firstgoto; /* index of first pending goto in this block */
lu_byte nactvar; /* # active locals outside the block */ lu_byte nactvar; /* # active locals outside the block */
lu_byte upval; /* true if some variable in the block is an upvalue */ lu_byte upval; /* true if some variable in the block is an upvalue */
lu_byte isbreakable; /* true if `block' is a loop */ lu_byte isbreakable; /* true if `block' is a loop */
@ -169,13 +169,13 @@ static int registerlocalvar (LexState *ls, TString *varname) {
static void new_localvar (LexState *ls, TString *name) { static void new_localvar (LexState *ls, TString *name) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
Varlist *vl = ls->varl; Dyndata *dyd = ls->dyd;
int reg = registerlocalvar(ls, name); int reg = registerlocalvar(ls, name);
checklimit(fs, vl->nactvar + 1 - fs->firstlocal, checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
MAXVARS, "local variables"); MAXVARS, "local variables");
luaM_growvector(ls->L, vl->actvar, vl->nactvar + 1, luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1,
vl->actvarsize, Vardesc, MAX_INT, "local variables"); dyd->actvar.size, Vardesc, MAX_INT, "local variables");
vl->actvar[vl->nactvar++].idx = cast(unsigned short, reg); dyd->actvar.arr[dyd->actvar.n++].idx = cast(unsigned short, reg);
} }
@ -188,7 +188,7 @@ static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) {
static LocVar *getlocvar (FuncState *fs, int i) { static LocVar *getlocvar (FuncState *fs, int i) {
int idx = fs->ls->varl->actvar[fs->firstlocal + i].idx; int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx;
lua_assert(idx < fs->nlocvars); lua_assert(idx < fs->nlocvars);
return &fs->f->locvars[idx]; return &fs->f->locvars[idx];
} }
@ -204,7 +204,7 @@ static void adjustlocalvars (LexState *ls, int nvars) {
static void removevars (FuncState *fs, int tolevel) { static void removevars (FuncState *fs, int tolevel) {
fs->ls->varl->nactvar -= (fs->nactvar - tolevel); fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel);
while (fs->nactvar > tolevel) while (fs->nactvar > tolevel)
getlocvar(fs, --fs->nactvar)->endpc = fs->pc; getlocvar(fs, --fs->nactvar)->endpc = fs->pc;
} }
@ -332,19 +332,20 @@ static void enterlevel (LexState *ls) {
static void closegoto (LexState *ls, int g, Labeldesc *label) { static void closegoto (LexState *ls, int g, Labeldesc *label) {
int i; int i;
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
Gotodesc *gt = &ls->gtl->gt[g]; Dyndata *dyd = ls->dyd;
Labeldesc *gt = &dyd->gt.arr[g];
lua_assert(gt->name == label->name); lua_assert(gt->name == label->name);
if (gt->currlevel < label->nactvar) { if (gt->nactvar < label->nactvar) {
const char *msg = luaO_pushfstring(ls->L, const char *msg = luaO_pushfstring(ls->L,
"<goto> at line %d attemps to jump into the scope of local " LUA_QS, "<goto> at line %d attemps to jump into the scope of local " LUA_QS,
gt->line, getstr(getlocvar(fs, gt->currlevel)->varname));; gt->line, getstr(getlocvar(fs, gt->nactvar)->varname));;
luaX_syntaxerror(ls, msg); luaX_syntaxerror(ls, msg);
} }
luaK_patchlist(fs, gt->pc, label->pc); luaK_patchlist(fs, gt->pc, label->pc);
/* remove goto from pending list */ /* remove goto from pending list */
for (i = g; i < ls->gtl->ngt - 1; i++) for (i = g; i < dyd->gt.n - 1; i++)
ls->gtl->gt[i] = ls->gtl->gt[i + 1]; dyd->gt.arr[i] = dyd->gt.arr[i + 1];
ls->gtl->ngt--; dyd->gt.n--;
} }
@ -354,15 +355,15 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
static int findlabel (LexState *ls, int g) { static int findlabel (LexState *ls, int g) {
int i; int i;
BlockCnt *bl = ls->fs->bl; BlockCnt *bl = ls->fs->bl;
Labellist *labell = ls->labell; Dyndata *dyd = ls->dyd;
Gotodesc *gt = &ls->gtl->gt[g]; Labeldesc *gt = &dyd->gt.arr[g];
/* check labels in current block for a match */ /* check labels in current block for a match */
for (i = bl->firstlabel; i < labell->nlabel; i++) { for (i = bl->firstlabel; i < dyd->label.n; i++) {
Labeldesc *lb = &labell->label[i]; Labeldesc *lb = &dyd->label.arr[i];
if (lb->name == gt->name) { if (lb->name == gt->name) {
lua_assert(labell->label[i].pc <= gt->pc); lua_assert(lb->pc <= gt->pc);
if (gt->currlevel > lb->nactvar && if (gt->nactvar > lb->nactvar &&
(bl->upval || ls->labell->nlabel > bl->firstlabel)) (bl->upval || dyd->label.n > bl->firstlabel))
luaK_patchclose(ls->fs, gt->pc, lb->nactvar); luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
closegoto(ls, g, lb); /* close it */ closegoto(ls, g, lb); /* close it */
return 1; return 1;
@ -378,9 +379,9 @@ static int findlabel (LexState *ls, int g) {
*/ */
static void findgotos (LexState *ls, Labeldesc *lb) { static void findgotos (LexState *ls, Labeldesc *lb) {
int i; int i;
Gotolist *gtl = ls->gtl; Dyndata *dyd = ls->dyd;
for (i = ls->fs->bl->firstgoto; i < gtl->ngt; i++) { for (i = ls->fs->bl->firstgoto; i < dyd->gt.n; i++) {
if (gtl->gt[i].name == lb->name) if (dyd->gt.arr[i].name == lb->name)
closegoto(ls, i, lb); closegoto(ls, i, lb);
} }
} }
@ -394,17 +395,17 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
*/ */
static void movegotosout (FuncState *fs, BlockCnt *bl) { static void movegotosout (FuncState *fs, BlockCnt *bl) {
int i = bl->firstgoto; int i = bl->firstgoto;
LexState *ls = fs->ls; Dyndata *dyd = fs->ls->dyd;
/* correct pending gotos to current block and try to close it /* correct pending gotos to current block and try to close it
with visible labels */ with visible labels */
while (i < ls->gtl->ngt) { while (i < dyd->gt.n) {
Gotodesc *gt = &ls->gtl->gt[i]; Labeldesc *gt = &dyd->gt.arr[i];
if (gt->currlevel > bl->nactvar) { if (gt->nactvar > bl->nactvar) {
if (bl->upval) if (bl->upval)
luaK_patchclose(fs, gt->pc, bl->nactvar); luaK_patchclose(fs, gt->pc, bl->nactvar);
gt->currlevel = bl->nactvar; gt->nactvar = bl->nactvar;
} }
if (!findlabel(ls, i)) if (!findlabel(fs->ls, i))
i++; /* move to next one */ i++; /* move to next one */
} }
} }
@ -414,8 +415,8 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
bl->breaklist = NO_JUMP; bl->breaklist = NO_JUMP;
bl->isbreakable = isbreakable; bl->isbreakable = isbreakable;
bl->nactvar = fs->nactvar; bl->nactvar = fs->nactvar;
bl->firstlabel = fs->ls->labell->nlabel; bl->firstlabel = fs->ls->dyd->label.n;
bl->firstgoto = fs->ls->gtl->ngt; bl->firstgoto = fs->ls->dyd->gt.n;
bl->upval = 0; bl->upval = 0;
bl->previous = fs->bl; bl->previous = fs->bl;
fs->bl = bl; fs->bl = bl;
@ -427,7 +428,7 @@ static void leaveblock (FuncState *fs) {
BlockCnt *bl = fs->bl; BlockCnt *bl = fs->bl;
fs->bl = bl->previous; fs->bl = bl->previous;
removevars(fs, bl->nactvar); removevars(fs, bl->nactvar);
fs->ls->labell->nlabel = bl->firstlabel; /* remove local labels */ fs->ls->dyd->label.n = bl->firstlabel; /* remove local labels */
movegotosout(fs, bl); movegotosout(fs, bl);
if (bl->upval) { if (bl->upval) {
/* create a 'jump to here' to close upvalues */ /* create a 'jump to here' to close upvalues */
@ -479,7 +480,7 @@ static void open_func (LexState *ls, FuncState *fs) {
fs->nups = 0; fs->nups = 0;
fs->nlocvars = 0; fs->nlocvars = 0;
fs->nactvar = 0; fs->nactvar = 0;
fs->firstlocal = ls->varl->nactvar; fs->firstlocal = ls->dyd->actvar.n;
fs->bl = NULL; fs->bl = NULL;
f = luaF_newproto(L); f = luaF_newproto(L);
fs->f = f; fs->f = f;
@ -540,8 +541,8 @@ static void mainblock (LexState *ls, FuncState *fs) {
BlockCnt bl; BlockCnt bl;
enterblock(fs, &bl, 0); enterblock(fs, &bl, 0);
statlist(ls); /* read main block */ statlist(ls); /* read main block */
if (bl.firstgoto < ls->gtl->ngt) { /* check pending gotos */ if (bl.firstgoto < ls->dyd->gt.n) { /* check pending gotos */
Gotodesc *gt = &ls->gtl->gt[bl.firstgoto]; Labeldesc *gt = &ls->dyd->gt.arr[bl.firstgoto];
const char *msg = luaO_pushfstring(ls->L, const char *msg = luaO_pushfstring(ls->L,
"label " LUA_QS " (<goto> at line %d) undefined", "label " LUA_QS " (<goto> at line %d) undefined",
getstr(gt->name), gt->line); getstr(gt->name), gt->line);
@ -552,17 +553,16 @@ static void mainblock (LexState *ls, FuncState *fs) {
} }
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Varlist *varl, Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
Gotolist *gtl, Labellist *labell, const char *name) { Dyndata *dyd, const char *name) {
LexState lexstate; LexState lexstate;
FuncState funcstate; FuncState funcstate;
TString *tname = luaS_new(L, name); TString *tname = luaS_new(L, name);
setsvalue2s(L, L->top, tname); /* push name to protect it */ setsvalue2s(L, L->top, tname); /* push name to protect it */
incr_top(L); incr_top(L);
lexstate.buff = buff; lexstate.buff = buff;
lexstate.varl = varl; lexstate.dyd = dyd;
lexstate.gtl = gtl; dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
lexstate.labell = labell;
luaX_setinput(L, &lexstate, z, tname); luaX_setinput(L, &lexstate, z, tname);
open_mainfunc(&lexstate, &funcstate); open_mainfunc(&lexstate, &funcstate);
luaX_next(&lexstate); /* read first token */ luaX_next(&lexstate); /* read first token */
@ -1172,22 +1172,27 @@ static void breakstat (LexState *ls) {
luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
if (upval || if (upval ||
(fs->nactvar > bl->nactvar && (fs->nactvar > bl->nactvar &&
ls->labell->nlabel > bl->firstlabel)) ls->dyd->label.n > bl->firstlabel))
luaK_patchclose(fs, bl->breaklist, bl->nactvar); luaK_patchclose(fs, bl->breaklist, bl->nactvar);
} }
static int newlabelentry (LexState *ls, Labellist *l, TString *name,
int line, int pc) {
int n = l->n;
luaM_growvector(ls->L, l->arr, l->n, l->size, Labeldesc, MAX_INT, "labels");
l->arr[n].name = name;
l->arr[n].line = line;
l->arr[n].nactvar = ls->fs->nactvar;
l->arr[n].pc = pc;
l->n++;
return n;
}
static void gotostat (LexState *ls, TString *label, int line) { static void gotostat (LexState *ls, TString *label, int line) {
Gotolist *gtl = ls->gtl;
int g = gtl->ngt; /* index of new goto being created */
/* create new entry for this goto */ /* create new entry for this goto */
luaM_growvector(ls->L, gtl->gt, gtl->ngt, gtl->gtsize, int g = newlabelentry(ls, &ls->dyd->gt, label, line, luaK_jump(ls->fs));
Gotodesc, MAX_INT, "labels");
gtl->gt[g].name = label;
gtl->gt[g].line = line;
gtl->gt[g].currlevel = ls->fs->nactvar;
gtl->gt[g].pc = luaK_jump(ls->fs); /* create jump instruction */
gtl->ngt++;
findlabel(ls, g); findlabel(ls, g);
} }
@ -1195,21 +1200,17 @@ static void gotostat (LexState *ls, TString *label, int line) {
static void labelstat (LexState *ls, TString *label) { static void labelstat (LexState *ls, TString *label) {
/* label -> '@' NAME ':' */ /* label -> '@' NAME ':' */
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
Labellist *labell = ls->labell; int l; /* index of new label being created */
int l = labell->nlabel; /* index of new label being created */ Labeldesc *lb;
checknext(ls, ':'); checknext(ls, ':');
/* create new entry for this label */ /* create new entry for this label */
luaM_growvector(ls->L, labell->label, labell->nlabel, labell->labelsize, l = newlabelentry(ls, &ls->dyd->label, label, 0, fs->pc);
Labeldesc, MAX_INT, "labels"); lb = &ls->dyd->label.arr[l];
labell->label[l].name = label;
labell->label[l].pc = fs->pc;
/* if label is last statement in the block, /* if label is last statement in the block,
assume that local variables are already out of scope */ assume that local variables are already out of scope */
labell->label[l].nactvar = (ls->t.token == TK_END) if (ls->t.token == TK_END)
? fs->bl->nactvar lb->nactvar = fs->bl->nactvar;
: fs->nactvar; findgotos(ls, lb);
labell->nlabel++;
findgotos(ls, &labell->label[l]);
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.h,v 1.65 2010/07/07 16:27:29 roberto Exp roberto $ ** $Id: lparser.h,v 1.66 2011/02/04 17:34:43 roberto Exp roberto $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -59,47 +59,36 @@ typedef struct Vardesc {
} Vardesc; } Vardesc;
/* list of all active local variables */ /* description of pending goto statements and label statements */
typedef struct Varlist {
Vardesc *actvar;
int nactvar;
int actvarsize;
} Varlist;
/* description of pending goto statement */
typedef struct Gotodesc {
TString *name;
int pc; /* where it is coded */
int line; /* line where it appeared */
lu_byte currlevel; /* variable level where it appears in current block */
} Gotodesc;
/* list of pending gotos */
typedef struct Gotolist {
Gotodesc *gt;
int ngt;
int gtsize;
} Gotolist;
/* description of active labels */
typedef struct Labeldesc { typedef struct Labeldesc {
TString *name; TString *name; /* label identifier */
int pc; /* label position */ int pc; /* position in code */
lu_byte nactvar; /* variable level where it appears in current block */ int line; /* line where it appeared */
lu_byte nactvar; /* local level where it appears in current block */
} Labeldesc; } Labeldesc;
/* list of active labels */ /* list of labels or gotos */
typedef struct Labellist { typedef struct Labellist {
Labeldesc *label; Labeldesc *arr; /* array */
int nlabel; int n; /* number of entries in use */
int labelsize; int size; /* array size */
} Labellist; } Labellist;
/* dynamic structures used by the parser */
typedef struct Dyndata {
struct { /* list of active local variables */
Vardesc *arr;
int n;
int size;
} actvar;
Labellist gt; /* list of pending gotos */
Labellist label; /* list of active labels */
} Dyndata;
/* control of blocks */
struct BlockCnt; /* defined in lparser.c */ struct BlockCnt; /* defined in lparser.c */
@ -125,8 +114,7 @@ typedef struct FuncState {
LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
Varlist *varl, Gotolist *gtl, Dyndata *dyd, const char *name);
Labellist *labell, const char *name);
#endif #endif