Browse Source

some reorganization of dynamic data structures used by the parser

Roberto Ierusalimschy 14 years ago
parent
commit
f079749287
4 changed files with 104 additions and 118 deletions
  1. 10 13
      ldo.c
  2. 5 5
      llex.h
  3. 65 64
      lparser.c
  4. 24 36
      lparser.h

+ 10 - 13
ldo.c

@@ -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
 ** 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' */
   ZIO *z;
-  Mbuffer buff;  /* buffer to be used by the scanner */
-  Varlist varl;  /* list of local variables (to be used by the parser) */
-  Gotolist gtl;  /* list of pending gotos (") */
-  Labellist labell;  /* list of active labels (") */
+  Mbuffer buff;  /* dynamic structure used by the scanner */
+  Dyndata dyd;  /* dynamic structures used by the parser */
   const char *name;
 };
 
@@ -630,8 +628,7 @@ static void f_parser (lua_State *L, void *ud) {
   int c = luaZ_lookahead(p->z);
   tf = (c == LUA_SIGNATURE[0])
            ? luaU_undump(L, p->z, &p->buff, p->name)
-           : luaY_parser(L, p->z, &p->buff, &p->varl,
-                            &p->gtl, &p->labell, p->name);
+           : luaY_parser(L, p->z, &p->buff, &p->dyd, p->name);
   setptvalue2s(L, L->top, tf);
   incr_top(L);
   cl = luaF_newLclosure(L, tf);
@@ -646,15 +643,15 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
   int status;
   L->nny++;  /* cannot yield during parsing */
   p.z = z; p.name = name;
-  p.varl.actvar = NULL; p.varl.nactvar = p.varl.actvarsize = 0;
-  p.gtl.gt = NULL; p.gtl.ngt = p.gtl.gtsize = 0;
-  p.labell.label = NULL; p.labell.nlabel = p.labell.labelsize = 0;
+  p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
+  p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
+  p.dyd.label.arr = NULL; p.dyd.label.size = 0;
   luaZ_initbuffer(L, &p.buff);
   status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
   luaZ_freebuffer(L, &p.buff);
-  luaM_freearray(L, p.varl.actvar, p.varl.actvarsize);
-  luaM_freearray(L, p.gtl.gt, p.gtl.gtsize);
-  luaM_freearray(L, p.labell.label, p.labell.labelsize);
+  luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
+  luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
+  luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
   L->nny--;
   return status;
 }

+ 5 - 5
llex.h

@@ -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
 ** See Copyright Notice in lua.h
 */
@@ -48,19 +48,19 @@ typedef struct Token {
 } Token;
 
 
+/* state of the lexer plus state of the parser when shared by all
+   functions */
 typedef struct LexState {
   int current;  /* current character (charint) */
   int linenumber;  /* input line counter */
   int lastline;  /* line of last token `consumed' */
   Token t;  /* current 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;
   ZIO *z;  /* input stream */
   Mbuffer *buff;  /* buffer for tokens */
-  struct Varlist *varl;  /* list of all active local variables */
-  struct Gotolist *gtl;  /* list of pending gotos */
-  struct Labellist *labell;  /* list of active labels */
+  struct Dyndata *dyd;  /* dynamic structures used by the parser */
   TString *source;  /* current source name */
   TString *envn;  /* environment variable name */
   char decpoint;  /* locale decimal point */

+ 65 - 64
lparser.c

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

+ 24 - 36
lparser.h

@@ -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
 ** See Copyright Notice in lua.h
 */
@@ -59,47 +59,36 @@ typedef struct Vardesc {
 } Vardesc;
 
 
-/* list of all active local variables */
-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 */
+/* description of pending goto statements and label statements */
 typedef struct Labeldesc {
-  TString *name;
-  int pc;  /* label position */
-  lu_byte nactvar;  /* variable level where it appears in current block */
+  TString *name;  /* label identifier */
+  int pc;  /* position in code */
+  int line;  /* line where it appeared */
+  lu_byte nactvar;  /* local level where it appears in current block */
 } Labeldesc;
 
 
-/* list of active labels */
+/* list of labels or gotos */
 typedef struct Labellist {
-  Labeldesc *label;
-  int nlabel;
-  int labelsize;
+  Labeldesc *arr;  /* array */
+  int n;  /* number of entries in use */
+  int size;  /* array size */
 } 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 */
 
 
@@ -125,8 +114,7 @@ typedef struct FuncState {
 
 
 LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
-                              Varlist *varl, Gotolist *gtl,
-                              Labellist *labell,  const char *name);
+                              Dyndata *dyd, const char *name);
 
 
 #endif