//! JoinIR routing logic for loop lowering use crate::ast::ASTNode; use crate::mir::builder::MirBuilder; use crate::mir::ValueId; use super::trace; impl MirBuilder { /// Phase 49: Try JoinIR Frontend for mainline integration /// /// Returns `Ok(Some(value))` if the loop is successfully lowered via JoinIR, /// `Ok(None)` if no JoinIR pattern matched (unsupported loop structure). /// Phase 187-2: Legacy LoopBuilder removed - all loops must use JoinIR. /// /// # Phase 49-4: Multi-target support /// /// Targets are enabled via separate dev flags: /// - `HAKO_JOINIR_PRINT_TOKENS_MAIN=1`: JsonTokenizer.print_tokens/0 /// - `HAKO_JOINIR_ARRAY_FILTER_MAIN=1`: ArrayExtBox.filter/2 /// /// Note: Arity in function names does NOT include implicit `me` receiver. /// - Instance method `print_tokens()` → `/0` (no explicit params) /// - Static method `filter(arr, pred)` → `/2` (two params) pub(in crate::mir::builder) fn try_cf_loop_joinir( &mut self, condition: &ASTNode, body: &[ASTNode], ) -> Result, String> { // Get current function name let func_name = self .current_function .as_ref() .map(|f| f.signature.name.clone()) .unwrap_or_default(); // Phase 195: Use unified trace trace::trace().routing("router", &func_name, "try_cf_loop_joinir called"); // Phase 170-4: Structure-based routing option // When NYASH_JOINIR_STRUCTURE_ONLY=1, skip function name whitelist // and route purely based on loop structure analysis let structure_only = std::env::var("NYASH_JOINIR_STRUCTURE_ONLY") .ok() .as_deref() == Some("1"); if structure_only { trace::trace().routing("router", &func_name, "Structure-only mode enabled, skipping whitelist"); } else { // Phase 49-4 + Phase 80: Multi-target routing (legacy whitelist) // - Core ON なら代表2本(print_tokens / ArrayExt.filter)は JoinIR を優先し、失敗したら LoopBuilder へフォールバック // - Core OFF では従来通り dev フラグで opt-in // Note: Arity does NOT include implicit `me` receiver // Phase 188: Add "main" routing for loop pattern expansion // Phase 170: Add JsonParserBox methods for selfhost validation let core_on = crate::config::env::joinir_core_enabled(); let is_target = match func_name.as_str() { "main" => true, // Phase 188-Impl-1: Enable JoinIR for main function (Pattern 1) "JoinIrMin.main/0" => true, // Phase 188-Impl-2: Enable JoinIR for JoinIrMin.main/0 (Pattern 2) "JsonTokenizer.print_tokens/0" => { if core_on { true } else { std::env::var("HAKO_JOINIR_PRINT_TOKENS_MAIN") .ok() .as_deref() == Some("1") } } "ArrayExtBox.filter/2" => { if core_on { true } else { std::env::var("HAKO_JOINIR_ARRAY_FILTER_MAIN") .ok() .as_deref() == Some("1") } } // Phase 170-A-1: Enable JsonParserBox methods for JoinIR routing "JsonParserBox._trim/1" => true, "JsonParserBox._skip_whitespace/2" => true, "JsonParserBox._match_literal/2" => true, "JsonParserBox._parse_string/2" => true, "JsonParserBox._parse_array/2" => true, "JsonParserBox._parse_object/2" => true, // Phase 170-A-1: Test methods (simplified versions) "TrimTest.trim/1" => true, "Main.trim/1" => true, // Phase 171-fix: Main box variant "Main.trim_string_simple/1" => true, // Phase 33-13: Simple trim variant "TrimTest.main/0" => true, // Phase 170: TrimTest.main for loop pattern test // Phase 173: JsonParser P5 expansion test "JsonParserTest._skip_whitespace/3" => true, "JsonParserTest.main/0" => true, // Phase 174: JsonParser complex loop P5B extension test "JsonParserStringTest.parse_string_min/0" => true, "JsonParserStringTest.main/0" => true, // Phase 175: P5 multi-carrier support (2 carriers: pos + result) "JsonParserStringTest2.parse_string_min2/0" => true, "JsonParserStringTest2.main/0" => true, _ => false, }; if !is_target { return Ok(None); } } // Debug log when routing through JoinIR Frontend // Phase 195: Check trace flags directly from JoinLoopTrace let debug = trace::trace().is_loopform_enabled() || trace::trace().is_mainline_enabled(); trace::trace().routing("router", &func_name, "Routing through JoinIR Frontend mainline"); // Phase 49-3: Implement JoinIR Frontend integration self.cf_loop_joinir_impl(condition, body, &func_name, debug) } /// Phase 49-3: JoinIR Frontend integration implementation /// /// Routes loop compilation through either: /// 1. Pattern-based router (Phase 194+) - preferred for new patterns /// 2. Legacy binding path (Phase 49-3) - for whitelisted functions only pub(in crate::mir::builder) fn cf_loop_joinir_impl( &mut self, condition: &ASTNode, body: &[ASTNode], func_name: &str, debug: bool, ) -> Result, String> { // Phase 194: Use table-driven router instead of if/else chain use super::patterns::{route_loop_pattern, LoopPatternContext}; let ctx = LoopPatternContext::new(condition, body, &func_name, debug); if let Some(result) = route_loop_pattern(self, &ctx)? { trace::trace().routing("router", func_name, "Pattern router succeeded"); return Ok(Some(result)); } // Phase 187-2: Pattern router failed, try legacy whitelist trace::trace().routing("router", func_name, "Pattern router found no match, trying legacy whitelist"); // Delegate to legacy binding path (routing_legacy_binding.rs) self.cf_loop_joinir_legacy_binding(condition, body, func_name, debug) } }