aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2025-11-11 15:11:06 -0300
committerRoberto I <roberto@inf.puc-rio.br>2025-11-11 15:11:06 -0300
commit4cf498210e6a60637a7abb06d32460ec21efdbdc (patch)
tree7b9cffee61083a6b256311917019b58a1fbdd42a
parent5b7d9987642f72d44223a8e5e79e013bb2b3d579 (diff)
downloadlua-master.tar.gz
lua-master.tar.bz2
lua-master.zip
'__pairs' can also return a to-be-closed objectHEADmaster
-rw-r--r--lbaselib.c13
-rw-r--r--manual/manual.of4
-rw-r--r--testes/nextvar.lua7
3 files changed, 15 insertions, 9 deletions
diff --git a/lbaselib.c b/lbaselib.c
index b296c4b7..891bb90f 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -279,21 +279,22 @@ static int luaB_next (lua_State *L) {
279 279
280static int pairscont (lua_State *L, int status, lua_KContext k) { 280static int pairscont (lua_State *L, int status, lua_KContext k) {
281 (void)L; (void)status; (void)k; /* unused */ 281 (void)L; (void)status; (void)k; /* unused */
282 return 3; 282 return 4; /* __pairs did all the work, just return its results */
283} 283}
284 284
285static int luaB_pairs (lua_State *L) { 285static int luaB_pairs (lua_State *L) {
286 luaL_checkany(L, 1); 286 luaL_checkany(L, 1);
287 if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */ 287 if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
288 lua_pushcfunction(L, luaB_next); /* will return generator, */ 288 lua_pushcfunction(L, luaB_next); /* will return generator and */
289 lua_pushvalue(L, 1); /* state, */ 289 lua_pushvalue(L, 1); /* state */
290 lua_pushnil(L); /* and initial value */ 290 lua_pushnil(L); /* initial value */
291 lua_pushnil(L); /* to-be-closed object */
291 } 292 }
292 else { 293 else {
293 lua_pushvalue(L, 1); /* argument 'self' to metamethod */ 294 lua_pushvalue(L, 1); /* argument 'self' to metamethod */
294 lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */ 295 lua_callk(L, 1, 4, 0, pairscont); /* get 4 values from metamethod */
295 } 296 }
296 return 3; 297 return 4;
297} 298}
298 299
299 300
diff --git a/manual/manual.of b/manual/manual.of
index eaf0ce78..9b6976ca 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -6799,11 +6799,11 @@ In particular, you may set existing fields to nil.
6799@LibEntry{pairs (t)| 6799@LibEntry{pairs (t)|
6800 6800
6801If @id{t} has a metamethod @idx{__pairs}, 6801If @id{t} has a metamethod @idx{__pairs},
6802calls it with @id{t} as argument and returns the first three 6802calls it with @id{t} as argument and returns the first four
6803results from the call. 6803results from the call.
6804 6804
6805Otherwise, 6805Otherwise,
6806returns three values: the @Lid{next} function, the table @id{t}, and @nil, 6806returns the @Lid{next} function, the table @id{t}, plus two @nil values,
6807so that the construction 6807so that the construction
6808@verbatim{ 6808@verbatim{
6809for k,v in pairs(t) do @rep{body} end 6809for k,v in pairs(t) do @rep{body} end
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index 7e5bed56..098e7891 100644
--- a/testes/nextvar.lua
+++ b/testes/nextvar.lua
@@ -905,13 +905,18 @@ local function foo1 (e,i)
905 if i <= e.n then return i,a[i] end 905 if i <= e.n then return i,a[i] end
906end 906end
907 907
908setmetatable(a, {__pairs = function (x) return foo, x, 0 end}) 908local closed = false
909setmetatable(a, {__pairs = function (x)
910 local tbc = setmetatable({}, {__close = function () closed = true end})
911 return foo, x, 0, tbc
912 end})
909 913
910local i = 0 914local i = 0
911for k,v in pairs(a) do 915for k,v in pairs(a) do
912 i = i + 1 916 i = i + 1
913 assert(k == i and v == k+1) 917 assert(k == i and v == k+1)
914end 918end
919assert(closed) -- 'tbc' has been closed
915 920
916a.n = 5 921a.n = 5
917a[3] = 30 922a[3] = 30