66 lines
1.6 KiB
Lua
66 lines
1.6 KiB
Lua
|
--
|
||
|
-- Minetest asyncio: Lua 5.1 workarounds
|
||
|
--
|
||
|
|
||
|
|
||
|
local rawequal = rawequal
|
||
|
minetest.log('warning', '[asyncio] LuaJIT not installed, asyncio.iter() ' ..
|
||
|
'will be less efficient.')
|
||
|
|
||
|
-- Helper functions
|
||
|
local function pack_len(...)
|
||
|
local res = {...}
|
||
|
res.length = select('#', ...)
|
||
|
return res
|
||
|
end
|
||
|
|
||
|
local function unpack_len(t, i)
|
||
|
i = i or 1
|
||
|
if i <= t.length then
|
||
|
return t[i], unpack_len(t, i + 1)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- A workaround for non-LuaJIT Lua 5.1
|
||
|
-- Lua 5.1 does not allow coroutine.yield() inside iterators.
|
||
|
function asyncio.iter(func, ...)
|
||
|
local iter = asyncio._iter_start(func, ...)
|
||
|
|
||
|
-- Fetch all values first
|
||
|
local t = {}
|
||
|
while true do
|
||
|
local msg = pack_len(iter())
|
||
|
if msg[1] == nil then break end
|
||
|
table.insert(t, msg)
|
||
|
end
|
||
|
iter = nil
|
||
|
|
||
|
-- Get the values
|
||
|
return function()
|
||
|
local msg = table.remove(t, 1)
|
||
|
if type(msg) == 'table' then
|
||
|
return unpack_len(msg)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- A pcall() workaround/hack.
|
||
|
local last_error = ...
|
||
|
assert(type(last_error) == 'table')
|
||
|
local function pcall_hack(func, ...)
|
||
|
asyncio.yield(last_error, pack_len(func(...)))
|
||
|
end
|
||
|
|
||
|
function last_error.cleanup() last_error.msg = nil end
|
||
|
local old_pcall = pcall
|
||
|
function pcall(func, ...)
|
||
|
if not asyncio.running then return old_pcall(func, ...) end
|
||
|
local l, msg = asyncio._iter_start(pcall_hack, func, ...)()
|
||
|
if l == last_error then
|
||
|
return true, unpack_len(msg)
|
||
|
elseif l ~= nil then
|
||
|
return false, 'asyncio.yield() called outside of async iterator.'
|
||
|
end
|
||
|
return false, last_error.msg
|
||
|
end
|