pub enum Value {
Undef,
Bool(bool),
Int(i64),
Float(f64),
Str(Arc<String>),
Array(Arc<Vec<Value>>),
Hash(HashMap<String, Value>),
Status(i32),
Ref(Box<Value>),
NativeFn(u16),
Obj(u32),
}Expand description
Core value type — what lives on the stack and in variables.
Designed to be small (1 word tag + 1-2 words payload) so the dispatch loop stays cache-friendly.
Variants§
Undef
No value / uninitialized
Bool(bool)
Boolean (from conditionals, [[ ]], etc.)
Int(i64)
64-bit signed integer
Float(f64)
64-bit float
Str(Arc<String>)
Heap-allocated string (Arc for cheap clone in closures)
Array(Arc<Vec<Value>>)
Ordered array of values.
The payload is Arc<Vec<Value>> so cloning a Value — which the VM
does on every stack push, slot read, and global read — is a refcount
bump instead of a deep copy of the whole sequence. With a bare Vec
any per-element loop that re-loads the container (seq[i] lowered as
“load the collection, then index it”) was O(n) per iteration and so
O(n²) overall.
Semantics are unchanged: arrays are still values, not references.
Every mutation site goes through Value::array_mut /
Arc::make_mut, which copies when the buffer is shared, so a clone
taken before a mutation never observes that mutation. Copy-on-write is
observationally identical to the previous eager deep clone; it just
defers the copy to the writes, which are rare, from the reads, which
are the hot path.
Construct with Value::array rather than the variant directly.
Hash(HashMap<String, Value>)
Key-value associative array
Status(i32)
Exit status code (shell-specific but universal enough)
Ref(Box<Value>)
Reference to another value (for pass-by-reference, nested structures)
NativeFn(u16)
Native function pointer (builtin dispatch)
Obj(u32)
Opaque handle into a frontend object heap (e.g. elisp cons/symbol/vector
cells). The frontend’s extension handler/host owns the pointed-to object;
fusevm just carries the handle through the stack, slots, and globals.
Identity-comparable (the handle is the identity), which is what elisp
eq/setcar need and Array could not provide.
Implementations§
Source§impl Value
impl Value
Sourcepub fn str(s: impl Into<String>) -> Self
pub fn str(s: impl Into<String>) -> Self
Construct a string Value::Str from any type that converts to String.
The payload is wrapped in Arc so clones are cheap.
Sourcepub fn array(v: Vec<Value>) -> Self
pub fn array(v: Vec<Value>) -> Self
Construct an array Value::Array(v). The payload is wrapped in Arc
so subsequent clones of the Value are refcount bumps.
Sourcepub fn as_array(&self) -> Option<&Vec<Value>>
pub fn as_array(&self) -> Option<&Vec<Value>>
Borrow the elements of a Value::Array, or None for any other
variant. Read-only; never copies.
Sourcepub fn array_mut(&mut self) -> Option<&mut Vec<Value>>
pub fn array_mut(&mut self) -> Option<&mut Vec<Value>>
Mutable access to the elements of a Value::Array, copying the buffer
first if it is shared with another Value (copy-on-write). Returns
None for any other variant.
This is the only sanctioned way to mutate an array in place. Going
around it — e.g. Arc::get_mut — would let a mutation become visible
through a clone taken earlier and break the value semantics every
frontend relies on.
Sourcepub fn into_array(self) -> Option<Vec<Value>>
pub fn into_array(self) -> Option<Vec<Value>>
Take the elements of a Value::Array by value, avoiding the copy when
this is the only owner of the buffer. None for any other variant.
Sourcepub fn status(code: i32) -> Self
pub fn status(code: i32) -> Self
Construct a Value::Status(code) — used for $? / pipeline-exit
values so a numeric exit code stays distinguishable from plain
Value::Int(n) in is_truthy / display logic.
Sourcepub fn as_str_cow(&self) -> Cow<'_, str>
pub fn as_str_cow(&self) -> Cow<'_, str>
Coerce to string, borrowing when possible to avoid allocation.
Returns Cow::Borrowed for Str, Undef, Bool, Hash, Ref variants.