Status: Active Date: 2025-12-26 Scope: Phase 286 P2.6.1(Pattern3 Plan line を “完走” させる)手順書。実装は小刻みに、quick smoke green を維持する。 Related: - docs/development/current/main/phases/phase-286/README.md - docs/development/current/main/design/joinir-plan-frag-ssot.md - docs/development/current/main/design/edgecfg-fragments.md # Phase 286 P2.6.1: Pattern3(Loop with If‑Phi)Plan 完走 ## 目的 Pattern3(Loop body 内の if/else により carrier が条件更新される形)を、 legacy JoinIR line(JoinIR→bridge→merge)ではなく Plan/Frag SSOT(CorePlan→Frag→emit_frag)で完走させる。 ### 成功条件(必須) - `bash tools/smokes/v2/profiles/integration/apps/phase118_pattern3_if_sum_vm.sh` が PASS(期待値 12) - `./tools/smokes/v2/run.sh --profile quick` が 0 FAILED(154/154 PASS 維持) - `HAKO_JOINIR_DEBUG=1` で `route=plan ... Pattern3_IfPhi` が出て、legacy fallback に落ちない ## 現状(P2.6 途中の状態) - `extract_pattern3_plan()` は実装済み(DomainPlan を返す) - `PlanNormalizer::normalize_pattern3_if_phi()` は stub(`Err(...)` を返す) - router は Pattern3 のみ “stub fallback” 特例を持つ(`continue` して legacy へ) → P2.6.1 では **normalizer を実装**し、router の特例を撤去して **Fail-Fast** に揃える。 ## 実装方針(重要な制約) - terminator 直生成は禁止(SSOT: `Frag + compose::* + emit_frag()`) - extractor が `Some` を返したら、normalize/lower 失敗は Err(silent fallback 禁止) - Pattern1 の誤マッチ再発を防ぐ(既に router の `pattern_kind` ガードあり) ## 1) Pattern3 の CFG(Plan 側の正本) Pattern3 を “Loop + If + Merge(PHI) + Step” として正規化する。 ```text preheader → header(PHI: i_current, carrier_current) → body(if_condition) ↓ ↓ after then | else ↓ ↓ merge(PHI: carrier_next) ↓ step(i_next) ↓ back-edge to header ``` ポイント: - header に loop_var と carrier の PHI(2本) - then/else で carrier 更新値を作る - merge で carrier_next を PHI で合流 - step で i_next を作り、header に戻す(carrier_next も header PHI に渡る) ## 2) 実装タスク ### 2.1 normalizer 実装 対象: `src/mir/builder/control_flow/plan/normalizer.rs` - `normalize_pattern3_if_phi(...)` を stub から実装へ置換する - 既存の Pattern1/4/9/8 で確立した部品を流用する - `alloc_typed(...)` - `phi_bindings`(PHI dst を AST lowering 時に優先参照) - `lower_value_ast / lower_compare_ast / lower_binop_ast`(phi_bindings 伝播) 最低限の生成物: - blocks: `preheader_bb, header_bb, body_bb, then_bb, else_bb, merge_bb, step_bb, after_bb` - header PHI: - `loop_var_current` inputs: `(preheader_bb, i_init)`, `(step_bb, i_next)` - `carrier_current` inputs: `(preheader_bb, carrier_init)`, `(step_bb, carrier_next)` - merge PHI: - `carrier_next` inputs: `(then_bb, carrier_then)`, `(else_bb, carrier_else)` - frag branches/wires: - header: `if cond_loop then body else after` - body: `if if_condition then then_bb else else_bb` - then_bb: jump → merge_bb - else_bb: jump → merge_bb - merge_bb: jump → step_bb - step_bb: jump → header_bb(back-edge) - final_values: loop_var と carrier は header PHI の値を返す(既存パターンに合わせる) ### 2.2 router の Pattern3 特例撤去(Fail-Fast 統一) 対象: `src/mir/builder/control_flow/joinir/patterns/router.rs` 現状の特例(Pattern3 だけ normalize Err を握りつぶす)を削除し、以下へ統一する: - extractor が `Some(domain_plan)` を返したら `lower_via_plan(...)` の Err はそのまま伝播 - fallback は extractor が `Ok(None)` の場合のみ ## 3) 検証手順(コマンド) ### 3.1 Pattern3 の integration smoke(VM) `bash tools/smokes/v2/profiles/integration/apps/phase118_pattern3_if_sum_vm.sh` ### 3.2 quick regression `./tools/smokes/v2/run.sh --profile quick` ### 3.3 Plan 完走ログ(任意) `HAKO_JOINIR_DEBUG=1 ./target/release/hakorune --backend vm apps/tests/phase118_pattern3_if_sum_min.hako 2>&1 | rg \"route=plan.*Pattern3\"` ## 4) ドキュメント更新(完了時) 完走したら、以下を更新する(本文は短く、成果物リンク中心): - `docs/development/current/main/phases/phase-286/README.md` - P2.6 の Status を `COMPLETE` に更新 - “router の Pattern3 特例撤去(Fail-Fast 統一)” を設計決定として記載 - `docs/development/current/main/10-Now.md` - Current Focus の次対象を更新(例: Pattern2 の設計相談 / Pattern5 / PatternX など)