From bf10593a3a912cd3cac69569c7474e687c0d0cd8 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 29 Mar 2021 12:57:32 -0300 Subject: Allow yields inside '__pairs' --- lbaselib.c | 7 ++++++- testes/nextvar.lua | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lbaselib.c b/lbaselib.c index 83ad306d..fd6687e6 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -261,6 +261,11 @@ static int luaB_next (lua_State *L) { } +static int pairscont (lua_State *L, int status, lua_KContext k) { + (void)L; (void)status; (void)k; /* unused */ + return 3; +} + static int luaB_pairs (lua_State *L) { luaL_checkany(L, 1); if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */ @@ -270,7 +275,7 @@ static int luaB_pairs (lua_State *L) { } else { lua_pushvalue(L, 1); /* argument 'self' to metamethod */ - lua_call(L, 1, 3); /* get 3 values from metamethod */ + lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */ } return 3; } diff --git a/testes/nextvar.lua b/testes/nextvar.lua index 29cb05d5..076f6361 100644 --- a/testes/nextvar.lua +++ b/testes/nextvar.lua @@ -764,4 +764,25 @@ for k,v in ipairs(a) do end assert(i == a.n) + +-- testing yield inside __pairs +do + local t = setmetatable({10, 20, 30}, {__pairs = function (t) + local inc = coroutine.yield() + return function (t, i) + if i > 1 then return i - inc, t[i - inc] else return nil end + end, t, #t + 1 + end}) + + local res = {} + local co = coroutine.wrap(function () + for i,p in pairs(t) do res[#res + 1] = p end + end) + + co() -- start coroutine + co(1) -- continue after yield + assert(res[1] == 30 and res[2] == 20 and res[3] == 10 and #res == 3) + +end + print"OK" -- cgit v1.2.1