aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lparser.c23
-rw-r--r--lvm.c40
-rw-r--r--testes/files.lua4
3 files changed, 38 insertions, 29 deletions
diff --git a/lparser.c b/lparser.c
index ff6f4009..c0eb7890 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1558,6 +1558,7 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
1558 int prep, endfor; 1558 int prep, endfor;
1559 checknext(ls, TK_DO); 1559 checknext(ls, TK_DO);
1560 prep = luaK_codeABx(fs, forprep[isgen], base, 0); 1560 prep = luaK_codeABx(fs, forprep[isgen], base, 0);
1561 fs->freereg--; /* both 'forprep' remove one register from the stack */
1561 enterblock(fs, &bl, 0); /* scope for declared variables */ 1562 enterblock(fs, &bl, 0); /* scope for declared variables */
1562 adjustlocalvars(ls, nvars); 1563 adjustlocalvars(ls, nvars);
1563 luaK_reserveregs(fs, nvars); 1564 luaK_reserveregs(fs, nvars);
@@ -1591,8 +1592,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1591 luaK_int(fs, fs->freereg, 1); 1592 luaK_int(fs, fs->freereg, 1);
1592 luaK_reserveregs(fs, 1); 1593 luaK_reserveregs(fs, 1);
1593 } 1594 }
1594 adjustlocalvars(ls, 2); /* start scope for internal state variables */ 1595 adjustlocalvars(ls, 2); /* start scope for internal variables */
1595 fs->freereg--; /* OP_FORPREP removes one register from the stack */
1596 forbody(ls, base, line, 1, 0); 1596 forbody(ls, base, line, 1, 0);
1597} 1597}
1598 1598
@@ -1601,14 +1601,13 @@ static void forlist (LexState *ls, TString *indexname) {
1601 /* forlist -> NAME {,NAME} IN explist forbody */ 1601 /* forlist -> NAME {,NAME} IN explist forbody */
1602 FuncState *fs = ls->fs; 1602 FuncState *fs = ls->fs;
1603 expdesc e; 1603 expdesc e;
1604 int nvars = 5; /* gen, state, control, toclose, 'indexname' */ 1604 int nvars = 4; /* function, state, closing, control */
1605 int line; 1605 int line;
1606 int base = fs->freereg; 1606 int base = fs->freereg;
1607 /* create control variables */ 1607 /* create internal variables */
1608 new_localvarliteral(ls, "(for state)"); 1608 new_localvarliteral(ls, "(for state)"); /* iterator function */
1609 new_localvarliteral(ls, "(for state)"); 1609 new_localvarliteral(ls, "(for state)"); /* state */
1610 new_localvarliteral(ls, "(for state)"); 1610 new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */
1611 new_localvarliteral(ls, "(for state)");
1612 new_localvarkind(ls, indexname, RDKCONST); /* control variable */ 1611 new_localvarkind(ls, indexname, RDKCONST); /* control variable */
1613 /* other declared variables */ 1612 /* other declared variables */
1614 while (testnext(ls, ',')) { 1613 while (testnext(ls, ',')) {
@@ -1618,10 +1617,10 @@ static void forlist (LexState *ls, TString *indexname) {
1618 checknext(ls, TK_IN); 1617 checknext(ls, TK_IN);
1619 line = ls->linenumber; 1618 line = ls->linenumber;
1620 adjust_assign(ls, 4, explist(ls, &e), &e); 1619 adjust_assign(ls, 4, explist(ls, &e), &e);
1621 adjustlocalvars(ls, 4); /* control variables */ 1620 adjustlocalvars(ls, 3); /* start scope for internal variables */
1622 marktobeclosed(fs); /* last control var. must be closed */ 1621 marktobeclosed(fs); /* last internal var. must be closed */
1623 luaK_checkstack(fs, 3); /* extra space to call generator */ 1622 luaK_checkstack(fs, 2); /* extra space to call iterator */
1624 forbody(ls, base, line, nvars - 4, 1); 1623 forbody(ls, base, line, nvars - 3, 1);
1625} 1624}
1626 1625
1627 1626
diff --git a/lvm.c b/lvm.c
index bdfef434..8ab8753d 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1806,26 +1806,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1806 vmbreak; 1806 vmbreak;
1807 } 1807 }
1808 vmcase(OP_TFORPREP) { 1808 vmcase(OP_TFORPREP) {
1809 /* before: 'ra' has the iterator function, 'ra + 1' has the state,
1810 'ra + 2' has the initial value for the control variable, and
1811 'ra + 3' has the closing variable. This opcode then swaps the
1812 control and the closing variables and marks the closing variable
1813 as to-be-closed.
1814 */
1809 StkId ra = RA(i); 1815 StkId ra = RA(i);
1810 /* create to-be-closed upvalue (if needed) */ 1816 TValue temp; /* to swap control and closing variables */
1811 halfProtect(luaF_newtbcupval(L, ra + 3)); 1817 setobj(L, &temp, s2v(ra + 3));
1812 pc += GETARG_Bx(i); 1818 setobjs2s(L, ra + 3, ra + 2);
1813 i = *(pc++); /* go to next instruction */ 1819 setobj2s(L, ra + 2, &temp);
1820 /* create to-be-closed upvalue (if closing var. is not nil) */
1821 halfProtect(luaF_newtbcupval(L, ra + 2));
1822 pc += GETARG_Bx(i); /* go to end of the loop */
1823 i = *(pc++); /* fetch next instruction */
1814 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); 1824 lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i));
1815 goto l_tforcall; 1825 goto l_tforcall;
1816 } 1826 }
1817 vmcase(OP_TFORCALL) { 1827 vmcase(OP_TFORCALL) {
1818 l_tforcall: { 1828 l_tforcall: {
1819 StkId ra = RA(i);
1820 /* 'ra' has the iterator function, 'ra + 1' has the state, 1829 /* 'ra' has the iterator function, 'ra + 1' has the state,
1821 'ra + 2' has the control variable, and 'ra + 3' has the 1830 'ra + 2' has the closing variable, and 'ra + 3' has the control
1822 to-be-closed variable. The call will use the stack after 1831 variable. The call will use the stack starting at 'ra + 3',
1823 these values (starting at 'ra + 4') 1832 so that it preserves the first three values, and the first
1833 return will be the new value for the control variable.
1824 */ 1834 */
1825 /* push function, state, and control variable */ 1835 StkId ra = RA(i);
1826 memcpy(ra + 4, ra, 3 * sizeof(*ra)); 1836 setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */
1827 L->top.p = ra + 4 + 3; 1837 setobjs2s(L, ra + 4, ra + 1); /* copy state */
1828 ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ 1838 setobjs2s(L, ra + 3, ra); /* copy function */
1839 L->top.p = ra + 3 + 3;
1840 ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */
1829 updatestack(ci); /* stack may have changed */ 1841 updatestack(ci); /* stack may have changed */
1830 i = *(pc++); /* go to next instruction */ 1842 i = *(pc++); /* go to next instruction */
1831 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); 1843 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
@@ -1834,10 +1846,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1834 vmcase(OP_TFORLOOP) { 1846 vmcase(OP_TFORLOOP) {
1835 l_tforloop: { 1847 l_tforloop: {
1836 StkId ra = RA(i); 1848 StkId ra = RA(i);
1837 if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ 1849 if (!ttisnil(s2v(ra + 3))) /* continue loop? */
1838 setobjs2s(L, ra + 2, ra + 4); /* save control variable */
1839 pc -= GETARG_Bx(i); /* jump back */ 1850 pc -= GETARG_Bx(i); /* jump back */
1840 }
1841 vmbreak; 1851 vmbreak;
1842 }} 1852 }}
1843 vmcase(OP_SETLIST) { 1853 vmcase(OP_SETLIST) {
diff --git a/testes/files.lua b/testes/files.lua
index 78f962e5..599644f3 100644
--- a/testes/files.lua
+++ b/testes/files.lua
@@ -427,12 +427,12 @@ do -- testing closing file in line iteration
427 -- get the to-be-closed variable from a loop 427 -- get the to-be-closed variable from a loop
428 local function gettoclose (lv) 428 local function gettoclose (lv)
429 lv = lv + 1 429 lv = lv + 1
430 local stvar = 0 -- to-be-closed is 4th state variable in the loop 430 local stvar = 0 -- to-be-closed is 3th state variable in the loop
431 for i = 1, 1000 do 431 for i = 1, 1000 do
432 local n, v = debug.getlocal(lv, i) 432 local n, v = debug.getlocal(lv, i)
433 if n == "(for state)" then 433 if n == "(for state)" then
434 stvar = stvar + 1 434 stvar = stvar + 1
435 if stvar == 4 then return v end 435 if stvar == 3 then return v end
436 end 436 end
437 end 437 end
438 end 438 end