README

#eval package

The main entry point for parsing, resolving, and executing Starlark. Import connect0459/starlark/eval to run scripts, evaluate expressions, compile reusable programs, and configure the Starlark dialect.

#Key types

TypeDescription
ThreadExecution context: print callback, loader, step budget, thread-local storage
OptionsDialect flags (which language extensions are enabled)
ModuleFrozen result of a successful exec_file; holds the script's globals
ProgramPre-compiled program that can be executed multiple times without re-parsing
PredeclaredExtra host bindings injected before user globals
UniverseThe built-in environment (default: standard Starlark builtins)
DebugFrameRead-only snapshot of an active call frame

#Quick start

#Execute a Starlark file

///|
test {
let thread = @eval.Thread::new("main")
match
@eval.exec_file(
thread,
"build.star",
"greeting = 'hello ' + 'world'",
@eval.Options::default(),
) {
Ok(m) =>
match m.get("greeting") {
Some(@value.Value::String(s)) => assert_eq(s.raw(), "hello world")
_ => fail("expected string")
}
Err(e) => fail(e.to_string())
}
}

#Evaluate a single expression

///|
test {
let thread = @eval.Thread::new("expr")
let env = @value.StringDict::new()
env.set("n", @value.Value::new_int(7L))
match @eval.eval_expr(thread, "<expr>", "n * 6", env) {
Ok(@value.Value::Int(v)) => assert_eq(v, 42N)
_ => fail("expected int 42")
}
}

#Inject host bindings (predeclared)

///|
test {
let thread = @eval.Thread::new("main")
let predeclared = @eval.Predeclared::from_map({
"VERSION": @value.Value::new_string("1.0"),
})
match
@eval.exec_file_with_predeclared(
thread,
"check.star",
"v = VERSION",
@eval.Options::default(),
predeclared,
) {
Ok(m) => assert_true(m.get("v") is Some(@value.Value::String(_)))
Err(e) => fail(e.to_string())
}
}

#Compile a program for repeated execution

///|
test {
let prog_result = @eval.source_program(
"lib.star",
"def double(n): return n * 2",
@eval.Options::default(),
fn(_) { false },
)
match prog_result {
Ok(prog) => {
let t1 = @eval.Thread::new("run1")
let t2 = @eval.Thread::new("run2")
// prog.init() returns Result[Module, EvalError]; execute independently per thread.
match prog.init(t1, @eval.Predeclared::new()) {
Ok(m) => assert_true(m.get("double") is Some(@value.Value::Function(_)))
Err(e) => fail(e.to_string())
}
let _ = prog.init(t2, @eval.Predeclared::new())
}
Err(e) => fail(e.to_string())
}
}

#Thread cancellation

///|
test {
let thread = @eval.Thread::new("main")
thread.cancel("timeout")
match @eval.exec_file(thread, "x.star", "x = 1", @eval.Options::default()) {
Err(e) => assert_true(e.msg().contains("timeout"))
Ok(_) => fail("expected cancellation")
}
}

#Non-standard dialect options

///|
test {
let opts = @eval.Options::default().with_allow_recursion(true)
let thread = @eval.Thread::new("main")
let src = "def fact(n): return 1 if n == 0 else n * fact(n - 1)"
let _ = @eval.exec_file(thread, "r.star", src, opts)
}

#API reference

#Execution functions

FunctionSignatureDescription
exec_file(Thread, String, String, Options) -> Result[Module, @errors.EvalError]Execute a Starlark source file
exec_file_with_predeclared(Thread, String, String, Options, Predeclared) -> Result[Module, @errors.EvalError]Execute with extra host bindings visible to the script
exec_file_with_universe(Thread, String, String, Options, Universe) -> Result[Module, @errors.EvalError]Execute with a custom built-in universe instead of the standard one
exec_repl_chunk(Thread, String, String, @value.StringDict, Options) -> Result[Unit, @errors.EvalError]Execute one REPL chunk; updates the persistent globals dict in place
eval_expr(Thread, String, String, @value.StringDict) -> Result[@value.Value, @errors.EvalError]Evaluate a single Starlark expression with default options
eval_expr_with_opts(Thread, String, String, Options, @value.StringDict) -> Result[@value.Value, @errors.EvalError]Like eval_expr but with explicit options
eval_parsed_expr(Thread, @syntax.Expr, Options, @value.StringDict) -> Result[@value.Value, @errors.EvalError]Evaluate a pre-parsed expression node
call(Thread, @value.Value, Array[@value.Value], Array[(String, @value.Value)]) -> Result[@value.Value, @errors.EvalError]Call any Starlark callable from host code

#Parsing and compilation

FunctionSignatureDescription
parse_file(String, String) -> Result[@syntax.File, @errors.EvalError]Parse Starlark source to an AST
parse_expr(String, String) -> Result[@syntax.Expr, @errors.EvalError]Parse a single Starlark expression to an AST node
source_program(String, String, Options, (String)->Bool) -> Result[Program, @errors.EvalError]Parse and resolve without executing; returns a reusable Program
source_program_with_file(String, String, Options, (String)->Bool) -> Result[(@syntax.File, Program), @errors.EvalError]Like source_program but also returns the parsed AST
file_program(@syntax.File, Options, (String)->Bool) -> Result[Program, @errors.EvalError]Resolve an already-parsed @syntax.File into a Program
compiled_program(Bytes) -> Result[Program, @errors.EvalError]Reload a Program from bytes produced by Program::write, skipping parse + resolve

#Operator dispatch

Apply Starlark operators by name from host code.

FunctionSignatureDescription
binary(String, @value.Value, @value.Value) -> Result[@value.Value, @errors.EvalError]Apply a binary operator by name ("+", "-", "*", etc.)
unary(String, @value.Value) -> Result[@value.Value, @errors.EvalError]Apply a unary operator by name ("-", "~", "not")
compare(String, @value.Value, @value.Value) -> Result[Bool, @errors.EvalError]Apply a comparison operator by name ("==", "<", etc.)


