Memory Management
NG's runtime model: value semantics, cell-backed references, and an explicit GC-free heap. No garbage collector exists or is planned for the first release.
Runtime values
Every NG value is a Value: integers and floats by value; strings, arrays, tuples, structs, and enums as shared_ptr-backed aggregates; references as (cell, steps) views; opaque tokens for native handles; ranges as (start, end) pairs.
Copy-first value semantics
Copy values deep-copy on bind, call, and return; aggregates never alias through ordinary copies. Affine nominal types move instead, with clone/move expressions making the choice explicit (see References, Moves & Ownership).
References are views, not ownership
ref/ref mut capture the root cell plus place steps; writes through them stay visible after rebinds. They never escape their scope (no returns, no aggregate storage except a recursive enum's own payload), so no lifetime syntax is needed. Loans release at last use (NLL).
Drop
impl Drop runs exactly once per initialized affine value on scope exit, including early returns and block fall-through; partial moves are field-aware so a destructor never double-owns.
The explicit heap (no GC)
The memory module exposes native handles with explicit release and a concrete Box whose Drop frees its cell when the box goes out of scope:
import memory;
fun make() -> i64 {
let mut cell = box(7);
write(ref cell, 9);
return read(ref cell); // cell's Box drops here, freeing the handle
}outstanding() reports live allocations. Generic Box<T>, Gc, Arc, arenas, and new arrive with the runtime-session work; until then, recursive structures use ref-payload enums (List<T>) and native handles.
Interop
Native hosts receive deep-copied Values and return Values; opaque handles cross the boundary as tokens (type X = native;). See C++ Compatibility.