Problem
A Ref/STRef created and used inside a function compiles to a heap table {value = …}, with reads as .value and writes as .value = …. When the cell never escapes (not returned, not stored in another structure, not captured past its region), the table buys nothing over a plain mutable local, yet every new/read/modify/write pays a table allocation and a field access. This is the companion cost to native loop lowering: a forE accumulating into a local ref allocates the cell once and touches .value twice per iteration.
A non-escaping Ref.new v can emit as local x = v, reads as x, and writes as x = …, keeping the boxed form only when the cell escapes.
Approach
An escape check plus a lowering choice. A cell is unboxable when every use is a direct read/write/modify on the same binding and it never flows anywhere as a whole value. That "never used as a whole value" test is precisely the Capture information from the analysis-lattice issue. When it holds, lower new v to a mutable local, read r to the local, and write v r / modify f r to an assignment; otherwise keep {value = …}.
Prerequisites / Relations
Blocked by #231 (the Complexity/Capture analysis lattice): the escape test is the Capture flag ("used as a whole value" is exactly "escapes"). Strong synergy with the native ST/Effect loop issue: the two together turn a ref-accumulating loop into an allocation-free Lua for. Independent of magicDo.
Verification / Measurement
A function that allocates a local ref, mutates it in a loop, and returns the final read compiles with zero {value=} tables and plain local assignment in golden.lua; the eval golden proves identical output. A cell that escapes (returned or stored) keeps its boxed form, the soundness guard, tested directly. Allocation-counter drop through #172.
Problem
A
Ref/STRefcreated and used inside a function compiles to a heap table{value = …}, with reads as.valueand writes as.value = …. When the cell never escapes (not returned, not stored in another structure, not captured past its region), the table buys nothing over a plain mutable local, yet everynew/read/modify/writepays a table allocation and a field access. This is the companion cost to native loop lowering: aforEaccumulating into a local ref allocates the cell once and touches.valuetwice per iteration.A non-escaping
Ref.new vcan emit aslocal x = v, reads asx, and writes asx = …, keeping the boxed form only when the cell escapes.Approach
An escape check plus a lowering choice. A cell is unboxable when every use is a direct
read/write/modifyon the same binding and it never flows anywhere as a whole value. That "never used as a whole value" test is precisely theCaptureinformation from the analysis-lattice issue. When it holds, lowernew vto a mutable local,read rto the local, andwrite v r/modify f rto an assignment; otherwise keep{value = …}.Prerequisites / Relations
Blocked by #231 (the Complexity/Capture analysis lattice): the escape test is the
Captureflag ("used as a whole value" is exactly "escapes"). Strong synergy with the native ST/Effect loop issue: the two together turn a ref-accumulating loop into an allocation-free Luafor. Independent of magicDo.Verification / Measurement
A function that allocates a local ref, mutates it in a loop, and returns the final read compiles with zero
{value=}tables and plain local assignment ingolden.lua; the eval golden proves identical output. A cell that escapes (returned or stored) keeps its boxed form, the soundness guard, tested directly. Allocation-counter drop through #172.