浏览代码

implementation of `global' statement

Roberto Ierusalimschy 23 年之前
父节点
当前提交
7ff21273d6
共有 4 个文件被更改,包括 211 次插入106 次删除
  1. 4 4
      llimits.h
  2. 187 82
      lparser.c
  3. 18 18
      lparser.h
  4. 2 2
      ltests.c

+ 4 - 4
llimits.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: llimits.h,v 1.38 2002/03/05 16:22:54 roberto Exp roberto $
+** $Id: llimits.h,v 1.39 2002/03/07 18:11:51 roberto Exp roberto $
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -96,9 +96,9 @@ typedef unsigned long Instruction;
 #define MAXSTACK	250
 #define MAXSTACK	250
 
 
 
 
-/* maximum number of local variables */
-#ifndef MAXLOCALS
-#define MAXLOCALS 200           /* arbitrary limit (<MAXSTACK) */
+/* maximum number of variables declared in a function */
+#ifndef MAXVARS
+#define MAXVARS 200           /* arbitrary limit (<MAXSTACK) */
 #endif
 #endif
 
 
 
 

+ 187 - 82
lparser.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.c,v 1.167 2002/02/14 21:46:58 roberto Exp $
+** $Id: lparser.c,v 1.168 2002/03/08 19:10:32 roberto Exp roberto $
 ** Lua Parser
 ** Lua Parser
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -24,14 +24,17 @@
 
 
 
 
 /*
 /*
-** nodes for break list (list of active breakable loops)
+** nodes for block list (list of active blocks)
 */
 */
-typedef struct Breaklabel {
-  struct Breaklabel *previous;  /* chain */
+typedef struct BlockCnt {
+  struct BlockCnt *previous;  /* chain */
   int breaklist;  /* list of jumps out of this loop */
   int breaklist;  /* list of jumps out of this loop */
-  int nactloc;  /* # of active local variables outside the breakable structure */
-} Breaklabel;
-
+  int nactloc;  /* # active local variables outside the breakable structure */
+  int nactvar;
+  int defaultglob;
+  int upval;  /* true if some variable in the block is an upvalue */
+  int isbreakable;  /* true if `block' is a loop */
+} BlockCnt;
 
 
 
 
 
 
@@ -77,9 +80,7 @@ static void check (LexState *ls, int c) {
 }
 }
 
 
 
 
-static void check_condition (LexState *ls, int c, const char *msg) {
-  if (!c) luaK_error(ls, msg);
-}
+#define check_condition(ls,c,msg)	{ if (!(c)) luaK_error(ls, msg); }
 
 
 
 
 static int optional (LexState *ls, int c) {
 static int optional (LexState *ls, int c) {
@@ -143,41 +144,51 @@ static int luaI_registerlocalvar (LexState *ls, TString *varname) {
 }
 }
 
 
 
 
-static void new_localvar (LexState *ls, TString *name, int n) {
+static vardesc *new_var (LexState *ls, int n) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
-  luaX_checklimit(ls, fs->nactloc+n+1, MAXLOCALS, "local variables");
-  fs->actloc[fs->nactloc+n] = luaI_registerlocalvar(ls, name);
+  luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "variables");
+  return &fs->actvar[fs->nactvar+n];
+}
+
+
+static void new_localvar (LexState *ls, TString *name, int n) {
+  vardesc *v = new_var(ls, n);  
+  v->k = VLOCAL;
+  v->i = luaI_registerlocalvar(ls, name);
+  v->level = ls->fs->nactloc + n;
 }
 }
 
 
 
 
 static void adjustlocalvars (LexState *ls, int nvars) {
 static void adjustlocalvars (LexState *ls, int nvars) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   while (nvars--) {
   while (nvars--) {
-    fs->f->locvars[fs->actloc[fs->nactloc]].startpc = fs->pc;
-    resetbit(fs->wasup, fs->nactloc);
+    lua_assert(fs->actvar[fs->nactvar].k == VLOCAL);
+    fs->f->locvars[fs->actvar[fs->nactvar].i].startpc = fs->pc;
+    fs->nactvar++;
     fs->nactloc++;
     fs->nactloc++;
   }
   }
 }
 }
 
 
 
 
