diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-08 16:10:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-08 16:10:32 -0300 |
commit | bd8b9c94b38ddaa3cd7324cbca98571633e03f91 (patch) | |
tree | 599551d4713dc039c2603e1830cc13acc9552779 | |
parent | 4db04555f06b90f3b2cda96c2f4aaeb78266ea86 (diff) | |
download | lua-bd8b9c94b38ddaa3cd7324cbca98571633e03f91.tar.gz lua-bd8b9c94b38ddaa3cd7324cbca98571633e03f91.tar.bz2 lua-bd8b9c94b38ddaa3cd7324cbca98571633e03f91.zip |
generic for (with any number of control variables)
-rw-r--r-- | lcode.c | 27 | ||||
-rw-r--r-- | lcode.h | 4 | ||||
-rw-r--r-- | ldebug.c | 21 | ||||
-rw-r--r-- | lopcodes.c | 5 | ||||
-rw-r--r-- | lopcodes.h | 10 | ||||
-rw-r--r-- | lparser.c | 84 | ||||
-rw-r--r-- | lvm.c | 15 |
7 files changed, 98 insertions, 68 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.89 2002/02/05 22:39:12 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.90 2002/03/05 12:42: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 | */ |
@@ -158,6 +158,11 @@ void luaK_patchlist (FuncState *fs, int list, int target) { | |||
158 | } | 158 | } |
159 | 159 | ||
160 | 160 | ||
161 | void luaK_patchtohere (FuncState *fs, int list) { | ||
162 | luaK_patchlist(fs, list, luaK_getlabel(fs)); | ||
163 | } | ||
164 | |||
165 | |||
161 | void luaK_concat (FuncState *fs, int *l1, int l2) { | 166 | void luaK_concat (FuncState *fs, int *l1, int l2) { |
162 | if (*l1 == NO_JUMP) | 167 | if (*l1 == NO_JUMP) |
163 | *l1 = l2; | 168 | *l1 = l2; |
@@ -171,16 +176,22 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { | |||
171 | } | 176 | } |
172 | 177 | ||
173 | 178 | ||
174 | void luaK_reserveregs (FuncState *fs, int n) { | 179 | void luaK_checkstack (FuncState *fs, int n) { |
175 | fs->freereg += n; | 180 | int newstack = fs->freereg + n; |
176 | if (fs->freereg > fs->f->maxstacksize) { | 181 | if (newstack > fs->f->maxstacksize) { |
177 | if (fs->freereg >= MAXSTACK) | 182 | if (newstack >= MAXSTACK) |
178 | luaK_error(fs->ls, "function or expression too complex"); | 183 | luaK_error(fs->ls, "function or expression too complex"); |
179 | fs->f->maxstacksize = cast(lu_byte, fs->freereg); | 184 | fs->f->maxstacksize = cast(lu_byte, newstack); |
180 | } | 185 | } |
181 | } | 186 | } |
182 | 187 | ||
183 | 188 | ||
189 | void luaK_reserveregs (FuncState *fs, int n) { | ||
190 | luaK_checkstack(fs, n); | ||
191 | fs->freereg += n; | ||
192 | } | ||
193 | |||
194 | |||
184 | static void freereg (FuncState *fs, int reg) { | 195 | static void freereg (FuncState *fs, int reg) { |
185 | if (reg >= fs->nactloc && reg < MAXSTACK) { | 196 | if (reg >= fs->nactloc && reg < MAXSTACK) { |
186 | fs->freereg--; | 197 | fs->freereg--; |
@@ -533,7 +544,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { | |||
533 | } | 544 | } |
534 | } | 545 | } |
535 | luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ | 546 | luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ |
536 | luaK_patchlist(fs, e->t, luaK_getlabel(fs)); | 547 | luaK_patchtohere(fs, e->t); |
537 | e->t = NO_JUMP; | 548 | e->t = NO_JUMP; |
538 | } | 549 | } |
539 | 550 | ||
@@ -560,7 +571,7 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) { | |||
560 | } | 571 | } |
561 | } | 572 | } |
562 | luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ | 573 | luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ |
563 | luaK_patchlist(fs, e->f, luaK_getlabel(fs)); | 574 | luaK_patchtohere(fs, e->f); |
564 | e->f = NO_JUMP; | 575 | e->f = NO_JUMP; |
565 | } | 576 | } |
566 | 577 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ | 2 | ** $Id: lcode.h,v 1.27 2002/02/05 22:39:12 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 | */ |
@@ -42,6 +42,7 @@ void luaK_error (LexState *ls, const char *msg); | |||
42 | int luaK_codeABc (FuncState *fs, OpCode o, int A, unsigned int Bc); | 42 | int luaK_codeABc (FuncState *fs, OpCode o, int A, unsigned int Bc); |
43 | int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); | 43 | int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); |
44 | void luaK_nil (FuncState *fs, int from, int n); | 44 | void luaK_nil (FuncState *fs, int from, int n); |
45 | void luaK_checkstack (FuncState *fs, int n); | ||
45 | void luaK_reserveregs (FuncState *fs, int n); | 46 | void luaK_reserveregs (FuncState *fs, int n); |
46 | int luaK_stringK (FuncState *fs, TString *s); | 47 | int luaK_stringK (FuncState *fs, TString *s); |
47 | int luaK_numberK (FuncState *fs, lua_Number r); | 48 | int luaK_numberK (FuncState *fs, lua_Number r); |
@@ -57,6 +58,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | |||
57 | void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); | 58 | void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); |
58 | int luaK_jump (FuncState *fs); | 59 | int luaK_jump (FuncState *fs); |
59 | void luaK_patchlist (FuncState *fs, int list, int target); | 60 | void luaK_patchlist (FuncState *fs, int list, int target); |
61 | void luaK_patchtohere (FuncState *fs, int list); | ||
60 | void luaK_concat (FuncState *fs, int *l1, int l2); | 62 | void luaK_concat (FuncState *fs, int *l1, int l2); |
61 | int luaK_getlabel (FuncState *fs); | 63 | int luaK_getlabel (FuncState *fs); |
62 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); | 64 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.97 2002/01/09 22:02:47 roberto Exp $ | 2 | ** $Id: ldebug.c,v 1.100 2002/02/05 22:39:12 roberto Exp $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -375,9 +375,10 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
375 | check(c < MAXSTACK && b < c); | 375 | check(c < MAXSTACK && b < c); |
376 | break; | 376 | break; |
377 | } | 377 | } |
378 | case OP_JMP: | ||
379 | case OP_FORLOOP: | 378 | case OP_FORLOOP: |
380 | case OP_TFORLOOP: { | 379 | checkreg(pt, a+2); |
380 | /* go through */ | ||
381 | case OP_JMP: { | ||
381 | int dest = pc+1+b; | 382 | int dest = pc+1+b; |
382 | check(0 <= dest && dest < pt->sizecode); | 383 | check(0 <= dest && dest < pt->sizecode); |
383 | /* not full check and jump is forward and do not skip `lastpc'? */ | 384 | /* not full check and jump is forward and do not skip `lastpc'? */ |
@@ -385,6 +386,12 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
385 | pc += b; /* do the jump */ | 386 | pc += b; /* do the jump */ |
386 | break; | 387 | break; |
387 | } | 388 | } |
389 | case OP_TFORLOOP: { | ||
390 | checkreg(pt, a+c); | ||
391 | checkreg(pt, a+2); /* at least 2 for table generators */ | ||
392 | check(pc+2 < pt->sizecode); /* check skip */ | ||
393 | break; | ||
394 | } | ||
388 | case OP_CALL: { | 395 | case OP_CALL: { |
389 | if (b != 0) { | 396 | if (b != 0) { |
390 | checkreg(pt, a+b-1); | 397 | checkreg(pt, a+b-1); |
@@ -408,8 +415,14 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
408 | break; | 415 | break; |
409 | } | 416 | } |
410 | case OP_CLOSURE: { | 417 | case OP_CLOSURE: { |
418 | int nup; | ||
411 | check(b < pt->sizep); | 419 | check(b < pt->sizep); |
412 | check(pc + pt->p[b]->nupvalues < pt->sizecode); | 420 | nup = pt->p[b]->nupvalues; |
421 | check(pc + nup < pt->sizecode); | ||
422 | for (; nup>0; nup--) { | ||
423 | OpCode op1 = GET_OPCODE(pt->code[pc+nup]); | ||
424 | check(op1 == OP_GETUPVAL || op1 == OP_MOVE); | ||
425 | } | ||
413 | break; | 426 | break; |
414 | } | 427 | } |
415 | default: break; | 428 | default: break; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.8 2001/12/11 22:48:44 roberto Exp $ | 2 | ** $Id: lopcodes.c,v 1.11 2002/02/05 22:39:12 roberto Exp roberto $ |
3 | ** extracted automatically from lopcodes.h by mkprint.lua | 3 | ** extracted automatically from lopcodes.h by mkprint.lua |
4 | ** DO NOT EDIT | 4 | ** DO NOT EDIT |
5 | ** See Copyright Notice in lua.h | 5 | ** See Copyright Notice in lua.h |
@@ -60,6 +60,7 @@ const char *const luaP_opnames[] = { | |||
60 | ((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \ | 60 | ((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \ |
61 | ((sa)<<OpModesetA) | ((k)<<OpModeK) | (x)<<OpModeNoTrace | (m)) | 61 | ((sa)<<OpModesetA) | ((k)<<OpModeK) | (x)<<OpModeNoTrace | (m)) |
62 | 62 | ||
63 | |||
63 | const lu_byte luaP_opmodes[NUM_OPCODES] = { | 64 | const lu_byte luaP_opmodes[NUM_OPCODES] = { |
64 | /* T n B C sA K mode opcode */ | 65 | /* T n B C sA K mode opcode */ |
65 | opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */ | 66 | opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */ |
@@ -94,7 +95,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
94 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */ | 95 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */ |
95 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */ | 96 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */ |
96 | ,opmode(0,1,0,0, 0,0,iAsBc) /* OP_FORLOOP */ | 97 | ,opmode(0,1,0,0, 0,0,iAsBc) /* OP_FORLOOP */ |
97 | ,opmode(0,1,0,0, 0,0,iAsBc) /* OP_TFORLOOP */ | 98 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_TFORLOOP */ |
98 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */ | 99 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */ |
99 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */ | 100 | ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */ |
100 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */ | 101 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.85 2002/01/09 22:02:47 roberto Exp $ | 2 | ** $Id: lopcodes.h,v 1.89 2002/02/14 21:43:01 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 | */ |
@@ -166,11 +166,13 @@ OP_TESTGE,/* A C if not (R(A) >= R/K(C)) then pc++ */ | |||
166 | OP_TESTT,/* A B if (R(B)) then R(A) := R(B) else pc++ */ | 166 | OP_TESTT,/* A B if (R(B)) then R(A) := R(B) else pc++ */ |
167 | OP_TESTF,/* A B if not (R(B)) then R(A) := R(B) else pc++ */ | 167 | OP_TESTF,/* A B if not (R(B)) then R(A) := R(B) else pc++ */ |
168 | 168 | ||
169 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))*/ | 169 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ |
170 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see (3)) */ | 170 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see (3)) */ |
171 | 171 | ||
172 | OP_FORLOOP,/* A sBc */ | 172 | OP_FORLOOP,/* A sBc R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBc */ |
173 | OP_TFORLOOP,/* A sBc */ | 173 | |
174 | OP_TFORLOOP,/* A C R(A+1), ... ,R(A+C) := R(A)(); | ||
175 | if R(A+1) ~= nil then pc++ */ | ||
174 | 176 | ||
175 | OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ | 177 | OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ |
176 | OP_SETLISTO,/* A Bc */ | 178 | OP_SETLISTO,/* A Bc */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ | 2 | ** $Id: lparser.c,v 1.167 2002/02/14 21:46:58 roberto Exp $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -247,12 +247,12 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
247 | } | 247 | } |
248 | 248 | ||
249 | 249 | ||
250 | static void code_params (LexState *ls, int nparams, short dots) { | 250 | static void code_params (LexState *ls, int nparams, int dots) { |
251 | FuncState *fs = ls->fs; | 251 | FuncState *fs = ls->fs; |
252 | adjustlocalvars(ls, nparams); | 252 | adjustlocalvars(ls, nparams); |
253 | luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); | 253 | luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); |
254 | fs->f->numparams = cast(short, fs->nactloc); /* `self' could be there already */ | 254 | fs->f->numparams = cast(lu_byte, fs->nactloc); |
255 | fs->f->is_vararg = dots; | 255 | fs->f->is_vararg = cast(lu_byte, dots); |
256 | if (dots) { | 256 | if (dots) { |
257 | new_localvarstr(ls, "arg", 0); | 257 | new_localvarstr(ls, "arg", 0); |
258 | adjustlocalvars(ls, 1); | 258 | adjustlocalvars(ls, 1); |
@@ -271,7 +271,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { | |||
271 | 271 | ||
272 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 272 | static void leavebreak (FuncState *fs, Breaklabel *bl) { |
273 | fs->bl = bl->previous; | 273 | fs->bl = bl->previous; |
274 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | 274 | luaK_patchtohere(fs, bl->breaklist); |
275 | lua_assert(bl->nactloc == fs->nactloc); | 275 | lua_assert(bl->nactloc == fs->nactloc); |
276 | } | 276 | } |
277 | 277 | ||
@@ -471,8 +471,11 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
471 | FuncState *fs = ls->fs; | 471 | FuncState *fs = ls->fs; |
472 | int reg = ls->fs->freereg; | 472 | int reg = ls->fs->freereg; |
473 | expdesc key, val; | 473 | expdesc key, val; |
474 | if (ls->t.token == TK_NAME) | 474 | if (ls->t.token == TK_NAME) { |
475 | luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); | ||
476 | cc->nh++; | ||
475 | checkname(ls, &key); | 477 | checkname(ls, &key); |
478 | } | ||
476 | else /* ls->t.token == '[' */ | 479 | else /* ls->t.token == '[' */ |
477 | luaY_index(ls, &key); | 480 | luaY_index(ls, &key); |
478 | check(ls, '='); | 481 | check(ls, '='); |
@@ -481,8 +484,6 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
481 | luaK_exp2anyreg(fs, &val); | 484 | luaK_exp2anyreg(fs, &val); |
482 | luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key)); | 485 | luaK_codeABC(fs, OP_SETTABLE, val.info, cc->t->info, luaK_exp2RK(fs, &key)); |
483 | fs->freereg = reg; /* free registers */ | 486 | fs->freereg = reg; /* free registers */ |
484 | luaX_checklimit(ls, cc->nh, MAX_INT, "items in a constructor"); | ||
485 | cc->nh++; | ||
486 | } | 487 | } |
487 | 488 | ||
488 | 489 | ||
@@ -893,7 +894,7 @@ static void whilestat (LexState *ls, int line) { | |||
893 | check(ls, TK_DO); | 894 | check(ls, TK_DO); |
894 | block(ls); | 895 | block(ls); |
895 | luaK_patchlist(fs, luaK_jump(fs), while_init); | 896 | luaK_patchlist(fs, luaK_jump(fs), while_init); |
896 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); | 897 | luaK_patchtohere(fs, v.f); |
897 | check_match(ls, TK_END, TK_WHILE, line); | 898 | check_match(ls, TK_END, TK_WHILE, line); |
898 | leavebreak(fs, &bl); | 899 | leavebreak(fs, &bl); |
899 | } | 900 | } |
@@ -922,24 +923,11 @@ static void exp1 (LexState *ls) { | |||
922 | } | 923 | } |
923 | 924 | ||
924 | 925 | ||
925 | static void forbody (LexState *ls, OpCode loopfor) { | ||
926 | /* forbody -> DO block END */ | ||
927 | FuncState *fs = ls->fs; | ||
928 | int basereg = fs->freereg - 3; | ||
929 | int prep = luaK_jump(fs); | ||
930 | int blockinit = luaK_getlabel(fs); | ||
931 | check(ls, TK_DO); | ||
932 | adjustlocalvars(ls, 3); /* scope for control variables */ | ||
933 | block(ls); | ||
934 | luaK_patchlist(fs, prep, luaK_getlabel(fs)); | ||
935 | luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit); | ||
936 | removelocalvars(ls, 3, 1); | ||
937 | } | ||
938 | |||
939 | |||
940 | static void fornum (LexState *ls, TString *varname) { | 926 | static void fornum (LexState *ls, TString *varname) { |
941 | /* fornum -> NAME = exp1,exp1[,exp1] forbody */ | 927 | /* fornum -> NAME = exp1,exp1[,exp1] DO body */ |
942 | FuncState *fs = ls->fs; | 928 | FuncState *fs = ls->fs; |
929 | int prep; | ||
930 | int base = fs->freereg; | ||
943 | new_localvar(ls, varname, 0); | 931 | new_localvar(ls, varname, 0); |
944 | new_localvarstr(ls, "(limit)", 1); | 932 | new_localvarstr(ls, "(limit)", 1); |
945 | new_localvarstr(ls, "(step)", 2); | 933 | new_localvarstr(ls, "(step)", 2); |
@@ -954,26 +942,42 @@ static void fornum (LexState *ls, TString *varname) { | |||
954 | luaK_reserveregs(fs, 1); | 942 | luaK_reserveregs(fs, 1); |
955 | } | 943 | } |
956 | luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); | 944 | luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); |
957 | forbody(ls, OP_FORLOOP); | 945 | luaK_jump(fs); |
946 | prep = luaK_getlabel(fs); | ||
947 | check(ls, TK_DO); | ||
948 | adjustlocalvars(ls, 3); /* scope for control variables */ | ||
949 | block(ls); | ||
950 | luaK_patchtohere(fs, prep-1); | ||
951 | luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep); | ||
952 | removelocalvars(ls, 3, 1); | ||
958 | } | 953 | } |
959 | 954 | ||
960 | 955 | ||
961 | static void forlist (LexState *ls, TString *indexname) { | 956 | static void forlist (LexState *ls, TString *indexname) { |
962 | /* forlist -> NAME,NAME IN exp1 forbody */ | 957 | /* forlist -> NAME {,NAME} IN exp1 DO body */ |
963 | FuncState *fs = ls->fs; | 958 | FuncState *fs = ls->fs; |
959 | int nvars = 0; | ||
960 | int prep; | ||
961 | int base = fs->freereg; | ||
964 | new_localvarstr(ls, "(table)", 0); | 962 | new_localvarstr(ls, "(table)", 0); |
965 | new_localvar(ls, indexname, 1); | 963 | new_localvar(ls, indexname, ++nvars); |
966 | if (optional(ls, ',')) { | 964 | while (optional(ls, ',')) { |
967 | new_localvar(ls, str_checkname(ls), 2); | 965 | new_localvar(ls, str_checkname(ls), ++nvars); |
968 | next(ls); /* skip var name */ | 966 | next(ls); |
969 | } | 967 | } |
970 | else | ||
971 | new_localvarstr(ls, "(val)", 2); | ||
972 | check(ls, TK_IN); | 968 | check(ls, TK_IN); |
973 | exp1(ls); /* table */ | 969 | exp1(ls); /* table */ |
974 | luaK_reserveregs(fs, 2); /* registers for index and val */ | 970 | luaK_checkstack(fs, 2); /* at least two slots, to traverse tables */ |
975 | luaK_codeABC(fs, OP_LOADNIL, fs->freereg - 2, fs->freereg - 1, 0); | 971 | luaK_reserveregs(fs, nvars); /* registers for vars */ |
976 | forbody(ls, OP_TFORLOOP); | 972 | luaK_codeABC(fs, OP_LOADNIL, base+1, base+nvars, 0); |
973 | adjustlocalvars(ls, nvars+1); /* scope for control variables */ | ||
974 | luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); | ||
975 | prep = luaK_jump(fs); | ||
976 | check(ls, TK_DO); | ||
977 | block(ls); | ||
978 | luaK_patchlist(fs, luaK_jump(fs), prep-1); | ||
979 | luaK_patchtohere(fs, prep); | ||
980 | removelocalvars(ls, nvars+1, 1); | ||
977 | } | 981 | } |
978 | 982 | ||
979 | 983 | ||
@@ -1013,18 +1017,18 @@ static void ifstat (LexState *ls, int line) { | |||
1013 | test_then_block(ls, &v); /* IF cond THEN block */ | 1017 | test_then_block(ls, &v); /* IF cond THEN block */ |
1014 | while (ls->t.token == TK_ELSEIF) { | 1018 | while (ls->t.token == TK_ELSEIF) { |
1015 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1019 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
1016 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); | 1020 | luaK_patchtohere(fs, v.f); |
1017 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ | 1021 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ |
1018 | } | 1022 | } |
1019 | if (ls->t.token == TK_ELSE) { | 1023 | if (ls->t.token == TK_ELSE) { |
1020 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1024 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
1021 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); | 1025 | luaK_patchtohere(fs, v.f); |
1022 | next(ls); /* skip ELSE */ | 1026 | next(ls); /* skip ELSE */ |
1023 | block(ls); /* `else' part */ | 1027 | block(ls); /* `else' part */ |
1024 | } | 1028 | } |
1025 | else | 1029 | else |
1026 | luaK_concat(fs, &escapelist, v.f); | 1030 | luaK_concat(fs, &escapelist, v.f); |
1027 | luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); | 1031 | luaK_patchtohere(fs, escapelist); |
1028 | check_match(ls, TK_END, TK_IF, line); | 1032 | check_match(ls, TK_END, TK_IF, line); |
1029 | } | 1033 | } |
1030 | 1034 | ||
@@ -1182,7 +1186,7 @@ static int statement (LexState *ls) { | |||
1182 | static void parlist (LexState *ls) { | 1186 | static void parlist (LexState *ls) { |
1183 | /* parlist -> [ param { `,' param } ] */ | 1187 | /* parlist -> [ param { `,' param } ] */ |
1184 | int nparams = 0; | 1188 | int nparams = 0; |
1185 | short dots = 0; | 1189 | int dots = 0; |
1186 | if (ls->t.token != ')') { /* is `parlist' not empty? */ | 1190 | if (ls->t.token != ')') { /* is `parlist' not empty? */ |
1187 | do { | 1191 | do { |
1188 | switch (ls->t.token) { | 1192 | switch (ls->t.token) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.217 2002/03/04 15:40:04 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.218 2002/03/04 21:33:09 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 | */ |
@@ -560,24 +560,21 @@ StkId luaV_execute (lua_State *L) { | |||
560 | break; | 560 | break; |
561 | } | 561 | } |
562 | case OP_TFORLOOP: { | 562 | case OP_TFORLOOP: { |
563 | int j = GETARG_sBc(i); | ||
564 | int loop = 0; | ||
565 | pc += j; /* jump back before tests (for error messages) */ | ||
566 | if (ttype(ra) == LUA_TTABLE) { | 563 | if (ttype(ra) == LUA_TTABLE) { |
567 | Table *t = hvalue(ra); | 564 | Table *t = hvalue(ra); |
568 | loop = luaH_next(L, t, ra+1); | 565 | if (luaH_next(L, t, ra+1)) |
566 | pc++; /* skip jump (keep looping) */ | ||
569 | } | 567 | } |
570 | else if (ttype(ra) == LUA_TFUNCTION) { | 568 | else if (ttype(ra) == LUA_TFUNCTION) { |
571 | setobj(ra+1, ra); | 569 | setobj(ra+1, ra); |
572 | L->top = ra+2; /* no arguments */ | 570 | L->top = ra+2; /* no arguments */ |
573 | luaD_call(L, ra+1, 2); | 571 | luaD_call(L, ra+1, GETARG_C(i)); |
574 | L->top = L->ci->top; | 572 | L->top = L->ci->top; |
575 | loop = (ttype(ra+1) != LUA_TNIL); | 573 | if (ttype(ra+1) != LUA_TNIL) |
574 | pc++; /* skip jump (keep looping) */ | ||
576 | } | 575 | } |
577 | else | 576 | else |
578 | luaD_error(L, "`for' generator must be a table or function"); | 577 | luaD_error(L, "`for' generator must be a table or function"); |
579 | if (!loop) | ||
580 | pc -= j; /* undo jump */ | ||
581 | break; | 578 | break; |
582 | } | 579 | } |
583 | case OP_SETLIST: | 580 | case OP_SETLIST: |