100%

parser-desugar

Goal

Verify while [label] expr do expr parsing and the landed canon-time desugar to loop { if !cond then break; body }, with typeck LoopForm owning the E0860/E0861 void-context validation.

Implementation Sketch

Verification framing against the landed architecture — not a parse-time rewrite.

Delivered Architecture Note — canon-time desugar is the landed, mission-aligned design

  • The proposal originally prescribed a parse-time desugar. The landed implementation (compiler_repo commit b9939de7d) is canon-time: it keeps ExprKind::While through typeck and desugars at canonicalization via desugar_while at compiler_repo/compiler/ori_canon/src/lower/expr.rs:317.
  • E0860/E0861 are enforced in typeck via LoopForm loop-context tracking — the LoopForm::While loop-context push at compiler_repo/compiler/ori_types/src/infer/expr/control_flow/loops.rs:217 (enum def compiler_repo/compiler/ori_types/src/infer/scope.rs:43) — no parse-level while-derived marker exists or is needed.
  • The landed canon-time design aligns with the missions.md ori_canon mission: sugar eliminated at canonicalization, one shape consumed identically by both backends.
  • w-90fd359e / w-42fab897 VERIFY the landed canon/typeck design (desugar lives in canon; E0860/E0861 live in typeck) and reconcile it against the superseded parse-time prescription — they do NOT contradict the landed work; they confirm it and record the supersession. Execute them as verification, NEVER as a parse-time rewrite. w-78dc9ae8 parse-coverage checks (dispatch, labels) verify as written against parse_while_expr (ori_parse/src/grammar/expr/primary/control_flow.rs:296; dispatch at primary/mod.rs:134); w-bd3a3651 is an audit + GAP-CLOSURE item — only 2 of its enumerated Rust parser tests exist at HEAD (see the item body for the missing cases to author).

Shared-path coverage — walking-skeleton typeck cross-reference + route-order note

  • This section verifies the desugar/typeck path shared with walking-skeleton (s-114d5c42). The HYG-01-001 typeck context-ordering finding is CODE-RESOLVED at HEAD: compiler_repo/compiler/ori_types/src/infer/expr/control_flow/loops.rs:211-218 pushes the LoopContext (form: LoopForm::While, break_value_allowed: false) BEFORE inferring the condition at loops.rs:221, which is the corrected spec-aligned ordering — the push-after-condition defect HYG-01-001 described does not exist at HEAD. The still-open walking-skeleton gaps in this same typeck path are HYG-01-004 (labeled-while matrix) and HYG-01-009 (interaction-test coverage).
  • This section’s parse/desugar deliverables (while parsing, canon-time desugar_while, typeck LoopForm ownership of E0860/E0861) verify INDEPENDENTLY against landed HEAD (feature shipped at compiler commit b9939de7d; execution_mode verify-first). HYG-01-004 / HYG-01-009 are walking-skeleton’s shared-path TEST-COVERAGE gaps, NOT soundness gates on this section — they are a cross-reference for the shared typeck path, not a hard block on this section’s verification. Where this section’s verification touches a cell HYG-01-004/HYG-01-009 also covers, cite the walking-skeleton finding rather than re-deriving it.
  • Route note (orchestrator-owned, not a section edit): route-level section ordering lives in plan.json (engine-owned, hook-denied — not editable from section content). The current route serves parser-desugar before walking-skeleton (the walking-skeleton root sorts last by lexorank). Reconciling that route-order inversion (whether the walking-skeleton root should precede the phase sections) is a plan-structure decision for the /continue-roadmap orchestrator via the plan-corpus route API — surfaced here for the execution record, never resolved by a section hand-edit.

Spec References

while-loop-proposal.md Design (Syntax/Semantics/Labels/No-yield); grammar.ebnf:541 + expression line 370.

Work Items

  • Parse while_expr = "while" [ label ] expression "do" expression . (grammar.ebnf:541) in compiler/ori_parse/ — dispatch on the while keyword in expression position (already reserved, ori-syntax.md keyword-36 list).
  • Verify the landed canon-time desugar: desugar_while (compiler_repo/compiler/ori_canon/src/lower/expr.rs:317) lowers ExprKind::While to loop { if !cond then break; body }; confirm NO parse-time desugar exists in ori_parse (parser emits ExprKind::While, never a synthetic loop) per the Delivered Architecture Note above.
  • Verify break/continue-value rejection ownership: typeck LoopForm loop-context tracking (LoopForm::While push at compiler_repo/compiler/ori_types/src/infer/expr/control_flow/loops.rs:217; enum def compiler_repo/compiler/ori_types/src/infer/scope.rs:43) rejects break value (E0860) / continue value (E0861) inside while — confirm NO parse-level while-derived marker exists or is consulted; the typeck loop-context IS the load-bearing detail. ALSO verify the while expression typechecks as void (per missions.md): binding a while to a non-void type (e.g. let $x: int = while c do body) is rejected by typeck — while...do yields void and cannot satisfy a non-void expected type.
  • Parser-test audit + gap closure: at HEAD only 2 of the enumerated Rust parser tests exist (test_while_loop_parses_with_cond_and_body at ori_parse/src/tests/parser.rs:1459; test_labeled_while_loop_carries_label at parser.rs:1487). Verify those 2, then AUTHOR the missing cases before this item flips complete: do-block body, &&-compound condition, nested while, and a while...yield rejection test (no yield form per the proposal). Labeled while:name cond do body parses with the label riding ExprKind::While (desugar is canon-time; no parse-time synthetic loop).