This repository has been archived on 2019-08-24. You can view files and clone it, but cannot push or open issues or pull requests.
asyncio/lua51.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