#Thread

Holds execution context: print callback, load callback, call stack, and step budget.

#Constructors

ConstructorSignatureDescription
Thread::new(String) -> ThreadThread with default print (stdout) and no loader
Thread::with_print(String, (Thread, String) -> Unit) -> ThreadThread with a custom print callback
Thread::with_loader(String, (Thread, String) -> Result[Module, @errors.EvalError]) -> ThreadThread with a module loader
Thread::with_step_budget(String, Int) -> ThreadThread that halts after n evaluation steps

The with_* constructors are composable: start from Thread::new(name) then call set_print, set_loader, set_max_steps, and set_on_max_steps in any combination.

#Accessors

MethodReturnsDescription
name()StringThread name
max_recursion_depth()IntCall depth limit (default 100)
max_steps()Int?Step budget; None if uncapped
execution_steps()IntSteps consumed so far
call_stack_depth()IntCurrent call depth
call_stack()@errors.CallStackSnapshot of the current call stack
call_frame(Int)@errors.CallFrame?Frame at depth n (0 = innermost)
debug_frame(Int)DebugFrame?Snapshot of an active call frame (0 = innermost Starlark function)

#Customization (mutators)

MethodDescription
set_print((Thread, String) -> Unit)Set the print callback
set_loader((Thread, String) -> Result[Module, @errors.EvalError])Set the module loader

#Step budget control

MethodDescription
set_max_steps(Int)Set the step budget (does not reset the accumulated count)
set_on_max_steps((Thread) -> Unit)Callback invoked when the budget is reached instead of halting
reset_steps()Reset the accumulated step counter to zero

#Thread-local storage

MethodDescription
set_local(String, @value.Value)Store a value under a string key
get_local(String) -> @value.Value?Retrieve a stored value; None if not set

#Cancellation

MethodDescription
cancel(String)Signal the thread to halt; raises EvalError at the next step check
uncancel()Clear a previous cancel signal


#Options

Feature flags that control the Starlark dialect. Options::default() is the spec-conformant dialect.

Standard features — part of the Starlark spec, enabled by default:

AccessorMutatorDefaultDescription
allow_set()with_allow_set(Bool)trueEnable {...} set literal and {x for x in ...} set comprehension syntax (mbt extension — starlark-go rejects this syntax). The set() built-in is spec-standard and always available regardless of this flag.
allow_lambda()with_allow_lambda(Bool)trueEnable lambda expressions
allow_bytes()with_allow_bytes(Bool)trueEnable bytes literals (b"...")
allow_float()with_allow_float(Bool)trueEnable float literals and float arithmetic

Non-standard extensions — disabled by default:

AccessorMutatorDefaultDescription
allow_recursion()with_allow_recursion(Bool)falseAllow recursive function calls (the spec forbids recursion)
allow_while()with_allow_while(Bool)falseEnable while loops
allow_top_level_control()with_allow_top_level_control(Bool)falseAllow if/for/while at module scope
allow_global_reassign()with_allow_global_reassign(Bool)falseAllow re-assigning module-level names
load_binds_globally()with_load_binds_globally(Bool)falseload imports are visible module-wide

Each with_* mutator returns a modified copy, so flags can be chained.

///|
test {
let opts = @eval.Options::default()
assert_eq(opts.allow_set(), true)
assert_eq(opts.allow_float(), true)
assert_eq(opts.allow_while(), false)
assert_eq(opts.allow_top_level_control(), false)
assert_eq(opts.allow_global_reassign(), false)
assert_eq(opts.load_binds_globally(), false)
}


#Module

The result of a successful exec_file call. Its globals dict is frozen on return.

MethodSignatureDescription
Module::new()-> ModuleEmpty unfrozen module
Module::from_map(Map[String, @value.Value])-> ModuleConstruct from a map (for testing)
get(String)-> @value.Value?Look up a global by name
global_names()-> Array[String]Names of all defined globals
globals_count()-> IntNumber of defined globals
predeclared_names()-> Array[String]Names of predeclared bindings
predeclared_count()-> IntNumber of predeclared bindings
is_frozen()-> BoolAlways true after exec_file returns
freeze()-> UnitFreeze the module manually (rarely needed)


#Program

A parsed-and-resolved Starlark program that can be executed multiple times without re-parsing. Unlike exec_file, Program::init does not freeze the returned module.

Program::write() -> Bytes serializes a compiled program so it can be persisted and reloaded with compiled_program. The format is not byte-compatible with starlark-go.

MethodSignatureDescription
filename()() -> StringSource file name used during compilation
num_loads()() -> IntNumber of load statements in the file
load(Int)(Int) -> (String, @errors.Position)Path and position of the i-th load statement
options()() -> OptionsThe dialect options the program was resolved with
init(Thread, Predeclared)-> Result[Module, @errors.EvalError]Execute the program and return an unfrozen module
write()() -> BytesSerialize the resolved program for later reload


#Predeclared and Universe

Predeclared holds extra bindings injected before user globals; scripts can read but not reassign them. Universe is the predeclared built-in environment shared across all threads.

Constructor / MethodPredeclaredUniverse
Empty constructorPredeclared::new()Universe::new()
From mapPredeclared::from_map(Map[String, Value])Universe::from_map(Map[String, Value])
Standard builtinsUniverse::standard()
get(String) -> Value?Look up a nameLook up a built-in
set(String, Value)Add or replaceAdd or replace
has(String) -> BoolMembership testMembership test
delete(String) -> BoolRemove; returns whether presentRemove; returns whether present
keys() -> Array[String]All bound namesAll built-in names
values() -> Array[Value]All bound valuesAll built-in values
each((String, Value) -> Unit)Iterate all pairsIterate all pairs


