feat(phase31): Step 3-A/B - Add early return and structure checks to LoopToJoinLowerer
Phase 31 Step 3-A: Add early return using is_case_a_minimal_target() filter - Check before LoopScopeShape construction for efficiency - Returns None immediately for non-target functions Phase 31 Step 3-B: Add structural validation to is_supported_case_a_loop() - Single exit check: loop_form.break_targets.len() <= 1 - Variable presence check: !carriers.is_empty() || !pinned.is_empty() - Debug logging for rejection reasons Also refactored lower_with_scope() from if-else chain to match expression for clarity. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -74,6 +74,19 @@ impl LoopToJoinLowerer {
|
||||
);
|
||||
}
|
||||
|
||||
// Phase 31 Step 3-A: 早期リターン(関数名フィルタ)
|
||||
// Note: scope 構築前でもチェック可能(現在は func_name のみで判定)
|
||||
// Step 3-B で構造チェックを追加予定(その時は scope 構築後に移動)
|
||||
if !func_name.map_or(false, super::loop_scope_shape::is_case_a_minimal_target) {
|
||||
if self.debug {
|
||||
eprintln!(
|
||||
"[LoopToJoinLowerer] early return: {:?} is not a Case-A minimal target",
|
||||
func_name.unwrap_or("<unknown>")
|
||||
);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
// Step 1: MirQuery を構築
|
||||
let query = MirQueryBox::new(func);
|
||||
|
||||
@ -99,7 +112,65 @@ impl LoopToJoinLowerer {
|
||||
self.lower_with_scope(scope, func_name)
|
||||
}
|
||||
|
||||
/// Case-A ループとしてサポートされているかチェック
|
||||
///
|
||||
/// Phase 31 Step 3-B: 関数名フィルタ + 構造チェック
|
||||
///
|
||||
/// # Case-A の定義
|
||||
///
|
||||
/// - 単一出口(break_targets が 1 箇所以下)
|
||||
/// - ループ変数または固定変数が存在
|
||||
/// - ネストループなし(将来チェック追加予定)
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `loop_form`: LoopForm(構造判定用)
|
||||
/// - `scope`: LoopScopeShape(変数分類用)
|
||||
/// - `func_name`: 関数名(Step 3-C まで限定フィルタ)
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `true`: Case-A として lowering 可能
|
||||
/// - `false`: 未サポート(フォールバック経路へ)
|
||||
#[allow(dead_code)] // Step 3-C/D で使用予定
|
||||
pub(crate) fn is_supported_case_a_loop(
|
||||
&self,
|
||||
loop_form: &LoopForm,
|
||||
scope: &LoopScopeShape,
|
||||
func_name: Option<&str>,
|
||||
) -> bool {
|
||||
// Phase 31 Step 3-A: 関数名フィルタ(Step 3-D で撤去予定)
|
||||
if !func_name.map_or(false, super::loop_scope_shape::is_case_a_minimal_target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Phase 31 Step 3-B: 構造チェック(追加)
|
||||
// 単一出口 (break が 1 箇所以下)
|
||||
if loop_form.break_targets.len() > 1 {
|
||||
if self.debug {
|
||||
eprintln!(
|
||||
"[LoopToJoinLowerer] rejected: multiple break targets ({})",
|
||||
loop_form.break_targets.len()
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ループ変数または固定変数がある(空ループは対象外)
|
||||
if scope.carriers.is_empty() && scope.pinned.is_empty() {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] rejected: no carriers or pinned vars");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// LoopScopeShape から JoinModule を生成(内部メソッド)
|
||||
///
|
||||
/// Phase 31 Step 2: 関数名で 4 パターンにディスパッチ
|
||||
/// Step 3 で汎用 Case-A lowering に統一予定
|
||||
fn lower_with_scope(
|
||||
&self,
|
||||
scope: LoopScopeShape,
|
||||
@ -107,44 +178,45 @@ impl LoopToJoinLowerer {
|
||||
) -> Option<JoinModule> {
|
||||
let name = func_name.unwrap_or("");
|
||||
|
||||
// Case A minimal targets へのディスパッチ
|
||||
if name.contains("skip") || name == "Main.skip/1" {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to skip_ws lowerer");
|
||||
// Phase 31: matches! で完全一致(is_case_a_minimal_target と同じ条件)
|
||||
let result = match name {
|
||||
"Main.skip/1" => {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to skip_ws lowerer");
|
||||
}
|
||||
generic_case_a::lower_case_a_skip_ws_with_scope(scope)
|
||||
}
|
||||
return generic_case_a::lower_case_a_skip_ws_with_scope(scope);
|
||||
}
|
||||
|
||||
if name.contains("trim") || name == "FuncScannerBox.trim/1" {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to trim lowerer");
|
||||
"FuncScannerBox.trim/1" => {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to trim lowerer");
|
||||
}
|
||||
generic_case_a::lower_case_a_trim_with_scope(scope)
|
||||
}
|
||||
return generic_case_a::lower_case_a_trim_with_scope(scope);
|
||||
}
|
||||
|
||||
if name.contains("append_defs") || name == "FuncScannerBox.append_defs/2" {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to append_defs lowerer");
|
||||
"FuncScannerBox.append_defs/2" => {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to append_defs lowerer");
|
||||
}
|
||||
generic_case_a::lower_case_a_append_defs_with_scope(scope)
|
||||
}
|
||||
return generic_case_a::lower_case_a_append_defs_with_scope(scope);
|
||||
}
|
||||
|
||||
if name.contains("resolve_for_source") || name == "Stage1UsingResolverBox.resolve_for_source/5" {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to stage1 lowerer");
|
||||
"Stage1UsingResolverBox.resolve_for_source/5" => {
|
||||
if self.debug {
|
||||
eprintln!("[LoopToJoinLowerer] dispatching to stage1 lowerer");
|
||||
}
|
||||
generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope)
|
||||
}
|
||||
return generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope);
|
||||
}
|
||||
_ => {
|
||||
// TODO: Phase 31 Step 3 で汎用 Case A 対応
|
||||
if self.debug {
|
||||
eprintln!(
|
||||
"[LoopToJoinLowerer] no matching pattern for {:?}, returning None",
|
||||
name
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Phase 31 Step 3 で汎用 Case A 対応
|
||||
if self.debug {
|
||||
eprintln!(
|
||||
"[LoopToJoinLowerer] no matching pattern for {:?}, returning None",
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
None
|
||||
result
|
||||
}
|
||||
|
||||
// ========================================
|
||||
|
||||
Reference in New Issue
Block a user