aboutsummaryrefslogtreecommitdiff
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-bf10593a3a912cd3cac69569c7474e687c0d0cd8.tar.gz
lua-bf10593a3a912cd3cac69569c7474e687c0d0cd8.tar.bz2
lua-bf10593a3a912cd3cac69569c7474e687c0d0cd8.zip
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) {
261} 261}
262 262
263 263
264static int pairscont (lua_State *L, int status, lua_KContext k) {
265 (void)L; (void)status; (void)k; /* unused */
266 return 3;
267}
268
264static int luaB_pairs (lua_State *L) { 269static int luaB_pairs (lua_State *L) {
265 luaL_checkany(L, 1); 270 luaL_checkany(L, 1);
266 if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */ 271 if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
@@ -270,7 +275,7 @@ static int luaB_pairs (lua_State *L) {
270 } 275 }
271 else { 276 else {
272 lua_pushvalue(L, 1); /* argument 'self' to metamethod */ 277 lua_pushvalue(L, 1); /* argument 'self' to metamethod */
273 lua_call(L, 1, 3); /* get 3 values from metamethod */ 278 lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */
274 } 279 }
275 return 3; 280 return 3;
276} 281}
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
764end 764end
765assert(i == a.n) 765assert(i == a.n)
766 766
767
768-- testing yield inside __pairs
769do
770 local t = setmetatable({10, 20, 30}, {__pairs = function (t)
771 local inc = coroutine.yield()
772 return function (t, i)
773 if i > 1 then return i - inc, t[i - inc] else return nil end
774 end, t, #t + 1
775 end})
776
777 local res = {}
778 local co = coroutine.wrap(function ()
779 for i,p in pairs(t) do res[#res + 1] = p end
780 end)
781
782 co() -- start coroutine
783 co(1) -- continue after yield
784 assert(res[1] == 30 and res[2] == 20 and res[3] == 10 and #res == 3)
785
786end
787
767print"OK" 788print"OK"