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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user