aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-12 14:15:50 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-12 14:15:50 -0200
commit5fda30b4f9f82b901113a6e666c797f835c708eb (patch)
treea8011434f8c2ccee920d955db05ba4917a00e5f8
parent9eafe9c053ef17a0980ab32082bf229bd58e963b (diff)
downloadlua-5fda30b4f9f82b901113a6e666c797f835c708eb.tar.gz
lua-5fda30b4f9f82b901113a6e666c797f835c708eb.tar.bz2
lua-5fda30b4f9f82b901113a6e666c797f835c708eb.zip
'lua_toclose' gets the index to be closed as an argument
Sometimes it is useful to mark to-be-closed an index that is not at the top of the stack (e.g., if the value to be closed came from a function call returning multiple values).
-rw-r--r--lapi.c13
-rw-r--r--ltests.c2
-rw-r--r--lua.h2
-rw-r--r--testes/api.lua18
4 files changed, 22 insertions, 13 deletions
diff --git a/lapi.c b/lapi.c
index 91a6e389..da866a66 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1207,12 +1207,19 @@ LUA_API int lua_next (lua_State *L, int idx) {
1207} 1207}
1208 1208
1209 1209
1210LUA_API void lua_toclose (lua_State *L) { 1210LUA_API void lua_toclose (lua_State *L, int idx) {
1211 int nresults = L->ci->nresults; 1211 int nresults;
1212 luaF_newtbcupval(L, L->top - 1); /* create new to-be-closed upvalue */ 1212 StkId o;
1213 lua_lock(L);
1214 o = index2stack(L, idx);
1215 nresults = L->ci->nresults;
1216 api_check(L, L->openupval == NULL || uplevel(L->openupval) < o,
1217 "there is an already marked index below");
1218 luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */
1213 if (!hastocloseCfunc(nresults)) /* function not marked yet? */ 1219 if (!hastocloseCfunc(nresults)) /* function not marked yet? */
1214 L->ci->nresults = codeNresults(nresults); /* mark it */ 1220 L->ci->nresults = codeNresults(nresults); /* mark it */
1215 lua_assert(hastocloseCfunc(L->ci->nresults)); 1221 lua_assert(hastocloseCfunc(L->ci->nresults));
1222 lua_unlock(L);
1216} 1223}
1217 1224
1218 1225
diff --git a/ltests.c b/ltests.c
index 192ae861..c5c1040a 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1551,7 +1551,7 @@ static struct X { int x; } x;
1551 return lua_yieldk(L1, nres, i, Cfunck); 1551 return lua_yieldk(L1, nres, i, Cfunck);
1552 } 1552 }
1553 else if EQ("toclose") { 1553 else if EQ("toclose") {
1554 lua_toclose(L); 1554 lua_toclose(L, getnum);
1555 } 1555 }
1556 else luaL_error(L, "unknown instruction %s", buff); 1556 else luaL_error(L, "unknown instruction %s", buff);
1557 } 1557 }
diff --git a/lua.h b/lua.h
index fe468c8e..6aa184d1 100644
--- a/lua.h
+++ b/lua.h
@@ -333,7 +333,7 @@ LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s);
333LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); 333LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
334LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); 334LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
335 335
336LUA_API void (lua_toclose) (lua_State *L); 336LUA_API void (lua_toclose) (lua_State *L, int idx);
337 337
338 338
339/* 339/*
diff --git a/testes/api.lua b/testes/api.lua
index a6ddca8e..ed857fd0 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -985,18 +985,20 @@ do
985 return x 985 return x
986 end 986 end
987 987
988 local a = T.testC([[ 988 local a, b = T.testC([[
989 call 0 1 # create resource 989 call 0 1 # create resource
990 toclose # mark it to be closed 990 pushint 34
991 return 1 991 toclose -2 # mark call result to be closed
992 toclose -1 # mark number to be closed (will be ignored)
993 return 2
992 ]], newresource) 994 ]], newresource)
993 assert(a[1] == 11) 995 assert(a[1] == 11 and b == 34)
994 assert(#openresource == 0) -- was closed 996 assert(#openresource == 0) -- was closed
995 997
996 -- repeat the test, but calling function in a 'multret' context 998 -- repeat the test, but calling function in a 'multret' context
997 local a = {T.testC([[ 999 local a = {T.testC([[
998 call 0 1 # create resource 1000 call 0 1 # create resource
999 toclose # mark it to be closed 1001 toclose 2 # mark it to be closed
1000 return 2 1002 return 2
1001 ]], newresource)} 1003 ]], newresource)}
1002 assert(type(a[1]) == "string" and a[2][1] == 11) 1004 assert(type(a[1]) == "string" and a[2][1] == 11)
@@ -1005,7 +1007,7 @@ do
1005 -- error 1007 -- error
1006 local a, b = pcall(T.testC, [[ 1008 local a, b = pcall(T.testC, [[
1007 call 0 1 # create resource 1009 call 0 1 # create resource
1008 toclose # mark it to be closed 1010 toclose -1 # mark it to be closed
1009 error # resource is the error object 1011 error # resource is the error object
1010 ]], newresource) 1012 ]], newresource)
1011 assert(a == false and b[1] == 11) 1013 assert(a == false and b[1] == 11)
@@ -1019,10 +1021,10 @@ do
1019 local a = T.testC([[ 1021 local a = T.testC([[
1020 pushvalue 2 1022 pushvalue 2
1021 call 0 1 # create resource 1023 call 0 1 # create resource
1022 toclose # mark it to be closed 1024 toclose -1 # mark it to be closed
1023 pushvalue 2 1025 pushvalue 2
1024 call 0 1 # create another resource 1026 call 0 1 # create another resource
1025 toclose # mark it to be closed 1027 toclose -1 # mark it to be closed
1026 pushvalue 3 1028 pushvalue 3
1027 pushint 2 # there should be two open resources 1029 pushint 2 # there should be two open resources
1028 call 1 0 1030 call 1 0