-static void closelevel (LexState *ls, int level) {
+static void adjustglobalvars (LexState *ls, int nvars, int level) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
-  int i;
-  for (i=level; i<fs->nactloc; i++)
-    if (testbit(fs->wasup, i)) {
-      luaK_codeABC(fs, OP_CLOSE, level, 0, 0);
-      return;
-    }
-  return;  /* nothing to close */
+  while (nvars--) {
+    fs->actvar[fs->nactvar].k = VGLOBAL;
+    fs->actvar[fs->nactvar].level = level;
+    fs->nactvar++;
+  }
 }
 }
 
 
 
 
-static void removelocalvars (LexState *ls, int nvars, int toclose) {
+static void removevars (LexState *ls, int tolevel) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
-  if (toclose)
-    closelevel(ls, fs->nactloc - nvars);
-  while (nvars--)
-    fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc;
+  while (fs->nactvar > tolevel) {
+    fs->nactvar--;
+    if (fs->actvar[fs->nactvar].k == VLOCAL) {
+      fs->nactloc--;
+      fs->f->locvars[fs->actvar[fs->nactvar].i].endpc = fs->pc;
+    }
+  }
 }
 }
 
 
 
 
@@ -186,6 +197,12 @@ static void new_localvarstr (LexState *ls, const char *name, int n) {
 }
 }
 
 
 
 
