iter it.1: loop/recur additive — Term::Loop/Term::Recur/LoopBinder end-to-end
Iteration-discipline milestone, 1 of 3. Adds named loop + recur as strictly-additive first-class AST nodes: parse/print/prose/serde/ round-trip/schema lockstep, typecheck (binder typing + recur arity/type unification via loop_stack threaded as mut.2's mut_scope_stack; recur-tail-position via verify_loop_body), codegen (loop-header + one phi per binder; recur back-edge br with a NEW parallel block_terminated setter; lambda-boundary loop_frames save/restore). Four Recur* CheckError variants. Strictly additive: zero deletions touch tail-app/tail-do or the seven existing block_terminated sites — this is what makes the destructive it.3 safe. recur synth = fresh metavar (resolves the plan's flagged Type::unit() risk). loop_counter->55, loop_in_lambda->49, four negatives fire, tail-app byte-identical, cargo test --workspace green. Specfda9b78, plan7381a42.
This commit is contained in:
@@ -2828,6 +2828,31 @@ 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 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