//! Phase 33-23: LoopViewBuilder - Loop lowering ディスパッチ箱 //! //! LoopToJoinLowererからlowering選択責務を分離した専用モジュール。 //! //! ## 責務 //! //! - **Pattern検出**: Pattern 1 (Simple While)検出 //! - **Shape検出**: CaseALoweringShape検出 //! - **Lowerer選択**: Shape/名前ベースでlowerer選択 //! - **Lowerer呼び出し**: 適切なlowererに委譲 //! //! ## 設計思想 //! //! - **単一責任**: Lowering選択ロジックのみを集約 //! - **拡張性**: 新しいパターン追加が容易 //! - **テスト容易性**: 独立したBoxで単体テスト可能 use crate::mir::join_ir::lowering::generic_case_a; use crate::mir::join_ir::lowering::loop_scope_shape::{CaseALoweringShape, LoopScopeShape}; use crate::mir::join_ir::lowering::loop_update_summary; // Phase 170-C-2b use crate::mir::join_ir::JoinModule; /// Loop lowering ディスパッチ箱 /// /// LoopScopeShapeからパターンを検出し、適切なlowererを選択する。 pub struct LoopViewBuilder { /// デバッグモード(詳細ログ出力) debug: bool, } impl Default for LoopViewBuilder { fn default() -> Self { Self::new() } } impl LoopViewBuilder { /// 新しいLoopViewBuilderを作成 pub fn new() -> Self { let debug = std::env::var("NYASH_LOOPTOJOIN_DEBUG") .map(|v| v == "1") .unwrap_or(false); Self { debug } } /// LoopScopeShapeからJoinModuleを生成 /// /// # 選択戦略(Phase 170-A-2: Structure-based + Name fallback) /// /// 1. Pattern 1検出(Simple While Loop) /// 2. Shape検出(CaseALoweringShape) /// 3. Shape別ディスパッチ /// 4. 名前ベースフォールバック(Generic/NotCaseAの場合) /// /// # Arguments /// /// - `scope`: LoopScopeShape(変数分類・構造情報) /// - `func_name`: 関数名(名前ベースフォールバック用) /// /// # Returns /// /// - `Some(JoinModule)`: Lowering成功 /// - `None`: 未サポートパターン(フォールバック経路へ) pub fn build( &self, scope: LoopScopeShape, func_name: Option<&str>, ) -> Option { let name = func_name.unwrap_or(""); // Phase 188-Impl-1: Pattern 1 (Simple While Loop) detection // Try Pattern 1 FIRST for main function (loop_min_while.hako target) if let Some(result) = self.try_pattern1(&scope, name) { return Some(result); } // Phase 170-A-2: Structure-based routing with CaseALoweringShape let carrier_names: Vec = scope.carriers.iter().cloned().collect(); let update_summary = loop_update_summary::analyze_loop_updates(&carrier_names); let stub_features = crate::mir::loop_pattern_detection::LoopFeatures { has_break: false, has_continue: false, has_if: false, has_if_else_phi: false, carrier_count: scope.carriers.len(), break_count: 0, continue_count: 0, update_summary: Some(update_summary), }; let has_progress_carrier = scope.progress_carrier.is_some(); let carrier_count = scope.carriers.len(); let shape = CaseALoweringShape::detect_with_updates( &stub_features, carrier_count, has_progress_carrier, ); if self.debug { eprintln!( "[LoopViewBuilder] Phase 170-C-2b: shape={:?}, name={:?}, carriers={:?}", shape.name(), name, carrier_names ); } // Shape-based dispatch self.dispatch_by_shape(shape, scope, name) } /// Pattern 1 (Simple While Loop) 検出・lowering試行 /// /// # 検出条件 /// /// - 関数名に "main" が含まれる /// - Pinned vars がない /// - Carriers が1つ以上 fn try_pattern1(&self, scope: &LoopScopeShape, name: &str) -> Option { if !name.contains("main") { return None; } if scope.pinned.is_empty() && !scope.carriers.is_empty() { if self.debug { eprintln!("[LoopViewBuilder] Trying Pattern 1 lowering for {:?}", name); } if let Some(result) = super::simple_while_minimal::lower_simple_while_minimal(scope.clone()) { if self.debug { eprintln!("[LoopViewBuilder] Pattern 1 lowering succeeded for {:?}", name); } return Some(result); } if self.debug { eprintln!("[LoopViewBuilder] Pattern 1 lowering failed, trying other lowerers"); } } None } /// Shape別にlowererをディスパッチ /// /// # Shape種別 /// /// - **StringExamination**: skip_ws lowerer /// - **ArrayAccumulation**: append_defs lowerer /// - **IterationWithAccumulation**: stage1 lowerer /// - **Generic/NotCaseA**: 名前ベースフォールバック fn dispatch_by_shape( &self, shape: CaseALoweringShape, scope: LoopScopeShape, name: &str, ) -> Option { match shape { CaseALoweringShape::StringExamination => { if self.debug { eprintln!("[LoopViewBuilder] Shape: StringExamination → skip_ws lowerer"); } generic_case_a::lower_case_a_skip_ws_with_scope(scope) } CaseALoweringShape::ArrayAccumulation => { if self.debug { eprintln!("[LoopViewBuilder] Shape: ArrayAccumulation → append_defs lowerer"); } generic_case_a::lower_case_a_append_defs_with_scope(scope) } CaseALoweringShape::IterationWithAccumulation => { if self.debug { eprintln!("[LoopViewBuilder] Shape: IterationWithAccumulation → stage1 lowerer"); } generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope) } CaseALoweringShape::Generic | CaseALoweringShape::NotCaseA => { if self.debug { eprintln!( "[LoopViewBuilder] Shape: {:?} → name-based fallback", shape.name() ); } self.dispatch_by_name(scope, name) } } } /// 名前ベースフォールバック(Legacy) /// /// # Phase 170-A-2 設計 /// /// Shape検出で未分類のループを名前で振り分ける。 /// 将来的にはShape検出を強化してこのフォールバックを削減する。 fn dispatch_by_name(&self, scope: LoopScopeShape, name: &str) -> Option { match name { "Main.skip/1" => { if self.debug { eprintln!("[LoopViewBuilder] [fallback] dispatching to skip_ws lowerer"); } generic_case_a::lower_case_a_skip_ws_with_scope(scope) } "FuncScannerBox.trim/1" => { if self.debug { eprintln!("[LoopViewBuilder] [fallback] dispatching to trim lowerer"); } generic_case_a::lower_case_a_trim_with_scope(scope) } "FuncScannerBox.append_defs/2" => { if self.debug { eprintln!("[LoopViewBuilder] [fallback] dispatching to append_defs lowerer"); } generic_case_a::lower_case_a_append_defs_with_scope(scope) } "Stage1UsingResolverBox.resolve_for_source/5" => { if self.debug { eprintln!("[LoopViewBuilder] [fallback] dispatching to stage1 lowerer"); } generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope) } _ => { // No shape match AND no whitelist match if self.debug && self.generic_case_a_enabled() { eprintln!( "[LoopViewBuilder] generic Case-A candidate: {:?} (no lowerer yet)", name ); } None } } } /// Phase 32 L-1.2: 汎用Case-A loweringが有効かどうか fn generic_case_a_enabled(&self) -> bool { crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_LOWER_GENERIC") } } #[cfg(test)] mod tests { use super::*; #[test] fn test_builder_creation() { let builder = LoopViewBuilder::new(); assert!(!builder.debug || builder.debug); // Just check it compiles } }