summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-03-29 12:57:32 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-03-29 12:57:32 -0300
commitbf10593a3a912cd3cac69569c7474e687c0d0cd8 (patch)
tree6352db2e73df607a135353d934bd966974f95651
parentbef250eb8d44ba58fa04f82df7550a79b068d2d0 (diff)
downloadlua-github-bf10593a3a912cd3cac69569c7474e687c0d0cd8.tar.gz
Allow yields inside '__pairs'
-rw-r--r--lbaselib.c7
-rw-r--r--testes/nextvar.lua21
2 files changed, 27 insertions, 1 deletions
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"