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:
@@ -1039,6 +1039,12 @@ impl<'a> Emitter<'a> {
|
||||
let _ = self.lower_term(lhs)?;
|
||||
self.lower_term(rhs)
|
||||
}
|
||||
Term::LetRec { .. } => {
|
||||
// Iter 16b.1: `Term::LetRec` is eliminated by the
|
||||
// desugar pass before codegen runs, so reaching it
|
||||
// here is a bug.
|
||||
unreachable!("Term::LetRec eliminated by desugar")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2122,6 +2128,10 @@ impl<'a> Emitter<'a> {
|
||||
Self::collect_captures(lhs, bound, captures, captures_set, builtins, top_level);
|
||||
Self::collect_captures(rhs, bound, captures, captures_set, builtins, top_level);
|
||||
}
|
||||
Term::LetRec { .. } => {
|
||||
// Iter 16b.1: eliminated by desugar before codegen.
|
||||
unreachable!("Term::LetRec eliminated by desugar")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2548,6 +2558,10 @@ impl<'a> Emitter<'a> {
|
||||
}
|
||||
}
|
||||
Term::Seq { rhs, .. } => self.synth_with_extras(rhs, extras),
|
||||
Term::LetRec { .. } => {
|
||||
// Iter 16b.1: eliminated by desugar before codegen.
|
||||
unreachable!("Term::LetRec eliminated by desugar")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2898,6 +2912,11 @@ fn apply_subst_to_term(t: &Term, subst: &BTreeMap<String, Type>) -> Term {
|
||||
lhs: Box::new(apply_subst_to_term(lhs, subst)),
|
||||
rhs: Box::new(apply_subst_to_term(rhs, subst)),
|
||||
},
|
||||
Term::LetRec { .. } => {
|
||||
// Iter 16b.1: eliminated by desugar before any
|
||||
// monomorphisation pass runs.
|
||||
unreachable!("Term::LetRec eliminated by desugar")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user