iter remove-mut-var-assign.1: atomic removal of mut/var/assign
mut/var/assign removed from AILang entirely and atomically. Deleted: Term::Mut/Term::Assign/struct MutVar; the three Form-A keywords + parse_mut/parse_assign + grammar EBNF; the 4 mut CheckError variants; the mut_scope_stack synth threading (param dropped from synth + every internal/external/test caller); the two lower_term arms; and every exhaustive no-_ Term::Mut/Term::Assign match arm across 17 source files — cut in lockstep with DESIGN.md, fixtures, the drift trio, carve-out and roadmap so the schema is honest at every commit. No catch-all wildcard introduced (verified). loop/recur + let/if are the surviving forms. The shared codegen alloca machinery survives (loop reuses it): mut_var_allocas renamed binder_allocas (representation-only, loop codegen byte-identical) and the shared Term::Lam escape guard simplified to !loop_stack.is_empty() with the loop half (LoopBinderCapturedByLambda) byte-equivalent. Feature-acceptance applied inverted: the removed feature fails clause 2 (redundant) and clause 3 (IS the iterated-mutable-state bug class). Behaviour preservation is executable: mut_counter/mut_sum_floats still print 55 after the faithful let/if rewrite. The removal is made executable by the new mut_removed_pin.rs (4 must-fail pins). Independent verification: cargo test --workspace 605/0, zero residual mut symbols in any crate source, loop/recur non-regression all green (55 / 500000500000 / infinite-compiles / the lambda_capturing_loop_binder pin), roundtrip_cli PASS. One DONE_WITH_CONCERNS: a 4th recurrence of the recon-undercount class (in-source mod tests + a drift-pin fn + 5 orphaned mut .ail.json carve-outs + a non-enumerated E0599); all resolved within implementer remit, no behaviour change. Milestone-close audit then fieldtest remain. spec docs/specs/2026-05-18-remove-mut-var-assign.md (grounding PASS) plan docs/plans/remove-mut-var-assign.1.md
This commit is contained in:
@@ -2853,20 +2853,17 @@ fn str_clone_cross_realisation_uniform_abi() {
|
||||
assert_eq!(live, 0, "no leaked heap-Str slabs allowed; live={live}");
|
||||
}
|
||||
|
||||
/// Iter mut.3: `examples/mut_counter.ail` exercises `Term::Mut` +
|
||||
/// `Term::Assign` codegen with an `Int` mut-var. The body
|
||||
/// `(mut (var sum Int 0) (assign sum (sum_helper 1 10 0)) sum)`
|
||||
/// stores the helper's result into `sum`'s alloca and prints the
|
||||
/// loaded value. End-to-end gate for the entry-block-hoist /
|
||||
/// store / load lowering.
|
||||
/// `examples/mut_counter.ail` sums 1..10 via a tail-recursive
|
||||
/// `sum_helper` and prints the result. Behaviour-preservation gate:
|
||||
/// the fixture's value assertion stays `55` after the let/if rewrite,
|
||||
/// proving the rewrite loses no expressivity.
|
||||
#[test]
|
||||
fn mut_counter_prints_55() {
|
||||
let stdout = build_and_run("mut_counter.ail");
|
||||
assert_eq!(stdout.trim(), "55", "mut_counter must print 55, got {stdout:?}");
|
||||
}
|
||||
|
||||
/// Iter mut.3: Float twin of `mut_counter_prints_55`. The mut-var
|
||||
/// is `Float`, init is `0.0`, the recursive helper returns the
|
||||
/// Float twin of `mut_counter_prints_55`: `sum_helper` returns the
|
||||
/// sum 1.0+...+10.0 = 55.0. The polymorphic `print` routes through
|
||||
/// `Show Float.show` → `float_to_str`'s libc `%g` formatter, which
|
||||
/// strips the trailing `.0` — so the canonical stdout for Float
|
||||
|
||||
Reference in New Issue
Block a user