From 58badbab9933e0a50d9b9f3fec78ac50d15d5414 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 18 Mar 2002 11:49:46 -0300 Subject: [PATCH] special treatment for 'global in nil' --- lopcodes.h | 5 +++-- lparser.c | 46 ++++++++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/lopcodes.h b/lopcodes.h index 4568fe46..d6528220 100644 --- a/lopcodes.h +++ b/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 ** 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_REG1 (NO_REG+1) /* diff --git a/lparser.c b/lparser.c index 78a6846f..f03475e8 100644 --- a/lparser.c +++ b/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 ** 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); if (var->k == VGLOBAL) { 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); 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; + int k; expr(ls, &e); + k = e.k; luaK_exp2nextreg(ls->fs, &e); + return k; } @@ -1000,8 +1005,8 @@ static void fornum (LexState *ls, TString *varname) { int prep; int base = fs->freereg; 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, '='); exp1(ls); /* initial value */ 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_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_jump(fs); prep = luaK_getlabel(fs); check(ls, TK_DO); - adjustlocalvars(ls, 3); /* scope for control variables */ block(ls); luaK_patchtohere(fs, prep-1); 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 prep; int base = fs->freereg; - new_localvarstr(ls, "(table)", 0); + new_localvarstr(ls, "(for generator)", 0); new_localvar(ls, indexname, ++nvars); while (optional(ls, ',')) { new_localvar(ls, str_checkname(ls), ++nvars); @@ -1126,26 +1131,27 @@ static void localstat (LexState *ls) { static void globalstat (LexState *ls) { /* stat -> GLOBAL NAME {`,' NAME} [IN exp] | GLOBAL IN exp */ FuncState *fs = ls->fs; + int nvars = 0; 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 { 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)"); - } + } + 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, "*"); } }