Files
hakorune/docs/development/current/main/phase121_legacy_path_analysis.md
nyash-codex bb3dd6c2a4 docs(joinir): Phase 121 hako_check JoinIR integration design
## Phase 121: hako_check JoinIR 統合設計 (完了)

### 概要
hako_check経路のJoinIR統合に向けた設計と現状調査を完了。
実装修正なし、設計と調査のみ(Phase 122+で実装予定)。

### 完了タスク
-  設計ドキュメント作成: hako_check_design.md
-  現状調査完了: phase121_hako_check_investigation.md
-  旧MIR/PHI経路特定: phase121_legacy_path_analysis.md
-  統合計画策定: phase121_integration_roadmap.md
-  Phase 120との関係整理完了

### 重要な発見
1. **hako_checkは.hakoスクリプト**
   - Rustバイナリではなく、.hakoスクリプトとして実装
   - tools/hako_check/cli.hako がエントリーポイント
   - VM の MirBuilder に JoinIR 統合すれば自動的に対応

2. **If文は旧経路、Loopは部分統合**
   - If文 (src/mir/builder/if_form.rs):  旧PHI生成器使用中
   - Loop (src/mir/builder/control_flow.rs): ⚠️ Mainline Targetsのみ統合

3. **環境変数未整備**
   - JoinIR経路選択の統一的な環境変数なし
   - Phase 122で `NYASH_HAKO_CHECK_JOINIR=1` 追加予定

### Phase 122-124 統合計画
**3段階移行戦略**:
- **Phase 122**: 環境変数で選択可能(デフォルト旧経路)
- **Phase 123**: JoinIR デフォルト化(旧経路は NYASH_LEGACY_PHI=1)
- **Phase 124**: 旧経路完全削除(JoinIR のみ)

**タイムライン**: 3日で hako_check JoinIR 統合完了見込み

### Phase 122 への指針
**最優先課題**:
1. If文の JoinIR 統合 (src/mir/builder/if_form.rs)
2. Loop の JoinIR 統合拡張 (Mainline Targets 制限解除)
3. 環境変数 NYASH_HAKO_CHECK_JOINIR=1 の追加

**実装ステップ** (Phase 122):
- Step 1: 環境変数読み込み (30分)
- Step 2: If文の JoinIR 統合 (2-3時間)
- Step 3: Loop の JoinIR 統合拡張 (1-2時間)
- Step 4: テスト追加 (1-2時間)
- Step 5: ドキュメント更新 (30分)

### ファイル構成
**新規作成**:
- docs/development/current/main/phase121_hako_check_joinir_design.md (指示書)
- docs/development/current/main/hako_check_design.md (設計)
- docs/development/current/main/phase121_hako_check_investigation.md (調査)
- docs/development/current/main/phase121_legacy_path_analysis.md (旧経路特定)
- docs/development/current/main/phase121_integration_roadmap.md (統合計画)

**修正**:
- CURRENT_TASK.md (Phase 121完了記録追加)

### 技術的成果
- Phase 120: selfhost経路のベースライン確立
- Phase 121: hako_check統合計画の設計 ← Complete
- Phase 122+: 段階的実装(予定)

設計First原則の実践により、実装前に明確な指針を確立しました。

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 04:42:32 +09:00

11 KiB
Raw Blame History

Phase 121: 旧 MIR/PHI 経路の特定

旧経路の定義

旧 MIR/PHI 経路とは:

  • JoinIR Lowering 前の PHI 生成器を直接使用している経路
  • Phase 33 以前の実装If/Loop PHI 生成が直接 MirBuilder に組み込まれていた時期)
  • Phase 33-10 で JoinIR If/Loop Lowering が実装されたが、MirBuilder への統合は未完

特定方法

1. ファイル名での特定

旧経路候補

