special treatment for 'global in nil'

This commit is contained in:
Roberto Ierusalimschy 2002-03-18 11:49:46 -03:00
parent da81845cd5
commit 58badbab99
2 changed files with 29 additions and 22 deletions

View File

@ -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)
/* /*

View File

@ -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, "(for limit)", 1);
new_localvarstr(ls, "(step)", 2); 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? */ if (ls->t.token == TK_NAME) {
exp1(ls);
fs->defaultglob = fs->freereg - 1;
create_local(ls, "(global table)");
}
else {
int nvars = 0;
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 */ if (!optional(ls, TK_IN)) { /* free globals? */
else { if (nvars == 0) /* default - free is invalid */
exp1(ls); error_expected(ls, TK_IN);
adjustglobalvars(ls, nvars, ls->fs->freereg - 1); adjustglobalvars(ls, nvars, NO_REG); /* mark globals as free */
create_local(ls, "(global table)"); }
} 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, "*");
} }
} }