diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-07-07 13:27:29 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-07-07 13:27:29 -0300 |
| commit | 81dd13f4c6a70f08d83f7b7360e4e15cf79dd573 (patch) | |
| tree | b379d2c248dd57e71f9461db581c6d0cfa0f24f8 | |
| parent | 6a02bbe1e2f8ad1b98a077bd2aac44e776fd107c (diff) | |
| download | lua-81dd13f4c6a70f08d83f7b7360e4e15cf79dd573.tar.gz lua-81dd13f4c6a70f08d83f7b7360e4e15cf79dd573.tar.bz2 lua-81dd13f4c6a70f08d83f7b7360e4e15cf79dd573.zip | |
new way to distinguish between indexing tables in registers and
tables in upvalues (+ fixed small bug when checking conflicts in
multiple assignments)
| -rw-r--r-- | lcode.c | 28 | ||||
| -rw-r--r-- | lparser.c | 36 | ||||
| -rw-r--r-- | lparser.h | 23 |
3 files changed, 41 insertions, 46 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.47 2010/06/30 14:11:17 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.48 2010/07/02 20:42:40 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -373,15 +373,13 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 373 | break; | 373 | break; |
| 374 | } | 374 | } |
| 375 | case VINDEXED: { | 375 | case VINDEXED: { |
| 376 | OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ | ||
| 376 | freereg(fs, e->u.ind.idx); | 377 | freereg(fs, e->u.ind.idx); |
| 377 | freereg(fs, e->u.ind.t); | 378 | if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ |
| 378 | e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); | 379 | freereg(fs, e->u.ind.t); |
| 379 | e->k = VRELOCABLE; | 380 | op = OP_GETTABLE; |
| 380 | break; | 381 | } |
| 381 | } | 382 | e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); |
| 382 | case VINDEXEDUP: { | ||
| 383 | freereg(fs, e->u.ind.idx); | ||
| 384 | e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx); | ||
| 385 | e->k = VRELOCABLE; | 383 | e->k = VRELOCABLE; |
| 386 | break; | 384 | break; |
| 387 | } | 385 | } |
| @@ -551,13 +549,9 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
| 551 | break; | 549 | break; |
| 552 | } | 550 | } |
| 553 | case VINDEXED: { | 551 | case VINDEXED: { |
| 552 | OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; | ||
| 554 | int e = luaK_exp2RK(fs, ex); | 553 | int e = luaK_exp2RK(fs, ex); |
| 555 | luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e); | 554 | luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); |
| 556 | break; | ||
| 557 | } | ||
| 558 | case VINDEXEDUP: { | ||
| 559 | int e = luaK_exp2RK(fs, ex); | ||
| 560 | luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e); | ||
| 561 | break; | 555 | break; |
| 562 | } | 556 | } |
| 563 | default: { | 557 | default: { |
| @@ -705,7 +699,9 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | |||
| 705 | lua_assert(!hasjumps(t)); | 699 | lua_assert(!hasjumps(t)); |
| 706 | t->u.ind.t = t->u.info; | 700 | t->u.ind.t = t->u.info; |
| 707 | t->u.ind.idx = luaK_exp2RK(fs, k); | 701 | t->u.ind.idx = luaK_exp2RK(fs, k); |
| 708 | t->k = (t->k == VUPVAL) ? VINDEXEDUP : VINDEXED; | 702 | t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL |
| 703 | : check_exp(vkisinreg(t->k), VLOCAL); | ||
| 704 | t->k = VINDEXED; | ||
| 709 | } | 705 | } |
| 710 | 706 | ||
| 711 | 707 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 2.88 2010/06/21 16:30:12 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.89 2010/07/02 20:42:40 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -969,26 +969,25 @@ struct LHS_assign { | |||
| 969 | ** local value in a safe place and use this safe copy in the previous | 969 | ** local value in a safe place and use this safe copy in the previous |
| 970 | ** assignment. | 970 | ** assignment. |
| 971 | */ | 971 | */ |
| 972 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v, | 972 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { |
| 973 | expkind ix, OpCode op) { | ||
| 974 | FuncState *fs = ls->fs; | 973 | FuncState *fs = ls->fs; |
| 975 | int extra = fs->freereg; /* eventual position to save local variable */ | 974 | int extra = fs->freereg; /* eventual position to save local variable */ |
| 976 | int conflict = 0; | 975 | int conflict = 0; |
| 977 | for (; lh; lh = lh->prev) { | 976 | for (; lh; lh = lh->prev) { |
| 978 | if (lh->v.k == ix) { | 977 | /* conflict in table 't'? */ |
| 979 | if (lh->v.u.ind.t == v->u.info) { /* conflict? */ | 978 | if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { |
| 980 | conflict = 1; | 979 | conflict = 1; |
| 981 | lh->v.k = VINDEXED; | 980 | lh->v.u.ind.vt = VLOCAL; |
| 982 | lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ | 981 | lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ |
| 983 | } | 982 | } |
| 984 | if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { /* conflict? */ | 983 | /* conflict in index 'idx'? */ |
| 985 | conflict = 1; | 984 | if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { |
| 986 | lua_assert(lh->v.k == VINDEXED); | 985 | conflict = 1; |
| 987 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ | 986 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ |
| 988 | } | ||
| 989 | } | 987 | } |
| 990 | } | 988 | } |
| 991 | if (conflict) { | 989 | if (conflict) { |
| 990 | OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; | ||
| 992 | luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */ | 991 | luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */ |
| 993 | luaK_reserveregs(fs, 1); | 992 | luaK_reserveregs(fs, 1); |
| 994 | } | 993 | } |
| @@ -997,16 +996,13 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v, | |||
| 997 | 996 | ||
| 998 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 997 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { |
| 999 | expdesc e; | 998 | expdesc e; |
| 1000 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXEDUP, | 999 | check_condition(ls, vkisvar(lh->v.k), "syntax error"); |
| 1001 | "syntax error"); | ||
| 1002 | if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ | 1000 | if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ |
| 1003 | struct LHS_assign nv; | 1001 | struct LHS_assign nv; |
| 1004 | nv.prev = lh; | 1002 | nv.prev = lh; |
| 1005 | primaryexp(ls, &nv.v); | 1003 | primaryexp(ls, &nv.v); |
| 1006 | if (nv.v.k == VLOCAL) | 1004 | if (nv.v.k != VINDEXED) |
| 1007 | check_conflict(ls, lh, &nv.v, VINDEXED, OP_MOVE); | 1005 | check_conflict(ls, lh, &nv.v); |
| 1008 | else if (nv.v.k == VUPVAL) | ||
| 1009 | check_conflict(ls, lh, &nv.v, VINDEXEDUP, OP_GETUPVAL); | ||
| 1010 | checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, | 1006 | checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, |
| 1011 | "variable names"); | 1007 | "variable names"); |
| 1012 | assignment(ls, &nv, nvars+1); | 1008 | assignment(ls, &nv, nvars+1); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.h,v 1.63 2010/03/12 19:14:06 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.64 2010/07/02 20:42:40 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -23,27 +23,30 @@ typedef enum { | |||
| 23 | VFALSE, | 23 | VFALSE, |
| 24 | VK, /* info = index of constant in `k' */ | 24 | VK, /* info = index of constant in `k' */ |
| 25 | VKNUM, /* nval = numerical value */ | 25 | VKNUM, /* nval = numerical value */ |
| 26 | VNONRELOC, /* info = result register */ | ||
| 26 | VLOCAL, /* info = local register */ | 27 | VLOCAL, /* info = local register */ |
| 27 | VUPVAL, /* info = index of upvalue in 'upvalues' */ | 28 | VUPVAL, /* info = index of upvalue in 'upvalues' */ |
| 28 | VINDEXED, /* t = table register; idx = index R/K */ | 29 | VINDEXED, /* t = table register/upvalue; idx = index R/K */ |
| 29 | VINDEXEDUP, /* t = table upvalue; idx = index R/K */ | ||
| 30 | VJMP, /* info = instruction pc */ | 30 | VJMP, /* info = instruction pc */ |
| 31 | VRELOCABLE, /* info = instruction pc */ | 31 | VRELOCABLE, /* info = instruction pc */ |
| 32 | VNONRELOC, /* info = result register */ | ||
| 33 | VCALL, /* info = instruction pc */ | 32 | VCALL, /* info = instruction pc */ |
| 34 | VVARARG /* info = instruction pc */ | 33 | VVARARG /* info = instruction pc */ |
| 35 | } expkind; | 34 | } expkind; |
| 36 | 35 | ||
| 37 | 36 | ||
| 37 | #define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) | ||
| 38 | #define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) | ||
| 39 | |||
| 38 | typedef struct expdesc { | 40 | typedef struct expdesc { |
| 39 | expkind k; | 41 | expkind k; |
| 40 | union { | 42 | union { |
| 41 | struct { | 43 | struct { /* for indexed variables (VINDEXED) */ |
| 42 | short idx; | 44 | short idx; /* index (R/K) */ |
| 43 | lu_byte t; | 45 | lu_byte t; /* table (register or upvalue) */ |
| 44 | } ind; /* for indexed variables */ | 46 | lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ |
| 45 | int info; | 47 | } ind; |
| 46 | lua_Number nval; | 48 | int info; /* for generic use */ |
| 49 | lua_Number nval; /* for VKNUM */ | ||
| 47 | } u; | 50 | } u; |
| 48 | int t; /* patch list of `exit when true' */ | 51 | int t; /* patch list of `exit when true' */ |
| 49 | int f; /* patch list of `exit when false' */ | 52 | int f; /* patch list of `exit when false' */ |