ファイル 状態 用途
src/mir/builder/if_form.rs 現役 旧 If PHI 生成器JoinIR 未統合)
src/mir/builder/control_flow.rs ⚠️ 部分統合 Loop PHI 生成器Mainline のみ JoinIR
src/mir/loop_builder.rs 調査中 旧 Loop PHI 生成器Phase 33-10 で削除済み?)

JoinIR 経路

ファイル 状態 用途
src/mir/join_ir/lowering/if_select.rs 実装済み JoinIR If Lowering
src/mir/join_ir/lowering/loop_*.rs 実装済み JoinIR Loop Lowering
src/mir/join_ir/frontend/mod.rs 実装済み AST → JoinIR 変換

2. 関数名での特定

旧経路の特徴的関数

If 文src/mir/builder/if_form.rs:

// 旧 If PHI 生成器Phase 121 時点で現役)
pub fn cf_if(
    &mut self,
    condition: &ASTNode,
    then_block: &ASTNode,
    else_block: Option<&ASTNode>,
) -> Result<ValueId, String> {
    // 旧 PHI 生成ロジック
    // - BasicBlock 直接操作
    // - PHI 命令を手動で挿入
    // - JoinIR Lowering を経由しない
}

特徴:

  • BasicBlock::phi() を直接呼び出し
  • merge_phi_for_if() 等のヘルパー関数使用
  • JoinIR Lowering を経由しない

Loopsrc/mir/builder/control_flow.rs:

// Phase 49: 部分的に JoinIR 統合済み
pub fn cf_loop(
    &mut self,
    condition: &ASTNode,
    body: &ASTNode,
) -> Result<ValueId, String> {
    // Phase 49/80: Try JoinIR Frontend route for mainline targets
    if let Some(result) = self.try_cf_loop_joinir(&condition, &body)? {
        return Ok(result);
    }

    // Fallback: 旧 LoopBuilder
    self.cf_loop_legacy(condition, body)
}

特徴:

  • try_cf_loop_joinir() で JoinIR 経由を試みる
  • 失敗時は cf_loop_legacy() へフォールバック
  • Mainline Targets のみ JoinIR 経由

JoinIR 経路の関数

If Loweringsrc/mir/join_ir/lowering/if_select.rs:

// JoinIR If LoweringPhase 33-10 実装済み)
pub fn lower_if_to_mir(...) -> Result<ValueId, String> {
    // JoinIR ベースの If Lowering
    // - IfMerge/IfSelect 命令を生成
    // - PHI 命令を自動生成
}

Loop Loweringsrc/mir/join_ir/lowering/loop_*.rs:

// JoinIR Loop LoweringPhase 33 実装済み)
pub fn lower_loop_to_mir(...) -> Result<ValueId, String> {
    // JoinIR ベースの Loop Lowering
    // - LoopForm を使用
    // - PHI 命令を自動生成
}

3. 環境変数での特定

旧経路のフラグ

Phase 121 調査結果: 明示的な旧経路フラグは存在しない

理由:

  • 旧経路がデフォルトのため、フラグで有効化する必要がない
  • Phase 122 で NYASH_LEGACY_PHI=1 を導入予定

JoinIR 経路のフラグ

環境変数 用途 実装箇所
NYASH_JOINIR_STRICT=1 フォールバック禁止(厳格モード) src/config/env.rs
NYASH_JOINIR_CORE=1 JoinIR Core 有効化 src/config/env.rs
HAKO_JOINIR_PRINT_TOKENS_MAIN=1 print_tokens を JoinIR 経由 src/mir/builder/control_flow.rs
HAKO_JOINIR_ARRAY_FILTER_MAIN=1 ArrayExt.filter を JoinIR 経由 src/mir/builder/control_flow.rs

hako_check での使用状況

If 文の PHI 生成

使用経路: 旧経路src/mir/builder/if_form.rs

根拠:

  1. ファイル: src/mir/builder/if_form.rs が現役
  2. 関数: cf_if() が JoinIR Lowering を呼び出していない
  3. コード抜粋:
