|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
** $Id: lparser.c,v 2.119 2011/09/14 17:40:26 roberto Exp roberto $ |
|
|
|
** $Id: lparser.c,v 2.120 2011/09/30 12:44:45 roberto Exp roberto $ |
|
|
|
** Lua Parser |
|
|
|
** See Copyright Notice in lua.h |
|
|
|
*/ |
|
|
@ -1106,31 +1106,34 @@ struct LHS_assign { |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** check whether, in an assignment to a local variable, the local variable |
|
|
|
** is needed in a previous assignment (to a table). If so, save original |
|
|
|
** local value in a safe place and use this safe copy in the previous |
|
|
|
** assignment. |
|
|
|
** check whether, in an assignment to an upvalue/local variable, the |
|
|
|
** upvalue/local variable is begin used in a previous assignment to a |
|
|
|
** table. If so, save original upvalue/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) { |
|
|
|
FuncState *fs = ls->fs; |
|
|
|
int extra = fs->freereg; /* eventual position to save local variable */ |
|
|
|
int conflict = 0; |
|
|
|
for (; lh; lh = lh->prev) { |
|
|
|
/* 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 */ |
|
|
|
for (; lh; lh = lh->prev) { /* check all previous assignments */ |
|
|
|
if (lh->v.k == VINDEXED) { /* assigning to a table? */ |
|
|
|
/* table is the upvalue/local being assigned now? */ |
|
|
|
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 */ |
|
|
|
} |
|
|
|
/* index is the local being assigned? (index cannot be upvalue) */ |
|
|
|
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) { |
|
|
|
/* copy upvalue/local value to a temporary (in position 'extra') */ |
|
|
|
OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; |
|
|
|
luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */ |
|
|
|
luaK_codeABC(fs, op, extra, v->u.info, 0); |
|
|
|
luaK_reserveregs(fs, 1); |
|
|
|
} |
|
|
|
} |
|
|
|