pub fn instantiate(
data: Rc<ModuleData>,
frame: &[Value],
ctx: &Ctx,
) -> Result<Value, Raised>Expand description
Instantiate a compiled module: build its Module
terminal — the environment its item bodies run in — and hand it back as the
Value::Module that is that terminal.
This is where a module gets an identity. The Rc is fresh per call, so two
instantiations of the same ModuleData are distinct objects, and one
instance is equal to itself across accesses. It is also where the module’s
id block is reserved: one bump of the context’s id source covering every
item, so materializing item i can stamp its closure with the stable
id_base + i rather than a fresh id (see materialize_body and
docs/done/2026-08-13_elly-modules-env.md).
frame supplies the module’s outer values, positionally, against the names
ModuleData::frame_names recorded at compile time — the module’s import
signature, filled in. A length mismatch raises .module_arity rather than
going through: it is memory-safe (indices are checked) but silently wrong, so
it is worth catching where the mistake is. A module with no frame takes an
empty slice.
The values are copied into a flat Frame node, which is the
shape a fixed slot list wants. The terminal’s frame is a plain Env, so a
consumer that needs a cons chain instead — recur, whose frame is the
enclosing lexical environment — builds the terminal directly rather than
through here.