Skip to content
BANG

BANG → v1 · North-Star Roadmap

⚠️ K-keyframe roadmap — predates ADR-0016 (third design revision). K0-K3 milestones (effect-row oracle; reference eval; calculated machines) all landed and remain the research narrative. K4+ keyframes have been REPLACED by the two-hop architecture of ADR-0016 (graded-CBPV → CalcVM → WasmFX) and the ◊-checkpoint progression in ROADMAP.md.

READING ORDER: this doc for the research narrative + intellectual lineage; ROADMAP.md for the orchestrator's current map; CLAUDE.mdCONTEXT.md for current state; docs/decisions/0016-*.md for the architecture in force.

Drift from the original:

  • Effect TS / WasmFX as "K5 optional lowerings" gone. WasmFX is the primary compiler target per ADR-0016.
  • Harness retired (TS differential tests deleted with the wasmfx merge; the standing gate is now Bang/Audit.lean per Phase B PROOF_ORDER).
  • oracle-lean/Bang/... paths are now Bang/... (post-flatten; see commit 4a1b7a4).

Keyframes are committed poses (states that must hold). Inbetweens are implementation, drawn later. Proof rides the reference; the shipping path is kept honest by the harness; performance is summoned only when it touches the user; the machine is an output of the calculation, never hand-designed.

Status: K0 locked · K1 done · K2 done (the pure core calculated + proven across 4 increments) · K3 in progress (Throws + State calculated + proven, both composed with the closure/CBN core, both together in one machine — CalcCBNEffSt; and the reification frontier reachedCalcReify, a flat generalised-continuation machine for multi-shot/non-tail handlers, machine + 7 rfl-verified demonstrators, its general theorem the named next step. runState×throw and a user-extensible effect set still open). Eight machines fully proven + the reification machine validated, zero sorrys (asserts only what it proves). Live detail: AGENTS.md "Current playhead".


0 · Locked v0 decisions

#decisionwasnowwhy
D1reactivitylet sig keywordmut + operator: introduces (silent), = updates (notifies subscribers); collapses declare/assign/create-signal/update → 2 operators
D2binding formslet / mut / sig / tvarlet / mut / tvarsig absorbed by D1 → kernel shrinks
D3captureimplicit lexicalexplicit & trackedthunks trivially serializable → distribution + durable exec; deps fully visible; simpler calculated closures
D4canonical targetEffect TS transpile (MVP)calculated VM (owned)own the runtime; correct-by-construction; ecosystem-independent
D5Effect TS / Koka-CPS / WasmFXthe backendoptional K5 loweringsdemoted: foundation → fast-path
D6STMprivileged kernel primitiveunchanged — axiomatized in VM, not derivedjournal/retry/conflict needs runtime support; "everything is a handler" has exactly this one ceiling

Force is $ (prefix); parens group without forcing. Bare name = description; $name = value. ! is freed for actor-send. (Superseded the earlier !-as-force note — see ADR-0007, which is the source of truth.)


1 · Keyframe arc

diagram

frameposeinvariant that holdsprovesrunsstatus
K0model sheetcore semantics in Lean: thunk · $ force · rows-as-sets · 1-shot handlers · STM; D1–D6 baked inmodel sheet typecheckscore programs, interpreted✅ locked
K1oracle speaksreference is executable; unifier verified (Finset semilattice); harness drives candidatesunify_sound; laws inheritedharness · 20k cases green✅ done
K2machine falls outBahr–Hutton derives (compile, Code, exec) from eval; pure core done — arithmetic → let/var → CBV closures → CBN+$force, all proven exec ∘ compile ≡ eval (Calc/CalcHO/CalcCBN)exec ∘ compile ≡ evalcore BANG on owned machine✅ proven (fuel, not partiality monad)
K3effects on the machineper-effect calculated machines: Throws → handler stack + unwinding (CalcEff), State → threaded register (CalcSt), both proven; both composed with the closure/CBN coreCalcCBNEff + CalcCBNSt, and both together in one machine (CalcCBNEffSt, the effect-row model, State persists through a throw), proven; handler stack → config, effect ops → instructions; STM axiomatizedcorrectness over the effect monadeffectful BANG end-to-end🟡 Throws+State proven · composed with closures, proven · both-at-once proven · reification + runState×throw open
K4front end is realparse → typed AST → effect-row inference (on the verified unifier) → core IRinference soundness via oraclereal .bang files
K5fast path (optional)optimized bytecode interp (C/Rust/Zig) and/or calculated lowering → C·Wasm·WasmFX·Effect TS; diff-tested vs execlowering refines execUX-acceptable speed · portable
K6toolchain eats itselfbuild = thunk graph (targets=thunks, deps=R, incremental=content-addressed memo); BANG-nativerebuild ⟺ inputs changedBANG builds BANG
K7v1 / north starsyntax + effect-typed front end + verified core runtime + fast path + native build; harness standingthe chain holds frame→framesomething worth running (HMS constraint-evaluator slice)

2 · Architecture (what depends on what)

diagram

  • Reference (proven): eval → oracle → calculated VM. Changes rarely; no per-session babysitting.
  • Shipping (tested, not proven against): lowerings + front end, kept honest by the harness.
  • Invariant: anything that runs is either exec itself or differential-tested against it.

3 · The calculation (K2–K3 mechanics)

diagram

