Files
hakorune/docs/development/roadmap/phases/phase-25.1g
nyash-codex d3cbc71c9b feat(mir): Phase 25.1f完了 - Conservative PHI + ControlForm観測レイヤー
🎉 Conservative PHI Box理論による完全SSA構築

**Phase 7-B: Conservative PHI実装**
- 片方branchのみ定義変数に対応(emit_void使用)
- 全変数にPHI生成(Conservative Box理論)
- Stage-1 resolver全テスト緑化(3/3 PASS)

**Phase 25.1f: ControlForm観測レイヤー**
- LoopShape/IfShape/ControlForm構造定義
- Loop/If統一インターフェース実装
- debug_dump/debug_validate機能追加
- NYASH_CONTROL_FORM_TRACE環境変数対応

**主な変更**:
- src/mir/builder/phi.rs: Conservative PHI実装
- src/mir/control_form.rs: ControlForm構造(NEW)
- src/mir/loop_builder.rs: LoopForm v2デフォルト化

**テスト結果**:
 mir_stage1_using_resolver_min_fragment_verifies
 mir_stage1_using_resolver_full_collect_entries_verifies
 mir_parserbox_parse_program2_harness_parses_minimal_source

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: ChatGPT <chatgpt@openai.com>
2025-11-18 18:56:35 +09:00
..

Phase 25.1g — Conservative PHI ↔ ControlForm 統合(設計+小さな導線)

Status: planning設計・導線追加既存挙動は変えない

ゴール

  • 25.1f で整えた ControlForm 観測レイヤーLoopShape / IfShape + ControlFormを、
    Conservative PHI BoxIf/Loop 用 SSA/PHI ロジック)の入口として使えるようにする。
  • いきなりすべてを書き換えるのではなく、
    1. If 用 Conservative PHI → ControlForm 対応
    2. LoopForm v2 Exit PHI → ControlForm 対応 の順に、小さく段階的に寄せる。
  • 各ステップごとに Rust テストと tools/test_stageb_min.sh を流しつつ、
    SSA/PHI の赤ログが増えていないことを確認して進む。

前提25.1f までで揃ったもの)

  • Rust:
    • src/mir/control_form.rs:
      • LoopShape / IfShape / ControlKind / ControlForm / CfgLike / is_control_form_trace_on() が定義済み。
    • src/mir/loop_builder.rs:
      • LoopForm v2 経路(build_loop_with_loopform)の出口で LoopShapeControlForm::Loop を生成・トレース。
      • lower_if_in_loop の merge 部分で IfShapeControlForm::If を生成・トレース。
      • NYASH_CONTROL_FORM_TRACE(未設定=ON, 0/false=OFFでトレース ON/OFF 切り替え可能。
    • Conservative PHI:
      • If 用: src/mir/builder/phi.rs / src/mir/phi_core/if_phi.rsConservative PHI Box 実装)。
      • Loop 用: src/mir/phi_core/loopform_builder.rsLoopForm v2 の Exit PHI / Carrier/Pinned 対応)。
  • .hako:
    • lang/src/shared/mir/control_form_box.hako:
      • static box ControlFormBoxkind_name + loop_* / if_* + entry/exitsだけ実装済みまだ未使用

