lua

A copy of the Lua development repository
Log | Files | Refs | README

commit bf10593a3a912cd3cac69569c7474e687c0d0cd8
parent bef250eb8d44ba58fa04f82df7550a79b068d2d0
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Mon, 29 Mar 2021 12:57:05 -0300

Allow yields inside '__pairs'

Diffstat:
Mlbaselib.c | 7++++++-
Mtestes/nextvar.lua | 21+++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)

diff --git 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 @@ -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"