Lua implemented in vanilla Lua without any libraries.
Compiles Lua src to a bytecode run by an emulator implemented in Lua. Used in sandboxed environment where loadstring, metatables, and coroutines are not allowed. ~10-30x slower than "native" Lua. Goto and label not implemented but metatables and coroutines works.
Divided up in a parser and a compiler. The parser outputs a parse tree and the compiler creates a nested Lua function of the parse tree. The parser can be parsed by the parser and the parse-tree then compiled by the compiler thus reducing the code foot print.
dofile("luaParser.lua")
dofile("luaCompiler.lua")
dofile("lib/json.lua")
Toolbox_Module.LuaParser.init(nil,{})
Toolbox_Module.LuaCompiler.init(nil,{})
local function main()
code([[
print("Coroutine test")
local function foo() for i=1,5 do print("Foo:"..i) coroutine.yield() end end
local function bar() for j=6,10 do print("Bar"..j) coroutine.yield() end end
local co_foo = coroutine.create(foo)
local co_bar = coroutine.create(bar)
for k=1,6 do
coroutine.resume(co_foo)
coroutine.resume(co_bar)
end
-------------------------------------------
print("metatable test")
function setDefault (t, d)
local mt = {__index = function () return d end}
setmetatable(t, mt)
end
tab = {x=10, y=20}
print(tab.x, tab.z) --> 10 nil
setDefault(tab, 0)
print(tab.x, tab.z) --> 10 0
-------------------------------------------
-- print("HTTP test") -- turning async calls into synchronous...
-- local function myMain(co)
-- local function httpRequest(url)
-- net.HTTPClient():request(url,{
-- options={},
-- success =function(res)
-- local r = json.decode(res.data)
-- coroutine.resume(co,"success",r.datetime)
-- end,
-- error = function(res) coroutine.resume(co,"error",res) end,
-- })
-- return coroutine.yield()
-- end
-- -- Now we can call httpRequest as a synchronous function that returns the value immediatly - no more callbacks
-- -- Disclaimer, this is not the best/most efficient way to do it but it demonstrates the principle....
-- local code,res = httpRequest("http://worldtimeapi.org/api/ip") -- Note this server sometimes refuses with 'success'
-- print(code,res)
-- local code,res = httpRequest("http://worldtimeapi.org/api/ip")
-- print(code,res)
-- end
-- local co = coroutine.create(myMain)
-- coroutine.resume(co,co)
------------------------------------------------
print("Illegal boundary test")
function foo() fopp() print("Never here") end
function bar() print("..on the other side, 'yield' will barf") coroutine.yield() end
local c = coroutine.create(foo)
coroutine.resume(c)
coroutine.resume(c)
]])
end
function fopp() print("Crossing..") bar() end -- Non-LuaLua function to test with
local debug = {}
function run() debug={struct=false,codel=false,trace=false} main() end
function debugC() debug={struct=false,codel=false,trace=true} main() end
function debugCStar() debug={struct=false,codel=true,trace=true} main() end
comp = Toolbox_Module.LuaCompiler.inited
function code(str)
return comp.load(str,nil,nil,comp.stdFuns,debug)()
end
run()
A simple function with all tracing bells turned on
debug={struct=true,codel=true,trace=true}
code([[function fact(x) if x == 0 then return 1 else return x*fact(x-1) end end; print(fact(3))]])
gives the following output
DEBUG: ["block",[["nop",["function","glob","fun",["glob","fact"],["x"],false,["block",[["if",["==",["var","x"],0],["block",[["return1",[1]]]],[],["block",[["return1",[["*",["var","x"],["call",["glob","fact"],[["-",["var","x"],1]]]]]]]]]]]]],["nop",["call",["glob","print"],[["call",["glob","fact"],[3]]]]]]]
DEBUG: PC: 1 ["function",["x"],false,"glob","fun",["glob","fact"],[["var","x"],["push",0],["eq"],["ifnskip3",5],["push",1],["return",1],["pop"],["goto",10],["var","x"],["var","x"],["push",1],["sub"],["glob","fact"],["call",1,["glob","fact"]],["mul"],["return",1],["pop"],["return",0]]]
DEBUG: PC: 2 ["pop"]
DEBUG: PC: 3 ["push",3]
DEBUG: PC: 4 ["glob","fact"]
DEBUG: PC: 5 ["call",1,["glob","fact"]]
DEBUG: PC: 6 ["glob","print"]
DEBUG: PC: 7 ["call",1,["glob","print"]]
DEBUG: PC: 8 ["pop"]
DEBUG: PC: 9 ["return",0]
TRACE: main PC:001 ST:000 ["function",["x"],false,"glob","fun",["glob","fact"],[["var","x"],["push",0],["e null
TRACE: main PC:002 ST:001 ["pop"] <non-json>
TRACE: main PC:003 ST:000 ["push",3] null
TRACE: main PC:004 ST:001 ["glob","fact"] 3
TRACE: main PC:005 ST:002 ["call",1,["glob","fact"]] <non-json>
TRACE: main PC:001 ST:000 ["var","x"] null
TRACE: main PC:002 ST:001 ["push",0] 3
TRACE: main PC:003 ST:002 ["eq"] 0
TRACE: main PC:004 ST:001 ["ifnskip3",5] false
TRACE: main PC:009 ST:000 ["var","x"] null
TRACE: main PC:010 ST:001 ["var","x"] 3
TRACE: main PC:011 ST:002 ["push",1] 3
TRACE: main PC:012 ST:003 ["sub"] 1
TRACE: main PC:013 ST:002 ["glob","fact"] 2
TRACE: main PC:014 ST:003 ["call",1,["glob","fact"]] <non-json>
TRACE: main PC:001 ST:000 ["var","x"] null
TRACE: main PC:002 ST:001 ["push",0] 2
TRACE: main PC:003 ST:002 ["eq"] 0
TRACE: main PC:004 ST:001 ["ifnskip3",5] false
TRACE: main PC:009 ST:000 ["var","x"] null
TRACE: main PC:010 ST:001 ["var","x"] 2
TRACE: main PC:011 ST:002 ["push",1] 2
TRACE: main PC:012 ST:003 ["sub"] 1
TRACE: main PC:013 ST:002 ["glob","fact"] 1
TRACE: main PC:014 ST:003 ["call",1,["glob","fact"]] <non-json>
TRACE: main PC:001 ST:000 ["var","x"] null
TRACE: main PC:002 ST:001 ["push",0] 1
TRACE: main PC:003 ST:002 ["eq"] 0
TRACE: main PC:004 ST:001 ["ifnskip3",5] false
TRACE: main PC:009 ST:000 ["var","x"] null
TRACE: main PC:010 ST:001 ["var","x"] 1
TRACE: main PC:011 ST:002 ["push",1] 1
TRACE: main PC:012 ST:003 ["sub"] 1
TRACE: main PC:013 ST:002 ["glob","fact"] 0
TRACE: main PC:014 ST:003 ["call",1,["glob","fact"]] <non-json>
TRACE: main PC:001 ST:000 ["var","x"] null
TRACE: main PC:002 ST:001 ["push",0] 0
TRACE: main PC:003 ST:002 ["eq"] 0
TRACE: main PC:004 ST:001 ["ifnskip3",5] true
TRACE: main PC:005 ST:000 ["push",1] null
TRACE: main PC:006 ST:001 ["return",1] 1
TRACE: main PC:015 ST:002 ["mul"] 1
TRACE: main PC:016 ST:001 ["return",1] 1
TRACE: main PC:015 ST:002 ["mul"] 1
TRACE: main PC:016 ST:001 ["return",1] 2
TRACE: main PC:015 ST:002 ["mul"] 2
TRACE: main PC:016 ST:001 ["return",1] 6
TRACE: main PC:006 ST:001 ["glob","print"] 6
TRACE: main PC:007 ST:002 ["call",1,["glob","print"]] <non-json>
6
TRACE: main PC:008 ST:001 ["pop"] null
TRACE: main PC:009 ST:000 ["return",0] null
Program completed in 0.05 seconds (pid: 38158).