Files
AILang/docs/roadmap.md
T
Brummel 92e830e6c2 iter 23.5: prelude free fns + E2E — Eq/Ord milestone close
Five polymorphic prelude free fns (ne/lt/le/gt/ge) plus three E2E
fixtures: positive composition over Int/Bool/Str, user-ADT with
user-written Eq/Ord on IntBox, and Float-NoInstance with a
Float-aware diagnostic addendum cross-referencing DESIGN.md §"Float
semantics".

Two checker-side fixes were needed alongside the prelude additions,
both symmetric to the iter 23.4-prep visibility fix:
- linearity::check_module_with_visible — workspace-aware callee-mode
  resolution so a Borrow-mode user fn forwarding into a prelude poly
  fn (e.g. `at_most x y = not (gt x y)`) doesn't false-fire
  consume-while-borrowed.
- mono::collect_mono_targets — distinguish rigid forall vars from
  unbound metavars; rigid-bearing free-fn targets skip (they get
  re-collected with concrete subst when the enclosing fn itself
  monomorphises). Without this, a polymorphic body calling another
  polymorphic free fn produced a spurious __Unit specialisation
  whose body referenced compare at Unit.

Roadmap split: shipped Eq/Ord half checked, Show + print-rewire half
remains pending behind the heap-Str ABI prerequisite. DESIGN.md
§"Prelude classes" amended.

One pre-existing fixture (test_22b1_missing_method) renamed its
class method ne → tne to avoid collision with the new prelude `ne`.

Bench: check.py + cross_lang.py exit 0; compile_check.py exits 1
with one sub-ms check_ms.local_rec_capture at +26% (tolerance 25%) —
prelude-growth-related noise-band fluctuation, ratifiable per spec
§248-249 and journal Concerns.
2026-05-12 00:38:52 +02:00

13 KiB
Raw Blame History

AILang Roadmap

Priority-ordered list of upcoming work — milestones, features, todos, and ideas. The orchestrator maintains this file. The user can request additions; the orchestrator chooses what to remove or reprioritise as work progresses.

Conventions

  • One checkbox per entry. - [ ] is open; - [~] is in progress (work has started — a plan exists, a branch is open, or commits are landing); - [x] is done. A finished entry may stay briefly for context, then is removed (with a one-line mirror in docs/journals/).
  • Each entry is tagged by kind and lives under a priority bucket:
    • [milestone] — big chunk that will get a docs/specs/<milestone>.md.
    • [feature] — smaller addition inside a milestone, no full spec.
    • [todo] — concrete task that can run without a brainstorm (cleanup, doc fix, mechanical refactor, test backfill).
    • [idea] — not yet decision-ready, no commitment.
  • Optional depends on: line names another entry that has to land first.
  • Optional context: line points to the journal entry (per-iter file under docs/journals/ or, for pre-2026-05-11 entries, the archived docs/journal-archive.md) where the rationale lives. The roadmap is intentionally terse; rationale stays in the journals.
  • Priority buckets:
    • P0 — in flight. Spec or plan already exists.
    • P1 — next up. Decision made; not yet started.
    • P2 — medium-term. Decided in principle, scheduled later.
    • P3 — ideas. No commitment; may be cut.

P0 — In flight

(empty — canonical-type-names milestone closed 2026-05-11; Floats closed 2026-05-10 and was removed once it stopped being load-bearing context. Pick the next milestone from P1.)

P1 — Next

  • [milestone] Post-22 Prelude — Eq/Ord — shipped milestone 23 (2026-05-12). Ordering ADT, Eq/Ord classes, primitive instances on Int / Bool / Str, polymorphic free fns ne/lt/le/gt/ge, runtime ail_str_eq + ail_str_compare, end-to-end coverage including user-ADT-instance integration. Float has neither instance by design; polymorphic helpers at Float fire Float-aware NoInstance per DESIGN.md §"Float semantics".

  • [milestone] Post-22 Prelude — Show + print rewire — ship Show typeclass with Show Int/Bool/Str/Float instances; rewire print through Show.show. Gated on heap-Str ABI runtime work (int_to_str needs to allocate). Originally queued as 22b.4 in the typeclass milestone, kept on hold pending demand and the heap-Str prerequisite.

    • context: brainstorm 2026-05-12 (iter 23.5 wrap). Heap-Str ABI is the load-bearing prerequisite; until it ships, Show Int cannot allocate a Str to return.

