aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-03-04 17:18:15 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-03-04 17:18:15 -0300
commit563de491be90601f23a735aede89ea9a3ef86ee9 (patch)
treec92677f388289ead55c8a8778493b0af7e41f159
parent29e01934253adf5fbf43faff81d87d7470cef8ce (diff)
downloadlua-563de491be90601f23a735aede89ea9a3ef86ee9.tar.gz
lua-563de491be90601f23a735aede89ea9a3ef86ee9.tar.bz2
lua-563de491be90601f23a735aede89ea9a3ef86ee9.zip
a better way to control optimizations.
-rw-r--r--lcode.c160
-rw-r--r--lcode.h14
-rw-r--r--lopcodes.h4
-rw-r--r--lparser.c205
-rw-r--r--lparser.h19
-rw-r--r--lvm.c8
6 files changed, 218 insertions, 192 deletions
diff --git a/lcode.c b/lcode.c
index be97e2bb..d43103fd 100644
--- a/lcode.c
+++ b/lcode.c
@@ -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
23static 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*/
28static 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
38static void luaK_minus (LexState *ls, expdesc *v) { 47static 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
49static void luaK_gettable (LexState *ls, expdesc *v) { 58static 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
59static void luaK_add (LexState *ls, expdesc *v) { 68static 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
69static void luaK_sub (LexState *ls, expdesc *v) { 78static 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
82void luaK_retcode (LexState *ls, int nlocals, listdesc *e) { 91void 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
103static 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
93int luaK_code (LexState *ls, Instruction i, int delta) { 115int 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*/
133int luaK_getlabel (LexState *ls) {
134 FuncState *fs = ls->fs;
135 fs->lasttarget = fs->pc;
136 return fs->pc;
137}
138
139
107void luaK_deltastack (LexState *ls, int delta) { 140void 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
158int luaK_iscall (LexState *ls, int hasjumps) { 191int 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
165void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults) { 202void 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
185void luaK_2stack (LexState *ls, expdesc *var) { 217void 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
236void 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
224void luaK_prefix (LexState *ls, int op, expdesc *v) { 262void 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
232void luaK_infix (LexState *ls, expdesc *v) { 269void 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
241void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { 278void 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
diff --git a/lcode.h b/lcode.h
index 0ba83766..0f8eadc1 100644
--- a/lcode.h
+++ b/lcode.h
@@ -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 @@
22void luaK_error (LexState *ls, const char *msg); 22void luaK_error (LexState *ls, const char *msg);
23int luaK_primitivecode (LexState *ls, Instruction i); 23int luaK_primitivecode (LexState *ls, Instruction i);
24int luaK_code (LexState *ls, Instruction i, int delta); 24int luaK_code (LexState *ls, Instruction i, int delta);
25void luaK_retcode (LexState *ls, int nlocals, listdesc *e); 25void luaK_retcode (LexState *ls, int nlocals, int nexps);
26void luaK_fixjump (LexState *ls, int pc, int dest); 26void luaK_fixjump (LexState *ls, int pc, int dest);
27int luaK_getlabel (LexState *ls);
27void luaK_deltastack (LexState *ls, int delta); 28void luaK_deltastack (LexState *ls, int delta);
28void luaK_kstr (LexState *ls, int c); 29void luaK_kstr (LexState *ls, int c);
29void luaK_number (LexState *ls, real f); 30void luaK_number (LexState *ls, real f);
30void luaK_adjuststack (LexState *ls, int n); 31void luaK_adjuststack (LexState *ls, int n);
31int luaK_iscall (LexState *ls, int hasjumps); 32int luaK_lastisopen (LexState *ls);
32void luaK_setcallreturns (LexState *ls, int hasjumps, int nresults); 33void luaK_setcallreturns (LexState *ls, int nresults);
33void luaK_2stack (LexState *ls, expdesc *var); 34void luaK_tostack (LexState *ls, expdesc *var);
35void luaK_1tostack (LexState *ls, expdesc *var);
34void luaK_storevar (LexState *ls, const expdesc *var); 36void luaK_storevar (LexState *ls, const expdesc *var);
35void luaK_prefix (LexState *ls, int op, expdesc *v); 37void luaK_prefix (LexState *ls, int op, expdesc *v);
36void luaK_infix (LexState *ls, expdesc *v); 38void luaK_infix (LexState *ls, int op, expdesc *v);
37void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2); 39void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2);
38 40
39 41
diff --git a/lopcodes.h b/lopcodes.h
index b2819c3b..494cb84c 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -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) */
71CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ 71CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */
72TAILCALL,/* A B v_a-v_1 f (return) f(v1,...,v_a) */ 72TAILCALL,/* A B v_a-v_1 f (return) f(v1,...,v_a) */
73 73
74PUSHNIL,/* U - nil_0-nil_u */ 74PUSHNIL,/* U - nil_1-nil_u */
75POP,/* U a_u-a_1 - */ 75POP,/* U a_u-a_1 - */
76 76
77PUSHINT,/* S - (real)s */ 77PUSHINT,/* S - (real)s */
diff --git a/lparser.c b/lparser.c
index e39f77b0..4c1eeb80 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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);
53static void chunk (LexState *ls); 54static void chunk (LexState *ls);
54static void constructor (LexState *ls); 55static void constructor (LexState *ls);
55static void expr (LexState *ls, expdesc *v); 56static void expr (LexState *ls, expdesc *v);
56static int exp1 (LexState *ls); 57static void exp1 (LexState *ls);
57 58
58 59
59static void next (LexState *ls) { 60static void next (LexState *ls) {
@@ -256,9 +257,9 @@ static void pushupvalue (LexState *ls, TaggedString *n) {
256} 257}
257 258
258 259
259static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { 260static 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
383static void explist1 (LexState *ls, listdesc *d) { 385static 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
399static void explist (LexState *ls, listdesc *d) { 401static 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
412static void funcparams (LexState *ls, int slf) { 414static 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
700static int exp1 (LexState *ls) { 697static 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*/
712static int get_priority (int op, int *rp) { 708static 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*/
738static void operator_expr (LexState *ls, expdesc *v, int limit) { 735static 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
759static void expr (LexState *ls, expdesc *v) { 756static 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
849static void repeatstat (LexState *ls, int line) { 848static 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
873static void decinit (LexState *ls, listdesc *d) { 871static 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
884static void localstat (LexState *ls) { 882static 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) {
1073static void ret (LexState *ls) { 1072static 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 }
diff --git a/lparser.h b/lparser.h
index a64b8dda..adc7f012 100644
--- a/lparser.h
+++ b/lparser.h
@@ -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
51typedef enum { 49typedef 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
58typedef struct expdesc { 56typedef 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*/
69typedef 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 */
76typedef struct FuncState { 64typedef 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 */
diff --git a/lvm.c b/lvm.c
index 60a886c8..819e9a0e 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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