Files
hakorune/src/mir/utils/control_flow.rs

125 lines
3.8 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.

/*!
* Control Flow Utilities - 制御フロー処理の共通ユーティリティ
*
* PHI incoming修正とブロック終端検出の汎用関数群
* フェーズS即効止血からフェーズL根本解決まで共通利用
*/
use super::super::{BasicBlockId, MirBuilder};
/// **外部関数**: 現在のブロックが終端済みかチェック
///
/// loop_builder.rsで3箇所重複していた処理を統一
///
/// # 使用例
/// ```rust
/// if is_current_block_terminated(builder)? {
/// break; // 早期終了
/// }
/// ```
pub fn is_current_block_terminated(builder: &MirBuilder) -> Result<bool, String> {
let cur_id = builder
.current_block
.ok_or_else(|| "No current block".to_string())?;
if let Some(ref function) = builder.scope_ctx.current_function {
if let Some(bb) = function.get_block(cur_id) {
Ok(bb.is_terminated())
} else {
Ok(false)
}
} else {
Ok(false)
}
}
/// **外部関数**: 実到達ブロックを捕捉してJump発行
///
/// 最強モード指摘の「実到達predecessor捕捉」を汎用化
/// break/continue後の到達不能ブロックは除外
///
/// # 戻り値
/// - `Some(predecessor_id)`: Jump発行済み、PHI incomingに使用可能
/// - `None`: 既に終端済み、PHI incomingから除外すべき
///
/// # 使用例
/// ```rust
/// if let Some(pred_id) = capture_actual_predecessor_and_jump(builder, merge_bb)? {
/// phi_incomings.push((pred_id, value));
/// }
/// ```
pub fn capture_actual_predecessor_and_jump(
builder: &mut MirBuilder,
target_block: BasicBlockId,
) -> Result<Option<BasicBlockId>, String> {
let cur_id = builder
.current_block
.ok_or_else(|| "No current block".to_string())?;
let need_jump = !is_current_block_terminated(builder)?;
if need_jump {
// Jump発行前に実到達ブロックID捕捉重要
// 既存control_flowモジュールと同じパターンを使用
builder.emit_instruction(super::super::MirInstruction::Jump {
target: target_block,
edge_args: None,
})?;
Ok(Some(cur_id))
} else {
// 既に終端済みbreak/continue等、PHI incomingから除外
Ok(None)
}
}
/// **外部関数**: 条件付きPHI incoming収集
///
/// 到達可能な場合のみincomingをリストに追加
/// フェーズM、フェーズLでの型安全性向上にも対応
///
/// # 使用例
/// ```rust
/// let mut incomings = Vec::new();
/// collect_phi_incoming_if_reachable(&mut incomings, then_pred, then_value);
/// collect_phi_incoming_if_reachable(&mut incomings, else_pred, else_value);
/// ```
pub fn collect_phi_incoming_if_reachable(
incomings: &mut Vec<(BasicBlockId, super::super::ValueId)>,
predecessor: Option<BasicBlockId>,
value: super::super::ValueId,
) {
if let Some(pred_id) = predecessor {
incomings.push((pred_id, value));
}
// None到達不能の場合は何もしない
}
/// **外部関数**: 終端チェック付きステートメント実行
///
/// build_statement後の終端チェックを自動化
/// フェーズSでの「終端ガード徹底」を支援
///
/// # 戻り値
/// - `Ok(true)`: 正常実行、継続可能
/// - `Ok(false)`: 終端済み、ループ脱出すべき
/// - `Err(_)`: エラー
pub fn execute_statement_with_termination_check(
builder: &mut MirBuilder,
statement: crate::ast::ASTNode,
) -> Result<bool, String> {
let _result = builder.build_expression(statement)?;
// 終端チェック(統一処理)
let terminated = is_current_block_terminated(builder)?;
Ok(!terminated)
}
#[cfg(test)]
mod tests {
// ユニットテスト(将来追加)
// - 終端検出の正確性
// - 実到達ブロック捕捉の正確性
// - PHI incoming除外の正確性
}