Iter 6: deps hardening, multi-diagnose, DESIGN audit
- ail deps now filters builtins, fn params, and let/match-pattern bindings. New value_names() in ailang-check::builtins is the single source of truth shared with the typechecker install path. walk_term threads a scope set; qualified `prefix.def` refs pass through. - check_in_workspace returns Vec<CheckError>; check_workspace accumulates body diagnostics across defs and modules. Pass-1 (top-level symbol table) and per-module type-def setup stay fail-fast — corrupt env would taint later diagnostics. - DESIGN.md "What the MVP is NOT" was lying (ADTs, strings landed in Iter 2/3). Renamed to "What is not (yet) supported" and split into "not yet" + supported/smoke-tested. JOURNAL Iter 6 entry records the architecture self-check. Tests: 47 green (was 44). +2 deps filter tests in e2e, +1 multi-diagnose test in ailang-check workspace integration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -345,3 +345,88 @@ Architect agent invoked. Findings:
|
||||
|
||||
Order: 1 first (doc triviality), then 2 before 3 (deps is a tooling-
|
||||
truth fix, multi-diag is a structural extension).
|
||||
|
||||
## 2026-05-07 — Iter 6 done: deps hardening + multi-diagnose + DESIGN audit
|
||||
|
||||
Three things landed together. All small, all KISS — no architecture move,
|
||||
just paying off recorded debt.
|
||||
|
||||
**1. `ail deps` filters builtins, params, and let/match bindings (#22).**
|
||||
|
||||
Before: `sum -> +, -, ==, n, sum` and `ws_lib.add -> ws_lib.+`,
|
||||
`ws_lib.a`, `ws_lib.b`. After: `sum -> sum`, `ws_lib.add -> ws_lib.add`
|
||||
gone (no real deps; only the cross-module call from `ws_main` remains).
|
||||
|
||||
Implementation:
|
||||
- New helper `ailang_check::builtins::value_names()`: derives the
|
||||
Var-level builtin names (`+ - * / % == != < <= > >= not`) from
|
||||
`list()`, so the install-list and the deps-filter share one source of
|
||||
truth.
|
||||
- `walk_term` in `crates/ail/src/main.rs` now threads a `scope` set:
|
||||
fn-params seed it; `Let` adds the bound name for the body only;
|
||||
`Match` arms add their pattern variables (`bind_pattern` helper, MVP
|
||||
rule "ctor sub-patterns are Var/Wild") and roll them back after. Var
|
||||
refs that hit `scope` or `builtins` are dropped; qualified names
|
||||
(`prefix.def`) are passed through unconditionally — the typechecker
|
||||
forbids dots in def names, so no shadowing risk.
|
||||
- Tests added: `deps_filters_builtins_params_locals`,
|
||||
`deps_workspace_filters_builtins_and_params`. The Iter 5d test
|
||||
(`deps_workspace_includes_cross_module`) keeps passing — the only
|
||||
edge it asserted is the legitimate one.
|
||||
|
||||
**2. `check_module` / `check_workspace` are multi-diagnose (#20).**
|
||||
|
||||
`check_in_workspace` returns `Vec<CheckError>` instead of `Result<()>`.
|
||||
Pass-1 (top-level symbol table) stays fail-fast — corrupt globals would
|
||||
taint every later diagnostic. Type-def installation is fail-fast within
|
||||
a module (env corruption) but the outer module loop continues. The
|
||||
body-check loop is the multi-diagnose layer: each def is checked against
|
||||
the assembled env, errors accumulate, the next def is attempted.
|
||||
|
||||
Test: `body_errors_accumulate_across_defs` — one module with two
|
||||
independent body errors (arity mismatch + unknown var) yields two
|
||||
diagnostics with the right `def` field. The legacy single-error `check`
|
||||
keeps working by `.into_iter().next()`-ing the Vec, so internal snapshot
|
||||
tests in `crates/ailang-check/src/lib.rs` are unchanged.
|
||||
|
||||
Out of scope: intra-def collection. A single fn body with three type
|
||||
errors still reports one. The "see all broken defs at once" goal is met;
|
||||
intra-def will require unification deferral and isn't due now.
|
||||
|
||||
**3. DESIGN.md `What the MVP is NOT` audit (#24).**
|
||||
|
||||
The section was lying: it claimed "No ADTs / pattern matching" (delivered
|
||||
Iter 3) and "Only ints + bools + unit" (strings landed Iter 2). Renamed
|
||||
to `What is not (yet) supported`, restructured into "not yet" + "what is
|
||||
supported (smoke-tested)". New invariant: this section is meant to be
|
||||
the truth at the **end of the latest iteration**, not a 2026-05-07-day-0
|
||||
scope statement.
|
||||
|
||||
**Architecture check (the user-asked self-questioning):**
|
||||
|
||||
- *Would I use this language now?* For non-recursive arithmetic + ADT
|
||||
programs over int/bool/str: yes, comfortably. For anything that needs
|
||||
mapping, folding, generic data structures: no, closures are the
|
||||
blocker. That's the next big sprint, not Iter 7.
|
||||
- *Consistency:* DESIGN.md, JOURNAL.md, code, and CLI output now agree
|
||||
on what the language can do. The "What is not (yet) supported" block
|
||||
is the canonical truth surface.
|
||||
- *Visualisation:* `ail deps --workspace --json` is now a clean
|
||||
cross-module call graph (no builtin noise). Good enough for an
|
||||
external graph renderer to consume; a built-in DOT/ASCII renderer is
|
||||
*possible future tooling*, not "we need it now". KISS.
|
||||
- *Documentation:* the agents/ directory is the sub-prompt layer, the
|
||||
JOURNAL is the iteration log, DESIGN.md is the contract. No new doc
|
||||
axes needed at this scale.
|
||||
|
||||
**Tests:** 47 green (previously 44). +2 deps tests in `e2e.rs`, +1
|
||||
multi-diag test in `crates/ailang-check/tests/workspace.rs`.
|
||||
|
||||
**Plan iteration 7:**
|
||||
|
||||
Closures + higher-order functions. This is the big jump that
|
||||
DESIGN.md / Day 0 has been pointing at: it requires a typed IR (TIR)
|
||||
stage, closure conversion in lowering, and a heap-aware ABI. The
|
||||
multi-diag refactor in Iter 6 was scoped intentionally minimal — when
|
||||
TIR lands, intra-def diagnostics become structurally cheap and Task #20
|
||||
gets revisited.
|
||||
|
||||
Reference in New Issue
Block a user