浏览代码

special treatment for 'global in nil'

Roberto Ierusalimschy 23 年之前
父节点
当前提交
58badbab99
共有 2 个文件被更改,包括 29 次插入22 次删除
  1. 3 2
      lopcodes.h
  2. 26 20
      lparser.c

+ 3 - 2
lopcodes.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lopcodes.h,v 1.89 2002/02/14 21:43:01 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.90 2002/03/08 19:10:32 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -112,9 +112,10 @@ enum OpMode {iABC, iABc, iAsBc};  /* basic instruction format */
 
 
 
 
 /*
 /*
-** an invalid register that fits in 8 bits
+** invalid registers that fits in 8 bits
 */
 */
 #define NO_REG		MAXARG_A
 #define NO_REG		MAXARG_A
+#define NO_REG1		(NO_REG+1)
 
 
 
 
 /*
 /*

+ 26 - 20
lparser.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.c,v 1.169 2002/03/14 18:01:52 roberto Exp roberto $
+** $Id: lparser.c,v 1.170 2002/03/14 18:32:37 roberto Exp roberto $
 ** Lua Parser
 ** Lua Parser
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -255,6 +255,8 @@ static int singlevar_aux (FuncState *fs, TString *n, expdesc *var, int nd) {
       int k = singlevar_aux(fs->prev, n, var, nd && fs->defaultglob == NO_REG);
       int k = singlevar_aux(fs->prev, n, var, nd && fs->defaultglob == NO_REG);
       if (var->k == VGLOBAL) {
       if (var->k == VGLOBAL) {
         if (k == VNIL && nd && fs->defaultglob != NO_REG) {
         if (k == VNIL && nd && fs->defaultglob != NO_REG) {
+          if (fs->defaultglob == NO_REG1)
+            luaK_error(fs->ls, "undeclared global");
           init_exp(var, VLOCAL, fs->defaultglob);
           init_exp(var, VLOCAL, fs->defaultglob);
           k = VGLOBAL;  /* now there is a declaration */
           k = VGLOBAL;  /* now there is a declaration */
         }
         }
@@ -987,10 +989,13 @@ static void repeatstat (LexState *ls, int line) {
 }
 }
 
 
 
 
-static void exp1 (LexState *ls) {
+static int exp1 (LexState *ls) {
   expdesc e;
   expdesc e;
+  int k;
   expr(ls, &e);
   expr(ls, &e);
+  k = e.k;
   luaK_exp2nextreg(ls->fs, &e);
   luaK_exp2nextreg(ls->fs, &e);
+  return k;
 }
 }
 
 
 
 
@@ -1000,8 +1005,8 @@ static void fornum (LexState *ls, TString *varname) {
   int prep;
   int prep;
   int base = fs->freereg;
   int base = fs->freereg;
   new_localvar(ls, varname, 0);
   new_localvar(ls, varname, 0);
-  new_localvarstr(ls, "(limit)", 1);
-  new_localvarstr(ls, "(step)", 2);
+  new_localvarstr(ls, "(for limit)", 1);
+  new_localvarstr(ls, "(for step)", 2);
   check(ls, '=');
   check(ls, '=');
   exp1(ls);  /* initial value */
   exp1(ls);  /* initial value */
   check(ls, ',');
   check(ls, ',');
@@ -1012,11 +1017,11 @@ static void fornum (LexState *ls, TString *varname) {
     luaK_codeABc(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
     luaK_codeABc(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
     luaK_reserveregs(fs, 1);
     luaK_reserveregs(fs, 1);
   }
   }
+  adjustlocalvars(ls, 3);  /* scope for control variables */
   luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
   luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);
   luaK_jump(fs);
   luaK_jump(fs);
   prep = luaK_getlabel(fs);
   prep = luaK_getlabel(fs);
   check(ls, TK_DO);
   check(ls, TK_DO);
-  adjustlocalvars(ls, 3);  /* scope for control variables */
   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);
@@ -1029,7 +1034,7 @@ static void forlist (LexState *ls, TString *indexname) {
   int nvars = 0;
   int nvars = 0;
   int prep;
   int prep;
   int base = fs->freereg;
   int base = fs->freereg;
-  new_localvarstr(ls, "(table)", 0);
+  new_localvarstr(ls, "(for generator)", 0);
   new_localvar(ls, indexname, ++nvars);
   new_localvar(ls, indexname, ++nvars);
   while (optional(ls, ',')) {
   while (optional(ls, ',')) {
     new_localvar(ls, str_checkname(ls), ++nvars);
     new_localvar(ls, str_checkname(ls), ++nvars);
@@ -1126,26 +1131,27 @@ static void localstat (LexState *ls) {
 static void globalstat (LexState *ls) {
 static void globalstat (LexState *ls) {
   /* stat -> GLOBAL NAME {`,' NAME} [IN exp] | GLOBAL IN exp */
   /* stat -> GLOBAL NAME {`,' NAME} [IN exp] | GLOBAL IN exp */
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
+  int nvars = 0;
   next(ls);  /* skip GLOBAL */
   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;
+  if (ls->t.token == TK_NAME) {
     do {
     do {
       vardesc *v = new_var(ls, nvars++);  
       vardesc *v = new_var(ls, nvars++);  
       v->i = luaK_stringK(ls->fs, str_checkname(ls));
       v->i = luaK_stringK(ls->fs, str_checkname(ls));
       next(ls);  /* skip name */
       next(ls);  /* skip name */
     } while (optional(ls, ','));
     } 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)");
-    }
+  }
+  if (!optional(ls, TK_IN)) {  /* free globals? */
+    if (nvars == 0)  /* default - free is invalid */
+      error_expected(ls, TK_IN);
+    adjustglobalvars(ls, nvars, NO_REG);  /* mark globals as free */
+  }
+  else {
+    int baselocal = fs->freereg;
+    int k = exp1(ls);
+    if (nvars == 0)
+      fs->defaultglob = (k == VNIL) ? NO_REG1 : baselocal;
+    adjustglobalvars(ls, nvars, baselocal);
+    create_local(ls, "*");
   }
   }
 }
 }