You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua51.lua 1.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. --
  2. -- Minetest asyncio: Lua 5.1 workarounds
  3. --
  4. local rawequal = rawequal
  5. minetest.log('warning', '[asyncio] LuaJIT not installed, asyncio.iter() ' ..
  6. 'will be less efficient.')
  7. -- Keep the original asyncio.iter accessible, this is used in the workaround
  8. -- iter function and in the transpiler.
  9. asyncio._iter_start = asyncio.iter
  10. -- Helper functions
  11. local function pack_len(...)
  12. local res = {...}
  13. res.length = select('#', ...)
  14. return res
  15. end
  16. local function unpack_len(t, i)
  17. i = i or 1
  18. if i <= t.length then
  19. return t[i], unpack_len(t, i + 1)
  20. end
  21. end
  22. -- A workaround for non-LuaJIT Lua 5.1
  23. -- Lua 5.1 does not allow coroutine.yield() inside iterators.
  24. function asyncio.iter(func, ...)
  25. local iter = asyncio._iter_start(func, ...)
  26. -- Fetch all values first
  27. local t = {}
  28. while true do
  29. local msg = pack_len(iter())
  30. if msg[1] == nil then break end
  31. table.insert(t, msg)
  32. end
  33. iter = nil
  34. -- Get the values
  35. return function()
  36. local msg = table.remove(t, 1)
  37. if type(msg) == 'table' then
  38. return unpack_len(msg)
  39. end
  40. end
  41. end
  42. -- A pcall() workaround/hack.
  43. local last_error = ...
  44. assert(type(last_error) == 'table')
  45. local function pcall_hack(func, ...)
  46. asyncio.yield(last_error, pack_len(func(...)))
  47. end
  48. function last_error.cleanup() last_error.msg = nil end
  49. local old_pcall = pcall
  50. function pcall(func, ...)
  51. if not asyncio.running then return old_pcall(func, ...) end
  52. local l, msg = asyncio._iter_start(pcall_hack, func, ...)()
  53. if l == last_error then
  54. return true, unpack_len(msg)
  55. elseif l ~= nil then
  56. return false, 'asyncio.yield() called outside of async iterator.'
  57. end
  58. return false, last_error.msg
  59. end