Files
hakorune/docs/development/current/main/phases/phase-137
nyash-codex 5edd81e373 refactor(mir): Phase 138-P1-A - loop_canonicalizer を4モジュール分割
## 概要
- 931行の mod.rs を 4モジュール + 161行 mod.rs に分割
- 全14テスト PASS、退行なし

## モジュール構成
- skeleton_types.rs (213行) - LoopSkeleton/SkeletonStep/UpdateKind/CarrierSlot/ExitContract
- capability_guard.rs (104行) - RoutingDecision/capability_tags
- pattern_recognizer.rs (249行) - try_extract_skip_whitespace_pattern
- canonicalizer.rs (414行) - canonicalize_loop_expr + 統合テスト
- mod.rs (161行) - 型定義と re-export

## ファイルサイズ達成
- 最大ファイル: canonicalizer.rs 414行(目標250行を一部超過するが許容範囲)
- mod.rs: 931行 → 161行 (83%削減)
- 合計: 1141行(元の931行 + tests分離で増加)

## テスト結果
- 14 tests passed
- loop_canonicalizer::* 全テスト green
2025-12-16 06:41:46 +09:00
..

Phase 137: Loop Canonicalizer前処理 SSOT

Status

  • 状態: 🔶 進行中Phase 5 完了)

Goal

  • ループ形の組み合わせ爆発を抑えるため、AST → LoopSkeleton → (capability/routing) の前処理を SSOT 化する。
  • 既存の方針fixture + shape guard + Fail-Fastを維持したまま、pattern 数を増やさずにスケールさせる。

Phase 1完了: 型/語彙の SSOT

  • 実装: src/mir/loop_canonicalizer/mod.rs
    • LoopSkeleton / SkeletonStep / UpdateKind
    • ExitContract / CarrierSlot / CarrierRole
    • RoutingDecision / capability tagsCAP_MISSING_*
  • 注意: Phase 1 は「型と語彙」のみ。routing/lowering にはまだ介入しない。

Phase 2完了: dev-only 観測の導入

  • 入口:
    • Canonicalize: src/mir/loop_canonicalizer/mod.rscanonicalize_loop_expr
    • 観測ポイント: src/mir/builder/control_flow/joinir/routing.rsjoinir_dev_enabled() 配下)
  • 既定挙動: 不変dev-only 観測のみ)

Phase 3: Pattern 検出Skeleton→Decision の精密化)

Phase 3完了: skip_whitespace の安定認識

  • 実装: src/mir/loop_canonicalizer/mod.rstry_extract_skip_whitespace_pattern
  • 効果: tools/selfhost/test_pattern3_skip_whitespace.hakoPattern3IfPhi として認識し、missing_caps=[] を固定できるようになったdev-only 観測)。

注意:

  • routing/lowering の変更は “パリティ検証Phase 4” を挟んでから行う(既定挙動は不変)。

Phase 4完了: Router パリティ検証dev-only / Fail-Fast

  • 目標: 既存 JoinIR ルータ(現行の Pattern 選択)と Canonicalizer の RoutingDecision が一致することを検証し、ズレた場合は理由付きで Fail-Fastdev-only
  • 目的: いきなり routing を差し替えず、安全に "観測→一致→段階投入" の導線を作る。
  • 実装: src/mir/builder/control_flow/joinir/routing.rsverify_router_parity

Phase 5完了: Decision Policy SSOT 化

  • 目標: RoutingDecision.chosen を「lowerer 選択の最終結果」にする(構造クラス名ではなく)
  • 実装:
    • src/mir/loop_canonicalizer/mod.rs: ExitContract に基づく pattern 選択
    • has_break=truePattern2Break(構造的に Pattern3 に似ていても)
    • has_continue=truePattern4Continue
  • 検証: tools/selfhost/test_pattern3_skip_whitespace.hako で parity OKHAKO_JOINIR_STRICT=1
  • 効果:
    • Router と Canonicalizer の一致性確保
    • ExitContract が pattern 選択の決定要因として明確化
    • 構造的特徴if-else 等)は notes に記録(将来の Pattern 細分化に備える)

Phase 6: Router 委譲dev-only / 段階投入)

  • 目標: “既存 router の結果” を最終SSOTとして維持したまま、dev-only で Canonicalizer の RoutingDecision を router 選択に使う経路を用意する。
  • 方針:
    • まず dev-only で RoutingDecision.chosen を router に反映し、strict 時は parity を維持する(ズレたら Fail-Fast
    • 既定挙動dev flags OFFでは現行 router をそのまま使う。

SSOT

  • 設計 SSOT: docs/development/current/main/design/loop-canonicalizer.md
  • JoinIR 契約 SSOT: docs/development/current/main/joinir-architecture-overview.md