lambda-ref-cat
Lambda calculus with mutable reference cells and a pure-functional mark-sweep garbage collector, built on comp-cat-rs.
This is spike 2 of a comp-cat-rs reformulation of a web engine targeting Tauri integration. Spike 1 (lambda-cat) showed the idioms hold for a pure interpreter. Spike 2 raises the bar: a heap of mutable cells and a tracing collector, expressed without mut, without Rc/Arc, without RefCell/Cell/Mutex, and without unsafe.
Grammar
expr ::= seq_expr
seq_expr ::= right_expr (";" right_expr)*
right_expr ::= lambda | let | fix | assign_expr
lambda ::= "\" ident "." expr
let ::= "let" ident "=" expr "in" expr
fix ::= "fix" ident "." expr
assign_expr ::= app_expr (":=" right_expr)?
app_expr ::= atom atom*
atom ::= ident | "(" expr ")" | "ref" atom | "!" atom
ident ::= [a-zA-Z_][a-zA-Z0-9_]*
Precedence (loosest to tightest): ;, :=, application, prefix ref/!, atoms.
ref eallocates a fresh cell holding the value ofe, returns the cell's reference.!rdereferencesr, reading the cell's current value.r := vstoresvinto the cellrpoints to, and returnsv.e1 ; e2evaluatese1for effect, then evaluatese2and returns its value.
Usage
#
The mark-sweep collector is available via gc::collect. Tests in this crate exercise it directly to confirm that unreachable cells are freed and reachable cells survive, including across reference cycles.
How it stays pure
- Heap is
BTreeMap<Address, Value>plus a monotonic next-address counter.alloc,store, andretainall return newHeapvalues; the receiver is never mutated. - Evaluator threads
(Value, Heap, Fuel)through every step. Heap changes propagate through the return type, not through interior mutability. - Garbage collector is a pure function from
(roots, heap)to a newheapcontaining only reachable cells. Marking is a fold over reachable addresses; sweeping is aBTreeMap::filtershape implemented via iterator combinators.
Building
RUSTFLAGS="-D warnings"
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.