aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-07 14:42:05 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-07 14:42:05 -0200
commit7f6f70853c8a2730fca2e95d5968ad52cf470bda (patch)
tree948147a9cf6a5c5eb34232e7547c310eb06eadea /lvm.c
parentb8fed93215a23a3f443c5b0126f0de1725771b44 (diff)
downloadlua-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.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/lvm.c b/lvm.c
index 9977bda4..7d5ab9db 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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;