+static void create_local (LexState *ls, const char *name) {
+  new_localvarstr(ls, name, 0);
+  adjustlocalvars(ls, 1);
+}
+
+
 static int indexupvalue (FuncState *fs, expdesc *v) {
 static int indexupvalue (FuncState *fs, expdesc *v) {
   int i;
   int i;
   for (i=0; i<fs->f->nupvalues; i++) {
   for (i=0; i<fs->f->nupvalues; i++) {
@@ -199,28 +216,72 @@ static int indexupvalue (FuncState *fs, expdesc *v) {
 }
 }
 
 
 
 
-static void singlevar (FuncState *fs, TString *n, expdesc *var, int baselevel) {
-  if (fs == NULL)
-    init_exp(var, VGLOBAL, 0);  /* not local in any level; global variable */
-  else {  /* look up at current level */
-    int i;
-    for (i=fs->nactloc-1; i >= 0; i--) {
-      if (n == fs->f->locvars[fs->actloc[i]].varname) {
-        if (!baselevel)
-          setbit(fs->wasup, i);  /* will be upvalue in some other level */
-        init_exp(var, VLOCAL, i);
-        return;
+static vardesc *searchvar (FuncState *fs, TString *n) {
+  int i;
+  for (i=fs->nactvar-1; i >= 0; i--) {
+    vardesc *v = &fs->actvar[i];
+    if (v->k == VLOCAL ? n == fs->f->locvars[v->i].varname
+                       : n == tsvalue(&fs->f->k[v->i]))
+      return v;
+  }
+  return NULL;  /* not found */
+}
+
+
+static void markupval (FuncState *fs, int level) {
+  BlockCnt *bl = fs->bl;
+  while (bl && bl->nactloc > level) bl = bl->previous;
+  if (bl) bl->upval = 1;
+}
+
+
+static int singlevar_aux (FuncState *fs, TString *n, expdesc *var, int nd) {
+  if (fs == NULL) {  /* no more levels? */
+    init_exp(var, VGLOBAL, NO_REG);  /* default is free global */
+    return VNIL;  /* not found */
+  }
+  else {
+    vardesc *v = searchvar(fs, n);  /* look up at current level */
+    if (v) {
+      if (v->level == NO_REG) {  /* free global? */
+        lua_assert(v->k == VGLOBAL);
+        init_exp(var, VGLOBAL, NO_REG);
       }
       }
+      else
+        init_exp(var, VLOCAL, v->level);
+      return v->k;
     }
     }
-    /* not found at current level; try upper one */
-    singlevar(fs->prev, n, var, 0);
-    if (var->k == VGLOBAL) {
-      if (baselevel)
-        var->info = luaK_stringK(fs, n);  /* info points to global name */
+    else {  /* not found at current level; try upper one */
+      int k = singlevar_aux(fs->prev, n, var, nd && fs->defaultglob == NO_REG);
+      if (var->k == VGLOBAL) {
+        if (k == VNIL && nd && fs->defaultglob != NO_REG) {
+          init_exp(var, VLOCAL, fs->defaultglob);
+          k = VGLOBAL;  /* now there is a declaration */
+        }
+      }
+      else {  /* LOCAL or UPVAL */
+        if (var->k == VLOCAL)
+          markupval(fs->prev, var->info);  /* local will be used as an upval */
+        var->info = indexupvalue(fs, var);
+        var->k = VUPVAL;  /* upvalue in this level */
+      }
+      return k;
     }
     }
-    else {  /* local variable in some upper level? */
-      var->info = indexupvalue(fs, var);
-      var->k = VUPVAL;  /* upvalue in this level */
+  }
+}
+
+
+static void singlevar (FuncState *fs, TString *n, expdesc *var) {
+  int k = singlevar_aux(fs, n, var, 1);
+  if (k == VNIL || k == VGLOBAL) {  /* global? */
+    if (var->k == VGLOBAL)  /* free global? */
+      var->info = luaK_stringK(fs, n);
+    else {  /* `indexed' global */
+      expdesc e;
+      codestring(fs->ls, &e, n);
+      luaK_exp2anyreg(fs, var);
+      var->aux = luaK_exp2RK(fs, &e);
+      var->k = VINDEXED;
     }
     }
   }
   }
 }
 }
@@ -250,29 +311,38 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
 static void code_params (LexState *ls, int nparams, int dots) {
 static void code_params (LexState *ls, int nparams, int dots) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   adjustlocalvars(ls, nparams);
   adjustlocalvars(ls, nparams);
-  luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters");
+  luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters");
   fs->f->numparams = cast(lu_byte, fs->nactloc);
   fs->f->numparams = cast(lu_byte, fs->nactloc);
   fs->f->is_vararg = cast(lu_byte, dots);
   fs->f->is_vararg = cast(lu_byte, dots);
-  if (dots) {
-    new_localvarstr(ls, "arg", 0);
-    adjustlocalvars(ls, 1);
-  }
+  if (dots)
+    create_local(ls, "arg");
   luaK_reserveregs(fs, fs->nactloc);  /* reserve register for parameters */
   luaK_reserveregs(fs, fs->nactloc);  /* reserve register for parameters */
 }
 }
 
 
 
 
-static void enterbreak (FuncState *fs, Breaklabel *bl) {
+static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) {
   bl->breaklist = NO_JUMP;
   bl->breaklist = NO_JUMP;
+  bl->isbreakable = isbreakable;
   bl->nactloc = fs->nactloc;
   bl->nactloc = fs->nactloc;
+  bl->nactvar = fs->nactvar;
+  bl->defaultglob = fs->defaultglob;
+  bl->upval = 0;
   bl->previous = fs->bl;
   bl->previous = fs->bl;
   fs->bl = bl;
   fs->bl = bl;
 }
 }
 
 
 
 
-static void leavebreak (FuncState *fs, Breaklabel *bl) {
+static void leaveblock (FuncState *fs) {
+  BlockCnt *bl = fs->bl;
   fs->bl = bl->previous;
   fs->bl = bl->previous;
-  luaK_patchtohere(fs, bl->breaklist);
+  removevars(fs->ls, bl->nactvar);
+  if (bl->upval)
+    luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0);
   lua_assert(bl->nactloc == fs->nactloc);
   lua_assert(bl->nactloc == fs->nactloc);
+  lua_assert(bl->nactvar == fs->nactvar);
+  fs->defaultglob = bl->defaultglob;
+  fs->freereg = bl->nactloc;  /* free registers used by locals */
+  luaK_patchtohere(fs, bl->breaklist);
 }
 }
 
 
 
 
