diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-08-29 17:49:21 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-08-29 17:49:21 -0300 |
commit | 3b19af44b05ce5e7f7db3708d052cca25fe6d7d3 (patch) | |
tree | f4575f972c8f780e64d935ff211ebd5cd8f9a3cf | |
parent | 3390f9a35ac66d01c7bb0114083a4cb384783ff5 (diff) | |
download | lua-3b19af44b05ce5e7f7db3708d052cca25fe6d7d3.tar.gz lua-3b19af44b05ce5e7f7db3708d052cca25fe6d7d3.tar.bz2 lua-3b19af44b05ce5e7f7db3708d052cca25fe6d7d3.zip |
new method to handle tests without values (negative values)
-rw-r--r-- | lcode.c | 69 | ||||
-rw-r--r-- | lcode.h | 3 | ||||
-rw-r--r-- | lopcodes.c | 6 | ||||
-rw-r--r-- | lopcodes.h | 5 | ||||
-rw-r--r-- | lparser.c | 7 | ||||
-rw-r--r-- | lvm.c | 8 |
6 files changed, 58 insertions, 40 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.15 2005/08/17 18:32:09 roberto Exp $ |
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 | */ |
@@ -53,6 +53,11 @@ int luaK_jump (FuncState *fs) { | |||
53 | } | 53 | } |
54 | 54 | ||
55 | 55 | ||
56 | void luaK_ret (FuncState *fs, int first, int nret) { | ||
57 | luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); | ||
58 | } | ||
59 | |||
60 | |||
56 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { | 61 | static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { |
57 | luaK_codeABC(fs, op, A, B, C); | 62 | luaK_codeABC(fs, op, A, B, C); |
58 | return luaK_jump(fs); | 63 | return luaK_jump(fs); |
@@ -101,49 +106,50 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) { | |||
101 | ** check whether list has any jump that do not produce a value | 106 | ** check whether list has any jump that do not produce a value |
102 | ** (or produce an inverted value) | 107 | ** (or produce an inverted value) |
103 | */ | 108 | */ |
104 | static int need_value (FuncState *fs, int list, int cond) { | 109 | static int need_value (FuncState *fs, int list) { |
105 | for (; list != NO_JUMP; list = getjump(fs, list)) { | 110 | for (; list != NO_JUMP; list = getjump(fs, list)) { |
106 | Instruction i = *getjumpcontrol(fs, list); | 111 | Instruction i = *getjumpcontrol(fs, list); |
107 | if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1; | 112 | if (GET_OPCODE(i) != OP_TESTSET) return 1; |
108 | } | 113 | } |
109 | return 0; /* not found */ | 114 | return 0; /* not found */ |
110 | } | 115 | } |
111 | 116 | ||
112 | 117 | ||
113 | static void patchtestreg (Instruction *i, int reg) { | 118 | static void patchtestreg (Instruction *i, int reg) { |
114 | if (reg == NO_REG) reg = GETARG_B(*i); | 119 | if (reg != NO_REG) |
115 | SETARG_A(*i, reg); | 120 | SETARG_A(*i, reg); |
121 | else /* no register to put value; change TESTSET to TEST */ | ||
122 | *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); | ||
116 | } | 123 | } |
117 | 124 | ||
118 | 125 | ||
119 | static void patchlistaux (FuncState *fs, int list, | 126 | static void removevalues (FuncState *fs, int list) { |
120 | int ttarget, int treg, int ftarget, int freg, int dtarget) { | 127 | for (; list != NO_JUMP; list = getjump(fs, list)) { |
128 | Instruction *i = getjumpcontrol(fs, list); | ||
129 | if (GET_OPCODE(*i) == OP_TESTSET) | ||
130 | patchtestreg(i, NO_REG); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | |||
135 | static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, | ||
136 | int dtarget) { | ||
121 | while (list != NO_JUMP) { | 137 | while (list != NO_JUMP) { |
122 | int next = getjump(fs, list); | 138 | int next = getjump(fs, list); |
123 | Instruction *i = getjumpcontrol(fs, list); | 139 | Instruction *i = getjumpcontrol(fs, list); |
124 | if (GET_OPCODE(*i) != OP_TEST) { | 140 | if (GET_OPCODE(*i) == OP_TESTSET) { |
125 | lua_assert(dtarget != NO_JUMP); | 141 | patchtestreg(i, reg); |
126 | fixjump(fs, list, dtarget); /* jump to default target */ | 142 | fixjump(fs, list, vtarget); |
127 | } | ||
128 | else { | ||
129 | if (GETARG_C(*i)) { | ||
130 | lua_assert(ttarget != NO_JUMP); | ||
131 | patchtestreg(i, treg); | ||
132 | fixjump(fs, list, ttarget); | ||
133 | } | ||
134 | else { | ||
135 | lua_assert(ftarget != NO_JUMP); | ||
136 | patchtestreg(i, freg); | ||
137 | fixjump(fs, list, ftarget); | ||
138 | } | ||
139 | } | 143 | } |
144 | else | ||
145 | fixjump(fs, list, dtarget); /* jump to default target */ | ||
140 | list = next; | 146 | list = next; |
141 | } | 147 | } |
142 | } | 148 | } |
143 | 149 | ||
144 | 150 | ||
145 | static void dischargejpc (FuncState *fs) { | 151 | static void dischargejpc (FuncState *fs) { |
146 | patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc); | 152 | patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); |
147 | fs->jpc = NO_JUMP; | 153 | fs->jpc = NO_JUMP; |
148 | } | 154 | } |
149 | 155 | ||
@@ -153,7 +159,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) { | |||
153 | luaK_patchtohere(fs, list); | 159 | luaK_patchtohere(fs, list); |
154 | else { | 160 | else { |
155 | lua_assert(target < fs->pc); | 161 | lua_assert(target < fs->pc); |
156 | patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); | 162 | patchlistaux(fs, list, target, NO_REG, target); |
157 | } | 163 | } |
158 | } | 164 | } |
159 | 165 | ||
@@ -373,7 +379,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
373 | int final; /* position after whole expression */ | 379 | int final; /* position after whole expression */ |
374 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ | 380 | int p_f = NO_JUMP; /* position of an eventual LOAD false */ |
375 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ | 381 | int p_t = NO_JUMP; /* position of an eventual LOAD true */ |
376 | if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) { | 382 | if (need_value(fs, e->t) || need_value(fs, e->f)) { |
377 | int fj = NO_JUMP; /* first jump (over LOAD ops.) */ | 383 | int fj = NO_JUMP; /* first jump (over LOAD ops.) */ |
378 | if (e->k != VJMP) | 384 | if (e->k != VJMP) |
379 | fj = luaK_jump(fs); | 385 | fj = luaK_jump(fs); |
@@ -382,8 +388,8 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { | |||
382 | luaK_patchtohere(fs, fj); | 388 | luaK_patchtohere(fs, fj); |
383 | } | 389 | } |
384 | final = luaK_getlabel(fs); | 390 | final = luaK_getlabel(fs); |
385 | patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f); | 391 | patchlistaux(fs, e->f, final, reg, p_f); |
386 | patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t); | 392 | patchlistaux(fs, e->t, final, reg, p_t); |
387 | } | 393 | } |
388 | e->f = e->t = NO_JUMP; | 394 | e->f = e->t = NO_JUMP; |
389 | e->info = reg; | 395 | e->info = reg; |
@@ -492,7 +498,8 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |||
492 | 498 | ||
493 | static void invertjump (FuncState *fs, expdesc *e) { | 499 | static void invertjump (FuncState *fs, expdesc *e) { |
494 | Instruction *pc = getjumpcontrol(fs, e->info); | 500 | Instruction *pc = getjumpcontrol(fs, e->info); |
495 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TEST); | 501 | lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && |
502 | GET_OPCODE(*pc) != OP_TEST); | ||
496 | SETARG_A(*pc, !(GETARG_A(*pc))); | 503 | SETARG_A(*pc, !(GETARG_A(*pc))); |
497 | } | 504 | } |
498 | 505 | ||
@@ -502,13 +509,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { | |||
502 | Instruction ie = getcode(fs, e); | 509 | Instruction ie = getcode(fs, e); |
503 | if (GET_OPCODE(ie) == OP_NOT) { | 510 | if (GET_OPCODE(ie) == OP_NOT) { |
504 | fs->pc--; /* remove previous OP_NOT */ | 511 | fs->pc--; /* remove previous OP_NOT */ |
505 | return condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond); | 512 | return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); |
506 | } | 513 | } |
507 | /* else go through */ | 514 | /* else go through */ |
508 | } | 515 | } |
509 | discharge2anyreg(fs, e); | 516 | discharge2anyreg(fs, e); |
510 | freeexp(fs, e); | 517 | freeexp(fs, e); |
511 | return condjump(fs, OP_TEST, NO_REG, e->info, cond); | 518 | return condjump(fs, OP_TESTSET, NO_REG, e->info, cond); |
512 | } | 519 | } |
513 | 520 | ||
514 | 521 | ||
@@ -597,6 +604,8 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
597 | } | 604 | } |
598 | /* interchange true and false lists */ | 605 | /* interchange true and false lists */ |
599 | { int temp = e->f; e->f = e->t; e->t = temp; } | 606 | { int temp = e->f; e->f = e->t; e->t = temp; } |
607 | removevalues(fs, e->f); | ||
608 | removevalues(fs, e->t); | ||
600 | } | 609 | } |
601 | 610 | ||
602 | 611 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.43 2005/04/25 19:24:10 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.44 2005/05/20 15:53:42 roberto Exp $ |
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 | */ |
@@ -65,6 +65,7 @@ LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | |||
65 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); | 65 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); |
66 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); | 66 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); |
67 | LUAI_FUNC int luaK_jump (FuncState *fs); | 67 | LUAI_FUNC int luaK_jump (FuncState *fs); |
68 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); | ||
68 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); | 69 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); |
69 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); | 70 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); |
70 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); | 71 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.33 2005/05/04 20:42:28 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.34 2005/05/20 15:53:42 roberto Exp $ |
3 | ** See Copyright Notice in lua.h | 3 | ** See Copyright Notice in lua.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -43,6 +43,7 @@ const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
43 | "LT", | 43 | "LT", |
44 | "LE", | 44 | "LE", |
45 | "TEST", | 45 | "TEST", |
46 | "TESTSET", | ||
46 | "CALL", | 47 | "CALL", |
47 | "TAILCALL", | 48 | "TAILCALL", |
48 | "RETURN", | 49 | "RETURN", |
@@ -87,7 +88,8 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
87 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ | 88 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ |
88 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ | 89 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ |
89 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ | 90 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ |
90 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ | 91 | ,opmode(1, 0, OpArgR, OpArgU, iABC) /* OP_TEST */ |
92 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ | ||
91 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ | 93 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ |
92 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ | 94 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ |
93 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ | 95 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.120 2005/05/20 15:53:42 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.121 2005/06/06 13:30:25 roberto Exp $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -186,7 +186,8 @@ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ | |||
186 | OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ | 186 | OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ |
187 | OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ | 187 | OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ |
188 | 188 | ||
189 | OP_TEST,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ | 189 | OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ |
190 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ | ||
190 | 191 | ||
191 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ | 192 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ |
192 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ | 193 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.33 2005/08/22 18:54:32 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.34 2005/08/24 17:41:10 roberto Exp $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -375,7 +375,7 @@ static void close_func (LexState *ls) { | |||
375 | FuncState *fs = ls->fs; | 375 | FuncState *fs = ls->fs; |
376 | Proto *f = fs->f; | 376 | Proto *f = fs->f; |
377 | removevars(ls, 0); | 377 | removevars(ls, 0); |
378 | luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ | 378 | luaK_ret(fs, 0, 0); /* final return */ |
379 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); | 379 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); |
380 | f->sizecode = fs->pc; | 380 | f->sizecode = fs->pc; |
381 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); | 381 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); |
@@ -981,7 +981,6 @@ static int cond (LexState *ls) { | |||
981 | expdesc v; | 981 | expdesc v; |
982 | expr(ls, &v); /* read condition */ | 982 | expr(ls, &v); /* read condition */ |
983 | if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ | 983 | if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ |
984 | else if (v.k == VK) v.k = VTRUE; /* 'trues' too */ | ||
985 | luaK_goiftrue(ls->fs, &v); | 984 | luaK_goiftrue(ls->fs, &v); |
986 | return v.f; | 985 | return v.f; |
987 | } | 986 | } |
@@ -1279,7 +1278,7 @@ static void retstat (LexState *ls) { | |||
1279 | } | 1278 | } |
1280 | } | 1279 | } |
1281 | } | 1280 | } |
1282 | luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); | 1281 | luaK_ret(fs, first, nret); |
1283 | } | 1282 | } |
1284 | 1283 | ||
1285 | 1284 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.52 2005/08/22 18:54:49 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.53 2005/08/24 16:15:49 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -592,6 +592,12 @@ void luaV_execute (lua_State *L, int nexeccalls) { | |||
592 | continue; | 592 | continue; |
593 | } | 593 | } |
594 | case OP_TEST: { | 594 | case OP_TEST: { |
595 | if (l_isfalse(ra) == GETARG_C(i)) pc++; | ||
596 | else | ||
597 | dojump(L, pc, GETARG_sBx(*pc) + 1); | ||
598 | continue; | ||
599 | } | ||
600 | case OP_TESTSET: { | ||
595 | TValue *rb = RB(i); | 601 | TValue *rb = RB(i); |
596 | if (l_isfalse(rb) == GETARG_C(i)) pc++; | 602 | if (l_isfalse(rb) == GETARG_C(i)) pc++; |
597 | else { | 603 | else { |