diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-05-13 17:15:59 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-05-13 17:15:59 -0300 |
commit | 6d268b0b00ae63e5d06aedc4fb3cec105123a565 (patch) | |
tree | 26fac79b53bfd79a9351291427358eb2e89c7360 /lvm.c | |
parent | c7677471918fa55095f4993484eb5805091364fd (diff) | |
download | lua-6d268b0b00ae63e5d06aedc4fb3cec105123a565.tar.gz lua-6d268b0b00ae63e5d06aedc4fb3cec105123a565.tar.bz2 lua-6d268b0b00ae63e5d06aedc4fb3cec105123a565.zip |
new semantics for "for" local variables
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 52 |
1 files changed, 27 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.284 2003/04/03 13:35:34 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.285 2003/05/05 18:39:57 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 | */ |
@@ -639,43 +639,45 @@ StkId luaV_execute (lua_State *L) { | |||
639 | } | 639 | } |
640 | } | 640 | } |
641 | case OP_FORLOOP: { | 641 | case OP_FORLOOP: { |
642 | lua_Number step, idx, limit; | 642 | lua_Number step = nvalue(ra+2); |
643 | lua_Number idx = nvalue(ra) + step; /* increment index */ | ||
644 | lua_Number limit = nvalue(ra+1); | ||
645 | if (step > 0 ? idx <= limit : idx >= limit) { | ||
646 | dojump(pc, GETARG_sBx(i)); /* jump back */ | ||
647 | setnvalue(ra, idx); /* update internal index... */ | ||
648 | setnvalue(ra+3, idx); /* ...and external index */ | ||
649 | } | ||
650 | break; | ||
651 | } | ||
652 | case OP_FORPREP: { | ||
653 | const TObject *init = ra; | ||
643 | const TObject *plimit = ra+1; | 654 | const TObject *plimit = ra+1; |
644 | const TObject *pstep = ra+2; | 655 | const TObject *pstep = ra+2; |
645 | if (!ttisnumber(ra)) | 656 | if (!tonumber(init, ra)) |
646 | luaG_runerror(L, "`for' initial value must be a number"); | 657 | luaG_runerror(L, "`for' initial value must be a number"); |
647 | if (!tonumber(plimit, ra+1)) | 658 | else if (!tonumber(plimit, ra+1)) |
648 | luaG_runerror(L, "`for' limit must be a number"); | 659 | luaG_runerror(L, "`for' limit must be a number"); |
649 | if (!tonumber(pstep, ra+2)) | 660 | else if (!tonumber(pstep, ra+2)) |
650 | luaG_runerror(L, "`for' step must be a number"); | 661 | luaG_runerror(L, "`for' step must be a number"); |
651 | step = nvalue(pstep); | 662 | setnvalue(ra, nvalue(ra) - nvalue(pstep)); |
652 | idx = nvalue(ra) + step; /* increment index */ | 663 | dojump(pc, GETARG_sBx(i)); |
653 | limit = nvalue(plimit); | ||
654 | if (step > 0 ? idx <= limit : idx >= limit) { | ||
655 | dojump(pc, GETARG_sBx(i)); /* jump back */ | ||
656 | chgnvalue(ra, idx); /* update index */ | ||
657 | } | ||
658 | break; | 664 | break; |
659 | } | 665 | } |
660 | case OP_TFORLOOP: { | 666 | case OP_TFORLOOP: { |
661 | int nvar = GETARG_C(i) + 1; | 667 | StkId cb = ra + 3; /* call base */ |
662 | StkId cb = ra + nvar + 2; /* call base */ | ||
663 | setobjs2s(cb, ra); | ||
664 | setobjs2s(cb+1, ra+1); | ||
665 | setobjs2s(cb+2, ra+2); | 668 | setobjs2s(cb+2, ra+2); |
669 | setobjs2s(cb+1, ra+1); | ||
670 | setobjs2s(cb, ra); | ||
666 | L->top = cb+3; /* func. + 2 args (state and index) */ | 671 | L->top = cb+3; /* func. + 2 args (state and index) */ |
667 | luaD_call(L, cb, nvar); | 672 | luaD_call(L, cb, GETARG_C(i)); |
668 | L->top = L->ci->top; | 673 | L->top = L->ci->top; |
669 | ra = XRA(i) + 2; /* final position of first result */ | 674 | cb = XRA(i) + 3; /* previous call may change the stack */ |
670 | cb = ra + nvar; | 675 | if (ttisnil(cb)) /* break loop? */ |
671 | do { /* move results to proper positions */ | ||
672 | nvar--; | ||
673 | setobjs2s(ra+nvar, cb+nvar); | ||
674 | } while (nvar > 0); | ||
675 | if (ttisnil(ra)) /* break loop? */ | ||
676 | pc++; /* skip jump (break loop) */ | 676 | pc++; /* skip jump (break loop) */ |
677 | else | 677 | else { |
678 | setobjs2s(cb-1, cb); /* save control variable */ | ||
678 | dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ | 679 | dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ |
680 | } | ||
679 | break; | 681 | break; |
680 | } | 682 | } |
681 | case OP_TFORPREP: { /* for compatibility only */ | 683 | case OP_TFORPREP: { /* for compatibility only */ |