diff --git a/docs/roadmap.md b/docs/roadmap.md index e1d5467..7198348 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -265,6 +265,117 @@ clean. Pick the next milestone from P2.)_ exercising the LLM-natural Show-body shape. - context: per-iter journal 2026-05-13-iter-str-concat.md. +- [ ] **\[milestone\]** Stateful islands — bounded mutation for + streaming workloads (`Stateful a b` + `!Mut` effect + `mut` + syntactic block). Adds a sealed mutable-state layer on top of + the pure core: a `Stateful a b` first-class type whose interior + is mutable, whose exterior is a typed callable with `!Mut` in + its effect set, and whose state non-aliasing is enforced by + uniqueness inference at the block boundary. Targets the + online / streaming workload class — rolling indicators, IIR + filters, online aggregates, sensor fusion, online learning — + whose mathematics is "new sample + old state → new state + + output" per step, and which today's pure-functional state- + threading makes ergonomically expensive at scale (multi-record + explicit threading for the canonical sliding-window SMA, no + zero-allocation pipe combinator, growing tuple-state types as + pipelines lengthen). + + **Motivation.** AILang's signature-as-contract thesis is *better* + served by an explicit `Stateful a b` + `!Mut` annotation than by + the implicit-closure-mutation idiom of myc / Lua / JS factory + patterns: the signature tells the truth about time-identity + without the body needing to be read — exactly the LLM-author + correctness affordance AILang exists to deliver, extended to a + workload class it does not yet serve. Decision 10's constraint #3 + forbids *shared* mutable refs (DESIGN.md:1082); it does not + forbid uniqueness-bounded mutation. Lean 4 (`ST`), Roc (`Task`), + Haskell (`ST`/`IO`), and Koka (effects) all use a layered design + of this shape to host exactly this workload. AILang's existing + `own` / `borrow` mode machinery plus its effect-slot architecture + are the foundation; this milestone supplies the layer that sits + on top. + + **Scope (subject to brainstorm refinement).** + - `Stateful a b` as a first-class type — a sealed callable with a + hidden mutable env, externally a typed callable whose effect + set includes `!Mut`. + - `!Mut` effect, the first non-IO / non-Diverge effect; forces + the effect-handler infrastructure forward. + - `mut` block as the syntactic boundary in Form A — outside, + AILang's pure self; inside, `var` / `assign` / mutable arrays / + while-loops legal. + - `var x = expr` + `assign x expr` AST nodes, legal only inside + `mut`. + - Mutable array primitive (`MutArray a`, O(1) index/update under + uniqueness) — co-developed because the ring-buffer use case + that motivates the whole effort has no carrier today. + - `pipe : Stateful a b → Stateful b c → Stateful a c` as a + built-in combinator with zero-allocation lowering — composition + is fusion at codegen, not closure-pair layering at runtime. + - Decision 12 (or amendment to Decision 10) that names + uniqueness-bounded mutation as the legitimate exception to + "no shared mutable refs", and the pure / mutable-island layering + as the architectural shape. + + **Blockers (hard prerequisites + open design questions).** + - *Effect handlers absent.* DESIGN.md:2663 — "No effect + handlers — only the built-in IO and Diverge ops." `!Mut` is the + first non-trivial effect and forces handler infrastructure to + ship. May warrant lifting out as its own prerequisite milestone; + brainstorm decides. + - *Uniqueness inference through `var` captures.* Current + inference operates over the immutable RC graph; mutable + bindings captured by closures need a more powerful pass. Lean 4 + has a known algorithm; AILang does not implement it. + - *No mutable-array primitive.* No `Array a`, no slab container + of any kind in the language today. Separate spec needed inside + this milestone (representation, `own`-only or `borrow`-able, + bounds-checking discipline). + - *`runST`-equivalent escape discharge.* Producing a `Stateful` + that legitimately escapes its `mut` block while proving the + inner state doesn't leak. Haskell's rank-2 trick + (`runST :: (forall s. ST s a) -> a`) is unavailable — + DESIGN.md:1930 confirms higher-rank polymorphism is not + supported. Need an alternative — likely sealed-by-construction + at the factory boundary, or an effect-mode tag that gates + escape. + - *Form A surface design.* Decision 1 forbids macros (source = + data, not text), so `mut` / `var` / `assign` are genuine AST + nodes with round-trip-invariant coverage. Surface needs LLM- + utility validation (does the author reach for `var` / `mut` + unprompted?) before implementation. + - *Codegen for in-place struct-field writes.* `Term::ReuseAs` + today lowers ADT in-place rewrite; no direct mutable struct- + field-write path exists. `crates/ailang-codegen/src/escape.rs` + plus the lowering passes need extension. + - *Boundary escape analysis.* "Interior state doesn't leak" is an + escape analysis specifically over `var` / `ref` values; the + existing pass covers allocations, not mutable cells. + - *Decision-10 status.* Whether to amend Decision 10 inline or + add a Decision 12 that names the mutable-island layer alongside + the pure layer. The latter is probably cleaner — Decision 10 + stays load-bearing for the pure layer, Decision 12 names the + extension and its discipline. + - *Streaming bench corpus.* Current corpus (list_sum, tree_walk, + closure_chain, hof_pipeline) is all pure. Streaming-specific + benches (SMA pipeline, IIR filter, online stats) plus an + external baseline (myc, hand-C, Python/NumPy) need to exist to + validate that the layered design hits the zero-alloc + performance target that myc demonstrates. + - *LLM-utility test.* DESIGN.md §"Feature-acceptance criterion" + is the gate: the surface must produce code an LLM author + naturally writes. Fieldtest after spec, before any code + commits. + + - context: 2026-05-15 chat on the `~/sma_factory.myc` analysis — + myc's stateful-closure-plus-pipe idiom delivers a streaming + workload pattern (3-line SMA factory, 2-line pipeline, zero + runtime allocation per tick) that AILang's pure-only model + cannot match without this layered extension. Pending brainstorm + will produce `docs/specs/-stateful-islands.md` and decide + the effect-handler-prerequisite question. + ## P3 — Ideas - [x] **\[todo\]** `compare_primitives_smoke.ail` counterpart.