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:
nyash-codex
2025-11-26 06:02:52 +09:00
parent 7a29ebd268
commit acffd9974b

View File

@ -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 を構築 // Step 1: MirQuery を構築
let query = MirQueryBox::new(func); let query = MirQueryBox::new(func);
@ -99,7 +112,65 @@ impl LoopToJoinLowerer {
self.lower_with_scope(scope, func_name) 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 を生成(内部メソッド) /// LoopScopeShape から JoinModule を生成(内部メソッド)
///
/// Phase 31 Step 2: 関数名で 4 パターンにディスパッチ
/// Step 3 で汎用 Case-A lowering に統一予定
fn lower_with_scope( fn lower_with_scope(
&self, &self,
scope: LoopScopeShape, scope: LoopScopeShape,
@ -107,44 +178,45 @@ impl LoopToJoinLowerer {
) -> Option<JoinModule> { ) -> Option<JoinModule> {
let name = func_name.unwrap_or(""); let name = func_name.unwrap_or("");
// Case A minimal targets へのディスパッチ // Phase 31: matches! で完全一致is_case_a_minimal_target と同じ条件)
if name.contains("skip") || name == "Main.skip/1" { let result = match name {
if self.debug { "Main.skip/1" => {
eprintln!("[LoopToJoinLowerer] dispatching to skip_ws lowerer"); 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); "FuncScannerBox.trim/1" => {
} if self.debug {
eprintln!("[LoopToJoinLowerer] dispatching to trim lowerer");
if name.contains("trim") || name == "FuncScannerBox.trim/1" { }
if self.debug { generic_case_a::lower_case_a_trim_with_scope(scope)
eprintln!("[LoopToJoinLowerer] dispatching to trim lowerer");
} }
return generic_case_a::lower_case_a_trim_with_scope(scope); "FuncScannerBox.append_defs/2" => {
} if self.debug {
eprintln!("[LoopToJoinLowerer] dispatching to append_defs lowerer");
if name.contains("append_defs") || name == "FuncScannerBox.append_defs/2" { }
if self.debug { generic_case_a::lower_case_a_append_defs_with_scope(scope)
eprintln!("[LoopToJoinLowerer] dispatching to append_defs lowerer");
} }
return generic_case_a::lower_case_a_append_defs_with_scope(scope); "Stage1UsingResolverBox.resolve_for_source/5" => {
} if self.debug {
eprintln!("[LoopToJoinLowerer] dispatching to stage1 lowerer");
if name.contains("resolve_for_source") || name == "Stage1UsingResolverBox.resolve_for_source/5" { }
if self.debug { generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope)
eprintln!("[LoopToJoinLowerer] dispatching to stage1 lowerer");
} }
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 対応 result
if self.debug {
eprintln!(
"[LoopToJoinLowerer] no matching pattern for {:?}, returning None",
name
);
}
None
} }
// ======================================== // ========================================