glua
A library to embed Lua in Gleam programs.
Gleam wrapper around Luerl.
Types
The exception that happens when a functi Represents a chunk of Lua code that is already loaded into the Lua VM
pub type Chunk
Represents the errors than can happend during the parsing and execution of Lua code
pub type LuaError {
LuaCompilerException(messages: List(String))
LuaRuntimeException(
exception: LuaRuntimeExceptionKind,
state: Lua,
)
KeyNotFound
UnexpectedResultType(List(decode.DecodeError))
UnknownError
}
Constructors
-
LuaCompilerException(messages: List(String))There was an exception when compiling the Lua code.
-
LuaRuntimeException( exception: LuaRuntimeExceptionKind, state: Lua, )The Lua environment threw an exception during code execution.
-
KeyNotFoundA certain key was not found in the Lua environment.
-
UnexpectedResultType(List(decode.DecodeError))The value returned by the Lua environment could not be decoded using the provided decoder.
-
UnknownErrorAn error that could not be identified.
Represents the kind of exceptions that can happen at runtime during Lua code execution.
pub type LuaRuntimeExceptionKind {
IllegalIndex(value: String, index: String)
ErrorCall(messages: List(String))
UndefinedFunction(value: String)
BadArith(operator: String, args: List(String))
AssertError(message: String)
UnknownException
}
Constructors
-
IllegalIndex(value: String, index: String)The exception that happens when trying to access an index that does not exists on a table (also happens when indexing non-table values).
-
ErrorCall(messages: List(String))The exception that happens when the
errorfunction is called. -
UndefinedFunction(value: String)The exception that happens when trying to call a function that is not defined.
-
BadArith(operator: String, args: List(String))The exception that happens when an invalid arithmetic operation is performed.
-
AssertError(message: String)The exception that happens when a call to assert is made passing a value that evalues to
falseas the first argument. -
UnknownExceptionAn exception that could not be identified
Values
pub fn call_function(
state lua: Lua,
ref fun: ValueRef,
args args: List(Value),
using decoder: decode.Decoder(a),
) -> Result(#(Lua, List(a)), LuaError)
Calls a Lua function by reference.
Examples
let assert Ok(#(lua, fun)) = glua.ref_eval(state: glua.new(), code: "return math.sqrt")
let #(lua, encoded) = glua.int(lua, 81)
let assert Ok(#(_, [result])) = glua.call_function(
state: lua,
ref: fun,
args: [encoded],
using: decode.int
)
assert result == 9
let code = "function fib(n)
if n <= 1 then
return n
else
return fib(n - 1) + fib(n - 2)
end
end
return fib
"
let assert Ok(#(lua, fun)) = glua.ref_eval(state: glua.new(), code:)
let #(lua, encoded) = glua.int(lua, 10)
let assert Ok(#(_, [result])) = glua.call_function(
state: lua,
ref: fun,
args: [encoded],
using: decode.int
)
assert result == 55
pub fn call_function_by_name(
state lua: Lua,
keys keys: List(String),
args args: List(Value),
using decoder: decode.Decoder(a),
) -> Result(#(Lua, List(a)), LuaError)
Gets a reference to the function at keys, then inmediatly calls it with the provided args.
This is a shorthand for glua.ref_get followed by glua.call_function.
Examples
let #(lua, encoded) = glua.new() |> glua.string("hello from gleam!")
let assert Ok(#(_, [s])) = glua.call_function_by_name(
state: lua,
keys: ["string", "upper"],
args: [encoded],
using: decode.string
)
assert s == "HELLO FROM GLEAM!"
pub const default_sandbox: List(List(String))
List of Lua modules and functions that will be sandboxed by default
pub fn delete_private(state lua: Lua, key key: String) -> Lua
Remove a private value that is not exposed to the Lua runtime.
Examples
let lua = glua.set_private(glua.new(), "my_value", "will_be_removed"
assert glua.get(lua, "my_value", decode.string) == Ok("will_be_removed")
assert glua.delete_private(lua, "my_value")
|> glua.get("my_value", decode.string)
== Error(glua.KeyNotFound)
pub fn eval(
state lua: Lua,
code code: String,
using decoder: decode.Decoder(a),
) -> Result(#(Lua, List(a)), LuaError)
Evaluates a string of Lua code.
Examples
let assert Ok(#(_, results)) = glua.eval(
state: glua.new(),
code: "return 1 + 2",
using: decode.int
)
assert results == [3]
let my_decoder = decode.one_of(decode.string, or: [
decode.int |> decode.map(int.to_string)
])
let assert Ok(#(_, results)) = glua.eval(
state: glua.new(),
code: "return 'hello, world!', 10",
using: my_decoder
)
assert results == ["hello, world!", "10"]
glua.eval(state: glua.new(), code: "return 1 * ", using: decode.int)
// -> Error(glua.LuaCompilerException(
messages: ["syntax error before: ", "1"]
))
glua.eval(state: glua.new(), code: "return 'Hello, world!'", using: decode.int)
// -> Error(glua.UnexpectedResultType(
[decode.DecodeError("Int", "String", [])]
))
Note: If you are evaluating the same piece of code multiple times, instead of calling
glua.evalrepeatly it is recommended to first convert the code to a chunk by passing it toglua.load, and then evaluate that chunk usingglua.eval_chunkorglua.ref_eval_chunk.
pub fn eval_chunk(
state lua: Lua,
chunk chunk: Chunk,
using decoder: decode.Decoder(a),
) -> Result(#(Lua, List(a)), LuaError)
Evaluates a compiled chunk of Lua code.
Examples
let assert Ok(#(lua, chunk)) = glua.load(
state: glua.new(),
code: "return 'hello, world!'"
)
let assert Ok(#(_, results)) = glua.eval_chunk(
state: lua,
chunk:,
using: decode.string
)
assert results == ["hello, world!"]
pub fn eval_file(
state lua: Lua,
path path: String,
using decoder: decode.Decoder(a),
) -> Result(#(Lua, List(a)), LuaError)
Evaluates a Lua source file.
Examples
let assert Ok(#(_, results)) = glua.eval_file(
state: glua.new(),
path: "path/to/hello.lua",
using: decode.string
)
assert results == ["hello, world!"]
pub fn function(
lua: Lua,
f: fn(Lua, List(dynamic.Dynamic)) -> #(Lua, List(Value)),
) -> #(Lua, Value)
pub fn get(
state lua: Lua,
keys keys: List(String),
using decoder: decode.Decoder(a),
) -> Result(a, LuaError)
Gets a value in the Lua environment.
Examples
glua.get(state: glua.new(), keys: ["_VERSION"], using: decode.string)
// -> Ok("Lua 5.3")
let #(lua, encoded) = glua.new() |> glua.bool(True)
let assert Ok(lua) = glua.set(
state: lua,
keys: ["my_table", "my_value"],
value: encoded
)
glua.get(
state: lua,
keys: ["my_table", "my_value"],
using: decode.bool
)
// -> Ok(True)
glua.get(state: glua.new(), keys: ["non_existent"], using: decode.string)
// -> Error(glua.KeyNotFound)
pub fn get_private(
state lua: Lua,
key key: String,
using decoder: decode.Decoder(a),
) -> Result(a, LuaError)
Gets a private value that is not exposed to the Lua runtime.
Examples
assert glua.new()
|> glua.set_private("private_value", "secret_value")
|> glua.get_private("private_value", decode.string)
== Ok("secret_value")
pub fn list(
lua: Lua,
encoder: fn(Lua, a) -> #(Lua, Value),
values: List(a),
) -> #(Lua, List(Value))
pub fn load(
state lua: Lua,
code code: String,
) -> Result(#(Lua, Chunk), LuaError)
Parses a string of Lua code and returns it as a compiled chunk.
To eval the returned chunk, use glua.eval_chunk or glua.ref_eval_chunk.
pub fn load_file(
state lua: Lua,
path path: String,
) -> Result(#(Lua, Chunk), LuaError)
Parses a Lua source file and returns it as a compiled chunk.
To eval the returned chunk, use glua.eval_chunk or glua.ref_eval_chunk.
pub fn new_sandboxed(
allow excluded: List(List(String)),
) -> Result(Lua, LuaError)
Creates a new Lua VM instance with sensible modules and functions sandboxed.
Check glua.default_sandbox to see what modules and functions will be sandboxed.
This function accepts a list of paths to Lua values that will be excluded from being sandboxed,
so needed modules or functions can be enabled while keeping sandboxed the rest.
In case you want to sandbox more Lua values, pass to glua.sandbox the returned Lua state.
pub fn ref_call_function(
state lua: Lua,
ref fun: ValueRef,
args args: List(Value),
) -> Result(#(Lua, List(ValueRef)), LuaError)
Same as glua.call_function, but returns references to the values instead of decode them.
pub fn ref_call_function_by_name(
state lua: Lua,
keys keys: List(String),
args args: List(Value),
) -> Result(#(Lua, List(ValueRef)), LuaError)
Same as glua.call_function_by_name, but it chains glua.ref_get with glua.ref_call_function instead of glua.call_function
pub fn ref_eval(
state lua: Lua,
code code: String,
) -> Result(#(Lua, List(ValueRef)), LuaError)
Same as glua.eval, but returns references to the values instead of decode them
pub fn ref_eval_chunk(
state lua: Lua,
chunk chunk: Chunk,
) -> Result(#(Lua, List(ValueRef)), LuaError)
Same as glua.eval_chunk, but returns references to the values instead of decode them
pub fn ref_eval_file(
state lua: Lua,
path path: String,
) -> Result(#(Lua, List(ValueRef)), LuaError)
Same as glua.eval_file, but returns references to the values instead of decode them.
pub fn ref_get(
state lua: Lua,
keys keys: List(String),
) -> Result(ValueRef, LuaError)
Same as glua.get, but returns a reference to the value instead of decoding it
pub fn sandbox(
state lua: Lua,
keys keys: List(String),
) -> Result(Lua, LuaError)
Swaps out the value at keys with a function that causes a Lua error when called.
Examples
let assert Ok(lua) = glua.new() |> glua.sandbox(["os"], ["execute"])
let assert Error(glua.LuaRuntimeException(exception, _)) = glua.eval(
state: lua,
code: "os.execute(\"rm -f important_file\"); return 0",
using: decode.int
)
// 'important_file' was not deleted
assert exception == glua.ErrorCall(["os.execute is sandboxed"])
pub fn set(
state lua: Lua,
keys keys: List(String),
value val: Value,
) -> Result(Lua, LuaError)
Sets a value in the Lua environment.
All nested keys will be created as intermediate tables.
If successfull, this function will return the updated Lua state and the setted value will be available in Lua scripts.
Examples
let #(lua, encoded) = glua.new() |> glua.int(10)
let assert Ok(lua) = glua.set(
state: lua,
keys: ["my_number"],
value: encoded
)
glua.get(state: lua, keys: ["my_number"], using: decode.int)
// -> Ok(10)
let emails = ["jhondoe@example.com", "lucy@example.com"]
let #(lua, encoded) = glua.new() |> glua.list(glua.string, emails)
let assert Ok(lua) = glua.set(
state: lua,
keys: ["info", "emails"],
value: encoded
)
let assert Ok(#(_, results)) = glua.eval(
state: lua,
code: "return info.emails",
using: decode.string
)
assert results == emails
pub fn set_api(
lua: Lua,
keys: List(String),
values: List(#(String, Value)),
) -> Result(Lua, LuaError)
Sets a group of values under a particular table in the Lua environment.
pub fn set_lua_paths(
state lua: Lua,
paths paths: List(String),
) -> Result(Lua, LuaError)
Sets the paths where the Lua runtime will look when requiring other Lua files.
Warning: This function will not work properly if
["package"]or["require"]are sandboxed in the provided Lua state. If you constructed the Lua state usingglua.new_sandboxed, remember to allow the required values by passing[["package"], ["require"]]toglua.new_sandboxed.
Examples
let my_scripts_paths = ["app/scripts/lua/?.lua"]
let assert Ok(state) = glua.set_lua_paths(
state: glua.new(),
paths: my_scripts_paths
)
let assert Ok(#(_, [result])) = glua.eval(
state:,
code: "local my_math = require 'my_script'; return my_math.square(3)"
using: decode.int
)
assert result = 9
pub fn set_private(
state lua: Lua,
key key: String,
value value: a,
) -> Lua
Sets a value that is not exposed to the Lua runtime and can only be accessed from Gleam.
Examples
assert glua.new()
|> glua.set("secret_value", "private_value")
|> glua.get("secret_value")
== Ok("secret_value")
pub fn table(
lua: Lua,
encoders: #(
fn(Lua, a) -> #(Lua, Value),
fn(Lua, b) -> #(Lua, Value),
),
values: List(#(a, b)),
) -> #(Lua, Value)
pub fn table_decoder(
keys_decoder: decode.Decoder(a),
values_decoder: decode.Decoder(b),
) -> decode.Decoder(List(#(a, b)))