Staging — each a calculated (compiler, machine) pair; composition gives end-to-end correctness:

  1. Pure core → derive VM for thunk + $ force + application. (template: Calculating Dependently-Typed Compilers, Lean-shaped)
  2. + Effects → swap underlying monad to the effect-row monad. (Monadic Compiler Calculation)
  3. + Divergence → partiality monad + bisimilarity. ⚠ Lean's coinduction is the effortful spot.
  4. + Concurrency/STM → STM as machine primitives, not derived. (Calculating Compilers for Concurrency)
  5. Frontier (post-v1): multi-shot handlers (machine must reify continuations) → defer.

The VM is the output of step 1–4. Pre-committing to a VM design and justifying a compiler against it = CompCert mode = more work, none of the elegance.


4 · Kernel vs library = the VM contract

The design doc's kernel/library split is the machine's primitive/library boundary.

layercontents
kernel (VM must provide natively)thunks · force · application · effect rows + handler dispatch · pattern matching + ADTs · STM (journal, conflict detection, retry)
library (ordinary BANG over the kernel)State/IO/Throws · Reactive+signals · Spawn/Send/Receive+actors · async/await · logging/metrics/tracing · all runtimes (thread pools, event loops, green threads, deterministic schedulers) · all STM-built concurrency (channels, semaphores, futures, queues)

→ K2/K3 acceptance test = "the kernel column is native; the library column compiles to ordinary code."


5 · Effect-row model (already formalized, K1)

conceptmodelLeanlaw source
label setidempotent setFinset ℕ
composeunion = join (= )Mathlib Lattice
emptybottom (= )OrderBot
canonical ⟺ equalextensional eqFinset.extfree (was the F* keystone)
open row ...eset + tail var{ labels, tail : Option RVar }unify

Unification (sound, not principal — MGU deferred to differential test):

  • closed ⋈ closed → equal sets, else fail
  • open ⋈ closed → require open ⊆ closed; bind tail ← closed \ open (closed)
  • open ⋈ open → fresh tail f; bind each tail ← other's diff, tail f

→ This is the answer to the spec's open question "row variables with IO, ...e". We're ahead of the spec on the semantics; only surface syntax + infer-vs-annotate policy remain.


6 · Open forks still live (post-collapse)

forkoptionscurrent lean
capture syntaxC++ [x,&y] / Rust move / Swift [weak]-style listsexplicit list, TBD spelling
serializabilitytracked effect · type-class constraint · content-address-derivedcontent-address-derived
module constantsexplicit-pass vs free-to-referencefree (immutable, content-addressed, cheap to ship)
STM ⊂ reversibility?STM beside vs STM = a built-in reversible regionpost-v1 seam (could absorb D6's exception)
effect inference scopeinfer-all vs infer-internal/annotate-boundariesinfer internal, annotate at module boundary
transaction + IOforbid vs unsafePerformIO-style escapeforbid by default (retry ⇒ IO must be reversible)

7 · Frontier (beyond v1)

  • Reversibility / groupoids. Opt-in reversible effect/region; ops carry inverses. Buys time-travel debugging, undo-as-primitive, clean speculative rollback, bidirectional transforms. → STM becomes a special case of a reversible region with a conflict policy. Potentially simplifies the kernel (one privileged mechanism: reversible regions) rather than special-casing STM. Inverse likely lives in the handler, not the operation (different handlers compensate differently).
  • Distributed eval. Ship bare name (description, small) not $name (value, big); force at the data. Enabled by D3 (no implicit capture → serializable thunks).
  • Native multi-shot handlers. The hard machine extension; reify continuations.

8 · Reading canon — calculating correct compilers

PDFs: cs.nott.ac.uk/~pszgmh/bib.html · bahr.io/pubs. Read 2015 → 2017 → 2021 → 2022 → 2023.

yearpaperwhy for BANG
1967McCarthy & Painter — Correctness of a Compiler for Arithmetic Expressionsthe origin; everything is a reply to it
2004Hutton & Wright — Compiling Exceptions Correctly · Calculating an Exceptional Machinewhere calculate ≠ verify begins (defunctionalization)
2015Bahr & Hutton — Calculating Correct Compilers (JFP 25)the method. start here. Coq-formalized
2016Hutton & Bahr — Cutting Out Continuationsthe CPS intuition, in miniature
2017Hutton & Bahr — Compiling a 50-Year Journey (JFP 27)the map / retrospective
2020Bahr & Hutton — Calculating Correct Compilers II: Register Machines (JFP 30)generalizes off the stack
2021Pickard & Hutton — Calculating Dependently-Typed Compilers (ICFP)your Lean blueprint — intrinsically typed
2022Bahr & Hutton — Monadic Compiler Calculation (ICFP)the hook for effects — swap the monad; partiality for divergence
2023Bahr & Hutton — Calculating Compilers for Concurrency (ICFP)nearest BANG's fibers + STM
2024Garby, Hutton & Bahr — Calculating Compilers Effectively (Haskell)emit efficient, not tree-shaped, code
2024Bahr & Hutton — Beyond Trees: Graph-Based Compilers (ICFP)jumps / graph-structured code (HOAS)
2024Tsuyama et al. — An Intrinsically Typed Compiler for Algebraic Effect Handlers (PEPM)adjacent + vital — handlers → typed stack machine, in Agda; closest artifact to K3
Geeson (Oxford MSc) — Calculating Compilers and Algebraic Effectsworked precedent: method × effects, CBPV+exceptions

keyframes committed · inbetweens to be drawn · next pose to lock: K2