diff --git a/lcode.c b/lcode.c index 119d91ab..7ca895f1 100644 --- a/lcode.c +++ b/lcode.c @@ -753,10 +753,11 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { /* ** Convert a VKSTR to a VK */ -static void str2K (FuncState *fs, expdesc *e) { +static int str2K (FuncState *fs, expdesc *e) { lua_assert(e->k == VKSTR); e->u.info = stringK(fs, e->u.strval); e->k = VK; + return e->u.info; } @@ -1307,8 +1308,9 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { ** values in registers. */ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + int keystr = -1; if (k->k == VKSTR) - str2K(fs, k); + keystr = str2K(fs, k); lua_assert(!hasjumps(t) && (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ @@ -1336,7 +1338,8 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { t->k = VINDEXED; } } - t->u.ind.vidx = -1; /* by default, not a declared global */ + t->u.ind.keystr = keystr; /* string index in 'k' */ + t->u.ind.ro = 0; /* by default, not read-only */ } diff --git a/lparser.c b/lparser.c index 6658bb20..3c2f57ab 100644 --- a/lparser.c +++ b/lparser.c @@ -304,11 +304,9 @@ static void check_readonly (LexState *ls, expdesc *e) { varname = up->name; break; } - case VINDEXUP: case VINDEXSTR: case VINDEXED: { - int vidx = e->u.ind.vidx; - /* is it a read-only declared global? */ - if (vidx != -1 && ls->dyd->actvar.arr[vidx].vd.kind == GDKCONST) - varname = ls->dyd->actvar.arr[vidx].vd.name; + case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ + if (e->u.ind.ro) /* read-only? */ + varname = tsvalue(&fs->f->k[e->u.ind.keystr]); break; } default: @@ -483,8 +481,6 @@ static void buildvar (LexState *ls, TString *varname, expdesc *var) { if (var->k == VGLOBAL) { /* global name? */ expdesc key; int info = var->u.info; - lua_assert(info == -1 || - eqstr(ls->dyd->actvar.arr[info].vd.name, varname)); /* global by default in the scope of a global declaration? */ if (info == -1 && fs->bl->globdec) luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); @@ -495,7 +491,10 @@ static void buildvar (LexState *ls, TString *varname, expdesc *var) { luaK_exp2anyregup(fs, var); /* but could be a constant */ codestring(&key, varname); /* key is variable name */ luaK_indexed(fs, var, &key); /* env[varname] */ - var->u.ind.vidx = cast_short(info); /* mark it as a declared global */ + if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST) + var->u.ind.ro = 1; /* mark variable as read-only */ + else /* anyway must be a global */ + lua_assert(info == -1 || ls->dyd->actvar.arr[info].vd.kind == GDKREG); } } diff --git a/lparser.h b/lparser.h index 274fb1c4..524df6ea 100644 --- a/lparser.h +++ b/lparser.h @@ -45,16 +45,19 @@ typedef enum { info = absolute index in 'actvar.arr' */ VINDEXED, /* indexed variable; ind.t = table register; - ind.idx = key's R index */ + ind.idx = key's R index; + ind.ro = true if it represents a read-only global; + ind.keystr = if key is a string, index in 'k' of that string; + -1 if key is not a string */ VINDEXUP, /* indexed upvalue; - ind.t = table upvalue; - ind.idx = key's K index */ + ind.idx = key's K index; + ind.* as in VINDEXED */ VINDEXI, /* indexed variable with constant integer; ind.t = table register; ind.idx = key's value */ VINDEXSTR, /* indexed variable with literal string; - ind.t = table register; - ind.idx = key's K index */ + ind.idx = key's K index; + ind.* as in VINDEXED */ VJMP, /* expression is a test/comparison; info = pc of corresponding jump instruction */ VRELOC, /* expression can put result in any register; @@ -77,8 +80,9 @@ typedef struct expdesc { int info; /* for generic use */ struct { /* for indexed variables */ short idx; /* index (R or "long" K) */ - short vidx; /* index in 'actvar.arr' or -1 if not a declared global */ lu_byte t; /* table (register or upvalue) */ + lu_byte ro; /* true if variable is read-only */ + int keystr; /* index in 'k' of string key, or -1 if not a string */ } ind; struct { /* for local variables */ lu_byte ridx; /* register holding the variable */