方針Option B の範囲)

  • このフェーズでは:
    • Conservative PHI の「インターフェースと呼び出し位置」に ControlForm の導線を用意する。
    • ただし既存のロジック(引数で BlockId を受け取る形は残し、ControlForm 導線は 観測+補助的な入口 として扱う。
    • 影響範囲は If / Loop の PHI 部分に限定し、他の MIR 降下には触れない。
  • 実装方針:
    • 新しい API を「足す」→ 既存コードから段階的に使い始める、という形で進める。
    • 例:
      • If 用: merge_modified_at_merge_with_control(form: &ControlForm, ...) を追加。
      • Loop 用: build_exit_phis_for_control(form: &ControlForm, ...) を追加。
    • 最初のステップでは「ControlForm から必要な BlockId を取り出して、既存の関数に委譲するだけ」の薄いラッパにする。

タスク粒度

G1: If 用 Conservative PHI への ControlForm 導線

  • 目的:
    • loop_builder.rs::lower_if_in_loop から、ControlForm::If を PHI ロジックに渡せるようにする。
  • ステップ:
    1. src/mir/phi_core/if_phi.rs に薄いラッパ関数を追加:
      pub fn merge_modified_with_control<O: PhiMergeOps>(
          ops: &mut O,
          form: &crate::mir::control_form::ControlForm,
          pre_if_snapshot: &HashMap<String, ValueId>,
          then_map_end: &HashMap<String, ValueId>,
          else_map_end_opt: &Option<HashMap<String, ValueId>>,
          skip_var: Option<&str>,
      ) -> Result<(), String> {
          // ControlForm::If から cond/then/else/merge を取り出し、
          // 既存の merge_modified_at_merge_with に橋渡しするだけ(ロジックは変えない)。
      }
      
    2. lower_if_in_loop 側で:
      • 既存の merge_modified_at_merge_with 呼び出しの直前/直後にコメントを付け、
      • 将来的に merge_modified_with_control に置き換えられるように位置を明示する25.1g ではまだ呼び替えない or dev フラグで限定)。
    3. テスト:
      • cargo test -q mir_stage1_using_resolver_min_fragment_verifies -- --nocapture
      • cargo test -q mir_stage1_using_resolver_full_collect_entries_verifies -- --nocapture
      • 必要なら NYASH_CONTROL_FORM_TRACE=1 で IfShape ログを確認し、BlockId 対応が設計どおりかを確認。

G2: LoopForm v2 Exit PHI への ControlForm 導線

  • 目的:
    • LoopForm v2 Exit PHIloopform_builder.rs::build_exit_phis)にも ControlForm ベースの入口を用意する。
  • ステップ:
    1. src/mir/phi_core/loopform_builder.rs にラッパ関数追加:
      pub fn build_exit_phis_for_control<O: LoopFormOps>(
          loopform: &LoopFormBuilder,
          ops: &mut O,
          form: &crate::mir::control_form::ControlForm,
          exit_snapshots: &[(BasicBlockId, HashMap<String, ValueId>)],
      ) -> Result<(), String> {
          // form.kind が Loop の場合に限り、
          // shape.preheader/header/body/latch/exit から exit_id/branch_source_block を決めて
          // 既存の build_exit_phis に委譲するだけ。
      }
      
    2. LoopBuilder::build_loop_with_loopform からは:
      • 現在どおり loopform.build_exit_phis(self, exit_id, branch_source_block, &exit_snaps) を呼び続ける。
      • コメントで「ControlForm 経由の入口」があることを明示し、将来の切り替えポイントを固定する。
    3. テスト:
      • cargo test -q mir_loopform_exit_phi -- --nocapture
      • cargo test -q mir_stageb_loop_break_continue -- --nocapture
      • ./tools/test_stageb_min.sh を流して、Exit PHI 誘発系の赤ログが増えていないことを確認。

G3: ControlForm ↔ Conservative PHI の設計メモ更新

  • 目的:
    • 25.1d/e/f/g の成果をまとめ、「If/Loop の PHI が最終的にどのレイヤで SSOT を持つか」を文書で固定する。
  • ステップ:
    • phase-25.1d/README.mdphase-25.1f/README.md をリンクしつつ、
      • Conservative PHI Box の責務If/Loop 両方)
      • ControlForm レイヤの責務
      • .hako 側 ControlFormBox / LoopSSA の予定 を Phase 25 全体の流れの中に整理して追記する。
    • CURRENT_TASK.md に 25.1g の短いサマリを追加して、今どこまで進めたかをいつでも追えるようにする。

このフェーズで「しない」こと

  • 既存の Conservative PHI 実装を一気に ControlForm 専用に書き換えること:
    • 25.1g は「導線追加+ラッパ」「設計固め」まで。
    • 実際の置き換えOption B の本体)は、さらに小さなステップに分けて後続フェーズで行う。
  • LoopBuilder/If 降下の大規模リファクタOption C 相当):
    • これは Phase 25.2 以降の仕事として残しておく。