#Intentional extensions and dialect differences

The following behaviours differ from starlark-go by design.

#Set literal and set comprehension syntax

mbt accepts {1, 2, 3} (set literal) and {x for x in iterable} (set comprehension) as valid Starlark syntax that evaluates to a set. starlark-go rejects both forms with a parse error because the Starlark spec defines no set literal grammar.

The set() constructor (e.g., set([1, 2, 3])) is spec-standard and is supported by both implementations. The {...} notation is a mbt extension gated by allow_set (enabled by default). Scripts that disable allow_set are restricted to the spec-standard constructor form.

#Recursive-traversal depth guards

mbt enforces explicit depth limits on every recursive traversal path as a safety hardening measure, preventing native stack overflow on deeply-nested input. starlark-go relies on goroutine-stack growth and has no hard cap.

PathLimitDetails
Parser expression nesting80Raises a parse error; internal/parser is an internal package with no public README
repr / str / print value nesting200See value/README.mbt.md
json.encode / json.decode nesting10 000See lib/json/README.mbt.md

Exceeding any limit raises a Starlark runtime or parse error rather than crashing the process.

#Spell-hint on unexpected keyword argument

When a function call passes an unrecognised keyword argument, the error message includes a spell-hint:

function f got an unexpected keyword argument "nme" (did you mean name?)

