Current section

Files

Jump to
lattice lib lattice.ex
Raw

lib/lattice.ex

defmodule Lattice do
@moduledoc """
High-level Elixir interface for the Lattice DSL runtime.
## Usage
# Create a runtime
{:ok, rt} = Lattice.new()
# Evaluate expressions
{:ok, 6} = Lattice.eval(rt, "1 + 2 + 3")
{:ok, "hello world"} = Lattice.eval(rt, ~s("hello" + " " + "world"))
# Define and call functions
Lattice.eval(rt, ~s(
def add(a: Int, b: Int) -> Int {
a + b
}
))
{:ok, 7} = Lattice.call(rt, "add", [3, 4])
# Define types and use them
Lattice.eval(rt, "type Person { name: String, age: Int }")
{:ok, person} = Lattice.eval(rt, ~s(Person { name: "Alice", age: 30 }))
# person is %{"name" => "Alice", "age" => 30}
## Value Marshaling
Values are automatically converted between Elixir and Lattice:
| Lattice Type | Elixir Type |
|--------------|-------------|
| null | :null atom |
| Bool | boolean |
| Int | integer |
| Float | float |
| String | binary |
| Path | {:path, binary} |
| List | list |
| Map | map |
"""
alias Lattice.Native
@doc """
Create a new Lattice runtime.
The runtime is isolated - it has its own globals, functions, and types.
"""
def new do
Native.new_runtime()
end
@doc """
Create a new Lattice runtime with LLM support.
Requires OPENROUTER_API_KEY environment variable to be set.
"""
def new_with_llm do
Native.new_runtime_with_llm()
end
@doc """
Create a new Lattice runtime with SQL support (DuckDB).
Enables the SQL() function for querying CSV files and in-memory data.
"""
def new_with_sql do
Native.new_runtime_with_sql()
end
@doc """
Create a new Lattice runtime with both LLM and SQL support.
Requires OPENROUTER_API_KEY environment variable to be set.
"""
def new_with_all do
Native.new_runtime_with_all()
end
@doc """
Evaluate Lattice source code.
Returns `{:ok, value}` on success or `{:error, reason}` on failure.
## Examples
{:ok, 42} = Lattice.eval(rt, "40 + 2")
{:ok, "hello"} = Lattice.eval(rt, ~s("hello"))
{:ok, [1, 2, 3]} = Lattice.eval(rt, "[1, 2, 3]")
"""
def eval(runtime, source) do
Native.eval(runtime, source)
end
@doc """
Evaluate with pre-bound variables.
## Examples
{:ok, 30} = Lattice.eval_with_bindings(rt, "x + y", [{"x", 10}, {"y", 20}])
"""
def eval_with_bindings(runtime, source, bindings) do
Native.eval_with_bindings(runtime, source, bindings)
end
@doc """
Call a Lattice function by name.
## Examples
# First define a function
Lattice.eval(rt, "def double(x: Int) -> Int { x * 2 }")
# Then call it
{:ok, 10} = Lattice.call(rt, "double", [5])
"""
def call(runtime, name, args) do
Native.call_function(runtime, name, args)
end
@doc """
Get all registered type schemas.
Returns a list of type schema maps that can be used to generate
Elixir structs or validate data.
"""
def get_types(runtime) do
Native.get_types(runtime)
end
@doc """
Get all function signatures.
Returns a list of function signature maps with name, params,
return type, and metadata (is_llm, is_async).
"""
def get_function_signatures(runtime) do
Native.get_function_signatures(runtime)
end
@doc """
Check if a function exists.
"""
def has_function?(runtime, name) do
Native.has_function(runtime, name)
end
@doc """
Get a global variable.
Returns `{:ok, value}` if found, `{:error, :not_found}` otherwise.
"""
def get_global(runtime, name) do
Native.get_global(runtime, name)
end
@doc """
Set a global variable.
"""
def set_global(runtime, name, value) do
Native.set_global(runtime, name, value)
end
@doc """
Reset the runtime, clearing all state.
"""
def reset(runtime) do
Native.reset(runtime)
end
end