// src/mir/builder/if_form.rs:L1-L50
pub fn cf_if(
    &mut self,
    condition: &ASTNode,
    then_block: &ASTNode,
    else_block: Option<&ASTNode>,
) -> Result<ValueId, String> {
    // 旧 PHI 生成ロジックJoinIR Lowering 未使用)
    // ...
}

問題点:

  • Phase 33-10 で JoinIR If Lowering が実装済み(if_select.rs
  • しかし MirBuilder の cf_if() はまだ JoinIR を呼び出していない
  • hako_check で If 文を含むコードを解析する際、旧 PHI 生成器が使われる

Loop の PHI 生成

使用経路: ⚠️ 混在Mainline Targets のみ JoinIR 経由)

根拠:

  1. ファイル: src/mir/builder/control_flow.rs
  2. 関数: cf_loop()try_cf_loop_joinir()
  3. コード抜粋:
// src/mir/builder/control_flow.rs:L150-L200
pub fn cf_loop(
    &mut self,
    condition: &ASTNode,
    body: &ASTNode,
) -> Result<ValueId, String> {
    // Phase 49/80: Try JoinIR Frontend route for mainline targets
    if let Some(result) = self.try_cf_loop_joinir(&condition, &body)? {
        return Ok(result);
    }

    // Fallback: 旧 LoopBuilder
    self.cf_loop_legacy(condition, body)
}

Mainline Targets (JoinIR 経由):

  • JsonTokenizer.print_tokens/0
  • ArrayExtBox.filter/2

その他の Loop (旧経路):

  • 上記以外のすべての Loop 文

Phase 122+ での移行計画

移行必要箇所

1. If 文の JoinIR 統合(最優先)

ファイル: src/mir/builder/if_form.rs

現状: 旧 PHI 生成器を使用中

移行方法:

// Phase 122: 環境変数で JoinIR 経路を選択可能に
pub fn cf_if(
    &mut self,
    condition: &ASTNode,
    then_block: &ASTNode,
    else_block: Option<&ASTNode>,
) -> Result<ValueId, String> {
    // Phase 122: 環境変数チェック
    if crate::config::env::env_bool("NYASH_HAKO_CHECK_JOINIR") {
        // JoinIR If Lowering を使用
        return self.cf_if_joinir(condition, then_block, else_block);
    }

    // 旧 PHI 生成器(互換性維持)
    self.cf_if_legacy(condition, then_block, else_block)
}

fn cf_if_joinir(
    &mut self,
    condition: &ASTNode,
    then_block: &ASTNode,
    else_block: Option<&ASTNode>,
) -> Result<ValueId, String> {
    // JoinIR If Lowering を呼び出す
    use crate::mir::join_ir::lowering::if_select::lower_if_to_mir;
    lower_if_to_mir(self, condition, then_block, else_block)
}

実装ステップ:

  1. cf_if_joinir() 関数を追加JoinIR Lowering 呼び出し)
  2. cf_if() に環境変数チェックを追加
  3. 既存ロジックを cf_if_legacy() に移動

2. Loop の JoinIR 統合拡張(優先度中)

ファイル: src/mir/builder/control_flow.rs

現状: ⚠️ Mainline Targets のみ JoinIR 経由

移行方法:

// Phase 122: すべての Loop を JoinIR 経由に
pub fn cf_loop(
    &mut self,
    condition: &ASTNode,
    body: &ASTNode,
) -> Result<ValueId, String> {
    // Phase 122: 環境変数チェック
    if crate::config::env::env_bool("NYASH_HAKO_CHECK_JOINIR") {
        // すべての Loop を JoinIR 経由に
        if let Some(result) = self.try_cf_loop_joinir(&condition, &body)? {
            return Ok(result);
        }
    }

    // Phase 49: Mainline Targets のみ JoinIR 経由(既存ロジック)
    if let Some(result) = self.try_cf_loop_joinir(&condition, &body)? {
        return Ok(result);
    }

    // Fallback: 旧 LoopBuilder
    self.cf_loop_legacy(condition, body)
}