P2 — Medium-term

  • [feature] Operator routing through Eq / Ord==, < etc. resolved via the typeclass instead of the built-in primitive comparators. No commitment; gated on bench re-baselining to make sure the indirection doesn't tank latency.

    • context: JOURNAL 2026-05-09
    • depends on: Post-22 Prelude — Eq/Ord (shipped 23.5)
  • [todo] types / ctor_index overlay shape question — decide whether the env's two parallel ctor maps should collapse into one overlay, or stay split. Surfaced during the env-construction unify audit.

    • context: JOURNAL 2026-05-10 ("Audit close: env-construction unify")
  • [todo] CLI human-mode diagnostic surface for WorkspaceLoadError — non-JSON ail check routes ct.1 errors via anyhow/thiserror Display (Error: <message>) instead of going through workspace_error_to_diagnostic, so the bracketed [code] prefix the JSON path carries is missing. Plausibly applies to every CLI subcommand that calls load_workspace(&path)? directly.

    • context: JOURNAL 2026-05-11 ("Iteration ct.1") — surfaced by ct.1.8 tester.
  • [todo] Retire dead KindMismatch arm — validate_classdefs's walk_kind_mismatch path is structurally unreachable through well-formed schema post-ct.1 (the canonical-form validator catches the malformed Type::Con { name: param } shape earlier). The enum variant + walk_kind_mismatch helper stay as dead-but-defensive code; a future tidy can delete both.

    • context: JOURNAL 2026-05-11 ("Iteration ct.1").
  • [todo] Re-key Registry.type_def_module to handle bare-name-collision-across-modules — BTreeMap<String, String> keyed by bare type name silently overwrites when two modules each define type Foo; normalize_type_for_registry would then collapse M.Foo and N.Foo to whichever insert won. Acceptable for current corpus (distinct bare type names across modules), but the proper fix is to key by (owning_module, bare_name) → defining_module.

    • context: JOURNAL 2026-05-11 ("Iteration ct.1") — flagged by ct.1.5a quality reviewer.
  • [feature] 22c — typeclass corpus expansion. User-defined classes beyond the prelude four; multi-parameter classes; superclass chains; richer instance bodies. Deferred from milestone 22.

    • context: JOURNAL 2026-05-09
  • [milestone] Module-qualified class names + type-driven method dispatch — retire the MethodNameCollision workaround (crates/ailang-core/src/workspace.rs:472) that today keeps bare class names viable by enforcing workspace-global method-name uniqueness. Replaces name-driven method resolution (ModuleGlobals::class_methods: IndexMap<String, ClassMethodEntry>, crates/ailang-check/src/lib.rs:983; consumed by mono::rewrite_class_method_calls, crates/ailang-check/src/mono.rs:657) with type-driven dispatch — look up eq candidates by argument type, pick the unique class instance, fail closed on ambiguity. Once shipped, two libraries can each declare class Eq with their own eq. Carries its own DESIGN spec: inference rules, ambiguity diagnostics, and the canonical-form extension for class-reference fields (InstanceDef.class, SuperclassRef.class, Constraint.class) that the canonical-type-names milestone explicitly out-of-scoped.

    • context: docs/specs/2026-05-10-canonical-type-names.md "Out of scope: Class names" — the workaround is named there so it stays visible until this milestone retires it.
  • [todo] Boehm full retirement — remove the transitional Boehm GC path now that RC + uniqueness is the canonical memory story.

    • context: JOURNAL pre-22, "Boehm transitional"
  • [feature] Closure-pair slab / pool — codegen tweak to pool the env+code closure pairs instead of one-shot heap allocs. Bench-gated.

  • [todo] FnDef::synthetic flag — formalise the monomorphiser-emitted FnDefs so downstream passes can tell user-authored from synthesised at a glance. Currently inferred from symbol naming.

  • [todo] 21'h iteration — final 21' carry-over (latency methodology pass). Numbering kept for continuity with the 21' arc.

  • [todo] io/print_float always-emit-.0 — surface printer always emits . or e/E so re-lex routes to Float; the runtime printer (printf("%g\n", v)) doesn't, so 2.0 prints as 2 (Int-shaped). Asymmetric. Either switch the runtime path to a .0-fallback printer (matching surface) or document the %g contract in DESIGN.md §"Float semantics" so the LLM-author knows io/print_float's output is for-humans not round-trip.

    • context: docs/specs/2026-05-10-fieldtest-floats.md finding F1.
  • [todo] Rustdoc warning sweep — cargo doc --no-deps reports 16 pre-existing warnings (15 in ailang-check, 1 in ailang-core: private-item links from public doc, unresolved intra-crate links). All predate the design-md-consolidation milestone; treat as a one-off sweep.

    • context: JOURNAL 2026-05-10 ("Audit close: design-md-consolidation").
  • [todo] design_schema_drift.rs fidelity widening — current test checks anchor presence anywhere in DESIGN.md; the audit found that [high] schema gaps in §"Data model" are invisible because anchors live in Decision 11 instead. Constrain the test to scan only §"Data model" + ParamMode block, or extract JSON-schema blocks into a machine-readable file the test consumes.

    • context: JOURNAL 2026-05-10 ("Audit close").
  • [todo] Split BadCrossModuleTypeRef into two diagnostics — the current single shape collapses unknown-owner and known-owner / unknown-type-in-owner into one message. The two cases suggest different fixes (add (import <owner>) vs. fix the type name). In the known-owner branch, list the owner's available type defs as candidates the way bare-cross-module-type-ref lists candidates from imports.

    • context: fieldtest 2026-05-11 — examples/ct_3*.ailx exhibits both branches with identical-shape diagnostics.
  • [todo] Workspace search beyond entry-module's directory — load_workspace only finds sibling .ail.json files in the same directory as the entry module, so any consumer of prelude/std in a subdirectory has no way to resolve cross-module imports. Add either a --workspace-root flag on ail check / ail build / ail run, or upward-search from the entry module's directory. Alternatively ratify the flat-workspace assumption in DESIGN.md if intentional.

    • context: fieldtest 2026-05-11 — fieldtest fixtures could not be placed under examples/fieldtest/ because of this; predates the canonical-type-names milestone but surfaces every time.
  • [todo] ail check/build/run accept .ailx extension — today ail check foo.ailx produces a misleading JSON-parse error (json: expected value at line 1 column 1) because the loader only accepts .ail.json. Either teach the CLI subcommands to auto-parse .ailx internally, or detect the extension and emit a "did you mean ail parse foo.ailx?" hint. The LLM-author's natural first command should not be the one that produces a misleading diagnostic.

    • context: fieldtest 2026-05-11 — orthogonal to canonical-type-names but every fieldtest invocation hits this on its first command.
  • [todo] check_in_workspace per-module overlay narrowing — crates/ailang-check/src/lib.rs:1234 still clears+rebuilds env.ctor_index per-module; ct.3.2 narrowed the analogous mono overlay to types-only. The typecheck-side overlay's env.ctor_index half serves the duplicate-detection diagnostic at workspace-build time, not the runtime ctor lookup (which is type-driven post-ct.2.2). Narrowing is mechanical but needs a careful read to confirm no other consumer survives.

    • context: JOURNAL 2026-05-11 ("Iteration ct.4") — milestone close follow-up.