The suggestion uses Levenshtein edit distance with a 50% threshold (mirroring starlark-go's spell.Nearest). mbt uses all declared parameter names as candidates; starlark-go considers only the first ⌈nparams/2⌉ due to a known bug in UnpackArgs's candidate-collection loop. This is a quality-of-life extension; it does not affect correctness or accepted syntax.

#(1 << 31) in range(0, 1 << 32) returns True

starlark-go evaluates this as False because rangeValue.contains calls AsInt32 to classify the needle, and AsInt32 returns an error for any value outside the signed 32-bit range. 1<<31 = 2,147,483,648 exceeds math.MaxInt32, causing AsInt32 to return an out-of-range error; contains treats any such error as "not in range" and returns false without evaluating the bounds. This implementation performs the containment check with full Int64 precision, returning True.


#DebugFrame

A read-only snapshot of an active Starlark call frame. Obtain via Thread::debug_frame(depth).

MethodReturnsDescription
callable()@value.ValueThe Function or Builtin executing in this frame
num_locals()IntTotal number of local variables
frame_local(Int)(@errors.Binding, @value.Value?)Binding descriptor and current value of the i-th local
local_by_name(String)@value.Value?Current value of the named local; None if absent
position()@errors.PositionCurrent execution position within the frame (stub: always returns an invalid position)

#
DebugFrame

pub struct DebugFrame {
// private fields
}

A snapshot of a single Starlark call frame for debugger inspection. Obtained via Thread::debug_frame(depth).

#
DebugFrame::callable

Returns the callable value (Function or Builtin) that owns this frame.

Returns the Value representing the function or builtin being executed in this frame.

#
DebugFrame::frame_local

Returns the binding descriptor and current value of the i-th local. The value is None if the local has not yet been assigned.

Parameters:

  • self : The debug frame to inspect.
  • i : Zero-based index into the frame's local variable list.

Returns a tuple of the Binding descriptor (name and declaration position) and the current value of that local, or None if it has not been assigned.

#
DebugFrame::local_by_name

fn DebugFrame::local_by_name(self : DebugFrame, name : String) ->
Value
?

Returns the current value of the local variable named name, or None if the name is absent or the variable has not yet been assigned.

Parameters:

  • self : The debug frame to inspect.
  • name : The name of the local variable to look up.

Returns the current Value of the named local, or None if the name is not found or the variable has not yet been assigned.

#
DebugFrame::num_locals

fn DebugFrame::num_locals(self : DebugFrame) -> Int

Returns the number of local variables (parameters + body locals) in this frame.

Returns the total count of named locals, including both function parameters and variables declared in the function body.

#
DebugFrame::position

Returns the source position of the current execution point within this frame.

Returns the Position indicating where execution is currently paused inside this call frame.

#
Module

pub struct Module {
// private fields
}

The result of executing a Starlark file: a frozen mapping of global names to their values, plus any injected predeclared bindings.

#
Module::freeze

fn Module::freeze(self : Module) -> Unit

Freezes the module: marks the globals dict and all contained values as immutable so they can safely be shared across threads.

#
Module::freeze_checked

fn Module::freeze_checked(self : Module) -> Result[Unit, String]

Like Module::freeze but returns Err instead of aborting when the nesting depth limit is exceeded.

#
Module::from_map

Creates a frozen Module pre-populated from m.

Aborts (rather than returning an error) if any value in m is nested beyond freeze_limit. This is acceptable for static, shallow maps such as built-in library exports. For user-supplied code, use the exec_file* entry points, which call Module::freeze_checked and propagate depth errors as a EvalError.

Parameters:

  • m : A map of global name strings to their initial values.

Returns a new, frozen Module containing the bindings from m.

#
Module::get

fn Module::get(self : Module, name : String) ->
Value
?

Returns the value bound to name in the module globals, or None.

Parameters:

  • self : The module to look up in.
  • name : The global name to retrieve.

Returns Some(value) if name is present, None otherwise.

#
Module::global_names

fn Module::global_names(self : Module) -> Array[String]

Returns the names of all exported globals in insertion order.

Returns an Array[String] of every global name bound in the module.

#
Module::globals_count

fn Module::globals_count(self : Module) -> Int

Returns the number of exported globals in the module.

#
Module::is_frozen

fn Module::is_frozen(self : Module) -> Bool

Returns true if this module has been frozen.

#
Module::new

fn Module::new() -> Module

Creates an empty, unfrozen Module.

#
Module::predeclared_count

fn Module::predeclared_count(self : Module) -> Int

Returns the number of predeclared bindings injected before execution.

#
Module::predeclared_names

fn Module::predeclared_names(self : Module) -> Array[String]

Returns the names of all predeclared bindings that were injected before execution.

Returns an Array[String] of every predeclared name.

#
Options

pub struct Options {
// private fields
}

Feature-flag set controlling which optional Starlark dialect features are enabled. The default dialect is spec-conformant: the standard features allow_set, allow_lambda, allow_bytes, and allow_float default to true, while the non-standard extensions allow_recursion, allow_while, allow_top_level_control, allow_global_reassign, and load_binds_globally default to false — matching starlark-go's zero-value FileOptions for the extensions. The one intentional divergence is allow_set: starlark-go's zero value still has Set = false, but allow_set here controls only the {...} set literal and {x for x in ...} set comprehension syntax (mbt extensions not in the spec). The set() built-in is part of the Starlark spec and is always available regardless of this flag.

#
Options::allow_bytes

fn Options::allow_bytes(self : Options) -> Bool

Returns true if bytes literals and the bytes() builtin are allowed.

#
Options::allow_float

fn Options::allow_float(self : Options) -> Bool

Returns true if floating-point literals and float arithmetic are allowed.

#
Options::allow_global_reassign

fn Options::allow_global_reassign(self : Options) -> Bool

Returns true if module-level globals may be reassigned after their initial binding.

#
Options::allow_lambda

fn Options::allow_lambda(self : Options) -> Bool

Returns true if lambda expressions are allowed.

#
Options::allow_recursion

fn Options::allow_recursion(self : Options) -> Bool

Returns true if recursive function calls are allowed at runtime.

#
Options::allow_set

fn Options::allow_set(self : Options) -> Bool

Returns true if {...} set literals and set comprehensions are allowed.

#
Options::allow_top_level_control

fn Options::allow_top_level_control(self : Options) -> Bool

Returns true if if, for, and while statements are allowed at the module (top) level.

#
Options::allow_while

fn Options::allow_while(self : Options) -> Bool

Returns true if while loops are allowed.

#
Options::default

fn Options::default() -> Options

Returns the default Options: the spec-conformant Starlark dialect. The standard features (allow_set, allow_lambda, allow_bytes, allow_float) are enabled; the non-standard extensions (allow_recursion, allow_while, allow_top_level_control, allow_global_reassign, load_binds_globally) are disabled and must be opted into explicitly, matching starlark-go's zero-value FileOptions for those extensions. allow_set intentionally diverges from that zero value (Set = false) because the {...} literal and comprehension syntax is a useful mbt extension. The set() built-in itself is always available and is not controlled by this flag.

test {
let opts = Options::default()
// Standard features are on.
inspect(opts.allow_float(), content="true")
inspect(opts.allow_lambda(), content="true")
// Non-standard extensions are off.
inspect(opts.allow_recursion(), content="false")
inspect(opts.allow_while(), content="false")
}

#
Options::load_binds_globally

fn Options::load_binds_globally(self : Options) -> Bool

Returns true if load-imported names are bound at module (global) scope rather than file-local scope.

#
Options::with_allow_bytes

fn Options::with_allow_bytes(self : Options, v : Bool) -> Options

Returns a copy of self with allow_bytes set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_bytes flag.

Returns a new Options with the allow_bytes flag set to v.

test {
let opts = Options::default().with_allow_bytes(false)
inspect(opts.allow_bytes(), content="false")
// Other flags are unchanged.
inspect(opts.allow_recursion(), content="false")
}

#
Options::with_allow_float

fn Options::with_allow_float(self : Options, v : Bool) -> Options

Returns a copy of self with allow_float set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_float flag.

Returns a new Options with the allow_float flag set to v.

test {
let opts = Options::default().with_allow_float(false)
inspect(opts.allow_float(), content="false")
// Other flags are unchanged.
inspect(opts.allow_lambda(), content="true")
}

#
Options::with_allow_global_reassign

fn Options::with_allow_global_reassign(self : Options, v : Bool) -> Options

Returns a copy of self with allow_global_reassign set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_global_reassign flag.

Returns a new Options with the allow_global_reassign flag set to v.

test {
let opts = Options::default().with_allow_global_reassign(true)
inspect(opts.allow_global_reassign(), content="true")
// Other flags are unchanged.
inspect(opts.allow_float(), content="true")
}

#
Options::with_allow_lambda

fn Options::with_allow_lambda(self : Options, v : Bool) -> Options

Returns a copy of self with allow_lambda set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_lambda flag.

Returns a new Options with the allow_lambda flag set to v.

test {
let opts = Options::default().with_allow_lambda(false)
inspect(opts.allow_lambda(), content="false")
// Other flags are unchanged.
inspect(opts.allow_recursion(), content="false")
}

#
Options::with_allow_recursion

fn Options::with_allow_recursion(self : Options, v : Bool) -> Options

Returns a copy of self with allow_recursion set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_recursion flag.

Returns a new Options with the allow_recursion flag set to v.

test {
let opts = Options::default().with_allow_recursion(true)
inspect(opts.allow_recursion(), content="true")
// Other flags are unchanged.
inspect(opts.allow_float(), content="true")
}

#
Options::with_allow_set

fn Options::with_allow_set(self : Options, v : Bool) -> Options

Returns a copy of self with allow_set set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_set flag.

Returns a new Options with the allow_set flag set to v.

test {
let opts = Options::default().with_allow_set(false)
inspect(opts.allow_set(), content="false")
// Other flags are unchanged.
inspect(opts.allow_recursion(), content="false")
}

#
Options::with_allow_top_level_control

fn Options::with_allow_top_level_control(self : Options, v : Bool) -> Options

Returns a copy of self with allow_top_level_control set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_top_level_control flag.

Returns a new Options with the allow_top_level_control flag set to v.

test {
let opts = Options::default().with_allow_top_level_control(true)
inspect(opts.allow_top_level_control(), content="true")
// Other flags are unchanged.
inspect(opts.allow_float(), content="true")
}

#
Options::with_allow_while

fn Options::with_allow_while(self : Options, v : Bool) -> Options

Returns a copy of self with allow_while set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the allow_while flag.

Returns a new Options with the allow_while flag set to v.

test {
let opts = Options::default().with_allow_while(true)
inspect(opts.allow_while(), content="true")
// Other flags are unchanged.
inspect(opts.allow_float(), content="true")
}

#
Options::with_load_binds_globally

fn Options::with_load_binds_globally(self : Options, v : Bool) -> Options

Returns a copy of self with load_binds_globally set to v.

Parameters:

  • self : The options to copy.
  • v : The new value for the load_binds_globally flag.

Returns a new Options with the load_binds_globally flag set to v.

test {
let opts = Options::default().with_load_binds_globally(true)
inspect(opts.load_binds_globally(), content="true")
// Other flags are unchanged.
inspect(opts.allow_set(), content="true")
}

#
Predeclared

pub struct Predeclared {
// private fields
}

Per-execution extra bindings injected before user globals. Visible to both the resolver and evaluator but not exported in the resulting Module.

#
Predeclared::delete

fn Predeclared::delete(self : Predeclared, name : String) -> Bool

Removes the binding for name.

Parameters:

  • self : The predeclared set to modify.
  • name : The name to remove.

Returns true if name was present (and removed), false if absent.

#
Predeclared::each

fn Predeclared::each(self : Predeclared, f : (String,
Value
) -> Unit) -> Unit

Calls f(name, value) for every binding in the set.

Parameters:

  • self : The predeclared set to iterate.
  • f : Callback receiving each name and its bound value.

#
Predeclared::from_map

Creates a Predeclared set wrapping an existing map.

Parameters:

  • m : The map to wrap; keys are name strings, values are the bindings.

Returns a Predeclared backed by m.

#
Predeclared::get

Returns the value bound to name, or None.

Parameters:

  • self : The predeclared set to look up in.
  • name : The name to retrieve.

Returns Some(value) if name is present, None otherwise.

#
Predeclared::has

fn Predeclared::has(self : Predeclared, name : String) -> Bool

Returns true if name is present in the predeclared set.

Parameters:

  • self : The predeclared set to query.
  • name : The name to test for presence.

Returns true if name exists in the set.

#
Predeclared::keys

fn Predeclared::keys(self : Predeclared) -> Array[String]

Returns the predeclared names in lexicographic order.

Parameters:

  • self : The predeclared set whose names to retrieve.

Returns an array of all names sorted lexicographically.

#
Predeclared::new

Creates an empty Predeclared set.

#
Predeclared::set

fn Predeclared::set(self : Predeclared, name : String, v :
Value
) -> Unit

Adds or replaces the binding for name.

Parameters:

  • self : The predeclared set to modify.
  • name : The name to bind.
  • v : The value to associate with name.

#
Predeclared::values

Returns all bound values in the set.

Parameters:

  • self : The predeclared set whose values to retrieve.

Returns an array of all bound values.

#
Program

pub struct Program {
// private fields
}

A parsed and resolved Starlark source file. Execute via init; parsing and resolution costs are paid once. A Program may be init'd multiple times with different predeclared dictionaries.

#
Program::filename

fn Program::filename(self : Program) -> String

Returns the source filename recorded in the program.

Returns the filename string that was supplied when the program was created.

#
Program::init

fn Program::init(self : Program, thread : Thread, predeclared : Predeclared) -> Result[Module,
EvalError
]

Executes the program with the given predeclared bindings, returning an unfrozen Module. Unlike exec_file, does not freeze the module on return. May be called multiple times with different predeclared dictionaries.

Parameters:

  • self : The resolved program to execute.
  • thread : The thread context that carries the call stack and load handler.
  • predeclared : The set of predeclared name–value bindings visible to the program during execution.

Returns an unfrozen Module whose globals are the top-level bindings produced by the execution, or an EvalError if execution fails.

#
Program::load

fn Program::load(self : Program, i : Int) -> (String,
Position
)

Returns the path string and source position of the i-th load statement. Returns an empty string and unknown position if i is out of range.

Parameters:

  • self : The program whose load statements are queried.
  • i : Zero-based index of the load statement to retrieve.

Returns a tuple of the module path string and the source position of that load statement, or an empty string and unknown position if i is out of range.

#
Program::num_loads

fn Program::num_loads(self : Program) -> Int

Returns the number of load(...) statements in the program.

Returns the count of top-level load statements found in the program.

#
Program::options

fn Program::options(self : Program) -> Options

Returns the file-level dialect options this program was resolved with. These options are bound to the program (and survive serialization), so a Program plays the role starlark-go assigns to a file's FileOptions: per-file, immutable dialect configuration rather than global flags.

#
Program::write

fn Program::write(self : Program) -> Bytes

Serializes this program to a self-describing byte sequence that compiled_program can reload without re-parsing, re-resolving, or re-compiling the source. The encoding holds the compiled bytecode program plus the program's options; it is specific to this implementation and is NOT compatible with starlark-go's Program.Write format.

#
Thread

pub struct Thread {
// private fields
}

Execution context for a single Starlark evaluation. Carries the print and load callbacks, call stack, recursion limit, step budget, and cancellation state. A Thread is not safe for concurrent use.

#
Thread::call_frame

Returns the call frame at n steps from the innermost frame (0 = innermost, 1 = its caller, etc.), or None if out of range.

Parameters:

  • self : The thread whose call stack to inspect.
  • n : Distance from the innermost frame (0 = innermost).

Returns Some(frame) if the index is valid, None otherwise.

#
Thread::call_stack

Returns a snapshot of the current call stack (outermost frame first).

#
Thread::call_stack_depth

fn Thread::call_stack_depth(self : Thread) -> Int

Returns the current call-stack depth (number of active Starlark frames).

#
Thread::cancel

fn Thread::cancel(self : Thread, reason : String) -> Unit

Marks the thread as cancelled with the given reason. The evaluator checks this flag at each step and raises an error on the next opportunity. Only the first call takes effect.

Parameters:

  • self : The thread to cancel.
  • reason : A message describing why the thread was cancelled; used in the raised error.

#
Thread::debug_frame

fn Thread::debug_frame(self : Thread, depth : Int) -> DebugFrame?

Returns a snapshot of the active Starlark call frame at depth steps from the innermost frame (0 = innermost). Returns None if depth is out of range or the frame is not a Starlark function frame.

Parameters:

  • self : The thread whose debug call stack to inspect.
  • depth : Distance from the innermost Starlark function frame (0 = innermost).

Returns Some(frame) if a Starlark frame exists at that depth, None otherwise.

#
Thread::execution_steps

fn Thread::execution_steps(self : Thread) -> Int

Returns the total number of evaluation steps executed on this thread.

#
Thread::get_local

fn Thread::get_local(self : Thread, key : String) ->
Value
?

Retrieves the thread-local value previously stored under key, or None.

Parameters:

  • self : The thread to retrieve from.
  • key : The key identifying the thread-local slot.

Returns Some(value) if a value was stored under key, None otherwise.

#
Thread::max_recursion_depth

fn Thread::max_recursion_depth(self : Thread) -> Int

Returns the maximum call-stack depth before a recursion-limit error is raised.

#
Thread::max_steps

fn Thread::max_steps(self : Thread) -> Int?

Returns the current step budget, or None if no budget was set.

#
Thread::name

fn Thread::name(self : Thread) -> String

Returns the name the thread was created with.

#
Thread::new

fn Thread::new(name : String) -> Thread

Creates a Thread with the given name, printing to stdout, no loader, and the default recursion depth limit.

Parameters:

  • name : A label for the thread used in diagnostics.

Returns a new Thread ready for Starlark execution.

#
Thread::reset_steps

fn Thread::reset_steps(self : Thread) -> Unit

Resets the accumulated step counter to zero without changing the budget.

#
Thread::set_loader

fn Thread::set_loader(self : Thread, load_fn : (Thread, String) -> Result[Module,
EvalError
]) -> Unit

Replaces the load callback used by load() statements.

Parameters:

  • self : The thread to update.
  • load_fn : The new load callback; receives the active thread and the module path, returns the loaded module or an error.

#
Thread::set_local

fn Thread::set_local(self : Thread, key : String, value :
Value
) -> Unit

Stores a thread-local value under key. Used by extension libraries (e.g. time.now()) to communicate per-thread state such as clock overrides.

Parameters:

  • self : The thread to store the value on.
  • key : The key identifying this thread-local slot.
  • value : The value to store.

#
Thread::set_max_steps

fn Thread::set_max_steps(self : Thread, max : Int) -> Unit

Sets the execution-step budget without resetting the accumulated step count. Use reset_steps to zero the counter explicitly.

Parameters:

  • self : The thread to update.
  • max : The new maximum step count.

#
Thread::set_on_max_steps

fn Thread::set_on_max_steps(self : Thread, cb : (Thread) -> Unit) -> Unit

Registers a callback invoked when the step budget is exhausted, before the error is raised.

Parameters:

  • self : The thread to update.
  • cb : The callback to invoke when the step budget is exhausted.

#
Thread::set_print

fn Thread::set_print(self : Thread, print_fn : (Thread, Bytes) -> Unit) -> Unit

Replaces the print callback. Combined with set_loader and set_max_steps, this lets a single thread carry all three settings.

Parameters:

  • self : The thread to update.
  • print_fn : The new print callback; receives the active thread and the formatted message bytes (without trailing newline).

#
Thread::uncancel

fn Thread::uncancel(self : Thread) -> Unit

Clears a previous cancellation, allowing execution to resume.

#
Thread::with_loader

fn Thread::with_loader(name : String, load_fn : (Thread, String) -> Result[Module,
EvalError
]) -> Thread

Creates a Thread with a load callback for load() statements.

Parameters:

  • name : A label for the thread used in diagnostics.
  • load_fn : Callback invoked for each load("path", ...) statement; receives the active thread and the module path, returns the loaded module.

Returns a new Thread with the given load callback.

#
Thread::with_print

fn Thread::with_print(name : String, print_fn : (Thread, Bytes) -> Unit) -> Thread

Creates a Thread with a custom print callback.

Parameters:

  • name : A label for the thread used in diagnostics.
  • print_fn : Callback invoked for each print() call; receives the active thread and the formatted message bytes (without trailing newline).

Returns a new Thread with the given print callback.

#
Thread::with_step_budget

fn Thread::with_step_budget(name : String, max_steps : Int) -> Thread

Creates a Thread with a maximum step budget; execution raises an error when the budget is exhausted.

Parameters:

  • name : A label for the thread used in diagnostics.
  • max_steps : Maximum number of evaluation steps before the execution is cancelled with an error.

Returns a new Thread with the given step budget.

#
Universe

pub struct Universe {
// private fields
}

The set of predeclared built-in bindings shared across all modules. Universe::standard() provides the default Starlark built-ins; embedders may extend it with set().

#
Universe::delete

fn Universe::delete(self : Universe, name : String) -> Bool

Removes the binding for name.

Parameters:

  • self : The universe to modify.
  • name : The name to remove.

Returns true if name was present (and removed), false if absent.

#
Universe::each

fn Universe::each(self : Universe, f : (String,
Value
) -> Unit) -> Unit

Calls f(name, value) for every binding in the universe.

Parameters:

  • self : The universe to iterate.
  • f : Callback receiving each name and its bound value.

#
Universe::from_map

Creates a Universe wrapping an existing binding map.

Parameters:

  • m : The map to wrap; keys are name strings, values are the bindings.

Returns a Universe backed by m.

#
Universe::get

fn Universe::get(self : Universe, name : String) ->
Value
?

Returns the value bound to name in the universe, or None.

Parameters:

  • self : The universe to look up in.
  • name : The predeclared name to retrieve.

Returns Some(value) if name is present, None otherwise.

#
Universe::has

fn Universe::has(self : Universe, name : String) -> Bool

Returns true if name is present in the universe.

Parameters:

  • self : The universe to query.
  • name : The name to test for presence.

Returns true if name exists in the universe.

#
Universe::keys

fn Universe::keys(self : Universe) -> Array[String]

Returns the predeclared names in lexicographic order.

Parameters:

  • self : The universe whose names to retrieve.

Returns an array of all names sorted lexicographically.

#
Universe::new

fn Universe::new() -> Universe

Creates an empty Universe with no predeclared names.

#
Universe::set

fn Universe::set(self : Universe, name : String, value :
Value
) -> Unit

Adds or replaces the binding for name in the universe.

Parameters:

  • self : The universe to modify.
  • name : The predeclared name to bind.
  • value : The value to associate with name.

#
Universe::standard

fn Universe::standard() -> Universe

Creates a Universe pre-populated with all standard Starlark built-ins (None, True, False, print, range, etc.).

#
Universe::values

Returns all bound values in the universe.

Parameters:

  • self : The universe whose values to retrieve.

Returns an array of all bound values.

#
binary

Applies a Starlark binary operator by name to x and y. Valid operators: "+", "-", "*", "/", "//", "%", "&", "|", "^", "<<", ">>".

Parameters:

  • op : The binary operator name.
  • x : The left-hand operand.
  • y : The right-hand operand.

Returns the operation result, or an EvalError on type mismatch or arithmetic error.

#
call

Invokes a Starlark callable from host code with positional args and keyword kwargs.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • func : The Starlark callable to invoke (function, builtin, or bound method).
  • args : Positional arguments to pass.
  • kwargs : Keyword arguments as (name, value) pairs.

Returns the call result, or an EvalError on failure.

#
compare

Applies a Starlark comparison operator by name to x and y. Valid operators: "==", "!=", "<", "<=", ">", ">=".

Parameters:

  • op : The comparison operator name.
  • x : The left-hand operand.
  • y : The right-hand operand.

Returns Ok(result) on success, or an EvalError on type mismatch.

#
compiled_program

fn compiled_program(data : Bytes) -> Result[Program,
EvalError
]

Reconstructs a Program from bytes produced by Program::write. The input is trusted to already carry the compiled bytecode program: neither resolution nor compilation is re-run during decode (re-resolution would require the original is_predeclared predicate), so the bytes hydrate straight into a runnable CompiledProgram. Returns an EvalError if the bytes are truncated, carry an unknown magic header, or were written by an incompatible serializer version.

#
eval_expr

Parses and evaluates a single Starlark expression with the default options, using env as the global environment.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • filename : Source file name used in error messages and position info.
  • src : Starlark expression source text to evaluate.
  • env : Global environment dict supplying variable bindings.

Returns the evaluated Value, or an EvalError on failure.

test {
let thread = Thread::new("test")
let env = @value.StringDict::new()
// Evaluate an arithmetic expression.
inspect(eval_expr(thread, "<e>", "2 + 3", env).unwrap().repr(), content="5")
// Supply a binding via env.
env.set("n", @value.Value::new_int(10L))
inspect(eval_expr(thread, "<e>", "n * 2", env).unwrap().repr(), content="20")
// An undefined name yields EvalError.
inspect(eval_expr(thread, "<e>", "ghost", env) is Err(_), content="true")
}

#
eval_expr_with_opts

Like eval_expr but accepts explicit opts.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • filename : Source file name used in error messages and position info.
  • src : Starlark expression source text to evaluate.
  • opts : Feature flags controlling which dialect features are active.
  • env : Global environment dict supplying variable bindings.

Returns the evaluated Value, or an EvalError on failure.

#
eval_parsed_expr

Evaluates a pre-parsed expression node under opts with the bindings in env as the global environment.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • expr : Pre-parsed expression AST node to evaluate.
  • opts : Feature flags controlling which dialect features are active.
  • env : Global environment dict supplying variable bindings.

Returns the evaluated Value, or an EvalError on runtime failure.

#
exec_file

fn exec_file(thread : Thread, filename : String, src : String, opts : Options) -> Result[Module,
EvalError
]

Parses, resolves, and executes a Starlark source file; returns the frozen module whose globals are the file's top-level bindings.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • filename : Source file name used in error messages and position info.
  • src : Starlark source text to execute.
  • opts : Feature flags controlling which dialect features are active.

Returns the frozen Module, or an EvalError on parse, resolve, or runtime failure.

test {
let thread = Thread::new("test")
let m = exec_file(thread, "test.star", "x = 1 + 2", Options::default()).unwrap()
inspect(m.get("x").unwrap().repr(), content="3")
// A syntax error yields EvalError.
let err = exec_file(Thread::new("t"), "bad.star", "???", Options::default())
inspect(err is Err(_), content="true")
}

#
exec_file_with_predeclared

fn exec_file_with_predeclared(thread : Thread, filename : String, src : String, opts : Options, predeclared : Predeclared) -> Result[Module,
EvalError
]

Like exec_file but injects extra predeclared bindings that are visible to the script but not included in the returned module's globals.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • filename : Source file name used in error messages and position info.
  • src : Starlark source text to execute.
  • opts : Feature flags controlling which dialect features are active.
  • predeclared : Extra per-execution bindings injected before user globals.

Returns the frozen Module, or an EvalError on failure.

test {
let thread = Thread::new("test")
let pre = Predeclared::from_map({ "base": @value.Value::new_int(10L) })
let m = exec_file_with_predeclared(
thread,
"p.star",
"result = base + 5",
Options::default(),
pre,
).unwrap()
inspect(m.get("result").unwrap().repr(), content="15")
// `base` is predeclared, not exported as a module global.
inspect(m.get("base") is None, content="true")
}

#
exec_file_with_universe

fn exec_file_with_universe(thread : Thread, filename : String, src : String, opts : Options, universe : Universe) -> Result[Module,
EvalError
]

Like exec_file but replaces the default built-in universe with universe, allowing the embedder to override or extend predeclared names.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • filename : Source file name used in error messages and position info.
  • src : Starlark source text to execute.
  • opts : Feature flags controlling which dialect features are active.
  • universe : Custom universe of predeclared bindings to use instead of the standard built-ins.

Returns the frozen Module, or an EvalError on failure.

test {
let thread = Thread::new("test")
let uni = Universe::from_map({ "answer": @value.Value::new_int(42L) })
let m = exec_file_with_universe(
thread,
"u.star",
"x = answer * 2",
Options::default(),
uni,
).unwrap()
inspect(m.get("x").unwrap().repr(), content="84")
// A syntax error yields EvalError.
let err = exec_file_with_universe(
Thread::new("t"),
"bad.star",
"???",
Options::default(),
uni,
)
inspect(err is Err(_), content="true")
}

#
exec_repl_chunk

fn exec_repl_chunk(thread : Thread, filename : String, src : String, globals :
StringDict
, opts : Options) -> Result[Unit,
EvalError
]

Executes one REPL chunk: parses src, resolves it against globals, evaluates it, and writes any new or updated bindings back into globals.

Parameters:

  • thread : Execution context providing print/load callbacks and step budget.
  • filename : Source file name used in error messages and position info.
  • src : Starlark source chunk to execute (may be statements or an expression).
  • globals : Mutable dict that persists global bindings across REPL chunks.
  • opts : Feature flags controlling which dialect features are active.

Returns Ok(()) on success, or an EvalError on failure.

test {
let thread = Thread::new("test")
let globals = @value.StringDict::new()
// First chunk: define x.
exec_repl_chunk(thread, "<repl>", "x = 6", globals, Options::default())
|> Result::unwrap
// Second chunk: x is still visible; bindings accumulate across calls.
exec_repl_chunk(thread, "<repl>", "y = x * 7", globals, Options::default())
|> Result::unwrap
inspect(globals.get("y").unwrap().repr(), content="42")
}

#
file_program

fn file_program(file :
File
, opts : Options, is_predeclared : (String) -> Bool) -> Result[Program,
EvalError
]

Resolves an already-parsed File AST with the given options, returning a Program ready for init. Skips lexing and parsing.

Parameters:

  • file : A previously parsed File AST to resolve.
  • opts : Evaluation options controlling language features.
  • is_predeclared : A predicate that returns true if a given name is provided by the embedder's predeclared environment.

Returns a resolved Program, or an EvalError if name resolution fails.

#
parse_expr

fn parse_expr(filename : String, src : String) -> Result[
Expr
,
EvalError
]

Parses src as a single Starlark expression and returns its AST node.

Parameters:

  • filename : Source file name used in error messages and position info.
  • src : Starlark expression source text to parse.

Returns the parsed @syntax.Expr, or an EvalError on syntax failure.

#
parse_file

fn parse_file(filename : String, src : String) -> Result[
File
,
EvalError
]

Parses src as a Starlark source file and returns its AST.

Parameters:

  • filename : Source file name used in error messages and position info.
  • src : Starlark source text to parse.

Returns the parsed @syntax.File, or an EvalError on syntax failure.

#
source_program

fn source_program(filename : String, src : String, opts : Options, is_predeclared : (String) -> Bool) -> Result[Program,
EvalError
]

Parses and resolves src as a Starlark file named filename, returning an immutable Program on success. is_predeclared answers whether a name is provided by the embedder's predeclared environment.

Parameters:

  • filename : The name used to identify this source file in error messages and stack traces.
  • src : The Starlark source text to parse and resolve.
  • opts : Evaluation options controlling language features.
  • is_predeclared : A predicate that returns true if a given name is provided by the embedder's predeclared environment.

Returns a Program ready for init, or an EvalError if parsing or resolution fails.

#
source_program_with_file

fn source_program_with_file(filename : String, src : String, opts : Options, is_predeclared : (String) -> Bool) -> Result[(
File
, Program),
EvalError
]

Like source_program but also returns the parsed File AST alongside the Program, useful when the caller needs to inspect load statements before executing.

Parameters:

  • filename : The name used to identify this source file in error messages and stack traces.
  • src : The Starlark source text to parse and resolve.
  • opts : Evaluation options controlling language features.
  • is_predeclared : A predicate that returns true if a given name is provided by the embedder's predeclared environment.

Returns a pair of the parsed File AST and the resolved Program, or an EvalError if parsing or resolution fails.

#
unary

Applies a Starlark unary operator by name to x. Valid operators: "+", "-", "~", "not".

Parameters:

  • op : The unary operator name.
  • x : The operand.

Returns the operation result, or an EvalError on type mismatch.