@@ -308,7 +378,9 @@ static void open_func (LexState *ls, FuncState *fs) {
   fs->nlineinfo = 0;
   fs->nlineinfo = 0;
   fs->nlocvars = 0;
   fs->nlocvars = 0;
   fs->nactloc = 0;
   fs->nactloc = 0;
+  fs->nactvar = 0;
   fs->lastline = 0;
   fs->lastline = 0;
+  fs->defaultglob = NO_REG;  /* default is free globals */
   fs->bl = NULL;
   fs->bl = NULL;
   f->code = NULL;
   f->code = NULL;
   f->source = ls->source;
   f->source = ls->source;
@@ -322,7 +394,7 @@ static void close_func (LexState *ls) {
   lua_State *L = ls->L;
   lua_State *L = ls->L;
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   Proto *f = fs->f;
   Proto *f = fs->f;
-  removelocalvars(ls, fs->nactloc, 0);
+  removevars(ls, 0);
   luaK_codeABC(fs, OP_RETURN, 0, 1, 0);  /* final return */
   luaK_codeABC(fs, OP_RETURN, 0, 1, 0);  /* final return */
   luaK_getlabel(fs);  /* close eventual list of pending jumps */
   luaK_getlabel(fs);  /* close eventual list of pending jumps */
   lua_assert(G(L)->roottable == fs->h);
   lua_assert(G(L)->roottable == fs->h);
@@ -352,8 +424,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) {
   open_func(&lexstate, &funcstate);
   open_func(&lexstate, &funcstate);
   next(&lexstate);  /* read first token */
   next(&lexstate);  /* read first token */
   chunk(&lexstate);
   chunk(&lexstate);
-  check_condition(&lexstate, (lexstate.t.token == TK_EOS),
-                             "<eof> expected");
+  check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
   close_func(&lexstate);
   close_func(&lexstate);
   lua_assert(funcstate.prev == NULL);
   lua_assert(funcstate.prev == NULL);
   lua_assert(funcstate.f->nupvalues == 0);
   lua_assert(funcstate.f->nupvalues == 0);
@@ -593,13 +664,13 @@ static void prefixexp (LexState *ls, expdesc *v) {
       return;
       return;
     }
     }
     case TK_NAME: {
     case TK_NAME: {
-      singlevar(ls->fs, str_checkname(ls), v, 1);
+      singlevar(ls->fs, str_checkname(ls), v);
       next(ls);
       next(ls);
       return;
       return;
     }
     }
     case '%': {  /* for compatibility only */
     case '%': {  /* for compatibility only */
       next(ls);  /* skip `%' */
       next(ls);  /* skip `%' */
-      singlevar(ls->fs, str_checkname(ls), v, 1);
+      singlevar(ls->fs, str_checkname(ls), v);
       check_condition(ls, v->k == VUPVAL, "global upvalues are obsolete");
       check_condition(ls, v->k == VUPVAL, "global upvalues are obsolete");
       next(ls);
       next(ls);
       return;
       return;
@@ -797,10 +868,11 @@ static int block_follow (int token) {
 static void block (LexState *ls) {
 static void block (LexState *ls) {
   /* block -> chunk */
   /* block -> chunk */
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
-  int nactloc = fs->nactloc;
+  BlockCnt bl;
+  enterblock(fs, &bl, 0);
   chunk(ls);
   chunk(ls);
-  removelocalvars(ls, fs->nactloc - nactloc, 1);
-  fs->freereg = nactloc;  /* free registers used by locals */
+  lua_assert(bl.breaklist == NO_JUMP);
+  leaveblock(fs);
 }
 }
 
 
 
 
@@ -887,8 +959,8 @@ static void whilestat (LexState *ls, int line) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   int while_init = luaK_getlabel(fs);
   int while_init = luaK_getlabel(fs);
   expdesc v;
   expdesc v;
-  Breaklabel bl;
-  enterbreak(fs, &bl);
+  BlockCnt bl;
+  enterblock(fs, &bl, 1);
   next(ls);
   next(ls);
   cond(ls, &v);
   cond(ls, &v);
   check(ls, TK_DO);
   check(ls, TK_DO);
@@ -896,7 +968,7 @@ static void whilestat (LexState *ls, int line) {
   luaK_patchlist(fs, luaK_jump(fs), while_init);
   luaK_patchlist(fs, luaK_jump(fs), while_init);
   luaK_patchtohere(fs, v.f);
   luaK_patchtohere(fs, v.f);
   check_match(ls, TK_END, TK_WHILE, line);
   check_match(ls, TK_END, TK_WHILE, line);
-  leavebreak(fs, &bl);
+  leaveblock(fs);
 }
 }
 
 
 
 
@@ -905,14 +977,14 @@ static void repeatstat (LexState *ls, int line) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   int repeat_init = luaK_getlabel(fs);
   int repeat_init = luaK_getlabel(fs);
   expdesc v;
   expdesc v;
-  Breaklabel bl;
-  enterbreak(fs, &bl);
+  BlockCnt bl;
+  enterblock(fs, &bl, 1);
   next(ls);
   next(ls);
   block(ls);
   block(ls);
   check_match(ls, TK_UNTIL, TK_REPEAT, line);
   check_match(ls, TK_UNTIL, TK_REPEAT, line);
   cond(ls, &v);
   cond(ls, &v);
   luaK_patchlist(fs, v.f, repeat_init);
   luaK_patchlist(fs, v.f, repeat_init);
-  leavebreak(fs, &bl);
+  leaveblock(fs);
 }
 }
 
 
 
 
@@ -949,7 +1021,6 @@ static void fornum (LexState *ls, TString *varname) {
   block(ls);
   block(ls);
   luaK_patchtohere(fs, prep-1);
   luaK_patchtohere(fs, prep-1);
   luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep);
   luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep);
