diff --git a/docs/specs/2026-05-11-23-eq-ord-prelude.md b/docs/specs/2026-05-11-23-eq-ord-prelude.md index 32f8d58..df3bbf2 100644 --- a/docs/specs/2026-05-11-23-eq-ord-prelude.md +++ b/docs/specs/2026-05-11-23-eq-ord-prelude.md @@ -32,10 +32,20 @@ seam. The corrected architecture unifies the two specialisers (see Architecture below) and ships the remaining free fns on top of -the unified pass. The three iter-23.4 prep commits are classified: -prep1 (linearity + checker bare-name) stays load-bearing, prep2 + -prep3 (codegen bare-name fall-throughs) become provably dead and -are rolled back in 23.4. +the unified pass. + +**Prep-commit status (verified against main 2026-05-11 after +iter/23.4 branch teardown):** prep1 (linearity + checker +bare-name) landed on main on 2026-05-11 via cherry-pick from the +stranded iter/23.4 branch; it stays load-bearing. prep2 and prep3 +(codegen bare-name fall-throughs) were attempted on the stranded +iter/23.4 branch and *never reached main*; with iter/23.4 deleted, +they are abandoned as git history without a rollback step. Their +architectural intent — make codegen handle bare polymorphic +free-fn names directly — is superseded by the mono-unification. +The unified pass rewrites bare polymorphic call sites to mono +symbols before codegen runs, making the fall-throughs structurally +unnecessary. `Show`, operator routing, `print`-rewire, and the heap-Str ABI remain out of scope; each is its own milestone with substantive @@ -44,7 +54,7 @@ reasons (see "Out of scope" — unchanged from original spec). ## Architecture The milestone no longer consumes the 22b.3 typeclass machinery -unchanged. Four artefacts: +unchanged. Three artefacts: ### 1. Mono-Pass unification (the corrected centrepiece) @@ -80,33 +90,7 @@ sites of `lower_polymorphic_call` (lines 1944, 1972) become direct calls to mono symbols after the typecheck-mono walker has rewritten them. -### 2. Rollback of iter-23.4-prep2 + prep3 - -Two existing codegen bare-name fall-throughs were anticipatory -patches for the prelude free fns: - -- commit `a06159d` (prep2): codegen — bare-name fall-through to - implicit-imported free fns. -- commit `c42a0f5` (prep3): codegen — polymorphic-free-fn bare-name - fall-through to implicit-imported modules. - -After Mono unification, codegen never sees bare polymorphic free-fn -names — the unified mono pass rewrites every call site to its mono -symbol before codegen runs. The two patches are provably dead and -are rolled back in 23.4. The rollback lands in the same iter as -the unification so the codebase never carries the fall-throughs -as visible-but-dead code. - -The third iter-23.4-prep is kept: - -- commit `8d39f13` (prep.1): linearity — register `Def::Class` method - types in globals. Required independent of mono — linearity walks - pre-mono. -- commit `aef4ab8` (prep.2): check — bare-name fall-through to - implicit-imported free fns. Required at typecheck time — bare `ne` - must resolve to the prelude `Def::Fn` *before* mono can specialise. - -### 3. Prelude AILang module +### 2. Prelude AILang module `examples/prelude.ail.json` already contains, from iters 23.1–23.3: the `Ordering` ADT, the `Eq` class with `Eq Int`/`Bool`/`Str` @@ -119,7 +103,7 @@ Iter 23.5 adds the five free fns: bodies pattern-matching `compare` against the appropriate `Ordering` shapes. -### 4. C-runtime functions +### 3. C-runtime functions `runtime/str.c` shipped its two functions in iter 23.2 and 23.3: `ail_str_eq(a, b) -> bool` (byte-equality on constant-string layouts) @@ -139,9 +123,9 @@ Int/Bool/Str is acknowledged and ratified as transitional. | 23.1 | shipped (2026-05-10) | `Ordering` ADT + prelude skeleton + auto-load via `check_workspace`. | | 23.2 | shipped (2026-05-10) | `class Eq` + `Eq Int/Bool/Str` + `ail_str_eq`. | | 23.3 | shipped (2026-05-10) | `class Ord extends Eq` + `Ord Int/Bool/Str` + `ail_str_compare`. | -| 23.4-prep | shipped, **kept** | commits `8d39f13` (linearity registers `Def::Class` method types in globals) + `aef4ab8` (check bare-name fall-through to implicit-imported free fns). Both resolve names *before* mono; independent of B1. | -| 23.4-prep2 / 23.4-prep3 | shipped, **rolled back in 23.4** | commits `a06159d` + `c42a0f5` — codegen bare-name fall-throughs. Provably dead after Mono unification. | -| **23.4** (revised) | upcoming | **Mono-Pass unification.** Restructure `crates/ailang-check/src/mono.rs::monomorphise_workspace` into one specialiser with two source-body entry points (class-method via `Registry::entries`, free-fn direct). Extend `collect_mono_targets` to also produce targets for polymorphic free-fn calls with fully-concrete substitutions. Remove `lower_polymorphic_call` + `module_polymorphic_fns` + `mono_queue` from codegen. Rollback prep2 + prep3. Amend DESIGN.md §"Resolution and monomorphisation" to describe the pass as covering all `Type::Forall`-Defs. Tests: existing polymorphic fixtures (`poly_id`, `poly_apply`, `poly_rec_capture`) green; new fixture `cmp_max_smoke` proves cross-cutting (`cmp_max : forall a. Ord a => (a, a) -> a` at Int synthesises both `cmp_max__Int` and nested `compare__Int` in one fixpoint). | +| 23.4-prep | shipped to main 2026-05-11 (cherry-picked from stranded iter/23.4), **kept** | commits on main: `0caaced` (linearity registers `Def::Class` method types in globals) + `923dd8c` (check bare-name fall-through to implicit-imported free fns). Both resolve names *before* mono; independent of B1. | +| 23.4-prep2 / 23.4-prep3 | **abandoned 2026-05-11 with iter/23.4 deletion** — never reached main | Attempted-but-stranded commits were `a06159d` + `c42a0f5` (codegen bare-name fall-throughs); they were anticipatory patches for an approach (codegen-time bare-name handling) the mono-unification supersedes. No rollback step is needed because no rollback target exists on main. | +| **23.4** (revised) | upcoming | **Mono-Pass unification.** Restructure `crates/ailang-check/src/mono.rs::monomorphise_workspace` into one specialiser with two source-body entry points (class-method via `Registry::entries`, free-fn direct). Extend `collect_mono_targets` to also produce targets for polymorphic free-fn calls with fully-concrete substitutions. Remove `lower_polymorphic_call` + `module_polymorphic_fns` + `mono_queue` from codegen. Amend DESIGN.md §"Resolution and monomorphisation" to describe the pass as covering all `Type::Forall`-Defs. Tests: existing polymorphic fixtures (`poly_id`, `poly_apply`, `poly_rec_capture`) green; new fixture `cmp_max_smoke` proves cross-cutting (`cmp_max : forall a. Ord a => (a, a) -> a` at Int synthesises both `cmp_max__Int` and nested `compare__Int` in one fixpoint). | | **23.5** (revised) | upcoming | **Prelude free fns + E2E.** Add `ne`/`lt`/`le`/`gt`/`ge` to `examples/prelude.ail.json`. E2E fixtures: (a) positive polymorphic helper at Int/Bool/Str, (b) negative — `eq f g` at Float typecheck-rejects with Float-aware diagnostic, (c) user-ADT — `IntBox` with `Eq`/`Ord` instances + polymorphic helper monomorphises to the user instance. Amend DESIGN.md §"Decision 11 / Prelude classes" — Eq/Ord shipped; the "Milestone 22 ships no built-in Prelude classes" wording stays as historical accuracy with a forward-pointing addendum. Roadmap: P1 Post-22 Prelude entry from `[~]` to `[x]` for Eq/Ord half; Show half stays. | ## Data flow @@ -271,8 +255,8 @@ The milestone closes when: 1. **23.4 has landed:** `crates/ailang-check/src/mono.rs::monomorphise_workspace` synthesises both class-method and polymorphic-free-fn mono Defs in one fixpoint loop. `crates/ailang-codegen/src/lib.rs::lower_polymorphic_call` + - `module_polymorphic_fns` + `mono_queue` are removed. Commits - `a06159d` (prep2) + `c42a0f5` (prep3) are rolled back. + `module_polymorphic_fns` + `mono_queue` are removed. (prep2 + + prep3 were never on main; no rollback step in scope.) 2. **DESIGN.md §"Resolution and monomorphisation" amended:** the pass description covers all `Type::Forall`-quantified Defs, not only class methods. @@ -362,8 +346,6 @@ New under B1 unification: `crates/ailang-codegen/src/lib.rs` (`lower_polymorphic_call`, `module_polymorphic_fns` fields, `mono_queue` machinery). Net code reduction expected. -- **23.4 rollback:** `git revert a06159d c42a0f5` plus adaptation - to the newly-dead code paths in codegen, estimated −80 LOC. - **23.5 prelude additions:** `examples/prelude.ail.json` +30-40 lines (five free fns with Forall-constraint signatures and bodies). Three new E2E `.ail.json` fixtures, ~60 lines JSON. @@ -394,14 +376,19 @@ relies on as currently-true. corresponding workspace Defs. 4. `examples/prelude.ail.json` today contains no free fns (only ADT, classes, instances). -5. Commits `a06159d` (prep2) and `c42a0f5` (prep3) added codegen - bare-name fall-throughs that were anticipatory patches for the - prelude free fns; they have no currently-active load-bearing - case outside the still-not-shipped 23.4 free fns. -6. Commit `8d39f13` (prep.1, linearity) and commit `aef4ab8` - (prep.2, check bare-name) operate at typecheck / linearity time - — before any mono pass — and are load-bearing for any prelude - free-fn resolution regardless of mono architecture. +5. prep2 and prep3 (the codegen bare-name fall-through patches) + *never reached main*. They lived on the stranded iter/23.4 + branch which was deleted on 2026-05-11. The current main + contains no codegen bare-name fall-through for polymorphic + free-fn calls — codegen rejects bare polymorphic free-fn calls + today, which is exactly what makes the original iter-23.4 BLOCK. +6. Commits on main `0caaced` (prep.1, linearity registers `Def::Class` + method types in globals) and `923dd8c` (prep.2, check bare-name + fall-through to implicit-imported free fns) operate at + typecheck / linearity time — before any mono pass — and are + load-bearing for any prelude free-fn resolution regardless of + mono architecture. (Originals from stranded branch: `8d39f13` + and `aef4ab8`; cherry-picked onto main 2026-05-11.) 7. `crates/ailang-codegen/src/lib.rs::lower_polymorphic_call` is invoked from two call sites today (lines 1944, 1972), both of which become direct mono-symbol calls after 23.4.