| Type | Description |
|---|---|
| Value | Union of all Starlark values (None, Bool, Int, Float, String, Bytes, List, Tuple, Dict, Set, Range, Function, Builtin, ExtVal, …) |
| StarlarkString | Immutable UTF-8 string |
| StarlarkList | Mutable, freezable sequence |
| StarlarkDict | Insertion-ordered mutable mapping |
| StarlarkSet | Insertion-ordered mutable hash set |
| StarlarkRange | Lazy integer range |
| StringDict | Host-side Map[String, Value] wrapper (used as eval_expr env) |
| CustomValue | Embedder-defined custom type for Value::ExtVal |
///|
test {
let n = @value.Value::new_int(42L)
let s = @value.Value::new_string("hello")
let lst = @value.Value::new_list([@value.Value::Bool(true), n])
assert_eq(n.type_name(), "int")
assert_eq(s.type_name(), "string")
assert_eq(lst.type_name(), "list")
assert_eq(n.truth(), true)
assert_eq(@value.Value::None.truth(), false)
}///|
test {
let lst = @value.StarlarkList::new([@value.Value::new_int(1L)])
let _ = lst.push(@value.Value::new_int(2L))
assert_eq(lst.length(), 2)
assert_true(lst.get(0) is Some(@value.Value::Int(_)))
lst.freeze()
assert_true(lst.is_frozen())
}///|
test {
let env = @value.StringDict::new()
env.set("x", @value.Value::new_int(10L))
assert_true(env.get("x") is Some(@value.Value::Int(_)))
assert_eq(env.has("y"), false)
}///|
test {
let add = @value.Value::new_builtin("add", fn(_ctx, args, _kw) {
match (args[0], args[1]) {
(@value.Value::Int(a), @value.Value::Int(b)) =>
Ok(@value.Value::Int(a + b))
_ => Err("expected two ints")
}
})
assert_eq(add.type_name(), "builtin_function_or_method")
}///|
pub enum Value {
None
Bool(Bool)
Int(BigInt) // arbitrary-precision integer; use `N` suffix in patterns: `42N`
Float(Double)
String(StarlarkString)
Bytes(Bytes)
List(StarlarkList)
Tuple(Array[Value])
Dict(StarlarkDict)
Set(StarlarkSet)
Range(StarlarkRange)
Function(StarlarkFunction)
Builtin(StarlarkBuiltinFunc)
BoundMethod(StarlarkBoundMethod)
Module(StarlarkModule)
StringElems(StarlarkStringElems) // str.elems()
StringCodepoints(StarlarkStringCodepoints) // str.codepoints()
BytesElems(StarlarkBytesElems) // bytes.elems()
ExtVal(CustomValue) // embedder-defined custom type
}| Method | Signature | Description |
|---|---|---|
| Value::new_int(Int64) | -> Value | Construct an Int value |
| Value::new_float(Double) | -> Value | Construct a Float value |
| Value::new_string(String) | -> Value | Construct a String value |
| Value::new_list(Array[Value]) | -> Value | Construct a List value |
| Value::new_dict() | -> Value | Construct an empty Dict value |
| Value::new_set() | -> Value | Construct an empty Set value |
| Value::new_builtin(String, (BuiltinCallCtx, Array[Value], Array[(String, Value)]) -> Result[Value, String]) | -> Value | Construct a host-provided callable built-in |
| repr() | -> String | repr() form (the Starlark literal) |
| to_str() | -> String | str() form (unquoted for strings) |
| type_name() | -> String | type() name |
| truth() | -> Bool | Truthiness for if/while/and/or |
| starlark_equals(Value) | -> Bool | Structural equality |
| hash() | -> Result[UInt, String] | Hash; Err for unhashable values |
| freeze() | -> Unit | Freeze this value (and, transitively, its contents); aborts on depth overflow |
| freeze_checked() | -> Result[Unit, String] | Like freeze but returns Err on depth overflow |
| Function | Signature | Description |
|---|---|---|
| equal | (Value, Value) -> Result[Bool, String] | Structural equality (depth-capped) |
| len_of | (Value) -> Int64 | Sequence length; returns -1 for non-sequences |
| length_of | (Value) -> Result[Int64, String] | Sequence length; Err for non-sequences |
| iterate | (Value) -> Result[StarlarkIterator, String] | Obtain an iterator over a Starlark iterable |
| number_to_int | (Value) -> Int64? | Convert Int or Float to Int64 |
| as_float | (Value) -> (Double, Bool) | Extract Float or convert Int; second is true on success |
| as_string | (Value) -> (String, Bool) | Extract raw string from String value; second is true on success |
| Symbol | Signature | Description |
|---|---|---|
| compare_limit | Int | Default recursion depth for comparison (value: 10) |
| freeze_limit | Int | Default recursion depth for Value::freeze / freeze_checked (value: 200) |
| hash_limit | Int | Default recursion depth for Value::hash (value: 200) |
| equal_depth | (Value, Value, Int) -> Result[Bool, String] | Equality with explicit depth limit |
| compare_depth | (String, Value, Value, Int) -> Result[Bool, String] | Comparison operator ("==", "<", …) with explicit depth limit |
| hash_value_depth | (Value, Int) -> Result[UInt, String] | Hash with explicit depth limit; use inside CustomValue::with_hash_depth callbacks |
| compare_values | (Value, Value, op? : String) -> Result[Int, String] | Internal / eval-engine only — embedders should use compare_depth instead |
| compare_values_depth | (Value, Value, Int, op? : String) -> Result[Int, String] | Internal / eval-engine only — embedders should use compare_depth instead |
| Symbol | Signature | Description |
|---|---|---|
| repr_limit | Int | Default nesting budget for repr / repr_checked (value: 200) |
| Value::repr | (Value) -> String | Starlark repr() string; aborts on depth overflow |
| Value::repr_checked | (Value) -> Result[String, String] | Like repr but returns Err on depth overflow |
| Value::repr_at_depth | (Value, Int) -> Result[String, String] | repr_checked with an explicit depth budget |
| Method | Signature | Description |
|---|---|---|
| StarlarkString::new(String) | -> StarlarkString | Construct from a MoonBit string |
| StarlarkString::from_bytes(Bytes) | -> StarlarkString | Construct from raw UTF-8 bytes |
| raw() | -> String | The underlying MoonBit string |
| to_bytes() | -> Bytes | UTF-8 byte representation |
| byte_len() | -> Int | Length in bytes |
| byte_at(Int) | -> Byte | The i-th byte |
| equals(StarlarkString) | -> Bool | Byte-wise equality |
| Method | Description |
|---|---|
| StarlarkList::new(Array[Value]) | Construct from an array |
| length() -> Int | Number of elements |
| is_empty() -> Bool | Whether the list has no elements |
| get(Int) -> Value? | Element at index; None if out of range |
| at(Int) -> Value | Element at index (panics if out of range; backs list[i] syntax) |
| set(Int, Value) -> Result[Unit, String] | Replace the element at index |
| push(Value) -> Result[Unit, String] | Append (Err if frozen) |
| insert(Int, Value) -> Result[Unit, String] | Insert at index |
| pop() -> Result[Value?, String] | Remove and return the last element |
| pop_at(Int, String) -> Result[Value, String] | Remove and return the element at index |
| clear() -> Result[Unit, String] | Remove all elements |
| reverse() -> Result[Unit, String] | Reverse in place |
| sort_by((Value, Value) -> Int) -> Result[Unit, String] | Sort in place with a comparator |
| each((Value) -> Unit) | Iterate elements |
| eachi((Int, Value) -> Unit) | Iterate elements with index |
| iter() -> Iter[Value] | Lazy iterator |
| is_frozen() -> Bool | Whether the list is frozen |
| freeze() -> Unit | Freeze the list (and transitively its values) |
| check_mutable(String) -> Result[Unit, String] | Err if frozen or being iterated; verb names the operation |
| Method | Description |
|---|---|
| StarlarkDict::new() | Empty dict |
| set(Value, Value) -> Result[Unit, String] | Insert or replace |
| get(Value) -> Result[Value?, String] | Look up by key (Err if unhashable) |
| contains(Value) -> Result[Bool, String] | Membership test (Err if unhashable) |
| delete(Value) -> Result[Bool, String] | Remove; returns whether present |
| clear() -> Result[Unit, String] | Remove all entries |
| length() -> Int | Number of entries |
| keys() -> Array[Value] | Keys in insertion order |
| each((Value, Value) -> Unit) | Iterate all key–value pairs |
| iter() -> Iter[Value] | Iterator over a snapshot of keys in insertion order |
| entries() -> Iter[(Value, Value)] | Iterator over key–value pairs in insertion order |
| pop_entry(Value) -> Result[Value?, String] | Remove and return the value for a key; None if absent |
| popitem() -> Result[(Value, Value)?, String] | Remove and return the first inserted pair |
| is_frozen() -> Bool | Whether the dict is frozen |
| freeze() -> Unit | Freeze the dict and its contents |
| Method | Description |
|---|---|
| StarlarkSet::new() | Empty set |
| add(Value) -> Result[Unit, String] | Add a member |
| contains(Value) -> Result[Bool, String] | Membership test (Err if unhashable) |
| remove(Value) -> Result[Bool, String] | Remove; returns whether present |
| pop_first() -> Result[Value?, String] | Remove and return the first inserted member |
| clear() -> Result[Unit, String] | Remove all members |
| length() -> Int | Number of members |
| each((Value) -> Unit) | Iterate members in insertion order |
| iter() -> Iter[Value] | Lazy iterator |
| is_frozen() -> Bool | Whether the set is frozen |
| freeze() -> Unit | Freeze the set and its members |
| Method | Signature | Description |
|---|---|---|
| StarlarkRange::new(Int64, Int64, Int64) | -> StarlarkRange | Construct from start, stop, step |
| start() / stop() / step() | -> Int64 | The three range parameters |
| length() | -> Int64 | Number of elements |
| index_at(Int64) | -> Int64 | The value at the i-th position |
| contains(Int64) | -> Bool | Membership test |
| Method | Description |
|---|---|
| StringDict::new() | Empty map |
| StringDict::from_map(Map[String, Value]) | Wrap an existing map |
| set(String, Value) | Add or replace a binding |
| get(String) -> Value? | Look up by key |
| has(String) -> Bool | Test for key presence |
| delete(String) -> Bool | Remove; returns whether present |
| keys() -> Array[String] | Sorted list of keys |
| values() -> Array[Value] | All contained values |
| each((String, Value) -> Unit) | Iterate all key-value pairs |
| freeze() | Transitively freeze all contained values |
| Method | Returns | Description |
|---|---|---|
| name() | String | Function name; "<lambda>" for lambdas |
| position() | @errors.Position | Source position of the def keyword |
| doc() | String | Docstring (first string literal in body); "" if absent |
| num_params() | Int | Total parameter count |
| num_kwonly_params() | Int | Number of keyword-only parameters (after *args) |
| has_varargs() | Bool | Whether the function has a *args parameter |
| has_kwargs() | Bool | Whether the function has a **kwargs parameter |
| param(Int) | (String, @errors.Position) | Name and position of the i-th parameter |
| param_default(Int) | Value? | Default value of the i-th parameter; None if required |
| num_free_vars() | Int | Number of captured (closure) variables |
| free_var(Int) | (String, Value)? | Name and current value of the i-th free variable |
| defining_module() | StarlarkModule? | Module that defined this function |
///|
test {
let thread = @eval.Thread::new("main")
match
@eval.exec_file(
thread,
"lib.star",
"CONST = 99\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return 'hi ' + name",
@eval.Options::default(),
) {
Ok(m) =>
match m.get("greet") {
Some(@value.Value::Function(f)) => {
assert_eq(f.name(), "greet")
assert_eq(f.num_params(), 1)
assert_eq(f.doc(), "Say hello.")
match f.defining_module() {
Some(mod_ref) => assert_true(mod_ref.get("CONST") is Some(_))
None => fail("expected module")
}
}
_ => fail("expected function")
}
Err(e) => fail(e.to_string())
}
}| Type | Constructor | Accessors | Description |
|---|---|---|---|
| StarlarkStringElems | new(StarlarkString, Bool) | source_string(), is_ords() | str.elems(); is_ords=true yields integer ordinals, false yields one-char substrings |
| StarlarkStringCodepoints | new(StarlarkString, Bool) | source_string(), is_ords() | str.codepoints(); is_ords=true yields codepoint integers, false yields substrings |
| StarlarkBytesElems | new(Bytes) | raw_bytes() | bytes.elems(); yields integer byte values |
| Type | Key methods | Description |
|---|---|---|
| StarlarkModule | StarlarkModule::new(String, Map[String, Value]), name(), get(String), attr_names() | Loaded module value (e.g. from load or StarlarkFunction::defining_module) |
| StarlarkIterator | next() -> Value?, done(), collect() -> Array[Value] | Iterator returned by @value.iterate; must call done() even on early exit |
| StarlarkBuiltinFunc | name(), receiver() -> Value?, bind_receiver(Value) | Host-provided callable; build with Value::new_builtin |
| StarlarkBoundMethod | StarlarkBoundMethod::new(Value, String), recv(), method_name() | Method bound to a receiver, e.g. "abc".upper |
| Method | Signature | Description |
|---|---|---|
| BuiltinCallCtx::new((Value, Array[Value], Array[(String, Value)]) -> Result[Value, String], get_local? : (String) -> Value?) | -> BuiltinCallCtx | Construct a call context with an invoke body and optional thread-local reader |
| invoke(Value, Array[Value], Array[(String, Value)]) | -> Result[Value, String] | Call a Starlark callable from within the built-in |
| get_local(String) | -> Value? | Read thread-local state set on the active Thread |
| Trait | Method(s) | Purpose |
|---|---|---|
| Container | has(Value) -> Result[Bool, String] | x in c membership |
| HasAttrs | get_attr(String), attr_names() | Attribute read (x.attr, dir(x)) |
| HasSetField | set_field(String, Value) | Attribute write (x.attr = v) |
| Indexable | indexable_get(Int), indexable_len() | Index read (x[i]) |
| HasSetIndex : Indexable | set_index(Int, Value) | Index write (x[i] = v) |
| Sliceable : Indexable | slice(Int, Int, Int) | Slicing (x[a:b:c]) |
| Mapping | mapping_get(Value), mapping_keys(), mapping_len() | Dict-like key access |
| IterableMapping : Mapping | items() | Key–value enumeration |
| HasBinary | binary_op(String, Value, Bool) | Custom binary operators |
| HasUnary | unary_op(String) | Custom unary operators |
| StarlarkComparable | compare_same_type(Value) | Same-type ordering for sorted/min/max |
| TotallyOrdered | cmp(Value) | Total ordering across comparisons |
| Unpacker (open) | unpack(Value) | Per-argument coercion for @unpack.unpack_args_with |
pub trait Indexable {
fn indexable_get(Self, Int) -> Result[Value, String]
fn indexable_len(Self) -> Int
}pub struct BuiltinCallCtx {
// private fields
}fn BuiltinCallCtx::invoke(self : BuiltinCallCtx, callee : Value, args : Array[Value], kwargs : Array[(String, Value)]) -> Result[Value, String]#internal(unsafe, "eval engine only; not part of the public embedding API")
fn BuiltinCallCtx::new(call : (Value, Array[Value], Array[(String, Value)]) -> Result[Value, String], get_local? : (String) -> Value?) -> BuiltinCallCtx#internal(unsafe, "closure machinery; not part of the public embedding API")
pub struct Cell {
// private fields
}pub struct CustomValue {
// private fields
}fn CustomValue::do_call(self : CustomValue, pos_args : Array[Value], kw_args : Array[(String, Value)]) -> Result[Value, String]?fn CustomValue::do_slice(self : CustomValue, start : Int, stop : Int, step : Int) -> Result[Value, String]?fn CustomValue::get_binary(self : CustomValue, op : String, rhs : Value, is_left : Bool) -> Result[Value, String]?fn CustomValue::get_set_field(self : CustomValue, name : String, v : Value) -> Result[Unit, String]?fn CustomValue::new(type_name_fn : () -> String, truth_fn : () -> Bool, repr_fn : () -> String) -> CustomValuefn CustomValue::with_attrs(self : CustomValue, get_attr_fn : (String) -> Result[Value?, String], attr_names_fn : () -> Array[String]) -> CustomValuefn CustomValue::with_binary(self : CustomValue, binary_fn : (String, Value, Bool) -> Result[Value, String]?) -> CustomValuefn CustomValue::with_call(self : CustomValue, call_fn : (Array[Value], Array[(String, Value)]) -> Result[Value, String]) -> CustomValuefn CustomValue::with_contains(self : CustomValue, contains_fn : (Value) -> Result[Bool, String]) -> CustomValuefn CustomValue::with_equals(self : CustomValue, equals_fn : (Value, Int) -> Result[Bool, String]) -> CustomValuefn CustomValue::with_get_index(self : CustomValue, get_index_fn : (Int) -> Result[Value, String]) -> CustomValuefn CustomValue::with_hash_depth(self : CustomValue, hash_depth_fn : (Int) -> Result[UInt, String]) -> CustomValuefn CustomValue::with_internal_get_attr(self : CustomValue, internal_get_attr_fn : (String) -> Result[Value?, String]) -> CustomValuefn CustomValue::with_items(self : CustomValue, items_fn : () -> Result[Array[(Value, Value)], String]) -> CustomValuefn CustomValue::with_iterate(self : CustomValue, iterate_fn : () -> Result[StarlarkIterator, String]) -> CustomValuefn CustomValue::with_repr_depth(self : CustomValue, repr_depth_fn : (Int) -> Result[String, String]) -> CustomValuefn CustomValue::with_set_field(self : CustomValue, set_field_fn : (String, Value) -> Result[Unit, String]) -> CustomValuefn CustomValue::with_set_index(self : CustomValue, set_index_fn : (Int, Value) -> Result[Unit, String]) -> CustomValuefn CustomValue::with_set_key(self : CustomValue, set_key_fn : (Value, Value) -> Result[Unit, String]) -> CustomValuefn CustomValue::with_slice(self : CustomValue, slice_fn : (Int, Int, Int) -> Result[Value, String]) -> CustomValuefn CustomValue::with_unary(self : CustomValue, unary_fn : (String) -> Result[Value, String]?) -> CustomValuepub struct StarlarkBoundMethod {
// private fields
}pub struct StarlarkBuiltinFunc {
// private fields
}fn StarlarkBuiltinFunc::bind_receiver(self : StarlarkBuiltinFunc, recv : Value) -> StarlarkBuiltinFuncfn StarlarkBuiltinFunc::call_body(self : StarlarkBuiltinFunc, ctx : BuiltinCallCtx, pos_args : Array[Value], kw_args : Array[(String, Value)]) -> Result[Value, String]?#internal(unsafe, "eval engine only; not part of the public embedding API")
fn StarlarkBuiltinFunc::dispatch(name : String) -> StarlarkBuiltinFuncpub struct StarlarkBytesElems {
// private fields
}pub struct StarlarkDict {
// private fields
}pub struct StarlarkFunction {
// private fields
}#internal(unsafe, "bytecode VM only; not part of the public embedding API")
fn StarlarkFunction::compiled_freevars(self : StarlarkFunction) -> Array[Cell]#internal(unsafe, "bytecode VM only; not part of the public embedding API")
fn StarlarkFunction::compiled_funcode(self : StarlarkFunction) -> Funcode?#internal(unsafe, "bytecode VM only; not part of the public embedding API")
fn StarlarkFunction::compiled_module_prog(self : StarlarkFunction) -> CompiledProgram?#internal(unsafe, "bytecode VM only; not part of the public embedding API")
fn StarlarkFunction::compiled_module_slots(self : StarlarkFunction) -> Array[Value?]#internal(unsafe, "bytecode VM only; not part of the public embedding API")
fn StarlarkFunction::defaults(self : StarlarkFunction) -> Array[Value?]#internal(unsafe, "bytecode VM only; not part of the public embedding API")
fn StarlarkFunction::from_compiled(name : String, funcode : Funcode, prog : CompiledProgram, slots : Array[Value?], defaults : Array[Value?], freevars : Array[Cell]) -> StarlarkFunction#internal(unsafe, "eval engine only; not part of the public embedding API")
fn StarlarkFunction::globals(self : StarlarkFunction) -> Map[String, Value]#internal(unsafe, "eval engine only; not part of the public embedding API")
fn StarlarkFunction::new(name : String, pos : Position) -> StarlarkFunctionpub struct StarlarkIterator {
// private fields
}pub struct StarlarkList {
// private fields
}#internal(unsafe, "eval engine only; not part of the public embedding API")
fn StarlarkList::check_mutable(self : StarlarkList, verb : String) -> Result[Unit, String]#internal(unsafe, "eval engine only; not part of the public embedding API")
fn StarlarkList::copy_items(self : StarlarkList) -> Array[Value]#internal(unsafe, "eval engine only; not part of the public embedding API")
fn StarlarkList::pop_at(self : StarlarkList, i : Int, verb : String) -> Result[Value, String]pub struct StarlarkModule {
// private fields
}pub struct StarlarkRange {
// private fields
}pub struct StarlarkSet {
// private fields
}pub struct StarlarkString {
// private fields
}pub struct StarlarkStringCodepoints {
// private fields
}pub struct StarlarkStringElems {
// private fields
}pub struct StringDict {
// private fields
}pub(all) enum Value {
None
Bool(Bool)
Int(BigInt)
Float(Double)
String(StarlarkString)
Bytes(Bytes)
List(StarlarkList)
Tuple(Array[Value])
Dict(StarlarkDict)
Set(StarlarkSet)
Range(StarlarkRange)
Function(StarlarkFunction)
Builtin(StarlarkBuiltinFunc)
BoundMethod(StarlarkBoundMethod)
Module(StarlarkModule)
StringElems(StarlarkStringElems)
StringCodepoints(StarlarkStringCodepoints)
BytesElems(StarlarkBytesElems)
ExtVal(CustomValue)
}test {
let v = Value::new_dict()
inspect(v.repr(), content="{}")
}test {
let v = Value::new_float(1.5)
inspect(v.repr(), content="1.5")
}test {
let v = Value::new_int(42L)
inspect(v.repr(), content="42")
}test {
let v = Value::new_list([Value::Int(1N), Value::Int(2N), Value::Int(3N)])
inspect(v.repr(), content="[1, 2, 3]")
}test {
let v = Value::new_set()
inspect(v.repr(), content="set([])")
}test {
let v = Value::new_string("hello")
inspect(v.repr(), content="\"hello\"")
}test {
inspect(Value::None.repr(), content="None")
inspect(Value::Bool(true).repr(), content="True")
inspect(Value::Int(42N).repr(), content="42")
inspect(Value::new_string("hi").repr(), content="\"hi\"")
// Cyclic list is shown with a placeholder rather than crashing.
let l = StarlarkList::new([Value::Int(0N)])
l.push(Value::List(l)) |> ignore
inspect(Value::List(l).repr().contains("[...]"), content="true")
}test {
inspect(Value::Int(99N).repr_checked().unwrap(), content="99")
// Exceeding the depth limit yields an Err rather than aborting.
let mut v : Value = Value::Int(0N)
for _ in 0..<(repr_limit + 1) {
v = Value::new_list([v])
}
inspect(v.repr_checked() is Err(_), content="true")
}test {
inspect(Value::None.truth(), content="false")
inspect(Value::Int(0N).truth(), content="false")
inspect(Value::new_string("").truth(), content="false")
inspect(Value::Int(1N).truth(), content="true")
inspect(Value::Bool(true).truth(), content="true")
}test {
inspect(Value::None.type_name(), content="NoneType")
inspect(Value::Int(1N).type_name(), content="int")
inspect(Value::Bool(true).type_name(), content="bool")
inspect(Value::new_string("").type_name(), content="string")
}let compare_limit : Intlet dict_key_hash_limit : Intlet freeze_limit : Intlet hash_limit : Int#internal(unsafe, "eval engine only; embedders use len_of")
fn length_of(v : Value) -> Result[Int64, String]let repr_limit : IntThe Starlark configuration language, implemented in Moonbit
Dependencies