refactor(mir): Phase 25.1o - do_break/continue 共通化(LoopExitKind型統一)
【変更内容】 1. LoopExitKind enum定義 - Break / Continue の型安全な区別 2. do_loop_exit() 共通メソッド作成(47行) - スナップショット取得(共通処理) - kind別のスナップショット保存 - kind別のジャンプターゲット - unreachable ブロック切り替え(共通処理) 3. do_break/continue をthin wrapperに変換 - do_break: 13行 → 4行 - do_continue: 12行 → 4行 - 合計21行削減 【効果】 - 構造改善: break/continue の共通ロジック一箇所に集約 - 保守性向上: デバッグログなどの共通処理が統一管理 - 拡張性向上: labeled break/continue等の将来拡張が容易 【検証結果】 - ビルド成功(警告なし) - mir_stageb_loop_break_continue_verifies: PASS - /tmp/loop_continue_fixed.hako: RC=3(期待通り) 関連: Phase 25.1m (continue PHI修正), Phase 25.1n (レガシー削除)
This commit is contained in:
@ -17,6 +17,15 @@ use super::utils::{
|
||||
capture_actual_predecessor_and_jump,
|
||||
};
|
||||
|
||||
/// ループ脱出の種類(箱化・共通化のための型)
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum LoopExitKind {
|
||||
/// break文(exit blockへジャンプ)
|
||||
Break,
|
||||
/// continue文(header blockへジャンプ)
|
||||
Continue,
|
||||
}
|
||||
|
||||
/// ループビルダー - SSA形式でのループ構築を管理
|
||||
pub struct LoopBuilder<'a> {
|
||||
/// 親のMIRビルダーへの参照
|
||||
@ -67,34 +76,64 @@ impl<'a> LoopBuilder<'a> {
|
||||
Ok(void_id)
|
||||
}
|
||||
|
||||
/// Handle a `break` statement: jump to loop exit and continue in a fresh unreachable block.
|
||||
fn do_break(&mut self) -> Result<ValueId, String> {
|
||||
// Snapshot variables at break point for exit PHI generation
|
||||
/// 【箱化】ループ脱出の共通処理(break/continue統一化)
|
||||
///
|
||||
/// Phase 25.1o: break と continue の共通パターンを抽出し、
|
||||
/// LoopExitKind で振る舞いを切り替える統一メソッド。
|
||||
///
|
||||
/// # 処理フロー
|
||||
/// 1. 現在の変数マップをスナップショット
|
||||
/// 2. 適切なスナップショットリストに追加(Break → exit_snapshots, Continue → continue_snapshots)
|
||||
/// 3. ターゲットブロックへジャンプ(Break → exit, Continue → header)
|
||||
/// 4. 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()?;
|
||||
eprintln!("[DEBUG/do_break] Saved snapshot from block {:?}, vars: {:?}",
|
||||
cur_block, snapshot.keys().collect::<Vec<_>>());
|
||||
self.exit_snapshots.push((cur_block, snapshot));
|
||||
|
||||
if let Some(exit_bb) = crate::mir::builder::loops::current_exit(self.parent_builder) {
|
||||
self.jump_with_pred(exit_bb)?;
|
||||
// 2. スナップショット保存(kind別処理)
|
||||
match kind {
|
||||
LoopExitKind::Break => {
|
||||
if std::env::var("NYASH_LOOPFORM_DEBUG").ok().as_deref() == Some("1") {
|
||||
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. ターゲットブロックへジャンプ(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 => {
|
||||
if let Some(header) = self.loop_header {
|
||||
self.jump_with_pred(header)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. unreachable ブロックに切り替え(共通処理)
|
||||
self.switch_to_unreachable_block_with_void()
|
||||
}
|
||||
|
||||
/// Handle a `break` statement: jump to loop exit and continue in a fresh unreachable block.
|
||||
/// 【箱化】do_loop_exit() への thin wrapper
|
||||
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
|
||||
fn do_continue(&mut self) -> Result<ValueId, String> {
|
||||
// Snapshot variables at current block to be considered as a predecessor input
|
||||
let snapshot = self.get_current_variable_map();
|
||||
let cur_block = self.current_block()?;
|
||||
self.block_var_maps.insert(cur_block, snapshot.clone());
|
||||
self.continue_snapshots.push((cur_block, snapshot));
|
||||
|
||||
if let Some(header) = self.loop_header {
|
||||
self.jump_with_pred(header)?;
|
||||
}
|
||||
|
||||
self.switch_to_unreachable_block_with_void()
|
||||
self.do_loop_exit(LoopExitKind::Continue)
|
||||
}
|
||||
|
||||
// =============================================================
|
||||
|
||||
Reference in New Issue
Block a user