Files
hakorune/docs/archive/phases/phase-150-167/phase154_mir_cfg_deadblocks.md
nyash-codex d4f90976da refactor(joinir): Phase 244 - ConditionLoweringBox trait unification
Unify condition lowering logic across Pattern 2/4 with trait-based API.

New infrastructure:
- condition_lowering_box.rs: ConditionLoweringBox trait + ConditionContext (293 lines)
- ExprLowerer implements ConditionLoweringBox trait (+51 lines)

Pattern migrations:
- Pattern 2 (loop_with_break_minimal.rs): Use trait API
- Pattern 4 (loop_with_continue_minimal.rs): Use trait API

Benefits:
- Unified condition lowering interface
- Extensible for future lowering strategies
- Clean API boundary between patterns and lowering logic
- Zero code duplication

Test results: 911/911 PASS (+2 new tests)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 02:35:31 +09:00

9.7 KiB
Raw Blame History

Phase 154: MIR CFG 統合 & ブロックレベル unreachable 検出

0. ゴール

hako_check に MIR CFG 情報を取り込み、「到達不能な basic block」を検出する HC020 ルールを追加する。

目的:

  • Phase 153 で復活した dead code 検出メソッド・Box 単位)を、ブロック単位まで細粒度化
  • JoinIR/MIR の CFG 情報を hako_check の Analysis IR に統合
  • 「unreachable basic block」を検出し、コード品質向上に寄与

1. Scope / Non-scope

やること

  1. MIR/CFG 情報のインベントリ

    • 現在の MIR JSON v0 に含まれる CFG 情報blocks, terminatorsを確認
    • hako_check の Analysis IR に追加すべきフィールドを特定
  2. DeadBlockAnalyzerBox の設計(箱化モジュール化)

    • Phase 153 の DeadCodeAnalyzerBox パターンを踏襲
    • 入力: Analysis IRCFG 情報付き)
    • 出力: 未到達ブロックのリスト
  3. hako_check パイプラインへの統合設計

    • Analysis IR 生成時に CFG 情報を含める方法を決定
    • HC020 ルールの位置付けHC019 の後に実行)
  4. テストケース設計(ブロックレベル)

    • 到達不能な if/else 分岐
    • 早期 return 後のコード
    • 常に false のループ条件
  5. 実装 & テスト

    • DeadBlockAnalyzerBox 実装
    • HC020 ルール実装
    • スモークテスト作成
  6. ドキュメント & CURRENT_TASK 更新

やらないこと

  • JoinIR/MIR の意味論を変えない(解析は「読むだけ」)
  • 新しい Stage-3 構文を追加しない
  • 環境変数を増やさないCLI フラグ --dead-blocks のみ)

2. Task 1: MIR/CFG 情報のインベントリ

対象ファイル

  • src/mir/join_ir/json.rs - JoinIR JSON シリアライズ
  • src/mir/join_ir_runner.rs - JoinIR 実行
  • src/mir/ - MIR 構造定義
  • tools/hako_check/analysis_ir.hako - 現在の Analysis IR 定義

やること

  1. MIR JSON v0 の CFG 情報を確認

    • blocks 配列の構造
    • terminator の種類Jump, Branch, Return
    • predecessors / successors の有無
  2. Analysis IR に追加すべきフィールドを特定

    • blocks: Array<BlockInfo> ?
    • cfg_edges: Array<Edge> ?
    • entry_block: BlockId ?
  3. JoinIR Strict モードでの動作確認

    • NYASH_JOINIR_STRICT=1 で MIR が正しく生成されているか
    • Phase 150 の代表ケースで CFG 情報が取れるか

成果物

  • CFG 情報インベントリ結果の記録

3. Task 2: DeadBlockAnalyzerBox の設計(箱化モジュール化)

目的

Phase 153 の DeadCodeAnalyzerBox パターンを踏襲し、ブロックレベル解析を箱化

方針

  • エントリブロックからの到達可能性を DFS/BFS で計算
  • 到達しなかったブロックを列挙
  • 各ブロックがどの関数に属するかも記録

箱単位の設計

DeadBlockAnalyzerBox として:

  • 入力: Analysis IRCFG 情報付き)
  • 出力: 「未到達ブロック」のリスト

API シグネチャ案

static box DeadBlockAnalyzerBox {
  method apply_ir(ir, path, out) {
    // CFG 情報を取得
    local blocks = ir.get("blocks")
    local edges = ir.get("cfg_edges")
    local entry = ir.get("entry_block")

    // 到達可能性解析
    local reachable = me._compute_reachability(entry, edges)

    // 未到達ブロックを検出
    me._report_unreachable_blocks(blocks, reachable, path, out)
  }

  method _compute_reachability(entry, edges) {
    // DFS/BFS で到達可能なブロックを収集
    // return: Set<BlockId>
  }

  method _report_unreachable_blocks(blocks, reachable, path, out) {
    // 到達不能なブロックを HC020 として報告
  }
}

出力フォーマット

[HC020] Unreachable basic block: fn=Main.main bb=10 (after early return)
[HC020] Unreachable basic block: fn=Foo.bar bb=15 (if false branch never taken)

成果物

  • DeadBlockAnalyzerBox の設計API シグネチャ)
  • Analysis IR 拡張フィールド決定

4. Task 3: hako_check パイプラインへの統合設計

目的

HC020 ルールを既存の hako_check パイプラインに統合

