block labels

This commit is contained in:
2026-06-28 08:51:01 +02:00
parent 3e54c6f9ad
commit eaa66511a0
7 changed files with 352 additions and 60 deletions
+16 -9
View File
@@ -360,7 +360,7 @@
fall out of these naturally
- follow-ups: a branch that early-`return`s instead of yielding, unwrap-`if` as a value
source, and `none`-before-concrete typing in untyped loops are done in 20.6; labeled value
blocks and `yield`/`break` to an outer loop are 20.7 (need labels in the IR)
blocks and `yield`/`break` to an outer loop are done in 20.7
20.6 value if/loop follow-ups (implemented; checker-only)
- a value-if branch may end in `yield` **or** exit on every path (`return`/`break`/
@@ -377,16 +377,23 @@
`none` yielded before any concrete value still resolves the result to `?T`
- still checker-only; no HIR/lowering change
20.7 labeled value blocks + `yield`/`break` to an outer loop (introduces labels in the IR)
20.7 labels — value blocks + yield/break to an outer loop (implemented; first lowering change)
- `x :: blk: { …; yield :blk v }` — a labeled value *block* (the disambiguated form of "an
if/loop at the end of a block"; an unlabeled trailing if/loop stays ambiguous and is not a
value source). `yield :blk v` exits the block with a value
- `yield :outer v` / labeled `break` to a non-innermost loop
- both need exit targets to carry a label: add `label` to HIR `.While`/`.For`/`.Break` and a
labeled `.Block`; generalize the lowering's `Loop_Ctx`/`State.loops` into an exit-target
stack keyed by label (plain `break`/`continue` stay innermost-only; a labeled `.Break`
searches by label; a labeled block pushes a non-loop target + an exit label after its body).
First lowering change in the `yield` line
value source). `yield :blk v` exits the block with a value; every path must yield. Carries
the same `{T, none}` → `?T` typing, defer-capture, and reassignment forms as value loops
- `yield :outer v` to an enclosing (non-innermost) value loop/block, plus plain `break :L` /
`continue :L` to an enclosing labeled loop
- a label now names a first-class exit target: `label` added to the HIR `Stmt` (on
`.While`/`.For`/`.Break`/`.Continue`) and a new HIR `.Block` kind (lowers to its body + an
exit label). The lowering's `Loop_Ctx`/`State.loops` became a label-keyed exit-target stack
(`is_loop` distinguishes loops from value blocks; plain `break`/`continue` take the innermost
loop, a labeled one searches by label). The checker tracks a `loop_labels` stack and a
`Yield_Target.defer_floor`; a `yield :L v` desugars to `slot = v; flush defers to L's body;
break :L`, reusing the milestone-18 break lowering — **no new IR opcode, no emitter change**
- deferred (`// ponytail:`): a labeled bare block as a *plain statement* with `break :blk`;
`none`-before-concrete typing in an untyped block whose first concrete yield references a
block local (annotate instead)
21. unions and tagged unions