From e258973dbaf2953c81421d41770c586e47fbbea7 Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Fri, 28 Nov 2025 19:12:59 +0900 Subject: [PATCH] feat(builder): Phase 49 cf_loop JoinIR Frontend mainline integration point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add try_cf_loop_joinir() method to control_flow.rs as the routing point for JoinIR Frontend mainline integration. - First target: JsonTokenizer.print_tokens/1 - Controlled by HAKO_JOINIR_PRINT_TOKENS_MAIN=1 flag - Currently falls through to legacy LoopBuilder (Phase 49-3 will implement) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/mir/builder/control_flow.rs | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/mir/builder/control_flow.rs b/src/mir/builder/control_flow.rs index 05276fd8..1e244038 100644 --- a/src/mir/builder/control_flow.rs +++ b/src/mir/builder/control_flow.rs @@ -21,11 +21,23 @@ impl super::MirBuilder { } /// Control-flow: loop + /// + /// # Phase 49: JoinIR Frontend Mainline Integration + /// + /// This is the unified entry point for all loop lowering. When enabled via + /// `HAKO_JOINIR_PRINT_TOKENS_MAIN=1`, specific functions (starting with + /// `JsonTokenizer.print_tokens/1`) are routed through JoinIR Frontend instead + /// of the traditional LoopBuilder path. pub(super) fn cf_loop( &mut self, condition: ASTNode, body: Vec, ) -> Result { + // Phase 49: Try JoinIR Frontend route for mainline targets + if let Some(result) = self.try_cf_loop_joinir(&condition, &body)? { + return Ok(result); + } + if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() { eprintln!("[cf_loop] CALLED from somewhere"); eprintln!("[cf_loop] Current stack (simulated): check build_statement vs build_expression_impl"); @@ -35,6 +47,50 @@ impl super::MirBuilder { loop_builder.build_loop(condition, body) } + /// Phase 49: Try JoinIR Frontend for mainline integration + /// + /// Returns `Ok(Some(value))` if the current function should use JoinIR Frontend, + /// `Ok(None)` to fall through to the legacy LoopBuilder path. + fn try_cf_loop_joinir( + &mut self, + _condition: &ASTNode, + _body: &[ASTNode], + ) -> Result, String> { + // Phase 49-2: Check if feature is enabled + if std::env::var("HAKO_JOINIR_PRINT_TOKENS_MAIN").ok().as_deref() != Some("1") { + return Ok(None); + } + + // Get current function name + let func_name = self + .current_function + .as_ref() + .map(|f| f.signature.name.as_str()) + .unwrap_or(""); + + // Phase 49-2: Only handle print_tokens for now + if func_name != "JsonTokenizer.print_tokens/1" { + return Ok(None); + } + + // Debug log when routing through JoinIR Frontend + if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() { + eprintln!( + "[cf_loop/joinir] Routing {} through JoinIR Frontend mainline", + func_name + ); + } + + // TODO(Phase 49-3): Implement actual JoinIR Frontend integration + // 1. Convert condition + body to AST JSON (Program) + // 2. Call AstToJoinIrLowerer::lower_program_json() + // 3. Convert JoinModule to MIR via convert_join_module_to_mir_with_meta() + // 4. Merge generated blocks into current_function + // + // For now, fall through to legacy path + Ok(None) + } + /// Control-flow: try/catch/finally pub(super) fn cf_try_catch( &mut self,