diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-03-29 12:57:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-03-29 12:57:32 -0300 |
commit | bf10593a3a912cd3cac69569c7474e687c0d0cd8 (patch) | |
tree | 6352db2e73df607a135353d934bd966974f95651 | |
parent | bef250eb8d44ba58fa04f82df7550a79b068d2d0 (diff) | |
download | lua-bf10593a3a912cd3cac69569c7474e687c0d0cd8.tar.gz lua-bf10593a3a912cd3cac69569c7474e687c0d0cd8.tar.bz2 lua-bf10593a3a912cd3cac69569c7474e687c0d0cd8.zip |
Allow yields inside '__pairs'
-rw-r--r-- | lbaselib.c | 7 | ||||
-rw-r--r-- | testes/nextvar.lua | 21 |
2 files changed, 27 insertions, 1 deletions
@@ -261,6 +261,11 @@ static int luaB_next (lua_State *L) { | |||
261 | } | 261 | } |
262 | 262 | ||
263 | 263 | ||
264 | static int pairscont (lua_State *L, int status, lua_KContext k) { | ||
265 | (void)L; (void)status; (void)k; /* unused */ | ||
266 | return 3; | ||
267 | } | ||
268 | |||
264 | static int luaB_pairs (lua_State *L) { | 269 | static 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 | |||
764 | end | 764 | end |
765 | assert(i == a.n) | 765 | assert(i == a.n) |
766 | 766 | ||
767 | |||
768 | -- testing yield inside __pairs | ||
769 | do | ||
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 | |||
786 | end | ||
787 | |||
767 | print"OK" | 788 | print"OK" |