Current section
Files
Jump to
Current section
Files
lib/firebird/quick.ex
defmodule Firebird.Quick do
@moduledoc """
Quick helpers for common WASM patterns.
These functions prioritize developer convenience over raw performance.
Perfect for scripts, prototyping, `iex` sessions, and tests.
## Examples
# Define and call a WASM function in one expression
add = Firebird.Quick.wat_fn("add", "(param i32 i32) (result i32)",
"local.get 0 local.get 1 i32.add")
add.(5, 3)
# => {:ok, [8]}
# Quick math with inline WAT
result = Firebird.Quick.eval_wat(\"""
(module
(func (export "main") (result i32)
i32.const 42))
\""", "main", [])
# => {:ok, [42]}
"""
@doc """
Create a callable function from WAT function body.
Returns a function that loads a WASM instance, calls the function,
and cleans up — all transparently.
## Examples
add = Firebird.Quick.wat_fn("add", "(param i32 i32) (result i32)",
"local.get 0 local.get 1 i32.add")
{:ok, [8]} = add.(5, 3)
{:ok, [12]} = add.(7, 5)
"""
@spec wat_fn(String.t(), String.t(), String.t()) :: (... -> {:ok, list()} | {:error, term()})
def wat_fn(name, signature, body) do
wat = """
(module
(func (export "#{name}") #{signature}
#{body}))
"""
case Firebird.compile_wat(wat) do
{:ok, wasm_bytes} ->
fn args ->
Firebird.run(wasm_bytes, name, args)
end
{:error, reason} ->
fn _args -> {:error, reason} end
end
end
@doc """
Evaluate a WAT module by calling a function and returning the result.
Compiles WAT, loads it, calls the function, and cleans up.
## Examples
{:ok, [42]} = Firebird.Quick.eval_wat(\"""
(module
(func (export "answer") (result i32)
i32.const 42))
\""", "answer", [])
{:ok, [8]} = Firebird.Quick.eval_wat(\"""
(module
(func (export "add") (param i32 i32) (result i32)
local.get 0 local.get 1 i32.add))
\""", "add", [5, 3])
"""
@spec eval_wat(String.t(), String.t() | atom(), list()) :: {:ok, list()} | {:error, term()}
def eval_wat(wat_source, function, args \\ []) do
with {:ok, wasm_bytes} <- Firebird.compile_wat(wat_source) do
Firebird.run(wasm_bytes, function, args)
end
end
@doc """
Like `eval_wat/3` but raises on error.
## Examples
[42] = Firebird.Quick.eval_wat!(\"""
(module
(func (export "answer") (result i32) i32.const 42))
\""", "answer")
"""
@spec eval_wat!(String.t(), String.t() | atom(), list()) :: list()
def eval_wat!(wat_source, function, args \\ []) do
case eval_wat(wat_source, function, args) do
{:ok, results} -> results
{:error, reason} -> raise "WAT eval failed: #{inspect(reason)}"
end
end
@doc """
Load a WASM file and return a map of callable functions.
Inspects the WASM module and returns a map where each key is a function
name (atom) and each value is a callable function.
## Examples
fns = Firebird.Quick.load_as_functions("math.wasm")
{:ok, [8]} = fns.add.([5, 3])
{:ok, [55]} = fns.fibonacci.([10])
"""
@spec load_as_functions(String.t() | binary(), keyword()) :: map()
def load_as_functions(wasm_source, opts \\ []) do
{:ok, instance} = Firebird.load(wasm_source, opts)
fns =
for func <- Firebird.exports(instance), into: %{} do
callable = fn args ->
Firebird.call(instance, func, args)
end
{func, callable}
end
Map.put(fns, :__instance__, instance)
|> Map.put(:__stop__, fn -> Firebird.stop(instance) end)
end
end