diff options
Diffstat (limited to '')
-rw-r--r-- | lparser.c | 23 | ||||
-rw-r--r-- | lvm.c | 40 | ||||
-rw-r--r-- | testes/files.lua | 4 |
3 files changed, 38 insertions, 29 deletions
@@ -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 | ||
@@ -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 |