diff --git a/src/mir/join_ir/lowering/loop_to_join.rs b/src/mir/join_ir/lowering/loop_to_join.rs index 24c3f481..abe165e8 100644 --- a/src/mir/join_ir/lowering/loop_to_join.rs +++ b/src/mir/join_ir/lowering/loop_to_join.rs @@ -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("") + ); + } + 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 { 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 } // ========================================