diff options
-rw-r--r-- | lcode.c | 160 | ||||
-rw-r--r-- | lcode.h | 14 | ||||
-rw-r--r-- | lopcodes.h | 4 | ||||
-rw-r--r-- | lparser.c | 205 | ||||
-rw-r--r-- | lparser.h | 19 | ||||
-rw-r--r-- | lvm.c | 8 |
6 files changed, 218 insertions, 192 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.4 2000/03/03 18:53:17 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.5 2000/03/03 20:30:47 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 | */ |
@@ -20,10 +20,19 @@ void luaK_error (LexState *ls, const char *msg) { | |||
20 | } | 20 | } |
21 | 21 | ||
22 | 22 | ||
23 | static Instruction *last_i (LexState *ls, expdesc *v) { | 23 | /* |
24 | ** Returns the address of the previous instruction, for optimizations. | ||
25 | ** If there is a jump target between this and the current instruction, | ||
26 | ** returns the address of a dummy instruction to avoid wrong optimizations. | ||
27 | */ | ||
28 | static Instruction *previous_instruction (LexState *ls) { | ||
24 | FuncState *fs = ls->fs; | 29 | FuncState *fs = ls->fs; |
25 | int last_pc = (v->info != NOJUMPS) ? v->info : fs->pc-1; | 30 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ |
26 | return &fs->f->code[last_pc]; | 31 | return &fs->f->code[fs->pc-1]; /* returns previous instruction */ |
32 | else { | ||
33 | static Instruction dummy = CREATE_0(ENDCODE); | ||
34 | return &dummy; /* no optimizations after an `ENDCODE' */ | ||
35 | } | ||
27 | } | 36 | } |
28 | 37 | ||
29 | 38 | ||
@@ -35,61 +44,74 @@ int luaK_primitivecode (LexState *ls, Instruction i) { | |||
35 | } | 44 | } |
36 | 45 | ||
37 | 46 | ||
38 | static void luaK_minus (LexState *ls, expdesc *v) { | 47 | static void luaK_minus (LexState *ls) { |
39 | Instruction *last = last_i(ls, v); | 48 | Instruction *previous = previous_instruction(ls); |
40 | switch(GET_OPCODE(*last)) { | 49 | switch(GET_OPCODE(*previous)) { |
41 | case PUSHINT: *last = SETARG_S(*last, -GETARG_S(*last)); return; | 50 | case PUSHINT: *previous = SETARG_S(*previous, -GETARG_S(*previous)); return; |
42 | case PUSHNUM: *last = SET_OPCODE(*last, PUSHNEGNUM); return; | 51 | case PUSHNUM: *previous = SET_OPCODE(*previous, PUSHNEGNUM); return; |
43 | case PUSHNEGNUM: *last = SET_OPCODE(*last, PUSHNUM); return; | 52 | case PUSHNEGNUM: *previous = SET_OPCODE(*previous, PUSHNUM); return; |
44 | default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); | 53 | default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); |
45 | } | 54 | } |
46 | } | 55 | } |
47 | 56 | ||
48 | 57 | ||
49 | static void luaK_gettable (LexState *ls, expdesc *v) { | 58 | static void luaK_gettable (LexState *ls) { |
50 | Instruction *last = last_i(ls, v); | 59 | Instruction *previous = previous_instruction(ls); |
51 | luaK_deltastack(ls, -1); | 60 | luaK_deltastack(ls, -1); |
52 | switch(GET_OPCODE(*last)) { | 61 | switch(GET_OPCODE(*previous)) { |
53 | case PUSHSTRING: *last = SET_OPCODE(*last, GETDOTTED); break; | 62 | case PUSHSTRING: *previous = SET_OPCODE(*previous, GETDOTTED); break; |
54 | default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); | 63 | default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); |
55 | } | 64 | } |
56 | } | 65 | } |
57 | 66 | ||
58 | 67 | ||
59 | static void luaK_add (LexState *ls, expdesc *v) { | 68 | static void luaK_add (LexState *ls) { |
60 | Instruction *last = last_i(ls, v); | 69 | Instruction *previous = previous_instruction(ls); |
61 | luaK_deltastack(ls, -1); | 70 | luaK_deltastack(ls, -1); |
62 | switch(GET_OPCODE(*last)) { | 71 | switch(GET_OPCODE(*previous)) { |
63 | case PUSHINT: *last = SET_OPCODE(*last, ADDI); break; | 72 | case PUSHINT: *previous = SET_OPCODE(*previous, ADDI); break; |
64 | default: luaK_primitivecode(ls, CREATE_0(ADDOP)); | 73 | default: luaK_primitivecode(ls, CREATE_0(ADDOP)); |
65 | } | 74 | } |
66 | } | 75 | } |
67 | 76 | ||
68 | 77 | ||
69 | static void luaK_sub (LexState *ls, expdesc *v) { | 78 | static void luaK_sub (LexState *ls) { |
70 | Instruction *last = last_i(ls, v); | 79 | Instruction *previous = previous_instruction(ls); |
71 | luaK_deltastack(ls, -1); | 80 | luaK_deltastack(ls, -1); |
72 | switch(GET_OPCODE(*last)) { | 81 | switch(GET_OPCODE(*previous)) { |
73 | case PUSHINT: | 82 | case PUSHINT: |
74 | *last = SET_OPCODE(*last, ADDI); | 83 | *previous = SET_OPCODE(*previous, ADDI); |
75 | *last = SETARG_S(*last, -GETARG_S(*last)); | 84 | *previous = SETARG_S(*previous, -GETARG_S(*previous)); |
76 | break; | 85 | break; |
77 | default: luaK_primitivecode(ls, CREATE_0(SUBOP)); | 86 | default: luaK_primitivecode(ls, CREATE_0(SUBOP)); |
78 | } | 87 | } |
79 | } | 88 | } |
80 | 89 | ||
81 | 90 | ||
82 | void luaK_retcode (LexState *ls, int nlocals, listdesc *e) { | 91 | void luaK_retcode (LexState *ls, int nlocals, int nexps) { |
83 | if (e->n > 0 && luaK_iscall(ls, e->info)) { | 92 | Instruction *previous = previous_instruction(ls); |
84 | Instruction *last = &ls->fs->f->code[ls->fs->pc-1]; | 93 | if (nexps > 0 && GET_OPCODE(*previous) == CALL) { |
85 | *last = SET_OPCODE(*last, TAILCALL); | 94 | LUA_ASSERT(ls->L, GETARG_B(*previous) == MULT_RET, "call should be open"); |
86 | *last = SETARG_B(*last, nlocals); | 95 | *previous = SET_OPCODE(*previous, TAILCALL); |
96 | *previous = SETARG_B(*previous, nlocals); | ||
87 | } | 97 | } |
88 | else | 98 | else |
89 | luaK_primitivecode(ls, CREATE_U(RETCODE, nlocals)); | 99 | luaK_primitivecode(ls, CREATE_U(RETCODE, nlocals)); |
90 | } | 100 | } |
91 | 101 | ||
92 | 102 | ||
103 | static void luaK_pushnil (LexState *ls, int n) { | ||
104 | Instruction *previous = previous_instruction(ls); | ||
105 | luaK_deltastack(ls, n); | ||
106 | switch(GET_OPCODE(*previous)) { | ||
107 | case PUSHNIL: | ||
108 | *previous = SETARG_U(*previous, GETARG_U(*previous)+n); | ||
109 | break; | ||
110 | default: luaK_primitivecode(ls, CREATE_U(PUSHNIL, n)); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | |||
93 | int luaK_code (LexState *ls, Instruction i, int delta) { | 115 | int luaK_code (LexState *ls, Instruction i, int delta) { |
94 | luaK_deltastack(ls, delta); | 116 | luaK_deltastack(ls, delta); |
95 | return luaK_primitivecode(ls, i); | 117 | return luaK_primitivecode(ls, i); |
@@ -104,6 +126,17 @@ void luaK_fixjump (LexState *ls, int pc, int dest) { | |||
104 | } | 126 | } |
105 | 127 | ||
106 | 128 | ||
129 | /* | ||
130 | ** returns current `pc' and marks it as a jump target (to avoid wrong | ||
131 | ** optimizations with consecutive instructions not in the same basic block). | ||
132 | */ | ||
133 | int luaK_getlabel (LexState *ls) { | ||
134 | FuncState *fs = ls->fs; | ||
135 | fs->lasttarget = fs->pc; | ||
136 | return fs->pc; | ||
137 | } | ||
138 | |||
139 | |||
107 | void luaK_deltastack (LexState *ls, int delta) { | 140 | void luaK_deltastack (LexState *ls, int delta) { |
108 | FuncState *fs = ls->fs; | 141 | FuncState *fs = ls->fs; |
109 | fs->stacksize += delta; | 142 | fs->stacksize += delta; |
@@ -151,28 +184,27 @@ void luaK_adjuststack (LexState *ls, int n) { | |||
151 | if (n > 0) | 184 | if (n > 0) |
152 | luaK_U(ls, POP, n, -n); | 185 | luaK_U(ls, POP, n, -n); |
153 | else if (n < 0) | 186 | else if (n < 0) |
154 | luaK_U(ls, PUSHNIL, (-n)-1, -n); | 187 | luaK_pushnil(ls, -n); |
155 | } | 188 | } |
156 | 189 | ||
157 | 190 | ||
158 | int luaK_iscall (LexState *ls, int hasjumps) { | 191 | int luaK_lastisopen (LexState *ls) { |
159 | if (hasjumps) return 0; /* a call cannot have internal jumps */ | 192 | /* check whether last instruction is an (open) function call */ |
160 | else /* check whether last instruction is a function call */ | 193 | Instruction *i = previous_instruction(ls); |
161 | return (GET_OPCODE(ls->fs->f->code[ls->fs->pc-1]) == CALL); | 194 | if (GET_OPCODE(*i) == CALL) { |
195 | LUA_ASSERT(ls->L, GETARG_B(*i) == MULT_RET, "call should be open"); | ||
196 | return 1; | ||
197 | } | ||
198 | else return 0; | ||
162 | } | 199 | } |
163 | 200 | ||
164 | 201 | ||
165 | void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults) { | 202 | void luaK_setcallreturns (LexState *ls, int nresults) { |
166 | if (!hasjumps) { /* if `hasjumps' cannot be a function call */ | 203 | Instruction *i = previous_instruction(ls); |
167 | Instruction *i = &ls->fs->f->code[ls->fs->pc-1]; | 204 | if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ |
168 | if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ | 205 | LUA_ASSERT(ls->L, GETARG_B(*i) == MULT_RET, "call should be open"); |
169 | int old_nresults = GETARG_B(*i); | 206 | *i = SETARG_B(*i, nresults); /* set nresults */ |
170 | if (old_nresults != MULT_RET) | 207 | luaK_deltastack(ls, nresults); /* push results */ |
171 | luaK_deltastack(ls, -old_nresults); /* pop old nresults */ | ||
172 | *i = SETARG_B(*i, nresults); /* set nresults */ | ||
173 | if (nresults != MULT_RET) | ||
174 | luaK_deltastack(ls, nresults); /* push results */ | ||
175 | } | ||
176 | } | 208 | } |
177 | } | 209 | } |
178 | 210 | ||
@@ -182,7 +214,7 @@ static void assertglobal (LexState *ls, int index) { | |||
182 | } | 214 | } |
183 | 215 | ||
184 | 216 | ||
185 | void luaK_2stack (LexState *ls, expdesc *var) { | 217 | void luaK_tostack (LexState *ls, expdesc *var) { |
186 | switch (var->k) { | 218 | switch (var->k) { |
187 | case VLOCAL: | 219 | case VLOCAL: |
188 | luaK_U(ls, PUSHLOCAL, var->info, 1); | 220 | luaK_U(ls, PUSHLOCAL, var->info, 1); |
@@ -192,14 +224,20 @@ void luaK_2stack (LexState *ls, expdesc *var) { | |||
192 | assertglobal(ls, var->info); /* make sure that there is a global */ | 224 | assertglobal(ls, var->info); /* make sure that there is a global */ |
193 | break; | 225 | break; |
194 | case VINDEXED: | 226 | case VINDEXED: |
195 | luaK_gettable(ls, var); | 227 | luaK_gettable(ls); |
196 | break; | 228 | break; |
197 | case VEXP: | 229 | case VEXP: |
198 | luaK_setcallreturns(ls, var->info, 1); /* call must return 1 value */ | 230 | return; /* exp result is already on stack */ |
199 | return; /* does not change var->info */ | ||
200 | } | 231 | } |
201 | var->k = VEXP; | 232 | var->k = VEXP; |
202 | var->info = NOJUMPS; | 233 | } |
234 | |||
235 | |||
236 | void luaK_1tostack (LexState *ls, expdesc *var) { | ||
237 | if (var->k == VEXP) | ||
238 | luaK_setcallreturns(ls, 1); /* call must return 1 value */ | ||
239 | else | ||
240 | luaK_tostack(ls, var); | ||
203 | } | 241 | } |
204 | 242 | ||
205 | 243 | ||
@@ -222,30 +260,29 @@ void luaK_storevar (LexState *ls, const expdesc *var) { | |||
222 | 260 | ||
223 | 261 | ||
224 | void luaK_prefix (LexState *ls, int op, expdesc *v) { | 262 | void luaK_prefix (LexState *ls, int op, expdesc *v) { |
225 | luaK_2stack(ls, v); | 263 | luaK_1tostack(ls, v); |
226 | if (op == '-') luaK_minus(ls, v); | 264 | if (op == '-') luaK_minus(ls); |
227 | else luaK_0(ls, NOTOP, 0); | 265 | else luaK_0(ls, NOTOP, 0); |
228 | v->info = NOJUMPS; | ||
229 | } | 266 | } |
230 | 267 | ||
231 | 268 | ||
232 | void luaK_infix (LexState *ls, expdesc *v) { | 269 | void luaK_infix (LexState *ls, int op, expdesc *v) { |
233 | luaK_2stack(ls, v); | 270 | luaK_1tostack(ls, v); |
234 | if (ls->token == AND) | 271 | if (op == AND) |
235 | v->info = luaK_0(ls, ONFJMP, -1); | 272 | v->info = luaK_0(ls, ONFJMP, -1); |
236 | else if (ls->token == OR) | 273 | else if (op == OR) |
237 | v->info = luaK_0(ls, ONTJMP, -1); | 274 | v->info = luaK_0(ls, ONTJMP, -1); |
238 | } | 275 | } |
239 | 276 | ||
240 | 277 | ||
241 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | 278 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { |
242 | luaK_2stack(ls, v2); | 279 | luaK_1tostack(ls, v2); |
243 | switch (op) { | 280 | switch (op) { |
244 | case AND: case OR: | 281 | case AND: case OR: |
245 | luaK_fixjump(ls, v1->info, ls->fs->pc); | 282 | luaK_fixjump(ls, v1->info, luaK_getlabel(ls)); |
246 | return; /* keep v1->info != NOJUMPS */ | 283 | break; |
247 | case '+': luaK_add(ls, v2); break; | 284 | case '+': luaK_add(ls); break; |
248 | case '-': luaK_sub(ls, v2); break; | 285 | case '-': luaK_sub(ls); break; |
249 | case '*': luaK_0(ls, MULTOP, -1); break; | 286 | case '*': luaK_0(ls, MULTOP, -1); break; |
250 | case '/': luaK_0(ls, DIVOP, -1); break; | 287 | case '/': luaK_0(ls, DIVOP, -1); break; |
251 | case '^': luaK_0(ls, POWOP, -1); break; | 288 | case '^': luaK_0(ls, POWOP, -1); break; |
@@ -257,6 +294,5 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
257 | case GE: luaK_0(ls, GEOP, -1); break; | 294 | case GE: luaK_0(ls, GEOP, -1); break; |
258 | case LE: luaK_0(ls, LEOP, -1); break; | 295 | case LE: luaK_0(ls, LEOP, -1); break; |
259 | } | 296 | } |
260 | v1->info = NOJUMPS; | ||
261 | } | 297 | } |
262 | 298 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.2 2000/03/03 12:33:59 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.3 2000/03/03 18:53:17 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 | */ |
@@ -22,18 +22,20 @@ | |||
22 | void luaK_error (LexState *ls, const char *msg); | 22 | void luaK_error (LexState *ls, const char *msg); |
23 | int luaK_primitivecode (LexState *ls, Instruction i); | 23 | int luaK_primitivecode (LexState *ls, Instruction i); |
24 | int luaK_code (LexState *ls, Instruction i, int delta); | 24 | int luaK_code (LexState *ls, Instruction i, int delta); |
25 | void luaK_retcode (LexState *ls, int nlocals, listdesc *e); | 25 | void luaK_retcode (LexState *ls, int nlocals, int nexps); |
26 | void luaK_fixjump (LexState *ls, int pc, int dest); | 26 | void luaK_fixjump (LexState *ls, int pc, int dest); |
27 | int luaK_getlabel (LexState *ls); | ||
27 | void luaK_deltastack (LexState *ls, int delta); | 28 | void luaK_deltastack (LexState *ls, int delta); |
28 | void luaK_kstr (LexState *ls, int c); | 29 | void luaK_kstr (LexState *ls, int c); |
29 | void luaK_number (LexState *ls, real f); | 30 | void luaK_number (LexState *ls, real f); |
30 | void luaK_adjuststack (LexState *ls, int n); | 31 | void luaK_adjuststack (LexState *ls, int n); |
31 | int luaK_iscall (LexState *ls, int hasjumps); | 32 | int luaK_lastisopen (LexState *ls); |
32 | void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults); | 33 | void luaK_setcallreturns (LexState *ls, int nresults); |
33 | void luaK_2stack (LexState *ls, expdesc *var); | 34 | void luaK_tostack (LexState *ls, expdesc *var); |
35 | void luaK_1tostack (LexState *ls, expdesc *var); | ||
34 | void luaK_storevar (LexState *ls, const expdesc *var); | 36 | void luaK_storevar (LexState *ls, const expdesc *var); |
35 | void luaK_prefix (LexState *ls, int op, expdesc *v); | 37 | void luaK_prefix (LexState *ls, int op, expdesc *v); |
36 | void luaK_infix (LexState *ls, expdesc *v); | 38 | void luaK_infix (LexState *ls, int op, expdesc *v); |
37 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2); | 39 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2); |
38 | 40 | ||
39 | 41 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.43 2000/03/03 14:58:26 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.44 2000/03/03 18:53:17 roberto Exp roberto $ |
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 | */ |
@@ -71,7 +71,7 @@ RETCODE,/* U - (return) */ | |||
71 | CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ | 71 | CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ |
72 | TAILCALL,/* A B v_a-v_1 f (return) f(v1,...,v_a) */ | 72 | TAILCALL,/* A B v_a-v_1 f (return) f(v1,...,v_a) */ |
73 | 73 | ||
74 | PUSHNIL,/* U - nil_0-nil_u */ | 74 | PUSHNIL,/* U - nil_1-nil_u */ |
75 | POP,/* U a_u-a_1 - */ | 75 | POP,/* U a_u-a_1 - */ |
76 | 76 | ||
77 | PUSHINT,/* S - (real)s */ | 77 | PUSHINT,/* S - (real)s */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.63 2000/03/03 18:53:17 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.64 2000/03/03 20:29:25 roberto Exp roberto $ |
3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,10 +23,11 @@ | |||
23 | 23 | ||
24 | 24 | ||
25 | /* | 25 | /* |
26 | ** check whether arbitrary limits fit in respective opcode types | 26 | ** check whether arbitrary limits fit into respective opcode types |
27 | */ | 27 | */ |
28 | #if MAXLOCALS>MAXARG_U || MAXUPVALUES>MAXARG_B || MAXVARSLH>MAXARG_B || \ | 28 | #if MAXLOCALS > MAXARG_U || MAXUPVALUES > MAXARG_B || MAXVARSLH > MAXARG_B || \ |
29 | MAXPARAMS>MAXLOCALS || MAXSTACK>MAXARG_A || LFIELDS_PER_FLUSH>MAXARG_B | 29 | MAXPARAMS > MAXLOCALS || MAXSTACK > MAXARG_A || \ |
30 | LFIELDS_PER_FLUSH > MAXARG_B || MULT_RET > MAXARG_B | ||
30 | #error invalid limits | 31 | #error invalid limits |
31 | #endif | 32 | #endif |
32 | 33 | ||
@@ -53,7 +54,7 @@ static void body (LexState *ls, int needself, int line); | |||
53 | static void chunk (LexState *ls); | 54 | static void chunk (LexState *ls); |
54 | static void constructor (LexState *ls); | 55 | static void constructor (LexState *ls); |
55 | static void expr (LexState *ls, expdesc *v); | 56 | static void expr (LexState *ls, expdesc *v); |
56 | static int exp1 (LexState *ls); | 57 | static void exp1 (LexState *ls); |
57 | 58 | ||
58 | 59 | ||
59 | static void next (LexState *ls) { | 60 | static void next (LexState *ls) { |
@@ -256,9 +257,9 @@ static void pushupvalue (LexState *ls, TaggedString *n) { | |||
256 | } | 257 | } |
257 | 258 | ||
258 | 259 | ||
259 | static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { | 260 | static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { |
260 | int diff = d->n - nvars; | 261 | int diff = nexps - nvars; |
261 | if (d->n == 0 || !luaK_iscall(ls, d->info)) { /* list is empty or closed */ | 262 | if (nexps == 0 || !luaK_lastisopen(ls)) { /* list is empty or closed */ |
262 | /* push or pop eventual difference between list lengths */ | 263 | /* push or pop eventual difference between list lengths */ |
263 | luaK_adjuststack(ls, diff); | 264 | luaK_adjuststack(ls, diff); |
264 | } | 265 | } |
@@ -266,10 +267,10 @@ static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { | |||
266 | diff--; /* do not count function call itself */ | 267 | diff--; /* do not count function call itself */ |
267 | if (diff <= 0) { /* more variables than values? */ | 268 | if (diff <= 0) { /* more variables than values? */ |
268 | /* function call must provide extra values */ | 269 | /* function call must provide extra values */ |
269 | luaK_setcallreturns(ls, d->info, -diff); | 270 | luaK_setcallreturns(ls, -diff); |
270 | } | 271 | } |
271 | else { /* more values than variables */ | 272 | else { /* more values than variables */ |
272 | luaK_setcallreturns(ls, d->info, 0); /* call should provide no value */ | 273 | luaK_setcallreturns(ls, 0); /* call should provide no value */ |
273 | luaK_adjuststack(ls, diff); /* pop eventual extra values */ | 274 | luaK_adjuststack(ls, diff); /* pop eventual extra values */ |
274 | } | 275 | } |
275 | } | 276 | } |
@@ -310,7 +311,7 @@ static void func_onstack (LexState *ls, FuncState *func) { | |||
310 | TProtoFunc *f = ls->fs->f; | 311 | TProtoFunc *f = ls->fs->f; |
311 | int i; | 312 | int i; |
312 | for (i=0; i<func->nupvalues; i++) | 313 | for (i=0; i<func->nupvalues; i++) |
313 | luaK_2stack(ls, &func->upvalues[i]); | 314 | luaK_1tostack(ls, &func->upvalues[i]); |
314 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, | 315 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, |
315 | constantEM, MAXARG_A); | 316 | constantEM, MAXARG_A); |
316 | f->kproto[f->nkproto++] = func->f; | 317 | f->kproto[f->nkproto++] = func->f; |
@@ -331,6 +332,7 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) { | |||
331 | fs->f = f; | 332 | fs->f = f; |
332 | f->source = source; | 333 | f->source = source; |
333 | fs->pc = 0; | 334 | fs->pc = 0; |
335 | fs->lasttarget = 0; | ||
334 | f->code = NULL; | 336 | f->code = NULL; |
335 | f->maxstacksize = 0; | 337 | f->maxstacksize = 0; |
336 | f->numparams = 0; /* default for main chunk */ | 338 | f->numparams = 0; /* default for main chunk */ |
@@ -380,57 +382,57 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { | |||
380 | /*============================================================*/ | 382 | /*============================================================*/ |
381 | 383 | ||
382 | 384 | ||
383 | static void explist1 (LexState *ls, listdesc *d) { | 385 | static int explist1 (LexState *ls) { |
386 | /* explist1 -> expr { ',' expr } */ | ||
387 | int n = 1; /* at least one expression */ | ||
384 | expdesc v; | 388 | expdesc v; |
385 | expr(ls, &v); | 389 | expr(ls, &v); |
386 | d->n = 1; | ||
387 | while (ls->token == ',') { | 390 | while (ls->token == ',') { |
388 | d->n++; | 391 | luaK_1tostack(ls, &v); /* gets only 1 value from previous expression */ |
389 | luaK_2stack(ls, &v); | 392 | next(ls); /* skip comma */ |
390 | next(ls); | ||
391 | expr(ls, &v); | 393 | expr(ls, &v); |
394 | n++; | ||
392 | } | 395 | } |
393 | luaK_2stack(ls, &v); | 396 | luaK_tostack(ls, &v); |
394 | luaK_setcallreturns(ls, v.info, MULT_RET); /* default for explists */ | 397 | return n; |
395 | d->info = v.info; | ||
396 | } | 398 | } |
397 | 399 | ||
398 | 400 | ||
399 | static void explist (LexState *ls, listdesc *d) { | 401 | static int explist (LexState *ls) { |
402 | /* explist -> [ explist1 ] */ | ||
400 | switch (ls->token) { | 403 | switch (ls->token) { |
401 | case ELSE: case ELSEIF: case END: case UNTIL: | 404 | case ELSE: case ELSEIF: case END: case UNTIL: |
402 | case EOS: case ';': case ')': | 405 | case EOS: case ';': case ')': |
403 | d->n = 0; | 406 | return 0; /* empty list */ |
404 | break; | ||
405 | 407 | ||
406 | default: | 408 | default: |
407 | explist1(ls, d); | 409 | return explist1(ls); |
408 | } | 410 | } |
409 | } | 411 | } |
410 | 412 | ||
411 | 413 | ||
412 | static void funcparams (LexState *ls, int slf) { | 414 | static void funcargs (LexState *ls, int slf) { |
413 | FuncState *fs = ls->fs; | 415 | FuncState *fs = ls->fs; |
414 | int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ | 416 | int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ |
415 | switch (ls->token) { | 417 | switch (ls->token) { |
416 | case '(': { /* funcparams -> '(' explist ')' */ | 418 | case '(': { /* funcargs -> '(' explist ')' */ |
417 | int line = ls->linenumber; | 419 | int line = ls->linenumber; |
418 | listdesc e; | 420 | int nargs; |
419 | next(ls); | 421 | next(ls); |
420 | explist(ls, &e); | 422 | nargs = explist(ls); |
421 | check_match(ls, ')', '(', line); | 423 | check_match(ls, ')', '(', line); |
422 | #ifdef LUA_COMPAT_ARGRET | 424 | #ifdef LUA_COMPAT_ARGRET |
423 | if (e.n > 0) /* arg list is not empty? */ | 425 | if (nargs > 0) /* arg list is not empty? */ |
424 | luaK_setcallreturns(ls, e.pc, 1); /* last call returns only 1 value */ | 426 | luaK_setcallreturns(ls, 1); /* last call returns only 1 value */ |
425 | #endif | 427 | #endif |
426 | break; | 428 | break; |
427 | } | 429 | } |
428 | 430 | ||
429 | case '{': /* funcparams -> constructor */ | 431 | case '{': /* funcargs -> constructor */ |
430 | constructor(ls); | 432 | constructor(ls); |
431 | break; | 433 | break; |
432 | 434 | ||
433 | case STRING: /* funcparams -> STRING */ | 435 | case STRING: /* funcargs -> STRING */ |
434 | code_string(ls, ls->seminfo.ts); /* must use `seminfo' before `next' */ | 436 | code_string(ls, ls->seminfo.ts); /* must use `seminfo' before `next' */ |
435 | next(ls); | 437 | next(ls); |
436 | break; | 438 | break; |
@@ -439,8 +441,8 @@ static void funcparams (LexState *ls, int slf) { | |||
439 | luaK_error(ls, "function arguments expected"); | 441 | luaK_error(ls, "function arguments expected"); |
440 | break; | 442 | break; |
441 | } | 443 | } |
442 | fs->stacksize = slevel; /* call will remove func and params */ | 444 | fs->stacksize = slevel; /* call will remove function and arguments */ |
443 | luaK_AB(ls, CALL, slevel, 0, 0); | 445 | luaK_AB(ls, CALL, slevel, MULT_RET, 0); |
444 | } | 446 | } |
445 | 447 | ||
446 | 448 | ||
@@ -449,37 +451,34 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { | |||
449 | switch (ls->token) { | 451 | switch (ls->token) { |
450 | case '.': /* var_or_func_tail -> '.' NAME */ | 452 | case '.': /* var_or_func_tail -> '.' NAME */ |
451 | next(ls); | 453 | next(ls); |
452 | luaK_2stack(ls, v); /* `v' must be on stack */ | 454 | luaK_1tostack(ls, v); /* `v' must be on stack */ |
453 | luaK_kstr(ls, checkname(ls)); | 455 | luaK_kstr(ls, checkname(ls)); |
454 | v->k = VINDEXED; | 456 | v->k = VINDEXED; |
455 | v->info = NOJUMPS; | ||
456 | break; | 457 | break; |
457 | 458 | ||
458 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ | 459 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ |
459 | next(ls); | 460 | next(ls); |
460 | luaK_2stack(ls, v); /* `v' must be on stack */ | 461 | luaK_1tostack(ls, v); /* `v' must be on stack */ |
461 | v->k = VINDEXED; | 462 | v->k = VINDEXED; |
462 | v->info = exp1(ls); | 463 | exp1(ls); |
463 | check(ls, ']'); | 464 | check(ls, ']'); |
464 | break; | 465 | break; |
465 | 466 | ||
466 | case ':': { /* var_or_func_tail -> ':' NAME funcparams */ | 467 | case ':': { /* var_or_func_tail -> ':' NAME funcargs */ |
467 | int name; | 468 | int name; |
468 | next(ls); | 469 | next(ls); |
469 | name = checkname(ls); | 470 | name = checkname(ls); |
470 | luaK_2stack(ls, v); /* `v' must be on stack */ | 471 | luaK_1tostack(ls, v); /* `v' must be on stack */ |
471 | luaK_U(ls, PUSHSELF, name, 1); | 472 | luaK_U(ls, PUSHSELF, name, 1); |
472 | funcparams(ls, 1); | 473 | funcargs(ls, 1); |
473 | v->k = VEXP; | 474 | v->k = VEXP; |
474 | v->info = NOJUMPS; | ||
475 | break; | 475 | break; |
476 | } | 476 | } |
477 | 477 | ||
478 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ | 478 | case '(': case STRING: case '{': /* var_or_func_tail -> funcargs */ |
479 | luaK_2stack(ls, v); /* `v' must be on stack */ | 479 | luaK_1tostack(ls, v); /* `v' must be on stack */ |
480 | funcparams(ls, 0); | 480 | funcargs(ls, 0); |
481 | v->k = VEXP; | 481 | v->k = VEXP; |
482 | v->info = NOJUMPS; | ||
483 | break; | 482 | break; |
484 | 483 | ||
485 | default: return; /* should be follow... */ | 484 | default: return; /* should be follow... */ |
@@ -493,7 +492,6 @@ static void var_or_func (LexState *ls, expdesc *v) { | |||
493 | if (optional(ls, '%')) { /* upvalue? */ | 492 | if (optional(ls, '%')) { /* upvalue? */ |
494 | pushupvalue(ls, str_checkname(ls)); | 493 | pushupvalue(ls, str_checkname(ls)); |
495 | v->k = VEXP; | 494 | v->k = VEXP; |
496 | v->info = NOJUMPS; | ||
497 | } | 495 | } |
498 | else /* variable name */ | 496 | else /* variable name */ |
499 | singlevar(ls, str_checkname(ls), v, 0); | 497 | singlevar(ls, str_checkname(ls), v, 0); |
@@ -593,7 +591,7 @@ static void constructor_part (LexState *ls, constdesc *cd) { | |||
593 | cd->k = 1; /* record */ | 591 | cd->k = 1; /* record */ |
594 | } | 592 | } |
595 | else { | 593 | else { |
596 | luaK_2stack(ls, &v); | 594 | luaK_tostack(ls, &v); |
597 | cd->n = listfields(ls); | 595 | cd->n = listfields(ls); |
598 | cd->k = 0; /* list */ | 596 | cd->k = 0; /* list */ |
599 | } | 597 | } |
@@ -693,15 +691,13 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
693 | return; | 691 | return; |
694 | } | 692 | } |
695 | v->k = VEXP; | 693 | v->k = VEXP; |
696 | v->info = NOJUMPS; | ||
697 | } | 694 | } |
698 | 695 | ||
699 | 696 | ||
700 | static int exp1 (LexState *ls) { | 697 | static void exp1 (LexState *ls) { |
701 | expdesc v; | 698 | expdesc v; |
702 | expr(ls, &v); | 699 | expr(ls, &v); |
703 | luaK_2stack(ls, &v); | 700 | luaK_1tostack(ls, &v); |
704 | return v.info; | ||
705 | } | 701 | } |
706 | 702 | ||
707 | 703 | ||
@@ -711,53 +707,54 @@ static int exp1 (LexState *ls) { | |||
711 | */ | 707 | */ |
712 | static int get_priority (int op, int *rp) { | 708 | static int get_priority (int op, int *rp) { |
713 | switch (op) { | 709 | switch (op) { |
714 | case AND: case OR: | 710 | |
715 | *rp = 1; return 1; | 711 | case '^': *rp = 8; return 9; /* right associative */ |
716 | case EQ: case NE: | 712 | |
717 | case '>': case '<': case LE: case GE: | ||
718 | *rp = 2; return 2; | ||
719 | case CONC: | ||
720 | *rp = 4; return 4; /* left associative (?) */ | ||
721 | case '+': case '-': | ||
722 | *rp = 5; return 5; | ||
723 | case '*': case '/': | ||
724 | *rp = 6; return 6; | ||
725 | #define UNARY_PRIORITY 7 | 713 | #define UNARY_PRIORITY 7 |
726 | case '^': | 714 | |
727 | *rp = 8; return 9; /* right associative */ | 715 | case '*': case '/': *rp = 6; return 6; |
728 | default: | 716 | |
729 | *rp = -1; return -1; | 717 | case '+': case '-': *rp = 5; return 5; |
718 | |||
719 | case CONC: *rp = 4; return 4; /* left associative (?) */ | ||
720 | |||
721 | case EQ: case NE: case '>': case '<': case LE: case GE: | ||
722 | *rp = 2; return 2; | ||
723 | |||
724 | case AND: case OR: *rp = 1; return 1; | ||
725 | |||
726 | default: *rp = -1; return -1; | ||
730 | } | 727 | } |
731 | } | 728 | } |
732 | 729 | ||
733 | 730 | ||
734 | /* | 731 | /* |
735 | ** expr -> simplexep | (NOT | '-') expr | expr binop expr | 732 | ** subexpr -> (simplexep | (NOT | '-') subexpr) { binop subexpr } |
736 | ** where `binop' is any binary operator with a priority higher than `limit' | 733 | ** where `binop' is any binary operator with a priority higher than `limit' |
737 | */ | 734 | */ |
738 | static void operator_expr (LexState *ls, expdesc *v, int limit) { | 735 | static void subexpr (LexState *ls, expdesc *v, int limit) { |
739 | int rp; | 736 | int rp; |
740 | if (ls->token == '-' || ls->token == NOT) { | 737 | if (ls->token == '-' || ls->token == NOT) { |
741 | int op = ls->token; /* operator */ | 738 | int op = ls->token; /* operator */ |
742 | next(ls); | 739 | next(ls); |
743 | operator_expr(ls, v, UNARY_PRIORITY); | 740 | subexpr(ls, v, UNARY_PRIORITY); |
744 | luaK_prefix(ls, op, v); | 741 | luaK_prefix(ls, op, v); |
745 | } | 742 | } |
746 | else simpleexp(ls, v); | 743 | else simpleexp(ls, v); |
747 | /* expand while following operators have a priority higher than `limit' */ | 744 | /* expand while operators have priorities higher than `limit' */ |
748 | while (get_priority(ls->token, &rp) > limit) { | 745 | while (get_priority(ls->token, &rp) > limit) { |
749 | int op = ls->token; /* operator */ | ||
750 | expdesc v2; | 746 | expdesc v2; |
751 | luaK_infix(ls, v); | 747 | int op = ls->token; /* current operator (with priority == `rp') */ |
752 | next(ls); | 748 | next(ls); |
753 | operator_expr(ls, &v2, rp); | 749 | luaK_infix(ls, op, v); |
750 | subexpr(ls, &v2, rp); /* read sub-expression with priority > `rp' */ | ||
754 | luaK_posfix(ls, op, v, &v2); | 751 | luaK_posfix(ls, op, v, &v2); |
755 | } | 752 | } |
756 | } | 753 | } |
757 | 754 | ||
758 | 755 | ||
759 | static void expr (LexState *ls, expdesc *v) { | 756 | static void expr (LexState *ls, expdesc *v) { |
760 | operator_expr(ls, v, -1); | 757 | subexpr(ls, v, -1); |
761 | } | 758 | } |
762 | 759 | ||
763 | /* }==================================================================== */ | 760 | /* }==================================================================== */ |
@@ -775,7 +772,7 @@ static void block (LexState *ls) { | |||
775 | FuncState *fs = ls->fs; | 772 | FuncState *fs = ls->fs; |
776 | int nlocalvar = fs->nlocalvar; | 773 | int nlocalvar = fs->nlocalvar; |
777 | chunk(ls); | 774 | chunk(ls); |
778 | luaK_adjuststack(ls, fs->nlocalvar - nlocalvar); | 775 | luaK_adjuststack(ls, fs->nlocalvar - nlocalvar); /* remove local variables */ |
779 | for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--) | 776 | for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--) |
780 | luaI_unregisterlocalvar(ls, fs->lastsetline); | 777 | luaI_unregisterlocalvar(ls, fs->lastsetline); |
781 | } | 778 | } |
@@ -793,12 +790,12 @@ static int assignment (LexState *ls, expdesc *v, int nvars) { | |||
793 | left = assignment(ls, &nv, nvars+1); | 790 | left = assignment(ls, &nv, nvars+1); |
794 | } | 791 | } |
795 | else { /* assignment -> '=' explist1 */ | 792 | else { /* assignment -> '=' explist1 */ |
796 | listdesc d; | 793 | int nexps;; |
797 | if (ls->token != '=') | 794 | if (ls->token != '=') |
798 | error_unexpected(ls); | 795 | error_unexpected(ls); |
799 | next(ls); | 796 | next(ls); |
800 | explist1(ls, &d); | 797 | nexps = explist1(ls); |
801 | adjust_mult_assign(ls, nvars, &d); | 798 | adjust_mult_assign(ls, nvars, nexps); |
802 | } | 799 | } |
803 | if (v->k != VINDEXED || left+(nvars-1) == 0) { | 800 | if (v->k != VINDEXED || left+(nvars-1) == 0) { |
804 | /* global/local var or indexed var without values in between */ | 801 | /* global/local var or indexed var without values in between */ |
@@ -821,7 +818,8 @@ static void whilestat (LexState *ls, int line) { | |||
821 | /* whilestat -> WHILE exp1 DO block END */ | 818 | /* whilestat -> WHILE exp1 DO block END */ |
822 | Instruction buffer[MAX_WHILE_EXP]; | 819 | Instruction buffer[MAX_WHILE_EXP]; |
823 | FuncState *fs = ls->fs; | 820 | FuncState *fs = ls->fs; |
824 | int while_init = fs->pc; | 821 | int while_init = luaK_getlabel(ls); |
822 | int loopentry; /* point to jump to repeat the loop */ | ||
825 | int cond_size; | 823 | int cond_size; |
826 | int i; | 824 | int i; |
827 | next(ls); /* skip WHILE */ | 825 | next(ls); /* skip WHILE */ |
@@ -836,20 +834,20 @@ static void whilestat (LexState *ls, int line) { | |||
836 | luaK_deltastack(ls, -1); | 834 | luaK_deltastack(ls, -1); |
837 | luaK_S(ls, JMP, 0, 0); /* initial jump to condition */ | 835 | luaK_S(ls, JMP, 0, 0); /* initial jump to condition */ |
838 | check(ls, DO); | 836 | check(ls, DO); |
837 | loopentry = luaK_getlabel(ls); | ||
839 | block(ls); | 838 | block(ls); |
840 | check_match(ls, END, WHILE, line); | 839 | check_match(ls, END, WHILE, line); |
841 | luaK_fixjump(ls, while_init, fs->pc); | 840 | luaK_fixjump(ls, while_init, luaK_getlabel(ls)); |
842 | /* copy condition to new position, and correct stack */ | 841 | /* copy condition to new position, and correct stack */ |
843 | for (i=0; i<cond_size; i++) luaK_primitivecode(ls, buffer[i]); | 842 | for (i=0; i<cond_size; i++) luaK_primitivecode(ls, buffer[i]); |
844 | luaK_deltastack(ls, 1); | 843 | luaK_deltastack(ls, 1); |
845 | luaK_fixjump(ls, luaK_S(ls, IFTJMP, 0, -1), while_init+1); | 844 | luaK_fixjump(ls, luaK_S(ls, IFTJMP, 0, -1), loopentry); |
846 | } | 845 | } |
847 | 846 | ||
848 | 847 | ||
849 | static void repeatstat (LexState *ls, int line) { | 848 | static void repeatstat (LexState *ls, int line) { |
850 | /* repeatstat -> REPEAT block UNTIL exp1 */ | 849 | /* repeatstat -> REPEAT block UNTIL exp1 */ |
851 | FuncState *fs = ls->fs; | 850 | int repeat_init = luaK_getlabel(ls); |
852 | int repeat_init = fs->pc; | ||
853 | next(ls); | 851 | next(ls); |
854 | block(ls); | 852 | block(ls); |
855 | check_match(ls, UNTIL, REPEAT, line); | 853 | check_match(ls, UNTIL, REPEAT, line); |
@@ -870,28 +868,28 @@ static int localnamelist (LexState *ls) { | |||
870 | } | 868 | } |
871 | 869 | ||
872 | 870 | ||
873 | static void decinit (LexState *ls, listdesc *d) { | 871 | static int decinit (LexState *ls) { |
874 | /* decinit -> ['=' explist1] */ | 872 | /* decinit -> ['=' explist1] */ |
875 | if (ls->token == '=') { | 873 | if (ls->token == '=') { |
876 | next(ls); | 874 | next(ls); |
877 | explist1(ls, d); | 875 | return explist1(ls); |
878 | } | 876 | } |
879 | else | 877 | else |
880 | d->n = 0; | 878 | return 0; /* no initializations */ |
881 | } | 879 | } |
882 | 880 | ||
883 | 881 | ||
884 | static void localstat (LexState *ls) { | 882 | static void localstat (LexState *ls) { |
885 | /* stat -> LOCAL localnamelist decinit */ | 883 | /* stat -> LOCAL localnamelist decinit */ |
886 | FuncState *fs = ls->fs; | 884 | FuncState *fs = ls->fs; |
887 | listdesc d; | ||
888 | int nvars; | 885 | int nvars; |
886 | int nexps; | ||
889 | check_debugline(ls); | 887 | check_debugline(ls); |
890 | next(ls); | 888 | next(ls); |
891 | nvars = localnamelist(ls); | 889 | nvars = localnamelist(ls); |
892 | decinit(ls, &d); | 890 | nexps = decinit(ls); |
893 | adjustlocalvars(ls, nvars, fs->lastsetline); | 891 | adjustlocalvars(ls, nvars, fs->lastsetline); |
894 | adjust_mult_assign(ls, nvars, &d); | 892 | adjust_mult_assign(ls, nvars, nexps); |
895 | } | 893 | } |
896 | 894 | ||
897 | 895 | ||
@@ -902,7 +900,7 @@ static int funcname (LexState *ls, expdesc *v) { | |||
902 | if (ls->token == ':' || ls->token == '.') { | 900 | if (ls->token == ':' || ls->token == '.') { |
903 | needself = (ls->token == ':'); | 901 | needself = (ls->token == ':'); |
904 | next(ls); | 902 | next(ls); |
905 | luaK_2stack(ls, v); | 903 | luaK_1tostack(ls, v); |
906 | luaK_kstr(ls, checkname(ls)); | 904 | luaK_kstr(ls, checkname(ls)); |
907 | v->k = VINDEXED; | 905 | v->k = VINDEXED; |
908 | } | 906 | } |
@@ -931,9 +929,9 @@ static void namestat (LexState *ls) { | |||
931 | check_debugline(ls); | 929 | check_debugline(ls); |
932 | var_or_func(ls, &v); | 930 | var_or_func(ls, &v); |
933 | if (v.k == VEXP) { /* stat -> func */ | 931 | if (v.k == VEXP) { /* stat -> func */ |
934 | if (!luaK_iscall(ls, v.info)) /* is just an upvalue? */ | 932 | if (!luaK_lastisopen(ls)) /* is just an upvalue? */ |
935 | luaK_error(ls, "syntax error"); | 933 | luaK_error(ls, "syntax error"); |
936 | luaK_setcallreturns(ls, v.info, 0); /* call statement uses no results */ | 934 | luaK_setcallreturns(ls, 0); /* call statement uses no results */ |
937 | } | 935 | } |
938 | else { /* stat -> ['%'] NAME assignment */ | 936 | else { /* stat -> ['%'] NAME assignment */ |
939 | int left = assignment(ls, &v, 1); | 937 | int left = assignment(ls, &v, 1); |
@@ -950,11 +948,11 @@ static void ifpart (LexState *ls, int line) { | |||
950 | int elseinit; | 948 | int elseinit; |
951 | next(ls); /* skip IF or ELSEIF */ | 949 | next(ls); /* skip IF or ELSEIF */ |
952 | exp1(ls); /* cond */ | 950 | exp1(ls); /* cond */ |
953 | c = luaK_S(ls, IFFJMP, 0, -1); /* jump `then' if `cond' is false */ | 951 | c = luaK_S(ls, IFFJMP, 0, -1); /* jump over `then' part if `cond' is false */ |
954 | check(ls, THEN); | 952 | check(ls, THEN); |
955 | block(ls); /* `then' part */ | 953 | block(ls); /* `then' part */ |
956 | je = luaK_S(ls, JMP, 0, 0); /* jump `else' part after `then' */ | 954 | je = luaK_S(ls, JMP, 0, 0); /* jump over `else' part after `then' */ |
957 | elseinit = fs->pc; | 955 | elseinit = luaK_getlabel(ls); |
958 | if (ls->token == ELSEIF) | 956 | if (ls->token == ELSEIF) |
959 | ifpart(ls, line); | 957 | ifpart(ls, line); |
960 | else { | 958 | else { |
@@ -962,14 +960,15 @@ static void ifpart (LexState *ls, int line) { | |||
962 | block(ls); /* `else' part */ | 960 | block(ls); /* `else' part */ |
963 | check_match(ls, END, IF, line); | 961 | check_match(ls, END, IF, line); |
964 | } | 962 | } |
965 | if (fs->pc > elseinit) /* is there an `else' part? */ | 963 | if (fs->pc > elseinit) { /* is there an `else' part? */ |
966 | luaK_fixjump(ls, je, fs->pc); /* last jump jumps over it */ | 964 | luaK_fixjump(ls, je, luaK_getlabel(ls)); /* last jump jumps over it */ |
967 | else { | 965 | luaK_fixjump(ls, c, elseinit); /* fix first jump to `else' part */ |
966 | } | ||
967 | else { /* no else part */ | ||
968 | fs->pc--; /* remove last jump */ | 968 | fs->pc--; /* remove last jump */ |
969 | elseinit--; /* first jump will be smaller */ | ||
970 | LUA_ASSERT(L, fs->pc == je, "jump out of place"); | 969 | LUA_ASSERT(L, fs->pc == je, "jump out of place"); |
970 | luaK_fixjump(ls, c, luaK_getlabel(ls)); /* fix first jump to `if' end */ | ||
971 | } | 971 | } |
972 | luaK_fixjump(ls, c, elseinit); /* fix first jump to `else' part */ | ||
973 | } | 972 | } |
974 | 973 | ||
975 | 974 | ||
@@ -1073,11 +1072,11 @@ static void body (LexState *ls, int needself, int line) { | |||
1073 | static void ret (LexState *ls) { | 1072 | static void ret (LexState *ls) { |
1074 | /* ret -> [RETURN explist sc] */ | 1073 | /* ret -> [RETURN explist sc] */ |
1075 | if (ls->token == RETURN) { | 1074 | if (ls->token == RETURN) { |
1076 | listdesc e; | 1075 | int nexps; /* number of expressions returned */ |
1077 | check_debugline(ls); | 1076 | check_debugline(ls); |
1078 | next(ls); | 1077 | next(ls); |
1079 | explist(ls, &e); | 1078 | nexps = explist(ls); |
1080 | luaK_retcode(ls, ls->fs->nlocalvar, &e); | 1079 | luaK_retcode(ls, ls->fs->nlocalvar, nexps); |
1081 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | 1080 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ |
1082 | optional(ls, ';'); | 1081 | optional(ls, ';'); |
1083 | } | 1082 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.8 2000/03/03 14:58:26 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.9 2000/03/03 18:53:17 roberto Exp roberto $ |
3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -46,13 +46,11 @@ | |||
46 | ** Expression descriptor | 46 | ** Expression descriptor |
47 | */ | 47 | */ |
48 | 48 | ||
49 | #define NOJUMPS 0 | ||
50 | |||
51 | typedef enum { | 49 | typedef enum { |
52 | VGLOBAL, /* info is constant index of global name */ | 50 | VGLOBAL, /* info is constant index of global name */ |
53 | VLOCAL, /* info is stack index */ | 51 | VLOCAL, /* info is stack index */ |
54 | VINDEXED, /* info is info of the index expression */ | 52 | VINDEXED, |
55 | VEXP /* info is NOJUMPS if exp has no internal jumps */ | 53 | VEXP /* info is jump target if exp has internal jumps */ |
56 | } expkind; | 54 | } expkind; |
57 | 55 | ||
58 | typedef struct expdesc { | 56 | typedef struct expdesc { |
@@ -61,22 +59,13 @@ typedef struct expdesc { | |||
61 | } expdesc; | 59 | } expdesc; |
62 | 60 | ||
63 | 61 | ||
64 | /* | ||
65 | ** Expression List descriptor: | ||
66 | ** tells number of expressions in the list, | ||
67 | ** and gives the `info' of last expression. | ||
68 | */ | ||
69 | typedef struct listdesc { | ||
70 | int n; | ||
71 | int info; /* 0 if last expression has no internal jumps */ | ||
72 | } listdesc; | ||
73 | |||
74 | 62 | ||
75 | /* state needed to generate code for a given function */ | 63 | /* state needed to generate code for a given function */ |
76 | typedef struct FuncState { | 64 | typedef struct FuncState { |
77 | TProtoFunc *f; /* current function header */ | 65 | TProtoFunc *f; /* current function header */ |
78 | struct FuncState *prev; /* enclosing function */ | 66 | struct FuncState *prev; /* enclosing function */ |
79 | int pc; /* next position to code */ | 67 | int pc; /* next position to code */ |
68 | int lasttarget; /* `pc' of last `jump target' */ | ||
80 | int stacksize; /* number of values on activation register */ | 69 | int stacksize; /* number of values on activation register */ |
81 | int nlocalvar; /* number of active local variables */ | 70 | int nlocalvar; /* number of active local variables */ |
82 | int nupvalues; /* number of upvalues */ | 71 | int nupvalues; /* number of upvalues */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.89 2000/02/22 18:12:46 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.90 2000/03/03 14:58:26 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -348,10 +348,10 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, | |||
348 | return base+GETARG_B(i); | 348 | return base+GETARG_B(i); |
349 | 349 | ||
350 | case PUSHNIL: { | 350 | case PUSHNIL: { |
351 | register int n = GETARG_U(i); | 351 | int n = GETARG_U(i); |
352 | do { | 352 | do { |
353 | ttype(top++) = LUA_T_NIL; | 353 | ttype(top++) = LUA_T_NIL; |
354 | } while (n--); | 354 | } while (--n > 0); |
355 | break; | 355 | break; |
356 | } | 356 | } |
357 | 357 | ||