iter revert: back out the Iteration-discipline milestone (it.1 + it.2)
One forward iteration; main never rewound.1ff7e81(the pre-9973546 commit) is the per-region byte oracle — every reverted source/test file is byte-identical to it; crates/ailang-check/src/lib.rs fully so. Root cause being corrected: the Iteration-discipline milestone was an over-escalation of fieldtest finding F1 (a [friction] item whose own minimal recommendation was a DESIGN.md note). Its totality dichotomy made the maximally-LLM-natural build(d:Int)=Node(1,build(d-1), build(d-1)) inexpressible (it.3 BLOCKED); the only in-thesis escape (A1/it.2b) conceded the language's first documented-unenforced totality precondition — a purity-pillar dilution the user rejected in favour of a full revert + rebuild. Removed: Term::Loop/Term::Recur/LoopBinder; the verify_structural_ recursion guardedness pass + term_contains_loop + Diverge-injection + the transitively-it.2 module_fns plumbing; the five Recur*/ NonStructuralRecursion CheckError variants (+ code() + the 3 dedicated ctx() arms); the it.1 codegen loop-header/phi/back-edge + parallel block_terminated setter; all Loop/Recur walker arms; 16 it.1/it.2 fixtures; 2 pin files; bench/it3-oracle/. Restored: 2 RC fixtures to1ff7e81content. Surgically kept (not in1ff7e81, landed with the milestone but independently sound): feature-acceptance clause 3 in DESIGN.md and skills/brainstorm/SKILL.md, with its worked example de-claimed from "shipped" to hypothetical-illustration form; the F3 P2 todo. bench/orchestrator-stats/2026-05-15-iter-it.{1,2,3}.json kept as historical record (like journals/plans). Sole net addition: an honest F1/F4 documented-idiom note in DESIGN.md (the tail-recursive accumulator fallback; examples/mut_counter.ail), guarded by a doc-presence test — "a documentation note is not a reshape", asserts nothing at the typecheck level. Roadmap: the Iteration-discipline block + blocking-fork section removed; the genuine total-Int-recursion ambition preserved as a deferred P2 milestone sequenced behind a future Nat/refinement-types milestone (not abandoned — correctly sequenced after the type machinery it needs). 2026-05-15-iteration-discipline.md carries a superseded header; it.1/it.2/it.3 journals + plans stay as history. Correctness gate PRISTINE: 164 surviving 1ff7e81-era fixtures ail check/ail run byte-identical to pre-milestone behaviour (verified against a1ff7e81worktree reference compiler, zero drift); cargo test --workspace 600/0; zero residual it.1/it.2 production surface. Spec docs/specs/2026-05-16-iteration-discipline-revert.md (b3853bf), plan docs/plans/2026-05-16-iter-revert.md (abf0013).
This commit is contained in:
@@ -1544,26 +1544,6 @@ fn walk_term(
|
||||
}
|
||||
walk_term(value, out, builtins, scope);
|
||||
}
|
||||
// Iter it.1: loop binder names bind inside the body and later
|
||||
// binder inits, mirroring `Term::Mut`. Recur args are uses.
|
||||
Term::Loop { binders, body } => {
|
||||
let mut newly = Vec::new();
|
||||
for b in binders {
|
||||
walk_term(&b.init, out, builtins, scope);
|
||||
if scope.insert(b.name.clone()) {
|
||||
newly.push(b.name.clone());
|
||||
}
|
||||
}
|
||||
walk_term(body, out, builtins, scope);
|
||||
for n in newly {
|
||||
scope.remove(&n);
|
||||
}
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args {
|
||||
walk_term(a, out, builtins, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2805,47 +2785,6 @@ fn rewrite_def(
|
||||
changed,
|
||||
);
|
||||
}
|
||||
// Iter it.1: rewrite types embedded in each
|
||||
// `LoopBinder.ty` (loop binders carry full Type
|
||||
// annotations like mut-vars) and recurse into each
|
||||
// binder's `init` and the body. `Term::Recur` has no
|
||||
// embedded type.
|
||||
Term::Loop { binders, body } => {
|
||||
for b in binders {
|
||||
rewrite_type(
|
||||
&mut b.ty,
|
||||
owning_module,
|
||||
local_types,
|
||||
import_names,
|
||||
changed,
|
||||
);
|
||||
rewrite_term(
|
||||
&mut b.init,
|
||||
owning_module,
|
||||
local_types,
|
||||
import_names,
|
||||
changed,
|
||||
);
|
||||
}
|
||||
rewrite_term(
|
||||
body,
|
||||
owning_module,
|
||||
local_types,
|
||||
import_names,
|
||||
changed,
|
||||
);
|
||||
}
|
||||
Term::Recur { args } => {
|
||||
for a in args {
|
||||
rewrite_term(
|
||||
a,
|
||||
owning_module,
|
||||
local_types,
|
||||
import_names,
|
||||
changed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,13 +101,6 @@ fn synthesised_print_uses_user_module_show_via_fallback() {
|
||||
|| contains_xmod_show_var(body)
|
||||
}
|
||||
Term::Assign { value, .. } => contains_xmod_show_var(value),
|
||||
// Iter it.1: a `Term::Loop` cannot itself host a synth'd
|
||||
// cross-module reference, but recurse defensively.
|
||||
Term::Loop { binders, body } => {
|
||||
binders.iter().any(|b| contains_xmod_show_var(&b.init))
|
||||
|| contains_xmod_show_var(body)
|
||||
}
|
||||
Term::Recur { args } => args.iter().any(contains_xmod_show_var),
|
||||
Term::Lit { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2828,56 +2828,6 @@ fn mut_counter_prints_55() {
|
||||
assert_eq!(stdout.trim(), "55", "mut_counter must print 55, got {stdout:?}");
|
||||
}
|
||||
|
||||
/// Iter it.1: `examples/loop_counter.ail` exercises `Term::Loop` +
|
||||
/// `Term::Recur` codegen — the loop-header block with one phi per
|
||||
/// binder and `recur` as a back-edge `br`. The body
|
||||
/// `(loop ((var acc Int 0) (var i Int 1)) (if (> i 10) acc (recur ...)))`
|
||||
/// sums 1..10 and prints 55. End-to-end gate for the loop-header /
|
||||
/// phi / recur-back-edge lowering.
|
||||
#[test]
|
||||
fn loop_counter_runs_and_prints_55() {
|
||||
let stdout = build_and_run("loop_counter.ail");
|
||||
assert_eq!(stdout.trim(), "55", "loop_counter must print 55, got {stdout:?}");
|
||||
}
|
||||
|
||||
/// Iter it.1: a `Term::Loop` inside a `Term::Lam` body, invoked via
|
||||
/// a returned closure. Protects the lambda-boundary invariant: the
|
||||
/// closure thunk scopes its own loop header / phis (the `loop_frames`
|
||||
/// save+reset+restore across the lambda boundary, mut.3 analogue) —
|
||||
/// a `recur` inside the lambda must back-edge to the lambda's own
|
||||
/// loop header, not the outer fn's. The lambda computes x*x by
|
||||
/// summing x exactly x times; apply 7 prints 49.
|
||||
#[test]
|
||||
fn loop_in_lambda_runs_and_prints_49() {
|
||||
let stdout = build_and_run("loop_in_lambda_e2e.ail");
|
||||
assert_eq!(stdout.trim(), "49", "loop_in_lambda must print 49, got {stdout:?}");
|
||||
}
|
||||
|
||||
/// Iter it.2 Phase-3: an it.2-clean structural recursion that runs.
|
||||
/// `struct_rec_sum_e2e` sums [1,2,3,4,5] via plain non-tail
|
||||
/// recursion on the Cons tail — the it.2 guardedness check
|
||||
/// classifies it pure + total (no `!Diverge`, no `tail-app`). This
|
||||
/// gate proves the structural-recursion "total" verdict is
|
||||
/// behaviourally sound, not merely a typecheck assertion: a plain
|
||||
/// (musttail-free) structurally-decreasing recursive call lowers
|
||||
/// and runs to the correct value.
|
||||
#[test]
|
||||
fn struct_rec_sum_runs_and_prints_15() {
|
||||
let stdout = build_and_run("struct_rec_sum_e2e.ail");
|
||||
assert_eq!(stdout.trim(), "15", "struct_rec_sum must print 15, got {stdout:?}");
|
||||
}
|
||||
|
||||
/// Iter it.2 Phase-3: the `Diverge`-path twin. `loop_needs_diverge`
|
||||
/// declares `!Diverge` (loop-bearing per DD-4) and runs the it.1
|
||||
/// accumulator loop to 55 — proving the Diverge-effect injection is
|
||||
/// purely a typecheck-layer obligation with no codegen impact (the
|
||||
/// loop lowers and runs identically to its pre-it.2 it.1 form).
|
||||
#[test]
|
||||
fn loop_needs_diverge_runs_and_prints_55() {
|
||||
let stdout = build_and_run("loop_needs_diverge.ail");
|
||||
assert_eq!(stdout.trim(), "55", "loop_needs_diverge 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
|
||||
/// sum 1.0+...+10.0 = 55.0. The polymorphic `print` routes through
|
||||
|
||||
Reference in New Issue
Block a user