Grasm v1.0.0 Get started

Learn

Ownership tiers

Most languages pick one memory model for everything. Grasm gives four and lets the value decide, so the common case stays simple and the hard case stays possible.

TierWhat it isCosts
0 — borrowThe default. A parameter borrows; the caller keeps the value.Nothing.
1 — regionA scope nothing allocated inside may outlive.Nothing at the boundary; the guarantee is checked.
2 — ref TA generational reference into a shared heap. Copies freely, stores in a struct, forms cycles.One allocation; a generation check on use.
3 — unsafeThe explicit escape, and an effect in the row.You are on your own, and the type says so.

Tier 2 in practice

let counter = ref(0)
counter.value += 1

let same = counter          // a reference is a word: it copies
same.value += 1
print("{counter.value}")    // 2 — both name one slot

release(counter)            // the slot goes back
print("{alive(counter)}")   // false, through every copy of it

Reclamation is manual. A slot returns to the pool when it is released and not before — which is the point of the tier: the lifetime is the program's to state. Releasing twice is not an error, so cleanup order is not something every caller has to track.

Tier 1 in practice

let n = region {
    let scratch = build_a_big_thing()
    scratch.len()               // a scalar may leave; an allocation may not
}

Three rules give the guarantee: a region may not write to a binding declared outside it, may not return through its brace, and yields a scalar or nothing. The rule is enforced today; the bulk deallocation it exists to make sound is not yet implemented, and the specification says so rather than implying otherwise.