実装ステップ:

  1. try_cf_loop_joinir() の Mainline Targets 制限を削除
  2. 環境変数で制御するように変更
  3. フォールバックロジックを整理

既に JoinIR 統合済み

1. Loop Mainline TargetsPhase 49

ファイル: src/mir/builder/control_flow.rs

詳細:

  • JsonTokenizer.print_tokens/0: JoinIR 経由で動作確認済み
  • ArrayExtBox.filter/2: JoinIR 経由で動作確認済み

実装:

// Phase 49: Mainline Integration
fn try_cf_loop_joinir(&mut self, condition: &ASTNode, body: &ASTNode) -> Result<Option<ValueId>, String> {
    let core_on = crate::config::env::joinir_core_enabled();

    // Mainline targets
    let mainline_targets = vec!["print_tokens", "filter"];

    if core_on && is_mainline_target(&func_name) {
        // JoinIR Frontend を使用
        return self.cf_loop_joinir_impl(condition, body, &func_name, debug);
    }

    Ok(None)
}

2. JoinIR FrontendPhase 49

ファイル: src/mir/join_ir/frontend/mod.rs

詳細:

  • AstToJoinIrLowerer: AST → JoinIR 変換
  • JSON v0 → JoinIR 変換
  • JoinModule 生成

旧経路と JoinIR 経路の比較

If 文

項目 旧経路 JoinIR 経路
ファイル src/mir/builder/if_form.rs src/mir/join_ir/lowering/if_select.rs
関数 cf_if() lower_if_to_mir()
PHI 生成 手動BasicBlock::phi() 自動IfMerge/IfSelect
統合状況 現役使用中 実装済み(未統合)
環境変数 なし NYASH_HAKO_CHECK_JOINIR=1Phase 122

Loop

項目 旧経路 JoinIR 経路
ファイル src/mir/builder/control_flow.rs src/mir/join_ir/frontend/mod.rs
関数 cf_loop_legacy() cf_loop_joinir_impl()
PHI 生成 手動LoopBuilder 自動LoopForm
統合状況 ⚠️ フォールバック経路 ⚠️ Mainline Targets のみ
環境変数 なし HAKO_JOINIR_*_MAIN=1

コード削減見込み

Phase 122 完了後

削減箇所:

  • src/mir/builder/if_form.rs: 旧 PHI 生成ロジック削除可能Phase 124
  • src/mir/builder/control_flow.rs: cf_loop_legacy() 削除可能Phase 124

削減見込み:

  • if_form.rs: 約 200-300 行削減
  • control_flow.rs: 約 100-150 行削減
  • 合計: 約 300-450 行削減

Phase 124 完了後(旧経路完全削除)

削減箇所:

  • 旧 PHI 生成ヘルパー関数削除
  • フォールバックロジック削除
  • 環境変数制御コード削除

削減見込み:

  • 合計: 約 500-600 行削減MirBuilder 全体の約 5-10%

まとめ

hako_check 経路の旧 MIR/PHI 使用状況:

旧経路使用中: 1箇所

  1. If 文の PHI 生成src/mir/builder/if_form.rs
    • ファイル: if_form.rs
    • 関数: cf_if()
    • 根拠: JoinIR Lowering を呼び出していない

⚠️ 部分的統合: 1箇所

  1. Loop の PHI 生成src/mir/builder/control_flow.rs
    • ファイル: control_flow.rs
    • 関数: cf_loop()try_cf_loop_joinir()
    • 根拠: Mainline Targets のみ JoinIR 経由、その他はフォールバック

JoinIR 統合済み: 0箇所完全統合は未完

Phase 122+ で段階的に JoinIR 統合を完了する。

最優先課題: If 文の JoinIR 統合src/mir/builder/if_form.rs