やること

  1. Analysis IR 生成の拡張

    • tools/hako_check/analysis_ir.hako を拡張
    • CFG 情報blocks, edges, entry_blockを含める
  2. CLI フラグ追加

    • --dead-blocks フラグで HC020 を有効化
    • または --dead-code に統合(ブロックレベルも含む)
  3. ルール実行順序

    • HC019dead codeの後に HC020dead blocksを実行
    • または --rules dead_blocks で個別指定可能に

設計方針

Option A: --dead-code に統合

# HC019 + HC020 を両方実行
./tools/hako_check.sh --dead-code target.hako

Option B: 別フラグ

# HC019 のみ
./tools/hako_check.sh --dead-code target.hako

# HC020 のみ
./tools/hako_check.sh --dead-blocks target.hako

# 両方
./tools/hako_check.sh --dead-code --dead-blocks target.hako

推奨: Option Aユーザーは「dead code」を広義に捉えるため

成果物

  • パイプライン統合設計
  • CLI フラグ仕様確定

5. Task 4: テストケース設計(ブロックレベル)

テストケース一覧

Case 1: 早期 return 後のコード

static box TestEarlyReturn {
  test(x) {
    if x > 0 {
      return 1
    }
    // ここに到達不能コード
    local unreachable = 42  // HC020 検出対象
    return unreachable
  }
}

Case 2: 常に false の条件

static box TestAlwaysFalse {
  test() {
    if false {
      // このブロック全体が到達不能
      return 999  // HC020 検出対象
    }
    return 0
  }
}

Case 3: 無限ループ後のコード

static box TestInfiniteLoop {
  test() {
    loop(true) {
      // 無限ループ
    }
    // ここに到達不能
    return 0  // HC020 検出対象
  }
}

Case 4: break 後のコード(ループ内)

static box TestAfterBreak {
  test() {
    loop(true) {
      break
      // break 後のコード
      local x = 1  // HC020 検出対象
    }
    return 0
  }
}

成果物

  • テスト .hako ファイル 4 本
  • 期待される HC020 出力の定義

6. Task 5: 実装 & テスト

実装ファイル

  1. tools/hako_check/rules/rule_dead_blocks.hako - 新規作成

    • DeadBlockAnalyzerBox 実装
    • HC020 ルール実装
  2. tools/hako_check/analysis_ir.hako - 拡張

    • CFG 情報フィールド追加
  3. tools/hako_check/cli.hako - 修正

    • --dead-blocks または --dead-code 拡張
    • HC020 実行統合

テストファイル

  1. apps/tests/hako_check/test_dead_blocks_early_return.hako
  2. apps/tests/hako_check/test_dead_blocks_always_false.hako
  3. apps/tests/hako_check/test_dead_blocks_infinite_loop.hako
  4. apps/tests/hako_check/test_dead_blocks_after_break.hako

スモークスクリプト

  • tools/hako_check_deadblocks_smoke.sh - HC020 スモークテスト

成果物

  • DeadBlockAnalyzerBox 実装
  • HC020 ルール実装
  • テストケース 4 本
  • スモークスクリプト

7. Task 6: ドキュメント & CURRENT_TASK 更新

ドキュメント更新

  1. phase154_mir_cfg_deadblocks.md に:

    • 実装結果を記録
    • CFG 統合の最終設計
  2. hako_check_design.md を更新:

    • HC020 ルールの説明
    • CFG 解析機能の説明
  3. CURRENT_TASK.md

    • Phase 154 セクションを追加
  4. CLAUDE.md

    • hako_check ワークフローに --dead-blocks 追記(必要なら)

成果物

  • 各種ドキュメント更新
  • git commit

完成チェックリストPhase 154

  • Task 1: MIR/CFG 情報インベントリ完了
    • CFG 構造確認
    • Analysis IR 拡張フィールド決定
  • Task 2: DeadBlockAnalyzerBox 設計
    • API シグネチャ決定
    • 到達可能性アルゴリズム決定
  • Task 3: パイプライン統合設計
    • CLI フラグ仕様確定
    • ルール実行順序確定
  • Task 4: テストケース設計
    • テスト .hako 4 本設計
  • Task 5: 実装 & テスト
    • DeadBlockAnalyzerBox 実装
    • HC020 ルール実装
    • テストケース実装
    • スモークスクリプト作成
  • Task 6: ドキュメント更新
    • phase154_mir_cfg_deadblocks.md 確定版
    • hako_check_design.md 更新
    • CURRENT_TASK.md 更新
    • git commit

技術的考慮事項

JoinIR Strict モードとの整合性

Phase 150 で確認済みの代表ケースで CFG 情報が取れることを確認:

  • peek_expr_block.hako - match 式、ブロック式
  • loop_min_while.hako - ループ変数、Entry/Exit PHI
  • joinir_min_loop.hako - break 制御
  • joinir_if_select_simple.hako - 早期 return

Analysis IR の CFG 拡張案

{
  "methods": [...],
  "calls": [...],
  "boxes": [...],
  "entrypoints": [...],
  "cfg": {
    "functions": [
      {
        "name": "Main.main",
        "entry_block": 0,
        "blocks": [
          {"id": 0, "successors": [1, 2], "terminator": "Branch"},
          {"id": 1, "successors": [3], "terminator": "Jump"},
          {"id": 2, "successors": [3], "terminator": "Jump"},
          {"id": 3, "successors": [], "terminator": "Return"}
        ]
      }
    ]
  }
}

次のステップ

Phase 154 完了後:

  • Phase 155+: より高度な解析(定数畳み込み、型推論など)
  • Phase 160+: .hako JoinIR/MIR 移植章

作成日: 2025-12-04 Phase: 154MIR CFG 統合 & ブロックレベル unreachable 検出) Status: Historical