P3 — Ideas

  • [todo] compare_primitives_smoke.ailx counterpart — the canonical happy-path exhibit for canonical-type-names ships only as JSON. Per Decision 6, Surface is the LLM-author surface; the milestone should have a .ailx counterpart. Two paths: author examples/compare_primitives_smoke.ailx to round-trip into the existing JSON, OR retire the JSON fixture in favour of examples/ct_1_ordering_signum.{ailx,ail.json} as the new canonical happy-path exhibit.

    • context: fieldtest 2026-05-11 (spec_gap).
  • [todo] Codegen lookup_ctor_in_pattern type-anchoring — crates/ailang-codegen/src/lib.rs:1790 still walks every module's ctor_index by bare ctor name. Plumbing the scrutinee's qualified Type::Con through pattern lowering would type-anchor it symmetric to the ct.2.2 typecheck-side fix. Not load-bearing (uniqueness is enforced at typecheck), but cleaner.

    • context: JOURNAL 2026-05-11 ("Iteration ct.3" + ct.4 close).
  • [todo] compare_primitives_smoke IR-shape assertion — observe compare__Int / compare__Bool / compare__Str symbols in the emitted IR. Blocked on emit-ir CLI not running mono; resolution paths include extending the CLI to run mono, using library APIs directly in e2e.rs, or adding --dump-ir to ail build. The E2E stdout assertion already covers correctness; the IR-shape test would catch refactor regressions that rename mono symbols.

    • context: JOURNAL 2026-05-11 ("Iteration ct.4") — dropped from ct.4.4 when the BLOCKED condition surfaced.
  • [idea] Latency methodology rework — switch from per-run timing to a histogram-based approach so tail-latency regressions are visible without re-running. Queued from 21'g.

  • [idea] Parser-test backfill for 22b.4a-era duplicate-clause sites (class × 3, class method × 2, instance × 3, instance method × 1). No regression pin today; only worth it if a 22b.4a-era diagnostic needs to change.

    • context: JOURNAL 2026-05-10 ("Iteration 22-tidy.7")
  • [idea] write_type Type::Forall arm in crates/ailang-prose/src/lib.rs silently drops constraints in inline-type rendering. Dormant — surface forms today only carry forall at fn-signature top level. Fix only if a future feature carries forall + constraints inline.

    • context: JOURNAL 2026-05-10 ("Iteration 22-tidy.6")
  • [idea] Richer integration paths between RC and uniqueness — deferred from the 21' arc; revisit once the uniqueness inference covers more program shapes.