## 目的 Canonicalizer の RoutingDecision.chosen を「lowerer 選択の最終結果」にする (構造クラス名ではなく ExitContract ベースの決定) ## 実装内容 ### 1. Canonicalizer の決定ロジック修正 - `src/mir/loop_canonicalizer/mod.rs` - `skip_whitespace` パターン認識で ExitContract (has_break=true) を考慮 - Pattern3IfPhi → Pattern2Break に修正(構造は似ているが break あり) - 単体テスト更新(Pattern2Break 期待に変更) ### 2. Parity 検証テスト修正 - `src/mir/builder/control_flow/joinir/routing.rs` - `test_parity_check_mismatch_detected` → `test_parity_check_skip_whitespace_match` - Canonicalizer と Router の一致を検証(ミスマッチ検出からマッチ検証へ) - Phase 137-5 の SSOT 原則を反映 ### 3. ドキュメント更新 - `docs/development/current/main/design/loop-canonicalizer.md` - Phase 137-5: Decision Policy SSOT セクション追加 - ExitContract 優先の原則を明記 - skip_whitespace の例を追加 - `docs/development/current/main/phases/phase-137/README.md` - Phase 4 完了マーク追加 - Phase 5 完了セクション追加(実装・検証・効果) ## 検証結果 - ✅ 単体テスト: `cargo test --release --lib loop_canonicalizer::tests` (11/11 passed) - ✅ Parity テスト: `cargo test --release --lib 'routing::tests::test_parity'` (2/2 passed) - ✅ Strict モード: `HAKO_JOINIR_STRICT=1` で skip_whitespace parity OK ## 効果 - Router と Canonicalizer の pattern 選択が一致 - ExitContract が pattern 決定の SSOT として明確化 - 構造的特徴(if-else 等)は notes に記録(将来拡張に備える) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Phase 137: Loop Canonicalizer(前処理 SSOT)
Status
- 状態: 🔶 進行中(Phase 3 完了)
Goal
- ループ形の組み合わせ爆発を抑えるため、
AST → LoopSkeleton → (capability/routing)の前処理を SSOT 化する。 - 既存の方針(fixture + shape guard + Fail-Fast)を維持したまま、pattern 数を増やさずにスケールさせる。
Phase 1(完了): 型/語彙の SSOT
- 実装:
src/mir/loop_canonicalizer/mod.rsLoopSkeleton/SkeletonStep/UpdateKindExitContract/CarrierSlot/CarrierRoleRoutingDecision/ capability tags(CAP_MISSING_*)
- 注意: Phase 1 は「型と語彙」のみ。routing/lowering にはまだ介入しない。
Phase 2(完了): dev-only 観測の導入
- 入口:
- Canonicalize:
src/mir/loop_canonicalizer/mod.rs(canonicalize_loop_expr) - 観測ポイント:
src/mir/builder/control_flow/joinir/routing.rs(joinir_dev_enabled()配下)
- Canonicalize:
- 既定挙動: 不変(dev-only 観測のみ)
Phase 3(次): Pattern 検出(Skeleton→Decision の精密化)
Phase 3(完了): skip_whitespace の安定認識
- 実装:
src/mir/loop_canonicalizer/mod.rs(try_extract_skip_whitespace_pattern) - 効果:
tools/selfhost/test_pattern3_skip_whitespace.hakoをPattern3IfPhiとして認識し、missing_caps=[]を固定できるようになった(dev-only 観測)。
注意:
- routing/lowering の変更は “パリティ検証(Phase 4)” を挟んでから行う(既定挙動は不変)。
Phase 4(完了): Router パリティ検証(dev-only / Fail-Fast)
- 目標: 既存 JoinIR ルータ(現行の Pattern 選択)と Canonicalizer の
RoutingDecisionが一致することを検証し、ズレた場合は理由付きで Fail-Fast(dev-only)。 - 目的: いきなり routing を差し替えず、安全に "観測→一致→段階投入" の導線を作る。
- 実装:
src/mir/builder/control_flow/joinir/routing.rs(verify_router_parity)
Phase 5(完了): Decision Policy SSOT 化
- 目標:
RoutingDecision.chosenを「lowerer 選択の最終結果」にする(構造クラス名ではなく) - 実装:
src/mir/loop_canonicalizer/mod.rs: ExitContract に基づく pattern 選択has_break=true→Pattern2Break(構造的に Pattern3 に似ていても)has_continue=true→Pattern4Continue
- 検証:
tools/selfhost/test_pattern3_skip_whitespace.hakoで parity OK(HAKO_JOINIR_STRICT=1) - 効果:
- Router と Canonicalizer の一致性確保
- ExitContract が pattern 選択の決定要因として明確化
- 構造的特徴(if-else 等)は
notesに記録(将来の Pattern 細分化に備える)
SSOT
- 設計 SSOT:
docs/development/current/main/design/loop-canonicalizer.md - JoinIR 契約 SSOT:
docs/development/current/main/joinir-architecture-overview.md