-module(glua). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/glua.gleam"). -export([nil/1, table_decoder/2, list/3, string/2, bool/2, int/2, float/2, table/3, new/0, function/2, get/3, get_private/3, ref_get/2, set/3, set_api/3, set_lua_paths/2, set_private/3, delete_private/2, load/2, load_file/2, eval/3, ref_eval/2, eval_chunk/3, ref_eval_chunk/2, eval_file/3, ref_eval_file/2, call_function/4, ref_call_function/3, call_function_by_name/4, ref_call_function_by_name/3]). -export_type([lua/0, lua_error/0, lua_runtime_exception_kind/0, chunk/0, value/0, value_ref/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " A library to embed Lua in Gleam programs.\n" "\n" " Gleam wrapper around [Luerl](https://github.com/rvirding/luerl).\n" ). -type lua() :: any(). -type lua_error() :: {lua_compiler_exception, list(binary())} | {lua_runtime_exception, lua_runtime_exception_kind(), lua()} | key_not_found | {unexpected_result_type, list(gleam@dynamic@decode:decode_error())} | unknown_error. -type lua_runtime_exception_kind() :: {illegal_index, binary(), binary()} | {error_call, list(binary())} | {undefined_function, binary()} | {bad_arith, binary(), list(binary())} | {assert_error, binary()} | unknown_exception. -type chunk() :: any(). -type value() :: any(). -type value_ref() :: any(). -file("src/glua.gleam", 59). -spec nil(lua()) -> {lua(), value()}. nil(Lua) -> glua_ffi:lua_nil(Lua). -file("src/glua.gleam", 93). -spec table_decoder( gleam@dynamic@decode:decoder(DQQ), gleam@dynamic@decode:decoder(DQS) ) -> gleam@dynamic@decode:decoder(list({DQQ, DQS})). table_decoder(Keys_decoder, Values_decoder) -> Inner = begin gleam@dynamic@decode:field( 0, Keys_decoder, fun(Key) -> gleam@dynamic@decode:field( 1, Values_decoder, fun(Val) -> gleam@dynamic@decode:success({Key, Val}) end ) end ) end, gleam@dynamic@decode:list(Inner). -file("src/glua.gleam", 116). -spec list(lua(), fun((lua(), DQY) -> {lua(), value()}), list(DQY)) -> {lua(), list(value())}. list(Lua, Encoder, Values) -> gleam@list:map_fold(Values, Lua, Encoder). -file("src/glua.gleam", 61). -spec string(lua(), binary()) -> {lua(), value()}. string(Lua, V) -> glua_ffi:encode(Lua, V). -file("src/glua.gleam", 65). -spec bool(lua(), boolean()) -> {lua(), value()}. bool(Lua, V) -> glua_ffi:encode(Lua, V). -file("src/glua.gleam", 69). -spec int(lua(), integer()) -> {lua(), value()}. int(Lua, V) -> glua_ffi:encode(Lua, V). -file("src/glua.gleam", 73). -spec float(lua(), float()) -> {lua(), value()}. float(Lua, V) -> glua_ffi:encode(Lua, V). -file("src/glua.gleam", 77). -spec table( lua(), {fun((lua(), DQN) -> {lua(), value()}), fun((lua(), DQO) -> {lua(), value()})}, list({DQN, DQO}) ) -> {lua(), value()}. table(Lua, Encoders, Values) -> {Key_encoder, Value_encoder} = Encoders, {Lua@4, Values@1} = gleam@list:map_fold( Values, Lua, fun(Lua@1, Pair) -> {Lua@2, K} = Key_encoder(Lua@1, erlang:element(1, Pair)), {Lua@3, V} = Value_encoder(Lua@2, erlang:element(2, Pair)), {Lua@3, {K, V}} end ), glua_ffi:encode(Lua@4, Values@1). -file("src/glua.gleam", 129). ?DOC(" Creates a new Lua VM instance\n"). -spec new() -> lua(). new() -> luerl:init(). -file("src/glua.gleam", 106). -spec function( lua(), fun((lua(), list(gleam@dynamic:dynamic_())) -> {lua(), list(value())}) ) -> {lua(), value()}. function(Lua, F) -> Fun = fun(Args, Lua@1) -> _pipe = F(Lua@1, luerl:decode_list(Args, Lua@1)), gleam@pair:swap(_pipe) end, glua_ffi:encode(Lua, Fun). -file("src/glua.gleam", 160). ?DOC( " Gets a value in the Lua environment.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " glua.get(state: glua.new(), keys: [\"_VERSION\"], using: decode.string)\n" " // -> Ok(\"Lua 5.3\")\n" " ```\n" "\n" " ```gleam\n" " let #(lua, encoded) = glua.new() |> glua.bool(True)\n" " let assert Ok(lua) = glua.set(\n" " state: lua,\n" " keys: [\"my_table\", \"my_value\"],\n" " value: encoded\n" " )\n" "\n" " glua.get(\n" " state: lua,\n" " keys: [\"my_table\", \"my_value\"],\n" " using: decode.bool\n" " )\n" " // -> Ok(True)\n" " ```\n" "\n" " ```gleam\n" " glua.get(state: glua.new(), keys: [\"non_existent\"], using: decode.string)\n" " // -> Error(glua.KeyNotFound)\n" " ```\n" ). -spec get(lua(), list(binary()), gleam@dynamic@decode:decoder(DRD)) -> {ok, DRD} | {error, lua_error()}. get(Lua, Keys, Decoder) -> gleam@result:'try'( glua_ffi:get_table_keys_dec(Lua, Keys), fun(Value) -> gleam@result:'try'( begin _pipe = gleam@dynamic@decode:run(Value, Decoder), gleam@result:map_error( _pipe, fun(Field@0) -> {unexpected_result_type, Field@0} end ) end, fun(Decoded) -> {ok, Decoded} end ) end ). -file("src/glua.gleam", 184). ?DOC( " Gets a private value that is not exposed to the Lua runtime.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " assert glua.new()\n" " |> glua.set_private(\"private_value\", \"secret_value\")\n" " |> glua.get_private(\"private_value\", decode.string)\n" " == Ok(\"secret_value\")\n" " ```\n" ). -spec get_private(lua(), binary(), gleam@dynamic@decode:decoder(DRH)) -> {ok, DRH} | {error, lua_error()}. get_private(Lua, Key, Decoder) -> gleam@result:'try'( glua_ffi:get_private(Lua, Key), fun(Value) -> gleam@result:'try'( begin _pipe = gleam@dynamic@decode:run(Value, Decoder), gleam@result:map_error( _pipe, fun(Field@0) -> {unexpected_result_type, Field@0} end ) end, fun(Decoded) -> {ok, Decoded} end ) end ). -file("src/glua.gleam", 198). ?DOC(" Same as `glua.get`, but returns a reference to the value instead of decoding it\n"). -spec ref_get(lua(), list(binary())) -> {ok, value_ref()} | {error, lua_error()}. ref_get(Lua, Keys) -> glua_ffi:get_table_keys(Lua, Keys). -file("src/glua.gleam", 243). ?DOC( " Sets a value in the Lua environment.\n" "\n" " All nested keys will be created as intermediate tables.\n" "\n" " If successfull, this function will return the updated Lua state\n" " and the setted value will be available in Lua scripts.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let #(lua, encoded) = glua.new() |> glua.int(10)\n" " let assert Ok(lua) = glua.set(\n" " state: lua,\n" " keys: [\"my_number\"],\n" " value: encoded\n" " )\n" "\n" " glua.get(state: lua, keys: [\"my_number\"], using: decode.int)\n" " // -> Ok(10)\n" " ```\n" "\n" " ```gleam\n" " let emails = [\"jhondoe@example.com\", \"lucy@example.com\"]\n" " let #(lua, encoded) = glua.new() |> glua.list(glua.string, emails)\n" " let assert Ok(lua) = glua.set(\n" " state: lua,\n" " keys: [\"info\", \"emails\"],\n" " value: encoded\n" " )\n" "\n" " let assert Ok(#(_, results)) = glua.eval(\n" " state: lua,\n" " code: \"return info.emails\",\n" " using: decode.string\n" " )\n" "\n" " assert results == emails\n" " ```\n" ). -spec set(lua(), list(binary()), value()) -> {ok, lua()} | {error, lua_error()}. set(Lua, Keys, Val) -> State = begin gleam@list:try_fold( Keys, {[], Lua}, fun(Acc, Key) -> {Keys@1, Lua@1} = Acc, Keys@2 = lists:append(Keys@1, [Key]), case glua_ffi:get_table_keys(Lua@1, Keys@2) of {ok, _} -> {ok, {Keys@2, Lua@1}}; {error, key_not_found} -> {Tbl, Lua@2} = luerl_emul:alloc_table([], Lua@1), _pipe = glua_ffi:set_table_keys(Lua@2, Keys@2, Tbl), gleam@result:map( _pipe, fun(Lua@3) -> {Keys@2, Lua@3} end ); {error, E} -> {error, E} end end ) end, gleam@result:'try'( State, fun(_use0) -> {Keys@3, Lua@4} = _use0, glua_ffi:set_table_keys(Lua@4, Keys@3, Val) end ). -file("src/glua.gleam", 283). ?DOC(" Sets a group of values under a particular table in the Lua environment.\n"). -spec set_api(lua(), list(binary()), list({binary(), value()})) -> {ok, lua()} | {error, lua_error()}. set_api(Lua, Keys, Values) -> gleam@list:try_fold( Values, Lua, fun(State, _use1) -> {Key, Val} = _use1, set(State, lists:append(Keys, [Key]), Val) end ). -file("src/glua.gleam", 311). ?DOC( " Sets the paths where the Lua runtime will look when requiring other Lua files.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let my_scripts_paths = [\"app/scripts/lua/?.lua\"]\n" " let assert Ok(state) = glua.set_lua_paths(\n" " state: glua.new(),\n" " paths: my_scripts_paths\n" " )\n" "\n" " let assert Ok(#(_, [result])) = glua.eval(\n" " state:,\n" " code: \"local my_math = require 'my_script'; return my_math.square(3)\"\n" " using: decode.int\n" " )\n" "\n" " assert result = 9\n" " ```\n" ). -spec set_lua_paths(lua(), list(binary())) -> {ok, lua()} | {error, lua_error()}. set_lua_paths(Lua, Paths) -> {Lua@1, Paths@1} = string(Lua, gleam@string:join(Paths, <<";"/utf8>>)), set(Lua@1, [<<"package"/utf8>>, <<"path"/utf8>>], Paths@1). -file("src/glua.gleam", 278). ?DOC( " Sets a value that is not exposed to the Lua runtime and can only be accessed from Gleam.\n" "\n" " ## Examples\n" " ```gleam\n" " assert glua.new()\n" " |> glua.set(\"secret_value\", \"private_value\")\n" " |> glua.get(\"secret_value\")\n" " == Ok(\"secret_value\")\n" " ```\n" ). -spec set_private(lua(), binary(), any()) -> lua(). set_private(Lua, Key, Value) -> luerl:put_private(Key, Value, Lua). -file("src/glua.gleam", 352). ?DOC( " Remove a private value that is not exposed to the Lua runtime. \n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let lua = glua.set_private(glua.new(), \"my_value\", \"will_be_removed\"\n" " assert glua.get(lua, \"my_value\", decode.string) == Ok(\"will_be_removed\")\n" "\n" " assert glua.delete_private(lua, \"my_value\")\n" " |> glua.get(\"my_value\", decode.string)\n" " == Error(glua.KeyNotFound)\n" " ```\n" ). -spec delete_private(lua(), binary()) -> lua(). delete_private(Lua, Key) -> luerl:delete_private(Key, Lua). -file("src/glua.gleam", 362). ?DOC( " Parses a string of Lua code and returns it as a compiled chunk.\n" "\n" " To eval the returned chunk, use `glua.eval_chunk` or `glua.ref_eval_chunk`.\n" ). -spec load(lua(), binary()) -> {ok, {lua(), chunk()}} | {error, lua_error()}. load(Lua, Code) -> glua_ffi:load(Lua, Code). -file("src/glua.gleam", 375). ?DOC( " Parses a Lua source file and returns it as a compiled chunk.\n" "\n" " To eval the returned chunk, use `glua.eval_chunk` or `glua.ref_eval_chunk`.\n" ). -spec load_file(lua(), binary()) -> {ok, {lua(), chunk()}} | {error, lua_error()}. load_file(Lua, Path) -> glua_ffi:load_file(Lua, Path). -file("src/glua.gleam", 429). ?DOC( " Evaluates a string of Lua code.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let assert Ok(#(_, results)) = glua.eval(\n" " state: glua.new(),\n" " code: \"return 1 + 2\",\n" " using: decode.int\n" " )\n" " assert results == [3]\n" " ```\n" "\n" " ```gleam\n" " let my_decoder = decode.one_of(decode.string, or: [\n" " decode.int |> decode.map(int.to_string)\n" " ])\n" "\n" " let assert Ok(#(_, results)) = glua.eval(\n" " state: glua.new(),\n" " code: \"return 'hello, world!', 10\",\n" " using: my_decoder\n" " )\n" " assert results == [\"hello, world!\", \"10\"]\n" " ```\n" "\n" " ```gleam\n" " glua.eval(state: glua.new(), code: \"return 1 * \", using: decode.int)\n" " // -> Error(glua.LuaCompilerException(\n" " messages: [\"syntax error before: \", \"1\"]\n" " ))\n" " ```\n" "\n" " ```gleam\n" " glua.eval(state: glua.new(), code: \"return 'Hello, world!'\", using: decode.int)\n" " // -> Error(glua.UnexpectedResultType(\n" " [decode.DecodeError(\"Int\", \"String\", [])]\n" " ))\n" " ```\n" "\n" " > **Note**: If you are evaluating the same piece of code multiple times,\n" " > instead of calling `glua.eval` repeatly it is recommended to first convert\n" " > the code to a chunk by passing it to `glua.load`, and then\n" " > evaluate that chunk using `glua.eval_chunk` or `glua.ref_eval_chunk`.\n" ). -spec eval(lua(), binary(), gleam@dynamic@decode:decoder(DSZ)) -> {ok, {lua(), list(DSZ)}} | {error, lua_error()}. eval(Lua, Code, Decoder) -> gleam@result:'try'( glua_ffi:eval_dec(Lua, Code), fun(_use0) -> {Lua@1, Ret} = _use0, gleam@result:'try'( begin _pipe = gleam@list:try_map( Ret, fun(_capture) -> gleam@dynamic@decode:run(_capture, Decoder) end ), gleam@result:map_error( _pipe, fun(Field@0) -> {unexpected_result_type, Field@0} end ) end, fun(Decoded) -> {ok, {Lua@1, Decoded}} end ) end ). -file("src/glua.gleam", 450). ?DOC(" Same as `glua.eval`, but returns references to the values instead of decode them\n"). -spec ref_eval(lua(), binary()) -> {ok, {lua(), list(value_ref())}} | {error, lua_error()}. ref_eval(Lua, Code) -> glua_ffi:eval(Lua, Code). -file("src/glua.gleam", 480). ?DOC( " Evaluates a compiled chunk of Lua code.\n" "\n" " ## Examples\n" " ```gleam\n" " let assert Ok(#(lua, chunk)) = glua.load(\n" " state: glua.new(),\n" " code: \"return 'hello, world!'\"\n" " )\n" "\n" " let assert Ok(#(_, results)) = glua.eval_chunk(\n" " state: lua,\n" " chunk:,\n" " using: decode.string\n" " )\n" "\n" " assert results == [\"hello, world!\"]\n" " ```\n" ). -spec eval_chunk(lua(), chunk(), gleam@dynamic@decode:decoder(DTN)) -> {ok, {lua(), list(DTN)}} | {error, lua_error()}. eval_chunk(Lua, Chunk, Decoder) -> gleam@result:'try'( glua_ffi:eval_chunk_dec(Lua, Chunk), fun(_use0) -> {Lua@1, Ret} = _use0, gleam@result:'try'( begin _pipe = gleam@list:try_map( Ret, fun(_capture) -> gleam@dynamic@decode:run(_capture, Decoder) end ), gleam@result:map_error( _pipe, fun(Field@0) -> {unexpected_result_type, Field@0} end ) end, fun(Decoded) -> {ok, {Lua@1, Decoded}} end ) end ). -file("src/glua.gleam", 501). ?DOC(" Same as `glua.eval_chunk`, but returns references to the values instead of decode them\n"). -spec ref_eval_chunk(lua(), chunk()) -> {ok, {lua(), list(value_ref())}} | {error, lua_error()}. ref_eval_chunk(Lua, Chunk) -> glua_ffi:eval_chunk(Lua, Chunk). -file("src/glua.gleam", 526). ?DOC( " Evaluates a Lua source file.\n" "\n" " ## Examples\n" " ```gleam\n" " let assert Ok(#(_, results)) = glua.eval_file(\n" " state: glua.new(),\n" " path: \"path/to/hello.lua\",\n" " using: decode.string\n" " )\n" "\n" " assert results == [\"hello, world!\"]\n" " ```\n" ). -spec eval_file(lua(), binary(), gleam@dynamic@decode:decoder(DUB)) -> {ok, {lua(), list(DUB)}} | {error, lua_error()}. eval_file(Lua, Path, Decoder) -> gleam@result:'try'( glua_ffi:eval_file_dec(Lua, Path), fun(_use0) -> {Lua@1, Ret} = _use0, gleam@result:'try'( begin _pipe = gleam@list:try_map( Ret, fun(_capture) -> gleam@dynamic@decode:run(_capture, Decoder) end ), gleam@result:map_error( _pipe, fun(Field@0) -> {unexpected_result_type, Field@0} end ) end, fun(Decoded) -> {ok, {Lua@1, Decoded}} end ) end ). -file("src/glua.gleam", 547). ?DOC(" Same as `glua.eval_file`, but returns references to the values instead of decode them.\n"). -spec ref_eval_file(lua(), binary()) -> {ok, {lua(), list(value_ref())}} | {error, lua_error()}. ref_eval_file(Lua, Path) -> glua_ffi:eval_file(Lua, Path). -file("src/glua.gleam", 600). ?DOC( " Calls a Lua function by reference.\n" "\n" " ## Examples\n" " ```gleam\n" " let assert Ok(#(lua, fun)) = glua.ref_eval(state: glua.new(), code: \"return math.sqrt\")\n" "\n" " let #(lua, encoded) = glua.int(lua, 81)\n" " let assert Ok(#(_, [result])) = glua.call_function(\n" " state: lua,\n" " ref: fun,\n" " args: [encoded],\n" " using: decode.int\n" " )\n" "\n" " assert result == 9\n" " ```\n" "\n" " ```gleam\n" " let code = \"function fib(n)\n" " if n <= 1 then\n" " return n\n" " else\n" " return fib(n - 1) + fib(n - 2)\n" " end\n" " end\n" "\n" " return fib\n" " \"\n" " let assert Ok(#(lua, fun)) = glua.ref_eval(state: glua.new(), code:)\n" "\n" " let #(lua, encoded) = glua.int(lua, 10)\n" " let assert Ok(#(_, [result])) = glua.call_function(\n" " state: lua,\n" " ref: fun,\n" " args: [encoded],\n" " using: decode.int\n" " )\n" "\n" " assert result == 55 \n" " ```\n" ). -spec call_function( lua(), value_ref(), list(value()), gleam@dynamic@decode:decoder(DUQ) ) -> {ok, {lua(), list(DUQ)}} | {error, lua_error()}. call_function(Lua, Fun, Args, Decoder) -> gleam@result:'try'( glua_ffi:call_function_dec(Lua, Fun, Args), fun(_use0) -> {Lua@1, Ret} = _use0, gleam@result:'try'( begin _pipe = gleam@list:try_map( Ret, fun(_capture) -> gleam@dynamic@decode:run(_capture, Decoder) end ), gleam@result:map_error( _pipe, fun(Field@0) -> {unexpected_result_type, Field@0} end ) end, fun(Decoded) -> {ok, {Lua@1, Decoded}} end ) end ). -file("src/glua.gleam", 623). ?DOC(" Same as `glua.call_function`, but returns references to the values instead of decode them.\n"). -spec ref_call_function(lua(), value_ref(), list(value())) -> {ok, {lua(), list(value_ref())}} | {error, lua_error()}. ref_call_function(Lua, Fun, Args) -> glua_ffi:call_function(Lua, Fun, Args). -file("src/glua.gleam", 655). ?DOC( " Gets a reference to the function at `keys`, then inmediatly calls it with the provided `args`.\n" "\n" " This is a shorthand for `glua.ref_get` followed by `glua.call_function`.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let #(lua, encoded) = glua.new() |> glua.string(\"hello from gleam!\")\n" " let assert Ok(#(_, [s])) = glua.call_function_by_name(\n" " state: lua,\n" " keys: [\"string\", \"upper\"],\n" " args: [encoded],\n" " using: decode.string\n" " )\n" "\n" " assert s == \"HELLO FROM GLEAM!\" \n" " ```\n" ). -spec call_function_by_name( lua(), list(binary()), list(value()), gleam@dynamic@decode:decoder(DVJ) ) -> {ok, {lua(), list(DVJ)}} | {error, lua_error()}. call_function_by_name(Lua, Keys, Args, Decoder) -> gleam@result:'try'( ref_get(Lua, Keys), fun(Fun) -> call_function(Lua, Fun, Args, Decoder) end ). -file("src/glua.gleam", 666). ?DOC(" Same as `glua.call_function_by_name`, but it chains `glua.ref_get` with `glua.ref_call_function` instead of `glua.call_function`\n"). -spec ref_call_function_by_name(lua(), list(binary()), list(value())) -> {ok, {lua(), list(value_ref())}} | {error, lua_error()}. ref_call_function_by_name(Lua, Keys, Args) -> gleam@result:'try'( ref_get(Lua, Keys), fun(Fun) -> ref_call_function(Lua, Fun, Args) end ).