diff --git a/lcode.c b/lcode.c index 084354fd..ec255a0f 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.47 2010/06/30 14:11:17 roberto Exp roberto $ +** $Id: lcode.c,v 2.48 2010/07/02 20:42:40 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -373,15 +373,13 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { break; } case VINDEXED: { + OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ freereg(fs, e->u.ind.idx); - freereg(fs, e->u.ind.t); - e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOCABLE; - break; - } - case VINDEXEDUP: { - freereg(fs, e->u.ind.idx); - e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } @@ -551,13 +549,9 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { break; } case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e); - break; - } - case VINDEXEDUP: { - int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e); + luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); break; } default: { @@ -705,7 +699,9 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { lua_assert(!hasjumps(t)); t->u.ind.t = t->u.info; t->u.ind.idx = luaK_exp2RK(fs, k); - t->k = (t->k == VUPVAL) ? VINDEXEDUP : VINDEXED; + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL + : check_exp(vkisinreg(t->k), VLOCAL); + t->k = VINDEXED; } diff --git a/lparser.c b/lparser.c index c0bf6316..49fe8d8c 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.88 2010/06/21 16:30:12 roberto Exp roberto $ +** $Id: lparser.c,v 2.89 2010/07/02 20:42:40 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -969,26 +969,25 @@ struct LHS_assign { ** local value in a safe place and use this safe copy in the previous ** assignment. */ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v, - expkind ix, OpCode op) { +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { FuncState *fs = ls->fs; int extra = fs->freereg; /* eventual position to save local variable */ int conflict = 0; for (; lh; lh = lh->prev) { - if (lh->v.k == ix) { - if (lh->v.u.ind.t == v->u.info) { /* conflict? */ - conflict = 1; - lh->v.k = VINDEXED; - lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ - } - if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { /* conflict? */ - conflict = 1; - lua_assert(lh->v.k == VINDEXED); - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ - } + /* conflict in table 't'? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { + conflict = 1; + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + } + /* conflict in index 'idx'? */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ } } if (conflict) { + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */ luaK_reserveregs(fs, 1); } @@ -997,16 +996,13 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v, static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; - check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXEDUP, - "syntax error"); + check_condition(ls, vkisvar(lh->v.k), "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); - if (nv.v.k == VLOCAL) - check_conflict(ls, lh, &nv.v, VINDEXED, OP_MOVE); - else if (nv.v.k == VUPVAL) - check_conflict(ls, lh, &nv.v, VINDEXEDUP, OP_GETUPVAL); + if (nv.v.k != VINDEXED) + check_conflict(ls, lh, &nv.v); checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, "variable names"); assignment(ls, &nv, nvars+1); diff --git a/lparser.h b/lparser.h index bef7bbc4..945a14a5 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.63 2010/03/12 19:14:06 roberto Exp roberto $ +** $Id: lparser.h,v 1.64 2010/07/02 20:42:40 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -23,27 +23,30 @@ typedef enum { VFALSE, VK, /* info = index of constant in `k' */ VKNUM, /* nval = numerical value */ + VNONRELOC, /* info = result register */ VLOCAL, /* info = local register */ VUPVAL, /* info = index of upvalue in 'upvalues' */ - VINDEXED, /* t = table register; idx = index R/K */ - VINDEXEDUP, /* t = table upvalue; idx = index R/K */ + VINDEXED, /* t = table register/upvalue; idx = index R/K */ VJMP, /* info = instruction pc */ VRELOCABLE, /* info = instruction pc */ - VNONRELOC, /* info = result register */ VCALL, /* info = instruction pc */ VVARARG /* info = instruction pc */ } expkind; +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + typedef struct expdesc { expkind k; union { - struct { - short idx; - lu_byte t; - } ind; /* for indexed variables */ - int info; - lua_Number nval; + struct { /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + lu_byte t; /* table (register or upvalue) */ + lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; + int info; /* for generic use */ + lua_Number nval; /* for VKNUM */ } u; int t; /* patch list of `exit when true' */ int f; /* patch list of `exit when false' */