diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 23 |
1 files changed, 14 insertions, 9 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.74 2010/01/05 18:46:58 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.75 2010/01/06 11:48:02 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 | */ |
@@ -452,7 +452,7 @@ static void fieldsel (LexState *ls, expdesc *v) { | |||
452 | /* fieldsel -> ['.' | ':'] NAME */ | 452 | /* fieldsel -> ['.' | ':'] NAME */ |
453 | FuncState *fs = ls->fs; | 453 | FuncState *fs = ls->fs; |
454 | expdesc key; | 454 | expdesc key; |
455 | luaK_exp2anyreg(fs, v); | 455 | luaK_exp2anyregup(fs, v); |
456 | luaX_next(ls); /* skip the dot or colon */ | 456 | luaX_next(ls); /* skip the dot or colon */ |
457 | checkname(ls, &key); | 457 | checkname(ls, &key); |
458 | luaK_indexed(fs, v, &key); | 458 | luaK_indexed(fs, v, &key); |
@@ -747,7 +747,7 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
747 | } | 747 | } |
748 | case '[': { /* `[' exp1 `]' */ | 748 | case '[': { /* `[' exp1 `]' */ |
749 | expdesc key; | 749 | expdesc key; |
750 | luaK_exp2anyreg(fs, v); | 750 | luaK_exp2anyregup(fs, v); |
751 | yindex(ls, &key); | 751 | yindex(ls, &key); |
752 | luaK_indexed(fs, v, &key); | 752 | luaK_indexed(fs, v, &key); |
753 | break; | 753 | break; |
@@ -951,24 +951,27 @@ struct LHS_assign { | |||
951 | ** local value in a safe place and use this safe copy in the previous | 951 | ** local value in a safe place and use this safe copy in the previous |
952 | ** assignment. | 952 | ** assignment. |
953 | */ | 953 | */ |
954 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | 954 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v, |
955 | expkind ix, OpCode op) { | ||
955 | FuncState *fs = ls->fs; | 956 | FuncState *fs = ls->fs; |
956 | int extra = fs->freereg; /* eventual position to save local variable */ | 957 | int extra = fs->freereg; /* eventual position to save local variable */ |
957 | int conflict = 0; | 958 | int conflict = 0; |
958 | for (; lh; lh = lh->prev) { | 959 | for (; lh; lh = lh->prev) { |
959 | if (lh->v.k == VINDEXED) { | 960 | if (lh->v.k == ix) { |
960 | if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ | 961 | if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ |
961 | conflict = 1; | 962 | conflict = 1; |
963 | lh->v.k = VINDEXED; | ||
962 | lh->v.u.s.info = extra; /* previous assignment will use safe copy */ | 964 | lh->v.u.s.info = extra; /* previous assignment will use safe copy */ |
963 | } | 965 | } |
964 | if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ | 966 | if (v->k == VLOCAL && lh->v.u.s.aux == v->u.s.info) { /* conflict? */ |
965 | conflict = 1; | 967 | conflict = 1; |
968 | lua_assert(lh->v.k == VINDEXED); | ||
966 | lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ | 969 | lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ |
967 | } | 970 | } |
968 | } | 971 | } |
969 | } | 972 | } |
970 | if (conflict) { | 973 | if (conflict) { |
971 | luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ | 974 | luaK_codeABC(fs, op, fs->freereg, v->u.s.info, 0); /* make copy */ |
972 | luaK_reserveregs(fs, 1); | 975 | luaK_reserveregs(fs, 1); |
973 | } | 976 | } |
974 | } | 977 | } |
@@ -976,14 +979,16 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
976 | 979 | ||
977 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 980 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { |
978 | expdesc e; | 981 | expdesc e; |
979 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, | 982 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXEDUP, |
980 | "syntax error"); | 983 | "syntax error"); |
981 | if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ | 984 | if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ |
982 | struct LHS_assign nv; | 985 | struct LHS_assign nv; |
983 | nv.prev = lh; | 986 | nv.prev = lh; |
984 | primaryexp(ls, &nv.v); | 987 | primaryexp(ls, &nv.v); |
985 | if (nv.v.k == VLOCAL) | 988 | if (nv.v.k == VLOCAL) |
986 | check_conflict(ls, lh, &nv.v); | 989 | check_conflict(ls, lh, &nv.v, VINDEXED, OP_MOVE); |
990 | else if (nv.v.k == VUPVAL) | ||
991 | check_conflict(ls, lh, &nv.v, VINDEXEDUP, OP_GETUPVAL); | ||
987 | checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, | 992 | checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, |
988 | "variable names"); | 993 | "variable names"); |
989 | assignment(ls, &nv, nvars+1); | 994 | assignment(ls, &nv, nvars+1); |