-  removelocalvars(ls, 3, 1);
 }
 }
 
 
 
 
@@ -977,7 +1048,6 @@ static void forlist (LexState *ls, TString *indexname) {
   block(ls);
   block(ls);
   luaK_patchlist(fs, luaK_jump(fs), prep-1);
   luaK_patchlist(fs, luaK_jump(fs), prep-1);
   luaK_patchtohere(fs, prep);
   luaK_patchtohere(fs, prep);
-  removelocalvars(ls, nvars+1, 1);
 }
 }
 
 
 
 
@@ -985,8 +1055,8 @@ static void forstat (LexState *ls, int line) {
   /* forstat -> fornum | forlist */
   /* forstat -> fornum | forlist */
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   TString *varname;
   TString *varname;
-  Breaklabel bl;
-  enterbreak(fs, &bl);
+  BlockCnt bl;
+  enterblock(fs, &bl, 1);
   next(ls);  /* skip `for' */
   next(ls);  /* skip `for' */
   varname = str_checkname(ls);  /* first variable name */
   varname = str_checkname(ls);  /* first variable name */
   next(ls);  /* skip var name */
   next(ls);  /* skip var name */
@@ -996,7 +1066,7 @@ static void forstat (LexState *ls, int line) {
     default: luaK_error(ls, "`=' or `in' expected");
     default: luaK_error(ls, "`=' or `in' expected");
   }
   }
   check_match(ls, TK_END, TK_FOR, line);
   check_match(ls, TK_END, TK_FOR, line);
-  leavebreak(fs, &bl);
+  leaveblock(fs);
 }
 }
 
 
 
 
@@ -1054,10 +1124,37 @@ static void localstat (LexState *ls) {
 }
 }
 
 
 
 
