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::Whilethrough typeck and desugars at canonicalization viadesugar_whileatcompiler_repo/compiler/ori_canon/src/lower/expr.rs:317. - E0860/E0861 are enforced in typeck via
LoopFormloop-context tracking — theLoopForm::Whileloop-context push atcompiler_repo/compiler/ori_types/src/infer/expr/control_flow/loops.rs:217(enum defcompiler_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_canonmission: 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-218pushes theLoopContext(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, typeckLoopFormownership 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-roadmaporchestrator 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) incompiler/ori_parse/— dispatch on thewhilekeyword 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) lowersExprKind::Whiletoloop { if !cond then break; body }; confirm NO parse-time desugar exists inori_parse(parser emitsExprKind::While, never a synthetic loop) per the Delivered Architecture Note above. - Verify break/continue-value rejection ownership: typeck
LoopFormloop-context tracking (LoopForm::Whilepush atcompiler_repo/compiler/ori_types/src/infer/expr/control_flow/loops.rs:217; enum defcompiler_repo/compiler/ori_types/src/infer/scope.rs:43) rejectsbreak 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 thewhileexpression typechecks asvoid(per missions.md): binding awhileto a non-void type (e.g.let $x: int = while c do body) is rejected by typeck —while...doyieldsvoidand 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_bodyat ori_parse/src/tests/parser.rs:1459;test_labeled_while_loop_carries_labelat parser.rs:1487). Verify those 2, then AUTHOR the missing cases before this item flips complete: do-block body,&&-compound condition, nested while, and awhile...yieldrejection test (no yield form per the proposal). Labeledwhile:name cond do bodyparses with the label ridingExprKind::While(desugar is canon-time; no parse-time synthetic loop).