Files
hakorune/src/mir/loop_builder/control.rs
nyash-codex 7a1a4bd964 refactor(mir): loop_builder.rs モジュール化 - 6ファイルに分割
## リファクタリング内容

### ファイル構造変更
- `src/mir/loop_builder.rs` (1515行) 削除
- `src/mir/loop_builder/` ディレクトリ新設(6ファイル、1529行)

### 新規モジュール構成

1. **mod.rs** (6,293行 → 実際は約150行)
   - モジュール定義とre-export
   - LoopBuilder構造体定義

2. **loop_form.rs** (25,988行 → 実際は約650行)
   - メインループlowering pipeline
   - デバッグ/実験フラグ集約

3. **if_lowering.rs** (15,600行 → 実際は約390行)
   - In-loop if lowering with JoinIR/PHI bridge
   - **Phase 61-2コード完全保持**:
     - JoinIR dry-run検証モード
     - PhiSpec計算とA/B比較

4. **phi_ops.rs** (12,844行 → 実際は約320行)
   - PHI emit helpers
   - LoopFormOps/PhiBuilderOps impls

5. **control.rs** (4,261行 → 実際は約107行)
   - break/continue capture
   - predecessor bookkeeping

6. **statements.rs** (1,673行 → 実際は約42行)
   - loop-body statement lowering entry point

7. **README.md** (752行 → 実際は約19行)
   - モジュール責務とサブモジュール説明

### 設計原則

- **責務分離**: CFG構築/PHI生成/制御フロー/文処理を分離
- **Phase 61-2保持**: if_lowering.rsにJoinIR dry-run完全移行
- **phi_core委譲**: PHI構築ロジックは`phi_core`に委譲

## テスト結果

- Phase 61-2テスト:  2/2 PASS(dry-runフラグ、PhiSpec)
- loopformテスト:  14/14 PASS(退行なし)
- ビルド:  成功(エラー0件)

## 統計

- **純削減**: -1,521行(25ファイル変更)
- **loop_builder**: 1515行 → 1529行(+14行、6ファイル化)
- **可読性**: 巨大単一ファイル → 責務別モジュール

## ChatGPT設計・Claude確認

大規模リファクタリングをChatGPTが実施、Claudeが検証完了。

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 12:44:40 +09:00

94 lines
4.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use super::{ConstValue, LoopBuilder, ValueId};
use crate::mir::BasicBlockId;
/// ループ脱出の種類(箱化・共通化のための型)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum LoopExitKind {
/// break文exit blockへジャンプ
Break,
/// continue文header blockへジャンプ
Continue,
}
impl<'a> LoopBuilder<'a> {
/// Emit a jump to `target` from the current block and record predecessor metadata.
fn jump_with_pred(&mut self, target: BasicBlockId) -> Result<(), String> {
let cur_block = self.current_block()?;
self.emit_jump(target)?;
let _ = crate::mir::builder::loops::add_predecessor(self.parent_builder, target, cur_block);
Ok(())
}
/// [LoopForm] 【箱化】ループ脱出の共通処理break/continue統一化
///
/// Phase 25.1o: break と continue の共通パターンを抽出し、
/// LoopExitKind で振る舞いを切り替える統一メソッド。
///
/// # 処理フロー
/// 1. 現在の変数マップをスナップショット
/// 2. [LoopForm] スナップショット保存Break → exit_snapshots, Continue → continue_snapshots
/// 3. Void を定義(戻り値用のダミー)
/// 4. [LoopForm] ターゲットブロックへジャンプBreak → exit, Continue → header/continue_merge
/// 5. 現在ブロックはジャンプで終端済みのまま維持(新しい unreachable ブロックは作らない)
fn do_loop_exit(&mut self, kind: LoopExitKind) -> Result<ValueId, String> {
// 1. スナップショット取得(共通処理)
let snapshot = self.get_current_variable_map();
let cur_block = self.current_block()?;
// 2. [LoopForm] exit-break path: スナップショット保存exit PHI入力用
// [LoopForm] continue-backedge path: スナップショット保存continue_merge → header
match kind {
LoopExitKind::Break => {
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
eprintln!(
"[DEBUG/do_break] Saved snapshot from block {:?}, vars: {:?}",
cur_block,
snapshot.keys().collect::<Vec<_>>()
);
}
self.exit_snapshots.push((cur_block, snapshot));
}
LoopExitKind::Continue => {
self.block_var_maps.insert(cur_block, snapshot.clone());
self.continue_snapshots.push((cur_block, snapshot));
}
}
// 3. 戻り値用のダミーを定義(現在ブロック内で完結させる)
let void_id = self.new_value();
self.emit_const(void_id, ConstValue::Void)?;
// 4. ターゲットブロックへジャンプkind別処理
match kind {
LoopExitKind::Break => {
if let Some(exit_bb) = crate::mir::builder::loops::current_exit(self.parent_builder)
{
self.jump_with_pred(exit_bb)?;
}
}
LoopExitKind::Continue => {
// 既定では header にジャンプするが、canonical continue merge を導入した場合は
// continue_target 側を優先する。
if let Some(target) = self.continue_target.or(self.loop_header) {
self.jump_with_pred(target)?;
}
}
}
// 5. 現在ブロックは jump で終端済み。新しい unreachable ブロックは作らない。
Ok(void_id)
}
/// Handle a `break` statement: jump to loop exit and continue in a fresh unreachable block.
/// 【箱化】do_loop_exit() への thin wrapper
pub(super) fn do_break(&mut self) -> Result<ValueId, String> {
self.do_loop_exit(LoopExitKind::Break)
}
/// Handle a `continue` statement: snapshot vars, jump to loop header, then continue in a fresh unreachable block.
/// 【箱化】do_loop_exit() への thin wrapper
pub(super) fn do_continue(&mut self) -> Result<ValueId, String> {
self.do_loop_exit(LoopExitKind::Continue)
}
}