rvirding / luerl Goto Github PK
View Code? Open in Web Editor NEWLua in Erlang
License: Apache License 2.0
Lua in Erlang
License: Apache License 2.0
Ok, then here is a more useful update maybe (I let the other issue stand as you are at it anyway).
I put it all into one lua file, without module or require, now I get a different error message, see below.
If it's best for you to just grab the all-in-one test file itself, it's here:
https://raw.github.com/Eonblast/luerl/henning/bench.lua
My branch is on henning
, tag issue4
. Just type make bench
to run (it compiles bench.erl
to call bench.lua
). To see what should result, do lua bench.lua
.
The error I get is:
{"init terminating in do_boot",{{badarg,nil,[1.000000e+00,nil]},[{luerl_eval,badarg_error,2,[{file,"src/luerl_eval.erl"},{line,865}]},{luerl_eval,le_op,4,[{file,"src/luerl_eval.erl"},{line,798}]},{luerl_eval,exp,2,[{file,"src/luerl_eval.erl"},{line,558}]},{luerl_eval,if_tests,3,[{file,"src/luerl_eval.erl"},{line,438}]},{luerl_eval,stats,2,[{file,"src/luerl_eval.erl"},{line,299}]},{luerl_eval,'-functioncall/3-fun-0-',4,[{file,"src/luerl_eval.erl"},{line,606}]},{luerl_eval,'-function_block/2-fun-0-',2,[{file,"src/luerl_eval.erl"},{line,630}]},{luerl_eval,with_block,2,[{file,"src/luerl_eval.erl"},{line,288}]}]}}
It seems to happen during call/2
, in my ./bench.erl
(tag issue4
), which does nothing but:
{ok, Chunk} = luerl:loadfile("./bench.lua"),
State = luerl:start(),
luerl:call(Chunk, State),
Branch new-engine
I have such code:
function test_err(bb)
local a = 'def'
if bb == 'asd' then
a = 'a'
elseif bb == 'qwe' then
a = 'b'
else
a = 'c'
end
return a
end
r1 = test_err('qwe')
r2 = test_err('asd')
r3 = test_err('rrr')
print("r1: "..r1..", r2: "..r2..", r3: "..r3)
When I run this code with native Lua, output is:
r1: b, r2: a, r3: c
But with luerl output is:
r1: def, r2: a, r3: def
To workaround this behaviour I moved whole if...end clause to separated function which just returns in each clause.
Slepher I would like to pull your "add undefined method exception" commits but without the commits where you change some floats to integers. It is easier to be consistent and always have floats. Is this doable?
I'm using a couple of hundred erlua states within one erlang process and I'm calling a tick function defined in Lua for each of the erlua states once per second. I've noticed that the erlang process's state is growing by ~1MB each tick, even when the Lua tick function was empty like this:
function tick(deltaTime)
-- do absolutely nothing
end
The function is called like this:
{_IgnoreResult, NewLuaState} = luerl:call_function([tick], [DeltaTime], LuaState)
The Lua module does define some global variables to keep state, but they are not touched from the tick function.
Calling the erlua garbage collector solved the problem. Not sure if it is an issue, but I'd be nice to know the reason for this behaviour. ;-)
Is this a safe way to sandbox luerl?
-- called with luerl:do
whitelist = {
_G = _G,
ipairs = ipairs,
next = next,
pairs = pairs,
pcall = pcall,
tonumber = tonumber,
tostring = tostring,
type = type,
unpack = unpack,
string = { byte = string.byte, char = string.char, find = string.find,
format = string.format, gmatch = string.gmatch, gsub = string.gsub,
len = string.len, lower = string.lower, match = string.match,
rep = string.rep, reverse = string.reverse, sub = string.sub,
upper = string.upper },
table = { insert = table.insert, maxn = table.maxn, remove = table.remove,
sort = table.sort }
}
for i in pairs(_G) do
if not whitelist[i] then
_G[i] = "prohibited in sandbox"
else
_G[i] = whitelist[i]
end
end
If I have a Lua script like so:
local Mod = {}
function Mod.foo()
print("Test")
end
return Mod
And I run it within the Luerl VM like so:
St0 = luerl:init(),
{Res, St1} = luerl:do(<<"Lua code above">>, St0),
erlang:display(Res)
I get back [{:tref, 16}]
in my particular script (not quite the one above). I can see this is a table reference ID but how do I execute the foo
function defined within the Lua script?
Simplest example:
luerl:do("print('\','')"). % two backslashes
** exception error: no match of right hand side value {error,[{1,luerl_scan,{illegal,"')"}}],[]}
in function luerl:do/2 (src/luerl.erl, line 60)
The bug is probably in leex, the regexes in luerl_scan seems to be correct.
Need to encode erlang's undefined to lua nil
Hi I've ran into a problem that a function seems unable to return a table.
St0 = luerl:init(), ok.
F = fun([], StIn) ->
{Tab, StOut} = luerl_emul:alloc_table([{<<"a">>, 1}], StIn),
{[Tab], StOut}
end.
St1 = luerl:set_table([t], F, St0), ok.
luerl:eval("return t", St1). %%=> {ok,[{function,#Fun<luerl.2.17475489>}]}
luerl:eval("return t()", St1). %% => {error,badarg}
The function is based on the pack function form luerl_lib_table:
Line 263 in 3e69763
It seems whenever there's a dofile("xxx.lua") in my lua code, I get this exception:
** exception error: undefined function luerl_comp:chunk/1
in function luerl_basic:do_passes/2 (src/luerl_basic.erl, line 359)
in call from luerl_basic:dofile/2 (src/luerl_basic.erl, line 390)
in call from luerl_emul:functioncall/4 (src/luerl_emul.erl, line 637)
in call from luerl_emul:functioncall/8 (src/luerl_emul.erl, line 610)
in call from luerl_emul:functioncall/5 (src/luerl_emul.erl, line 645)
in call from luerl_emul:functioncall/4 (src/luerl_emul.erl, line 632)
in call from luerl_emul:functioncall/3 (src/luerl_emul.erl, line 600)
I've tried it with all the branches currently in this repository with the same error.
math.floor(0) returns -1.0 instead of 0. The same error is in math.ceil(0), which returns 1.0 instead of 0. Incorrect results for all integer numbers also.
In luerl:
1> hd(element(1, luerl:do("return math.floor(0)"))).
-1.0
In LuaJIT:
> =math.floor(0)
0
Erlang atoms true and false are encoded as strings, because in luerl:encode atom clause is going before boolean clause.
But if I switch them, some internal errors appears:
([email protected])20> flu_lua:evalfile("json.lua", flu_lua:init()).
** exception error: no case clause matching {error,{lua_error,{badarg,nil,[true,<<>>]},
{luerl,{array,16,100,undefined,
{{{table,{array,0,10,nil,10},
{{{{empty,<<"_G">>,
{tref,0},
empty,<<"_VERSION">>,<<"Lua 5.2">>,empty},
<<"assert">>,
{function,#Fun<luerl_basic.1.72666515>},
{empty,<<"collectgarbage">>,
{function,#Fun<luerl_basic.2.72666515>},
empty}},
<<"dofile">>,
{function,#Fun<luerl_basic.3.72666515>},
{{empty,<<"eprint">>,
{function,#Fun<luerl_basic.4.72666515>},
empty},
<<"error">>,
{function,#Fun<luerl_basic.0.72666515>},
{empty,<<"flus"...>>,{...},...},
<<"http">>,
{tref,...},
{...}}},
<<"ipairs">>,
{function,#Fun<luerl_basic.6.72666515>},
{{{empty,<<"json">>,{tref,8},empty,<<"load">>,{...},...},
<<"loadfile">>,
{function,#Fun<luerl_basic.8.72666515>},
{empty,<<"load"...>>,{...},...}},
<<"next">>,
{function,#Fun<luerl_basic.10.72666515>},
{{empty,<<"os">>,{...},...},
<<"pcall">>,
{function,...},
{...}}},
Hi,
I need to use an env var ($API_STAGE)
. So I used:
stage = os.getenv("API_STAGE")
Look's like luerl does support os.getenv
However it does return nil
even if the variable is already set:
vernemq@broker-3325152631-yg68e:/$ echo $API_STAGE
dev
Right now, attempting to use any of the luerl:*file
functions on the following minimal file fails:
$ cat hello.lua
#!/usr/bin/env lua
print "Hello, world!"
The returned error is {:badmatch, {:error, [{1, :luerl_scan, {:illegal, '!'}}], []}}
.
This prevents loading and running many real-world Lua scripts. Ideally Luerl would silently ignore the shebang line if it is present--just as Lua itself does.
When I try to create a new state it crashes with this error message:
Eshell V5.9.3.1 (abort with ^G)
1> {ok, State} = luerl:init().
** exception error: no match of right hand side value
{luerl,{array,7,10,undefined,
{{table,{array,0,10,nil,10},
{{{{empty,<<"_G">>,
{tref,0},
empty,<<"_VERSION">>,<<"Lua 5.2">>,empty},
<<"assert">>,
{function,#Fun<luerl_basic.1.43970411>},
{empty,<<"collectgarbage">>,
{function,#Fun<luerl_basic.2.43970411>},
empty}},
<<"dofile">>,
{function,#Fun<luerl_basic.3.43970411>},
{{empty,<<"eprint">>,
{function,#Fun<luerl_basic.4.43970411>},
empty},
<<"error">>,
{function,#Fun<luerl_basic.0.43970411>},
{empty,<<"getmetatable">>,
{function,#Fun<luerl_basic.5.43970411>},
empty,<<"io">>,
{tref,2},
empty}}},
<<"ipairs">>,
{function,#Fun<luerl_basic.6.43970411>},
{{{empty,<<"load">>,
{function,#Fun<luerl_basic.7.43970411>},
empty},
<<"loadfile">>,
{function,#Fun<luerl_basic.8.43970411>},
{empty,<<"math">>,{tref,1},empty},
<<"next">>,
{function,#Fun<luerl_basic.9.43970411>},
{empty,<<"os">>,{tref,3},empty}},
<<"pairs">>,
{function,#Fun<luerl_basic.10.43970411>},
{{empty,<<"pcall">>,
{function,#Fun<luerl_basic.11.43970411>},
empty},
<<"print">>,
{function,#Fun<luerl_basic.12.43970411>},
{empty,<<"rawequal">>,
{function,#Fun<luerl_basic.13.43970411>},
empty}}},
<<"rawget">>,
{function,#Fun<luerl_basic.14.43970411>},
{{{empty,<<"rawlen">>,
{function,#Fun<luerl_basic.15.43970411>},
empty},
<<"rawset">>,
{function,#Fun<luerl_basic.16.43970411>},
{empty,<<"select">>,
{function,#Fun<luerl_basic.17.43970411>},
empty}},
<<"setmetatable">>,
{function,#Fun<luerl_basic.18.43970411>},
{{empty,<<"string">>,{tref,4},empty},
<<"table">>,
{tref,6},
{empty,<<"tonu"...>>,{...},...},
<<"tostring">>,
{function,...},
{...}}}},
nil},
{table,{array,0,10,nil,10},
{{{{empty,<<"abs">>,
{function,#Fun<luerl_math.2.36130362>},
empty},
<<"acos">>,
{function,#Fun<luerl_math.3.36130362>},
{empty,<<"asin">>,
{function,#Fun<luerl_math.4.36130362>},
empty}},
<<"atan">>,
{function,#Fun<luerl_math.5.36130362>},
{{empty,<<"atan2">>,
{function,#Fun<luerl_math.6.36130362>},
empty},
<<"ceil">>,
{function,#Fun<luerl_math.7.36130362>},
{empty,<<"cos">>,
{function,#Fun<luerl_math.8.36130362>},
empty}}},
<<"cosh">>,
{function,#Fun<luerl_math.9.36130362>},
{{{empty,<<"deg">>,
{function,#Fun<luerl_math.10.36130362>},
empty},
<<"exp">>,
{function,#Fun<luerl_math.11.36130362>},
{empty,<<"floor">>,
{function,#Fun<luerl_math.12.36130362>},
empty}},
<<"fmod">>,
{function,#Fun<luerl_math.13.36130362>},
{{empty,<<"frexp">>,
{function,#Fun<luerl_math.14.36130362>},
empty},
<<"huge">>,1.7976931348623157e308,
{empty,<<"ldexp">>,
{function,#Fun<luerl_math.15.36130362>},
empty}}},
<<"log">>,
{function,#Fun<luerl_math.16.36130362>},
{{{empty,<<"log10">>,
{function,#Fun<luerl_math.17.36130362>},
empty},
<<"max">>,
{function,#Fun<luerl_math.0.36130362>},
{empty,<<"min">>,
{function,#Fun<luerl_math.1.36130362>},
empty}},
<<"modf">>,
{function,#Fun<luerl_math.18.36130362>},
{{empty,<<"pi">>,3.141592653589793,empty},
<<"pow">>,
{function,#Fun<luerl_math.19.36130362>},
{empty,<<...>>,...}},
<<"random">>,
{function,#Fun<luerl_math.21.36130362>},
{{empty,<<...>>,...},<<"sin">>,{...},...}}},
nil},
{table,{array,0,10,nil,10},
{empty,<<"flush">>,
{function,#Fun<luerl_io.0.115329101>},
empty,<<"write">>,
{function,#Fun<luerl_io.1.115329101>},
empty},
nil},
{table,{array,0,10,nil,10},
{{empty,<<"clock">>,
{function,#Fun<luerl_os.0.53974525>},
empty},
<<"date">>,
{function,#Fun<luerl_os.1.53974525>},
{empty,<<"difftime">>,
{function,#Fun<luerl_os.2.53974525>},
empty},
<<"getenv">>,
{function,#Fun<luerl_os.3.53974525>},
{empty,<<"time">>,
{function,#Fun<luerl_os.4.53974525>},
empty}},
nil},
{table,{array,0,10,nil,10},
{{{empty,<<"byte">>,
{function,#Fun<luerl_string.0.115339544>},
empty},
<<"char">>,
{function,#Fun<luerl_string.1.115339544>},
{empty,<<"find">>,
{function,#Fun<luerl_string.2.115339544>},
empty}},
<<"format">>,
{function,#Fun<luerl_string.3.115339544>},
{{empty,<<"gmatch">>,
{function,#Fun<luerl_string.4.115339544>},
empty},
<<"gsub">>,
{function,#Fun<luerl_string.5.115339544>},
{empty,<<"len">>,
{function,#Fun<luerl_string.6.115339544>},
empty}},
<<"lower">>,
{function,#Fun<luerl_string.7.115339544>},
{{empty,<<"match">>,
{function,#Fun<luerl_string.8.115339544>},
empty},
<<"rep">>,
{function,#Fun<luerl_string.9.115339544>},
{empty,<<"reve"...>>,{...},...},
<<"sub">>,
{function,...},
{...}}},
nil},
{table,{array,0,10,nil,10},
{empty,<<"__index">>,{tref,4},empty},
nil},
{table,{array,0,10,nil,10},
{{empty,<<"concat">>,
{function,#Fun<luerl_table.0.123621961>},
empty},
<<"insert">>,
{function,#Fun<luerl_table.1.123621961>},
{empty,<<"pack">>,
{function,#Fun<luerl_table.2.123621961>},
empty},
<<"remove">>,
{function,#Fun<luerl_table.3.123621961>},
{empty,<<"sort">>,
{function,#Fun<luerl_table.4.123621961>},
empty,<<...>>,...}},
nil},
undefined,undefined,undefined}},
[],7,
{meta,nil,{tref,5},nil},
[{tref,0}],
false,#Ref<0.0.0.216>}
2>
Thoughts?
Thank you!
--Kai
P.S.> Sorry for the messy dump, but I think that's GitHub ...
Would you consider tagging your current HEAD as a release? It is being used by ejabberd-16.02, and it would be nice to package it as a formal release instead of a commit. Thanks!
What is it? BSD, MIT, Apache, GPL or whatever? It will be good to have such information in repository.
Try this:
luerl:do("x={};x[100000000]=1;for i,v in pairs(x) do print(i,v) end").
It takes a long time, while in vanilla lua such construction runs instantly.
how does lua call erlang? for example, lua want to send socket throuth erlang, or tell other node some info by erlang, how to do this? i don't know how to do it.
Hi Robert,
I want create table from Erlang. I do
-module(hello_table2).
-export([run/0]).
run() ->
State0 = luerl:init(),
{ok, Chunk, State1} = luerl:load("print(\"Hello, Chunk!\")", State0),
{_Ret, State2} = luerl:do(Chunk, State1),
State3 = luerl:set_table([ftbl, field], value, State2),
{Val, State4} = luerl:get_table([ftbl, field], State3),
io:format("(1) ~p~n", [Val]).
And I got huge list of lua errors started from this line
{"init terminating in do_boot",{{lua_error,{illegal_index,nil,<<"field">>},
Where is my mistake?
Followup on #71 to keep track. The idea was that a suffix of 1
to indicate a function handles internal data structures comes with the problem that it is less then obvious without knowledge of the code. Changing this would be a api breaking change so only sensible with during a major version change. Alternatives suggested in the original issue were:
_i
, _internal
, _r
or _raw
as suffixesThis seems like a bug to me:
inputs = ["one", nil, "three", 20.0]
res = luerl_lib:conv_list(inputs, [:lua_string, :lua_string, :lua_string, :integer])
erlang:display(res)
This gives back nil
because luerl_lib:conv_list
bails out if it has a nil
input argument instead of propogating nil
forwards to the output list.
Hi there.
I am playing with exposing an Erlang database driver to Luerl. With simple queries the string datatype works great. However for more complex arguments I would like to pass a Lua table type to the Erlang lib and convert it to either proplist or maybe map. What is the suggested way for doing this?
Cheers,
Andre
@rvirding hey, today I noticed that keys are not being deleted from table:
lua:
> t = {key=1}
> for k, v in pairs(t) do print(k, v) end
key 1
> t["key"]=nil
> for k, v in pairs(t) do print(k, v) end
>
luerl:
1> luerl:do("t={key=1}\n for k, v in pairs(t) do print(k, v) end\n t[\"key\"]=nil\n for k, v in pairs(t) do print(k, v) end").
key 1
key nil
I found a comment "Don't delete key for nil here!", but I haven't found a place where those keys are actually being deleted.
todd@ubuntu:~/bin/luaerl/luerl$ cat crash.txt
State = luerl:start() crashes the erlang vm with:
todd@ubuntu:~/bin/luaerl/luerl$ make hellol
-------------------------------------------
./examples/hello/hello.erl:
erlc -o ./ebin ./examples/hello/hello.erl
erl -pa ./ebin -s hello run -s init stop -noshell
Hello, Robert(o)!
Hello, File!
{"init terminating in do_boot",{undef,[{luerl,start,[],[]},{hello,run,0,[{file,"examples/hello/hello.erl"},{line,19}]},{init,start_it,1,[]},{init,start_em,1,[]}]}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
make: *** [hello1] Error 1
hello.erl
run() ->
% execute a string
luerl:do("print(\"Hello, Robert(o)!\")"),
% execute a file
luerl:dofile("./examples/hello/hello.lua"),
% separately parse, then execute
{ok, Chunk} = luerl:load("print(\"Hello, Chunk!\")"),
State = luerl:start(),
{_Ret, _NewState} = luerl:do(Chunk, State),
done.
Erlang version:
todd@ubuntu:~/bin/luaerl/luerl$ erl --version
Erlang R15B02 (erts-5.9.2) [source] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.2 (abort with ^G)
test1.lua
require "test2"
myprint()
test2.lua
function myprint()
print("myprint")
return 1
end
It works well when I type following in shell
[mingchaoyan@localhost ebin]$ lua test1.lua
myprint
But, it fails when using luerl:
[mingchaoyan@localhost ebin]$ erl
Erlang R15B02 (erts-5.9.2) [source] [64-bit] [async-threads:0] [hipe] [kernel- poll:false]
Eshell V5.9.2 (abort with ^G)
1> {ok, Form} = luerl:loadfile("test1.lua").
{ok,{code,[{fdef,1,0,1,
[{push_gvar,<<"require">>},
{load_lit,<<"test2">>},
multiple,
{call,1},
{load_gvar,<<"myprint">>},
{call,0}]}],
{cst}}}
2> {R1, S1} = luerl:do(Form).
...
in function luerl_lib:lua_error/2 (lib/luerl/src/luerl_lib.erl, line 39)
in call from luerl_emul:functioncall/8 (lib/luerl/src/luerl_emul.erl, line 625)
in call from luerl_emul:functioncall/5 (lib/luerl/src/luerl_emul.erl, line 670)
in call from luerl_emul:functioncall/4 (lib/luerl/src/luerl_emul.erl, line 644)
in call from luerl_emul:functioncall/3 (lib/luerl/src/luerl_emul.erl, line 615)
How to do this?
Thanks a lot~
Hello Robert,
lua:
> t={ 666 }; t[1]=nil; table.insert(t, 1); print(next(t));
1 1 -- table is not empty
luerl:
1> application:start(luerl).
2> luerl:do("t={ 666 }; t[1]=nil; table.insert(t, 1); print(next(t));").
nil % table empty, table.insert took no effect because of t[1]=nil
EDITED MESSAGE -- there was a change in src/luerl_eval.erl that I have reverted.
The /src/* of the tag linked below is now identical with your master again.
In the course I moved the tag issue3 to 761f83a.
I think I manage to get a nil instead of a {table,..} tuple in set_table_key/4
To reproduce the error, this is the best I can offer right now:
Diff: Eonblast/luerl@master...henning
This is tagged issue3
in the branch henning
.
If you check it out, you can run make bench
to produce the error.
I tried to narrow in the error in the Lua source code, but so far no luck. Maybe this already helps.
What the above tag contains, it's exactly our Luerl source, plus an old, simpler version of Luabench ( link to this old commit: https://github.com/Eonblast/Luabench/tree/feed3acfc575e61358d6307e91e49a909d7701db ) -- the least complicated and shortest.
I had tried making Luabench run and (no matter the version) this error is what I ran into.
{"init terminating in do_boot",{function_clause,[{luerl_eval,set_table_key,[<<4 bytes>>,<<7 bytes>>,nil,{luerl,[{0,{[{<<2 bytes>>,{table,0}},{<<8 bytes>>,<<7 bytes>>},{<<6 bytes>>,{function,#Fun<luerl_basic.1.112261489>}},{<<14 bytes>>,{function,#Fun<luerl_basic.2.112261489>}},{<<6 bytes>>,{function,#Fun<luerl_basic.3.112261489>}},{<<6 bytes>>,{function,#Fun<luerl_basic.4.112261489>}},{<<5 bytes>>,{function,#Fun<luerl_basic.0.112261489>}},{<<12 bytes>>,{function,#Fun<luerl_basic.5.112261489>}},{<<6 bytes>>,{function,#Fun<luerl_basic.6.112261489>}},{<<4 bytes>>,{function,#Fun<luerl_basic.7.112261489>}},{<<8 bytes>>,{function,#Fun<luerl_basic.8.112261489>}},{<<4 bytes>>,{table,1}},{<<4 bytes>>,{function,#Fun<luerl_basic.9.112261489>}},{<<2 bytes>>,{table,2}},{<<5 bytes>>,{function,#Fun<luerl_basic.10.112261489>}},{<<5 bytes>>,{function,#Fun<luerl_basic.11.112261489>}},{<<8 bytes>>,{function,#Fun<luerl_basic.12.112261489>}},{<<6 bytes>>,{function,#Fun<luerl_basic.13.112261489>}},{<<6 bytes>>,{function,#Fun<luerl_basic.14.112261489>}},{<<6 bytes>>,{function,#Fun<luerl_basic.15.112261489>}},{<<6 bytes>>,{function,#Fun<luerl_basic.16.112261489>}},{<<12 bytes>>,{function,#Fun<luerl_basic.17.112261489>}},{<<6 bytes>>,{table,3}},{<<5 bytes>>,{table,4}},{<<8 bytes>>,{function,#Fun<luerl_basic.18.112261489>}},{<<8 bytes>>,{function,#Fun<luerl_basic.19.112261489>}},{<<4 bytes>>,{function,#Fun<luerl_basic.20.112261489>}}],nil}},{1,{[{<<3 bytes>>,{function,#Fun<luerl_math.2.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.3.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.4.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.5.111038588>}},{<<5 bytes>>,{function,#Fun<luerl_math.6.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.7.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.8.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.9.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.10.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.11.111038588>}},{<<5 bytes>>,{function,#Fun<luerl_math.12.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.13.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.0.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.1.111038588>}},{<<2 bytes>>,3.141593e+00},{<<3 bytes>>,{function,#Fun<luerl_math.14.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.15.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.16.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.17.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.18.111038588>}},{<<3 bytes>>,{function,#Fun<luerl_math.19.111038588>}},{<<4 bytes>>,{function,#Fun<luerl_math.20.111038588>}}],nil}},{2,{[{<<8 bytes>>,{function,#Fun<luerl_os.0.46494757>}},{<<6 bytes>>,{function,#Fun<luerl_os.1.46494757>}},{<<4 bytes>>,{function,#Fun<luerl_os.2.46494757>}}],nil}},{3,{[{<<4 bytes>>,{function,#Fun<luerl_string.0.111733768>}},{<<4 bytes>>,{function,#Fun<luerl_string.1.111733768>}},{<<6 bytes>>,{function,#Fun<luerl_string.2.111733768>}},{<<3 bytes>>,{function,#Fun<luerl_string.3.111733768>}},{<<5 bytes>>,{function,#Fun<luerl_string.4.111733768>}},{<<3 bytes>>,{function,#Fun<luerl_string.5.111733768>}},{<<7 bytes>>,{function,#Fun<luerl_string.6.111733768>}},{<<3 bytes>>,{function,#Fun<luerl_string.7.111733768>}},{<<5 bytes>>,{function,#Fun<luerl_string.8.111733768>}}],nil}},{4,{[{<<6 bytes>>,{function,#Fun<luerl_table.0.66276491>}},{<<4 bytes>>,{function,#Fun<luerl_table.1.66276491>}},{<<6 bytes>>,{function,#Fun<luerl_table.2.66276491>}}],nil}},{5,{[],nil}}],[],6,[{table,5},{table,0}],false,#Ref<0.0.0.29>}],[{file,"src/luerl_eval.erl"},{line,126}]},{luerl_eval,assign_loop,3,[{file,"src/luerl_eval.erl"},{line,346}]},{luerl_eval,stats,2,[{file,"src/luerl_eval.erl"},{line,299}]},{luerl_eval,'-funchunk/2-fun-0-',2,[{file,"src/luerl_eval.erl"},{line,253}]},{luerl_eval,'-function_block/2-fun-0-',2,[{file,"src/luerl_eval.erl"},{line,630}]},{luerl_eval,with_block,2,[{file,"src/luerl_eval.erl"},{line,288}]},{luerl_eval,funchunk,2,[{file,"src/luerl_eval.erl"},{line,253}]},{bench,run,0,[{file,"bench.erl"},{line,14}]}]}}
Crash dump was written to: erl_crash.dump
test.lua
a = {a}
print(table.getn(a))
erlang shell
{ok, Form} = luerl:loadfile("test.lua").
{_, _} = luerl:do(Form).
then get
very long dump
....
in function luerl_lib:lua_error/2 (lib/luerl/src/luerl_lib.erl, line 39)
in call from luerl_emul:functioncall/8 (lib/luerl/src/luerl_emul.erl, line 625)
in call from luerl_emul:functioncall/5 (lib/luerl/src/luerl_emul.erl, line 670)
in call from luerl_emul:functioncall/4 (lib/luerl/src/luerl_emul.erl, line 644)
in call from luerl_emul:functioncall/3 (lib/luerl/src/luerl_emul.erl, line 615)
When I define custom erlang function in luerl state, it's reply is not validated.
If I just return:
luerl:encode(Value, State) than luerl fails with function_clause somewhere.
I've added patch for immediate validating of return value.
What is the interest in having a version of luerl which supports Lua 5.3? I just have to work out a simple way of supporting both 5.2 and 5.3 in git. Separate branches?
Disclaimer: I'm not terribly familiar with lua :)
Hi,
I'm currently evaluating how to run customer provided code/functions within a sandbox. I was also taking a look at JavaScript (via https://github.com/basho/erlang_js), but I somehow like lua better.
I was wondering, if there is any way to "seal" off parts of luas standard library, like access to filesystem etc.
Is it possible to create some object with callback functions that will return back to erlang?
For example, http client or some crypto?
This comment came from @snogglethorpe:
"Remember that the "module" function is considered obsolete in Lua 5.2:
Function module is deprecated. It is easy to set up a module with regular Lua code. Modules are not expected to set global variables.
Instead of using the "module" function, it's simpler and cleaner to just use a pattern like:
-- "oinker.lua", my crazy module!
local oinker = {} -- module
function oinker.crazy_fun () ... end
return oinker -- return module
[Note, none of that wackiness with "seeall" etc, no metatables, everything's just nice and straightforward.]"
Is this how module works internally? What happens if a module does set global variables? Is this an error, or just not recommended?
Would it be possible to implement coroutines support in Luerl? If so, can you give me some pointers on where I should start?
I'm trying to figure out, how to report errors caused by lua to the user.
Using this script (notice that foo
is not defined):
print("Hello World!")
foo()
and run it via
{error, State} = luerl:evalfile("test.lua").
State
will contain something about undef_function
, but I'm having a hard time to build a understandable error message out of it I can present my user.
Using C-lua I get
Hello World!
lua: test.lua:2: attempt to call global 'foo' (a nil value)
stack traceback:
test.lua:2: in main chunk
[C]: in ?
And I would like to present a similar error message. I could not find an example on how to deal with and report errors. Is there something I'm missing?
[0] State
is…
{lua_error,{undef_function,nil},
{luerl,{array,13,100,undefined,
{{{table,{array,0,10,nil,10},
{{{{empty,<<"_G">>,
{tref,0},
empty,<<"_VERSION">>,<<"Lua 5.2">>,empty},
<<"assert">>,
{function,#Fun<luerl_lib_basic.1.82106474>},
{empty,<<"bit32">>,{tref,5},empty},
<<"collectgarbage">>,
{function,#Fun<luerl_lib_basic.2.82106474>},
{empty,<<"debug">>,{tref,12},empty}},
<<"dofile">>,
{function,#Fun<luerl_lib_basic.3.82106474>},
{{empty,<<"eprint">>,
{function,#Fun<luerl_lib_basic.4.82106474>},
empty},
<<"error">>,
{function,#Fun<luerl_lib_basic.0.82106474>},
{empty,<<"getmetatable">>,
{function,#Fun<luerl_lib_basic.5.82106474>},
empty,<<...>>,...}}},
<<"ipairs">>,
{function,#Fun<luerl_lib_basic.6.82106474>},
{{{empty,<<"load">>,
{function,#Fun<luerl_lib_basic.7.82106474>},
empty},
<<"loadfile">>,
{function,#Fun<luerl_lib_basic.8.82106474>},
{empty,<<"loadstring">>,
{function,#Fun<luerl_lib_basic.9.82106474>},
empty,<<...>>,...}},
<<"next">>,
{function,#Fun<luerl_lib_basic.10.82106474>},
{{empty,<<"os">>,{tref,8},empty},
<<"package">>,
{tref,4},
{empty,<<...>>,...},
<<"pcal"...>>,{...},...}},
<<"rawequal">>,
{function,#Fun<luerl_lib_basic.14.82106474>},
{{{empty,<<"rawget">>,
{function,#Fun<luerl_lib_basic.15.82106474>},
empty},
<<"rawlen">>,
{function,#Fun<luerl_lib_basic.16.82106474>},
{empty,<<...>>,...}},
<<"select">>,
{function,#Fun<luerl_lib_basic.18.82106474>},
{{empty,<<...>>,...},<<"stri"...>>,{...},...},
<<"tonumber">>,
{function,...},
{...}}},
nil},
{table,{array,3,10,nil,
{nil,{function,#Fun<luerl_lib_package.2.74952575>},
{function,#Fun<luerl_lib_package.3.74952575>},
nil,nil,nil,nil,nil,nil,...}},
empty,nil},
{table,{array,0,10,nil,10},
{{{empty,<<"_G">>,{tref,0},empty},
<<"bit32">>,
{tref,5},
{empty,<<"debug">>,{tref,12},empty},
<<"io">>,
{tref,6},
{empty,<<"math">>,{tref,...},empty}},
<<"os">>,
{tref,8},
{{empty,<<"package">>,{tref,4},empty},
<<"string">>,
{tref,9},
{empty,<<"table">>,{tref,...},empty}}},
nil},
{table,{array,0,10,nil,10},empty,nil},
{table,{array,0,10,nil,10},
{{empty,<<"config">>,<<"/\n;\n?\n!\n-\n">>,empty},
<<"loaded">>,
{tref,2},
{empty,<<"path">>,<<"./?.lua;./?/"...>>,empty},
<<"preload">>,
{tref,3},
{empty,<<"sear"...>>,{...},...}},
nil},
{table,{array,0,10,nil,10},
{{{empty,<<"arshift">>,
{function,#Fun<luerl_lib_bit32.7.29927074>},
empty,<<"band">>,
{function,...},
empty},
<<"bnot">>,
{function,#Fun<luerl_lib_bit32.1.29927074>},
{empty,<<"bor">>,{function,...},empty}},
<<"btest">>,
{function,#Fun<luerl_lib_bit32.3.29927074>},
{{empty,<<"bxor">>,{function,...},empty},
<<"extract">>,
{function,#Fun<luerl_lib_bit32.10.29927074>},
{empty,...}},
<<"lshift">>,
{function,#Fun<luerl_lib_bit32.5.29927074>},
{{empty,...},<<...>>,...}},
nil},
{table,{array,0,10,nil,10},
{empty,<<"flush">>,
{function,#Fun<luerl_lib_io.0.101991831>},
empty,<<"write">>,
{function,#Fun<luerl_lib_io.1.101991831>},
empty},
nil},
{table,{array,0,10,nil,10},
{{{{empty,<<"abs">>,{function,...},empty},
<<"acos">>,
{function,#Fun<luerl_lib_math.3.97665772>},
{empty,...}},
<<"atan">>,
{function,#Fun<luerl_lib_math.5.97665772>},
{{empty,...},<<...>>,...}},
<<"cosh">>,
{function,#Fun<luerl_lib_math.9.97665772>},
{{{empty,...},<<...>>,...},<<"fmod">>,{...},...},
<<"log">>,
{function,...},
{...}},
nil},
{table,{array,0,10,nil,10},
{{empty,<<"clock">>,
{function,#Fun<luerl_lib_os.0.73040098>},
empty},
<<"date">>,
{function,#Fun<luerl_lib_os.1.73040098>},
{empty,<<...>>,...},
<<"gete"...>>,{...},...},
nil},
{table,{array,0,10,nil,10},
{{{empty,<<"byte">>,{...},...},
<<"char">>,
{function,...},
{...}},
<<"find">>,
{function,#Fun<luerl_lib_string.3.80821632>},
{{...},...},
<<...>>,...},
nil}},
{{table,{array,0,10,nil,10},
{empty,<<"__index">>,{tref,9},empty},
nil},
{table,{array,0,10,nil,10},
{{empty,<<"concat">>,
{function,#Fun<luerl_lib_table.0.51275605>},
empty},
<<"insert">>,
{function,#Fun<luerl_lib_table.1.51275605>},
{empty,<<"pack">>,
{function,#Fun<luerl_lib_table.2.51275605>},
empty},
<<"remove">>,
{function,#Fun<luerl_lib_table.3.51275605>},
{empty,<<"sort">>,
{function,#Fun<luerl_lib_table.4.51275605>},
empty,<<...>>,...}},
nil},
{table,{array,0,10,nil,10},
{{empty,<<"getmetatable">>,
{function,#Fun<luerl_lib_debug.0.67778288>},
empty},
<<"getuservalue">>,
{function,#Fun<luerl_lib_debug.1.67778288>},
{empty,<<"setmetatable">>,
{function,#Fun<luerl_lib_debug.2.67778288>},
empty,<<"setuserv"...>>,
{function,...},
empty}},
nil},
undefined,undefined,undefined,undefined,undefined,undefined,
undefined},
10,10,10,10,10,10,10,10,10}},
[],13,
{array,0,10,undefined,10},
[],0,
{tref,0},
[],
{meta,nil,nil,nil,{tref,10}},
#Ref<0.0.8.29>}}
lua 5.1.4:
> print("a: "..true)
stdin:1: attempt to concatenate a boolean value
stack traceback:
stdin:1: in main chunk
[C]: ?
luerl (branch develop):
11> luerl:eval("print(\"\"..true)").
{error,{lua_error,{badarg,nil,[<<>>,true]},
{luerl,{array,7,10,undefined,
{{table,{array,0,10,nil,10},
{{{{empty,<<"_G">>,
{tref,0},
empty,<<"_VERSION">>,<<"Lua 5.2">>,empty},
<<"assert">>,
{function,#Fun<luerl_basic.1.62550678>},
{empty,<<"collectgarbage">>,
{function,#Fun<luerl_basic.2.62550678>},
empty}},
<<"dofile">>,
{function,#Fun<luerl_basic.3.62550678>},
{{empty,<<"eprint">>,
{function,#Fun<luerl_basic.4.62550678>},
empty},
<<"error">>,
... {meta,nil,nil,nil,{tref,5}},
false,#Ref<0.0.0.23655>}},
[{luerl_lib,lua_error,2,
[{file,"src/luerl_lib.erl"},{line,39}]},
{luerl_emul,functioncall,3,
[{file,"deps/luerl/src/luerl_emul.erl"},{line,615}]},
{luerl_emul,do_op2,7,
[{file,"deps/luerl/src/luerl_emul.erl"},{line,579}]},
{luerl_emul,functioncall,5,
[{file,"deps/luerl/src/luerl_emul.erl"},{line,674}]},
{luerl_emul,functioncall,4,
[{file,"deps/luerl/src/luerl_emul.erl"},{line,644}]},
{luerl_emul,functioncall,3,
[{file,"deps/luerl/src/luerl_emul.erl"},{line,615}]},
{luerl,eval,2,[{file,"deps/luerl/src/luerl.erl"},{line,37}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,576}]}]}
I think that error message should be done a bit more explanatory? Is it possible?
luerl:dofile(Path[, State]) -> {Result, NewState}.
Load and execute the Lua code in the file and return its result, and the new Lua State. Equivalent to doing luerl:eval("dofile('FileName')").
Equivalent to doing luerl:eval("dofile("FileName")") or luerl:do("dofile("FileName")")?
As you say before "The do functions return results and a new Lua State".
The function signature for __newindex
in native Lua is function (table, key, value)
, while in luerl it is function (key, value)
. I personally don't have a use for the table
argument, but thought I'd create an issue since it could be useful for people migrating existing scripts to luerl.
When writing the data structures wiki page I stumbled about the situation where a function defined using the 1
interface receives a table reference as an argument but didn't found a luerl_emul
function related that would be the reverse of alloc_table
. So I was wondering how would one go about reading data that is stored behind the reference?
even though README says it is :(
cc @loucash
motiejus@yoda> make
erl -noinput -run leex file "src/luerl_scan.xrl" -run init stop -noshell
erlc -o ./ebin src/luerl_scan.erl
erl -noinput -run yecc file "src/luerl_parse.yrl" -run init stop -noshell
erlc -o ./ebin src/luerl_parse.erl
erlc -o ./ebin src/luerl_app.erl
erlc -o ./ebin src/luerl_basic.erl
src/luerl_basic.erl:229: Warning: function raw_get_index/2 is unused
src/luerl_basic.erl:231: Warning: function raw_get_key/2 is unused
erlc -o ./ebin src/luerl.erl
erlc -o ./ebin src/luerl_eval.erl
src/luerl_eval.erl:1068: Warning: variable 'T' is unused
erlc -o ./ebin src/luerl_io.erl
erlc -o ./ebin src/luerl_lib.erl
src/luerl_lib.erl:81: Warning: variable 'I' is unused
erlc -o ./ebin src/luerl_math.erl
erlc -o ./ebin src/luerl_os.erl
erlc -o ./ebin src/luerl_string.erl
erlc -o ./ebin src/luerl_sup.erl
erlc -o ./ebin src/luerl_table.erl
make: *** No rule to make target `hello.erl', needed by `hello.beam'. Stop.
hello.erl
is in examples/hello/hello.erl
. Not sure where you actually want to store it. It would be nice to have it fixed, since top-level make
fails without it.
It would be really nice to have a hex package for luerl!
I think it's pretty much only needed to run rebar3 hex publish
if not I'm happy to publish it, work out all the kinks, prepare a PR and then hand the package over.
I noticed a matching error:
lua
:
> print(string.find("<a>123</a>", "^([^<]*)<(%/?)([^>]-)(%/?)>"))
1 3 a
luerl
:
> luerl:do("print(string.find(\"<a>123</a>\",\"^([^<]*)<(%/?)([^>]-)(%/?)>\", 1))").
** exception error: {lua_error,invalid_char_set, _}
...
in function luerl_lib:lua_error/2 (src/luerl_lib.erl, line 43)
in call from luerl_lib_string:find/2 (src/luerl_lib_string.erl, line 116)
in call from luerl_emul:functioncall/4 (src/luerl_emul.erl, line 830)
in call from luerl_emul:functioncall/7 (src/luerl_emul.erl, line 733)
in call from luerl_emul:functioncall/5 (src/luerl_emul.erl, line 843)
in call from luerl_emul:functioncall/4 (src/luerl_emul.erl, line 818)
in call from luerl_emul:functioncall/3 (src/luerl_emul.erl, line 723)
in call from luerl_emul:call/3 (src/luerl_emul.erl, line 384)
Another sandboxing question: how would you go about limiting a the memory of the execution of some Lua code? What potential ways do users have to circumvent memory limits?
I first thought this would be as easy as simple as tacking a max_heap_size onto the process interfacing with luerl, but I infered from #78 that computations and/or storage may be done in a separate Lua VM process. Besides that, luerl uses ETS and the process dictionary, which I'm not sure is counted as a part of the heap of the owner process.
If I'm not mistaken, math.randomseed can set the global seed, which is a bad thing in sandboxed environments. A possible solution is to attach a randomness state to every Lua VM.
When building Luerl on R19, the following deprecation warnings are output in an otherwise clean compile:
==> luerl
erlc -o ./src src/luerl_scan.xrl
erlc -o ./ebin src/luerl_scan.erl
erlc -o ./src src/luerl_parse.yrl
erlc -o ./ebin src/luerl_parse.erl
erlc -o ./ebin src/luerl.erl
erlc -o ./ebin src/luerl_app.erl
erlc -o ./ebin src/luerl_comp.erl
erlc -o ./ebin src/luerl_comp_cg.erl
erlc -o ./ebin src/luerl_comp_env.erl
erlc -o ./ebin src/luerl_comp_locf.erl
erlc -o ./ebin src/luerl_comp_peep.erl
erlc -o ./ebin src/luerl_comp_vars.erl
erlc -o ./ebin src/luerl_emul.erl
erlc -o ./ebin src/luerl_lib.erl
erlc -o ./ebin src/luerl_lib_basic.erl
erlc -o ./ebin src/luerl_lib_bit32.erl
erlc -o ./ebin src/luerl_lib_debug.erl
erlc -o ./ebin src/luerl_lib_io.erl
erlc -o ./ebin src/luerl_lib_math.erl
src/luerl_lib_math.erl:213: Warning: random:uniform/0: the 'random' module is deprecated; use the 'rand' module instead
src/luerl_lib_math.erl:215: Warning: random:uniform/1: the 'random' module is deprecated; use the 'rand' module instead
src/luerl_lib_math.erl:218: Warning: random:uniform/1: the 'random' module is deprecated; use the 'rand' module instead
src/luerl_lib_math.erl:228: Warning: random:seed/3: the 'random' module is deprecated; use the 'rand' module instead
erlc -o ./ebin src/luerl_lib_os.erl
erlc -o ./ebin src/luerl_lib_package.erl
erlc -o ./ebin src/luerl_lib_string.erl
erlc -o ./ebin src/luerl_lib_string_format.erl
erlc -o ./ebin src/luerl_lib_table.erl
erlc -o ./ebin src/luerl_sup.erl
erlc -o ./ebin src/ttdict.erl
It seems that going forward, use of the random module should be replaced by the rand module.
I'd be happy to work up a patch for this and submit a pull request. However, it does mean dropping R17 support--any objections?
LUA_PATH env variable must be converted to binary in luerl_lib_package.erl, path/0:
path() ->
case os:getenv("LUA_PATH") of
false -> <<"./?.lua;./?/init.lua">>; %Default path
Path -> erlang:list_to_binary(Path)
end.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.