pub enum EnvNode {
Cons {
val: Value,
next: Env,
},
Module {
data: Rc<ModuleData>,
id_base: u64,
frame: Env,
},
Frame {
vals: Box<[Value]>,
home: Env,
},
}Expand description
One link of the environment list: a single binding carrying its val inline,
or the frame that terminates the walk. The empty environment is None.
Env is an Option<EnvRef>, utilizing the null-pointer niche to remain
one word wide, avoiding allocation and refcount traffic when ending a chain.
Lambda activations cons one Cons per bound name (zero for binder-less heads);
partial application environments share the consed prefix via Rc.
References are resolved to de Bruijn indices against this list’s shape.
Variants§
Cons
Module
Module instance terminal: carries the item’s module instead of the
empty terminal, allowing Expr::ModItem sibling references to resolve
by walking out (see crate::eval::eval_env). It binds no name and is not
counted by de Bruijn Local indices. Materialized closures capture an
environment ending in this node to keep the module alive.
This node is the module instance; Value::Module is a handle to it,
created by instantiate. M.name runs the body in this environment.
id_base is the module’s reserved ID block: item i stamps its closure
with id_base + i, ensuring M.f == M.f (see materialize_body).
frame is the environment the module was instantiated against (imports,
host prelude, and identities), with slot order fixed by
ModuleData::frame_names. De Bruijn indices walk through this node into
frame without counting the node itself. The frame can be a flat
Frame or a cons chain (recur).
This structure ensures temporal acyclicity: a frame holds only values existing before the frame, and immutability prevents them from pointing back to the frame.
Frame
A closure’s captured frame: values of free variables used by the body,
copied at creation in the order fixed by Lambda::captures. This terminates
the de Bruijn walk: an index beyond the consed cells selects vals[remaining]
(see lookup), allowing references to enclosing scopes to avoid walking
the entire program.
home stores the environment terminal (None or the Module
node) beyond the frame, so ModItem references in the body can still find
the module without new allocations.
Values are stored inline behind the environment’s Rc, making the frame
a single allocation.