Browse Source

Allow transpile.lua to be run directly.

 • Fix `async for` loops inside asynchronous functions.
 • Allow transpile.lua to be called directly.
master
luk3yx 3 weeks ago
parent
commit
d15e43528e
5 changed files with 55 additions and 9 deletions
  1. 15
    0
      README.md
  2. 1
    0
      core.lua
  3. 2
    2
      locks.lua
  4. 0
    2
      lua51.lua
  5. 37
    5
      transpile.lua

+ 15
- 0
README.md View File

@@ -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
- 0
core.lua View File

@@ -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'

+ 2
- 2
locks.lua View File

@@ -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

+ 0
- 2
lua51.lua View File

@@ -7,10 +7,6 @@ local rawequal = rawequal
minetest.log('warning', '[asyncio] LuaJIT not installed, asyncio.iter() ' ..
'will be less efficient.')

asyncio._iter_start = asyncio.iter

-- Helper functions
local function pack_len(...)
local res = {...}

+ 37
- 5
transpile.lua View File

@@ -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

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

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

return transpile
-- Print the output
print(transpile(code))
os.exit(0)
end

-- Lua 5.2+ compatibility

Loading…
Cancel
Save