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. Spec fda9b78, plan 7381a42.
This commit is contained in:
2026-05-15 14:38:55 +02:00
parent 7381a4233b
commit 96db54d15d
38 changed files with 1891 additions and 32 deletions
+25
View File
@@ -2410,6 +2410,22 @@ are real surface forms.
{ "t": "assign",
"name": "<id>",
"value": Term }
// Iter it.1: named loop head. `binders` declares one or more
// lexically-scoped, typed, initialised binders (initialised in
// order); `body` is a single Term in scope of all binders. `recur`
// re-enters the lexically nearest enclosing loop, rebinding the
// binders positionally; it must be in tail position of that loop's
// body. The loop's static type is `body`'s static type.
{ "t": "loop",
"binders": [ { "name": "<id>", "type": Type, "init": Term }, ... ],
"body": Term }
// Iter it.1: backward jump to the lexically nearest enclosing loop;
// tail-position-only; binds that loop's binders. The `args` array is
// always present in canonical JSON (even when empty).
{ "t": "recur",
"args": [ Term, ... ] }
```
In the MVP, `do` is only a direct call to a built-in effect op (no
@@ -2425,6 +2441,15 @@ mut-var into a lambda body is rejected at typecheck via
`CheckError::MutVarCapturedByLambda` (iter mut.4-tidy). See
`docs/specs/2026-05-15-mut-local.md`.
`loop`/`recur` are additive as of iter it.1 (2026-05-15): they
parse, print, prose-project, round-trip, typecheck (binder typing,
recur arity/type unification, recur tail-position) and codegen
(loop-header block with one phi per binder, `recur` as a back-edge
`br`) without removing or modifying the existing `tail-app`/`tail-do`
paths. The structural-recursion restriction and the `Diverge`
effect land in it.2; `tail-app`/`tail-do` are retired in it.3. See
`docs/specs/2026-05-15-iteration-discipline.md`.
**`Literal`**:
```jsonc