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' */ |