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: |
