diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-07 14:42:05 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-07 14:42:05 -0200 |
commit | 7f6f70853c8a2730fca2e95d5968ad52cf470bda (patch) | |
tree | 948147a9cf6a5c5eb34232e7547c310eb06eadea /lvm.c | |
parent | b8fed93215a23a3f443c5b0126f0de1725771b44 (diff) | |
download | lua-7f6f70853c8a2730fca2e95d5968ad52cf470bda.tar.gz lua-7f6f70853c8a2730fca2e95d5968ad52cf470bda.tar.bz2 lua-7f6f70853c8a2730fca2e95d5968ad52cf470bda.zip |
To-be-closed variable in 'for' loop separated from the state
The variable to be closed in a generic 'for' loop now is the
4th value produced in the loop initialization, instead of being
the loop state (the 2nd value produced). That allows a loop to
use a state with a '__toclose' metamethod but do not close it.
(As an example, 'f:lines()' might use the file 'f' as a state
for the loop, but it should not close the file when the loop ends.)
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 23 |
1 files changed, 12 insertions, 11 deletions
@@ -1654,11 +1654,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1654 | vmbreak; | 1654 | vmbreak; |
1655 | } | 1655 | } |
1656 | vmcase(OP_TFORPREP) { | 1656 | vmcase(OP_TFORPREP) { |
1657 | /* is 'state' a function or has a '__close' metamethod? */ | 1657 | /* is 'toclose' a function or has a '__close' metamethod? */ |
1658 | if (ttisfunction(s2v(ra + 1)) || | 1658 | if (ttisfunction(s2v(ra + 3)) || |
1659 | !ttisnil(luaT_gettmbyobj(L, s2v(ra + 1), TM_CLOSE))) { | 1659 | !ttisnil(luaT_gettmbyobj(L, s2v(ra + 3), TM_CLOSE))) { |
1660 | /* create to-be-closed upvalue for it */ | 1660 | /* create to-be-closed upvalue for it */ |
1661 | halfProtect(luaF_newtbcupval(L, ra + 1)); | 1661 | halfProtect(luaF_newtbcupval(L, ra + 3)); |
1662 | } | 1662 | } |
1663 | pc += GETARG_Bx(i); | 1663 | pc += GETARG_Bx(i); |
1664 | i = *(pc++); /* go to next instruction */ | 1664 | i = *(pc++); /* go to next instruction */ |
@@ -1668,13 +1668,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1668 | vmcase(OP_TFORCALL) { | 1668 | vmcase(OP_TFORCALL) { |
1669 | l_tforcall: | 1669 | l_tforcall: |
1670 | /* 'ra' has the iterator function, 'ra + 1' has the state, | 1670 | /* 'ra' has the iterator function, 'ra + 1' has the state, |
1671 | and 'ra + 2' has the control variable. The call will use | 1671 | 'ra + 2' has the control variable, and 'ra + 3' has the |
1672 | the stack after these values (starting at 'ra + 3') | 1672 | to-be-closed variable. The call will use the stack after |
1673 | these values (starting at 'ra + 4') | ||
1673 | */ | 1674 | */ |
1674 | /* push function, state, and control variable */ | 1675 | /* push function, state, and control variable */ |
1675 | memcpy(ra + 3, ra, 3 * sizeof(*ra)); | 1676 | memcpy(ra + 4, ra, 3 * sizeof(*ra)); |
1676 | L->top = ra + 6; | 1677 | L->top = ra + 4 + 3; |
1677 | Protect(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */ | 1678 | Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ |
1678 | if (trap) { /* stack may have changed? */ | 1679 | if (trap) { /* stack may have changed? */ |
1679 | updatebase(ci); /* keep 'base' correct */ | 1680 | updatebase(ci); /* keep 'base' correct */ |
1680 | ra = RA(i); /* keep 'ra' correct for next instruction */ | 1681 | ra = RA(i); /* keep 'ra' correct for next instruction */ |
@@ -1686,8 +1687,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1686 | } | 1687 | } |
1687 | vmcase(OP_TFORLOOP) { | 1688 | vmcase(OP_TFORLOOP) { |
1688 | l_tforloop: | 1689 | l_tforloop: |
1689 | if (!ttisnil(s2v(ra + 1))) { /* continue loop? */ | 1690 | if (!ttisnil(s2v(ra + 2))) { /* continue loop? */ |
1690 | setobjs2s(L, ra, ra + 1); /* save control variable */ | 1691 | setobjs2s(L, ra, ra + 2); /* save control variable */ |
1691 | pc -= GETARG_Bx(i); /* jump back */ | 1692 | pc -= GETARG_Bx(i); /* jump back */ |
1692 | } | 1693 | } |
1693 | vmbreak; | 1694 | vmbreak; |