+static void globalstat (LexState *ls) {
+  /* stat -> GLOBAL NAME {`,' NAME} [IN exp] | GLOBAL IN exp */
+  FuncState *fs = ls->fs;
+  next(ls);  /* skip GLOBAL */
+  if (optional(ls, TK_IN)) {  /* default declaration? */
+    exp1(ls);
+    fs->defaultglob = fs->freereg - 1;
+    create_local(ls, "(global table)");
+  }
+  else {
+    int nvars = 0;
+    do {
+      vardesc *v = new_var(ls, nvars++);  
+      v->i = luaK_stringK(ls->fs, str_checkname(ls));
+      next(ls);  /* skip name */
+    } while (optional(ls, ','));
+    if (!optional(ls, TK_IN))
+      adjustglobalvars(ls, nvars, NO_REG);  /* free globals */
+    else {
+      exp1(ls);
+      adjustglobalvars(ls, nvars, ls->fs->freereg - 1);
+      create_local(ls, "(global table)");
+    }
+  }
+}
+
+
 static int funcname (LexState *ls, expdesc *v) {
 static int funcname (LexState *ls, expdesc *v) {
   /* funcname -> NAME {field} [`:' NAME] */
   /* funcname -> NAME {field} [`:' NAME] */
   int needself = 0;
   int needself = 0;
-  singlevar(ls->fs, str_checkname(ls), v, 1);
+  singlevar(ls->fs, str_checkname(ls), v);
   next(ls);  /* skip var name */
   next(ls);  /* skip var name */
   while (ls->t.token == '.') {
   while (ls->t.token == '.') {
     luaY_field(ls, v);
     luaY_field(ls, v);
@@ -1125,11 +1222,17 @@ static void retstat (LexState *ls) {
 static void breakstat (LexState *ls) {
 static void breakstat (LexState *ls) {
   /* stat -> BREAK [NAME] */
   /* stat -> BREAK [NAME] */
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
-  Breaklabel *bl = fs->bl;
+  BlockCnt *bl = fs->bl;
+  int upval = 0;
+  next(ls);  /* skip BREAK */
+  while (bl && !bl->isbreakable) {
+    upval |= bl->upval;
+    bl = bl->previous;
+  }
   if (!bl)
   if (!bl)
     luaK_error(ls, "no loop to break");
     luaK_error(ls, "no loop to break");
-  next(ls);  /* skip BREAK */
-  closelevel(ls, bl->nactloc);
+  if (upval)
+    luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0);
   luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
   luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
 }
 }
 
 
@@ -1167,6 +1270,10 @@ static int statement (LexState *ls) {
       localstat(ls);
       localstat(ls);
       return 0;
       return 0;
     }
     }
+    case TK_GLOBAL: {  /* stat -> globalstat */
+      globalstat(ls);
+      return 0;
+    }
     case TK_RETURN: {  /* stat -> retstat */
     case TK_RETURN: {  /* stat -> retstat */
       retstat(ls);
       retstat(ls);
       return 1;  /* must be last statement */
       return 1;  /* must be last statement */
@@ -1207,10 +1314,8 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
   open_func(ls, &new_fs);
   open_func(ls, &new_fs);
   new_fs.f->lineDefined = line;
   new_fs.f->lineDefined = line;
   check(ls, '(');
   check(ls, '(');
-  if (needself) {
-    new_localvarstr(ls, "self", 0);
-    adjustlocalvars(ls, 1);
-  }
+  if (needself)
+    create_local(ls, "self");
   parlist(ls);
   parlist(ls);
   check(ls, ')');
   check(ls, ')');
   chunk(ls);
   chunk(ls);

+ 18 - 18
lparser.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
+** $Id: lparser.h,v 1.39 2002/02/08 22:42:41 roberto Exp roberto $
 ** Lua Parser
 ** Lua Parser
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -13,18 +13,6 @@
 #include "lzio.h"
 #include "lzio.h"
 
 
 
 
-
-/* small implementation of bit arrays */
-
-#define BPW	(CHAR_BIT*sizeof(unsigned int))  /* bits per word */
-
-#define words2bits(b)	(((b)-1)/BPW + 1)
-
-#define setbit(a, b)	((a)[(b)/BPW] |= (1 << (b)%BPW))
-#define resetbit(a, b)	((a)[(b)/BPW] &= ~((1 << (b)%BPW)))
-#define testbit(a, b)	((a)[(b)/BPW] & (1 << (b)%BPW))
-
-
 /*
 /*
 ** Expression descriptor
 ** Expression descriptor
 */
 */
@@ -37,7 +25,7 @@ typedef enum {
   VK,		/* info = index of constant in `k' */
   VK,		/* info = index of constant in `k' */
   VLOCAL,	/* info = local register */
   VLOCAL,	/* info = local register */
   VUPVAL,       /* info = index of upvalue in `upvalues' */
   VUPVAL,       /* info = index of upvalue in `upvalues' */
-  VGLOBAL,	/* info = index of global name in `k' */
+  VGLOBAL,	/* info = index of table; aux = index of global name in `k' */
   VINDEXED,	/* info = table register; aux = index register (or `k') */
   VINDEXED,	/* info = table register; aux = index register (or `k') */
   VRELOCABLE,	/* info = instruction pc */
   VRELOCABLE,	/* info = instruction pc */
   VNONRELOC,	/* info = result register */
   VNONRELOC,	/* info = result register */
@@ -53,6 +41,18 @@ typedef struct expdesc {
 } expdesc;
 } expdesc;
 
 
 
 
+/* describe declared variables */
+typedef struct vardesc {
+  int i;  /* if local, its index in `locvars';
+             if global, its name index in `k' */
+  lu_byte k;
+  lu_byte level;  /* if local, stack level;
+                     if global, corresponding local (NO_REG for free globals) */
+} vardesc;
+
+
+struct BlockCnt;  /* defined in lparser.c */
+
 /* state needed to generate code for a given function */
 /* state needed to generate code for a given function */
 typedef struct FuncState {
 typedef struct FuncState {
   Proto *f;  /* current function header */
   Proto *f;  /* current function header */
@@ -60,21 +60,21 @@ typedef struct FuncState {
   struct FuncState *prev;  /* enclosing function */
   struct FuncState *prev;  /* enclosing function */
   struct LexState *ls;  /* lexical state */
   struct LexState *ls;  /* lexical state */
   struct lua_State *L;  /* copy of the Lua state */
   struct lua_State *L;  /* copy of the Lua state */
-  struct Breaklabel *bl;  /* chain of breakable blocks */
+  struct BlockCnt *bl;  /* chain of current blocks */
   int pc;  /* next position to code (equivalent to `ncode') */
   int pc;  /* next position to code (equivalent to `ncode') */
   int lasttarget;   /* `pc' of last `jump target' */
   int lasttarget;   /* `pc' of last `jump target' */
   int jlt;  /* list of jumps to `lasttarget' */
   int jlt;  /* list of jumps to `lasttarget' */
   int freereg;  /* first free register */
   int freereg;  /* first free register */
+  int defaultglob;  /* where to look for non-declared globals */
   int nk;  /* number of elements in `k' */
   int nk;  /* number of elements in `k' */
   int np;  /* number of elements in `p' */
   int np;  /* number of elements in `p' */
   int nlineinfo;  /* number of elements in `lineinfo' */
   int nlineinfo;  /* number of elements in `lineinfo' */
   int nlocvars;  /* number of elements in `locvars' */
   int nlocvars;  /* number of elements in `locvars' */
   int nactloc;  /* number of active local variables */
   int nactloc;  /* number of active local variables */
+  int nactvar;  /* number of elements in array `actvar' */
   int lastline;  /* line where last `lineinfo' was generated */
   int lastline;  /* line where last `lineinfo' was generated */
   expdesc upvalues[MAXUPVALUES];  /* upvalues */
   expdesc upvalues[MAXUPVALUES];  /* upvalues */
-  int actloc[MAXLOCALS];  /* local-variable stack (indices to locvars) */
-  unsigned int wasup[words2bits(MAXLOCALS)];  /* bit array to mark whether a
-                             local variable was used as upvalue at some level */
+  vardesc actvar[MAXVARS];  /* declared-variable stack */
 } FuncState;
 } FuncState;
 
 
 
 

+ 2 - 2
ltests.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltests.c,v 1.110 2002/03/04 15:26:56 roberto Exp roberto $
+** $Id: ltests.c,v 1.111 2002/03/04 21:29:41 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -219,7 +219,7 @@ static int get_limits (lua_State *L) {
   lua_newtable(L);
   lua_newtable(L);
   setnameval(L, "BITS_INT", BITS_INT);
   setnameval(L, "BITS_INT", BITS_INT);
   setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
   setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
-  setnameval(L, "MAXLOCALS", MAXLOCALS);
+  setnameval(L, "MAXVARS", MAXVARS);
   setnameval(L, "MAXPARAMS", MAXPARAMS);
   setnameval(L, "MAXPARAMS", MAXPARAMS);
   setnameval(L, "MAXSTACK", MAXSTACK);
   setnameval(L, "MAXSTACK", MAXSTACK);
   setnameval(L, "MAXUPVALUES", MAXUPVALUES);
   setnameval(L, "MAXUPVALUES", MAXUPVALUES);