Iter 16b.1 — local recursive let (no-capture)
Add `(let-rec NAME (params ...) (type ...) (body ...) (in ...))` as a form-A surface and a `Term::LetRec` AST variant. The 16a desugar pass lifts each LetRec whose body has no captures from the enclosing scope to a synthetic top-level fn `<hint>$lr_N` and substitutes the original name; typecheck and codegen never see LetRec. Capture detection panics at desugar time, queued for 16b.2. Tests: 95 → 99 (+1 e2e local_rec_factorial_demo, +2 desugar unit, +1 parse unit). The new fixture `examples/local_rec_demo` runs `fact` at n=1, 3, 5 → prints 1, 6, 120. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -432,6 +432,24 @@ fn std_list_more_demo() {
|
||||
assert_eq!(lines, vec!["0", "3", "5", "5", "3", "0"]);
|
||||
}
|
||||
|
||||
/// Iter 16b.1: local recursive `let`. Property protected: a
|
||||
/// `(let-rec ...)` term in a fn body whose recursive body has no
|
||||
/// captures from the enclosing scope is lifted by the 16a desugar
|
||||
/// pass to a synthetic top-level fn (`<name>$lr_N`), and the
|
||||
/// resulting module type-checks and runs identically to a
|
||||
/// hand-written top-level recursive fn. The fixture exercises
|
||||
/// `fact` at n=1 (base case), n=3, n=5 — outputs 1, 6, 120.
|
||||
/// If the desugar lift regressed (e.g. failed to substitute call
|
||||
/// sites in the in-term, or generated a colliding lifted name),
|
||||
/// the build would fail at typecheck or the binary would print
|
||||
/// wrong values.
|
||||
#[test]
|
||||
fn local_rec_factorial_demo() {
|
||||
let stdout = build_and_run("local_rec_demo.ail.json");
|
||||
let lines: Vec<&str> = stdout.lines().collect();
|
||||
assert_eq!(lines, vec!["1", "6", "120"]);
|
||||
}
|
||||
|
||||
/// Guards `ail diff`: a modified body changes the hash of `sum`, while
|
||||
/// `main` stays unchanged. Expects exit code 1, `changed` contains exactly
|
||||
/// `sum`, `unchanged` contains `main`, `added`/`removed` empty.
|
||||
|
||||
Reference in New Issue
Block a user