Allow transpile.lua to be run directly.
• Fix `async for` loops inside asynchronous functions. • Allow transpile.lua to be called directly.
This commit is contained in:
parent
d2ac8715cf
commit
d15e43528e
15
README.md
15
README.md
|
@ -173,6 +173,21 @@ The following functions only work inside coroutines:
|
|||
The custom lua syntax introduced by this mod is "transpiled" back into regular
|
||||
lua, and can only be used with `asyncio.dofile` etc.
|
||||
|
||||
### Pre-runtime transpiling
|
||||
|
||||
**If you are going to be using Minetest's insecure environment from a file
|
||||
using this custom syntax, I strongly recommend avoiding `asyncio.loadfile`
|
||||
etc.**
|
||||
|
||||
To invoke the transpiler outside of Minetest, you can simply run
|
||||
`lua transpile.lua /path/to/file.async.lua`. This should print the transpiled
|
||||
code. If you want it to write the transpiled code to a different file, provided
|
||||
you are on a UNIX-like OS, you can run
|
||||
`lua transpile.lua file.async.lua > file.lua`.
|
||||
|
||||
*Note that `async for` loops will always be mangled ensure compatibility with
|
||||
Lua 5.1.*
|
||||
|
||||
## Coroutines
|
||||
|
||||
asyncio coroutines can be created in one of two ways:
|
||||
|
|
1
core.lua
1
core.lua
|
@ -200,6 +200,7 @@ local function iter(func, ...)
|
|||
end
|
||||
end
|
||||
asyncio.iter = iter
|
||||
asyncio._iter_start = iter
|
||||
|
||||
-- Lua 5.1 (excluding LuaJIT) compatibility
|
||||
asyncio.lua51 = _VERSION < 'Lua 5.2'
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
local lock_states = {}
|
||||
local lock_callbacks = {}
|
||||
|
||||
setmetatable(lock_states, {__mode = 'kv'})
|
||||
setmetatable(lock_callbacks, {__mode = 'k'})
|
||||
setmetatable(lock_states, {__mode = 'kv'})
|
||||
setmetatable(lock_callbacks, {__mode = 'k'})
|
||||
|
||||
-- Create the functions
|
||||
-- https://docs.python.org/3/library/asyncio-sync.html#lock
|
||||
|
|
|
@ -7,10 +7,6 @@ local rawequal = rawequal
|
|||
minetest.log('warning', '[asyncio] LuaJIT not installed, asyncio.iter() ' ..
|
||||
'will be less efficient.')
|
||||
|
||||
-- Keep the original asyncio.iter accessible, this is used in the workaround
|
||||
-- iter function and in the transpiler.
|
||||
asyncio._iter_start = asyncio.iter
|
||||
|
||||
-- Helper functions
|
||||
local function pack_len(...)
|
||||
local res = {...}
|
||||
|
|
|
@ -18,6 +18,7 @@ end
|
|||
|
||||
-- Matches
|
||||
-- These take 2-3 arguments (code, res, char) and should return code and res.
|
||||
local lua51 = not asyncio or asyncio.lua51
|
||||
local matches
|
||||
matches = {
|
||||
-- Handle multi-line strings and comments
|
||||
|
@ -121,6 +122,12 @@ matches = {
|
|||
local func = matches[char] or matches[pattern]
|
||||
assert(func, 'No function found for pattern!')
|
||||
code, res = func(code:sub(e + 1), res, char)
|
||||
|
||||
-- Increase the level for async for loops
|
||||
if lua51 and (pattern == '^async for ' or
|
||||
pattern == '[%s;%[]async for ') then
|
||||
lvl = lvl + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -147,7 +154,7 @@ matches = {
|
|||
}
|
||||
|
||||
-- A workaround for Lua 5.1's iterator limitations.
|
||||
if not asyncio or asyncio.lua51 then
|
||||
if lua51 then
|
||||
local orig = matches['async for ']
|
||||
matches['async for '] = function(code, res, char)
|
||||
if char:sub(1, 1) ~= 'a' then res = res .. char:sub(1, 1) end
|
||||
|
@ -209,12 +216,36 @@ local function transpile(code)
|
|||
return res .. code
|
||||
end
|
||||
|
||||
-- Testing
|
||||
if not asyncio then
|
||||
local f = io.open('test.lua')
|
||||
print(transpile(f:read '*a'))
|
||||
-- Handle being called outside of Minetest.
|
||||
if not asyncio or not minetest then
|
||||
-- If this is called via dofile(), just return the function.
|
||||
if not arg or debug.getinfo(3) then
|
||||
return transpile
|
||||
end
|
||||
|
||||
return transpile
|
||||
if not arg[1] or arg[1] == '' then
|
||||
print('Invalid usage.')
|
||||
print('Usage: transpile.lua <file>')
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
-- Read the file
|
||||
local f, err, errcode = io.open(arg[1], 'r')
|
||||
if not f then
|
||||
print(err)
|
||||
os.exit(errcode)
|
||||
end
|
||||
|
||||
local code, err, errcode = f:read('*a')
|
||||
f:close()
|
||||
if not code then
|
||||
print(err)
|
||||
os.exit(errcode)
|
||||
end
|
||||
|
||||
-- Print the output
|
||||
print(transpile(code))
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
-- Lua 5.2+ compatibility
|
||||
|
|
Reference in New Issue