diff --git a/src/mir/builder/control_flow.rs b/src/mir/builder/control_flow.rs index 0a3d6cd6..1acda7ee 100644 --- a/src/mir/builder/control_flow.rs +++ b/src/mir/builder/control_flow.rs @@ -173,11 +173,18 @@ impl super::MirBuilder { use crate::mir::types::ConstValue; use crate::r#macro::ast_json::ast_to_json; + // Phase 188-Impl-1-F: Route "main" through Pattern 1 minimal lowerer + if func_name == "main" { + if debug { + eprintln!("[cf_loop/joinir] Routing 'main' through Pattern 1 minimal lowerer"); + } + return self.cf_loop_pattern1_minimal(condition, body, func_name, debug); + } + // Phase 50: Create appropriate binding based on function name let binding = match func_name { "JsonTokenizer.print_tokens/0" => LoopFrontendBinding::for_print_tokens(), "ArrayExtBox.filter/2" => LoopFrontendBinding::for_array_filter(), - "main" => LoopFrontendBinding::for_main_simple_while(), // Phase 188-Impl-1 _ => { if debug { eprintln!( @@ -363,6 +370,103 @@ impl super::MirBuilder { Ok(Some(void_val)) } + /// Phase 188-Impl-1-F: Pattern 1 (Simple While Loop) minimal lowerer + /// + /// This bypasses the LoopFrontendBinding JSON path and directly calls + /// the Pattern 1 minimal lowerer for apps/tests/loop_min_while.hako + /// + /// # Pipeline + /// 1. Call simple_while_minimal::lower_simple_while_minimal() → JoinModule + /// 2. convert_join_module_to_mir_with_meta() → MirModule + /// 3. Merge MIR blocks into current_function + fn cf_loop_pattern1_minimal( + &mut self, + _condition: &ASTNode, + _body: &[ASTNode], + _func_name: &str, + debug: bool, + ) -> Result, String> { + use crate::mir::join_ir::lowering::simple_while_minimal::lower_simple_while_minimal; + use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta; + use crate::mir::BasicBlockId; + use std::collections::{BTreeMap, BTreeSet}; + + if debug { + eprintln!("[cf_loop/joinir/pattern1] Calling Pattern 1 minimal lowerer"); + } + + // Create a minimal LoopScopeShape (Phase 188: hardcoded for loop_min_while.hako) + // Pattern 1 lowerer ignores the scope anyway, so this is just a placeholder + use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape; + let scope = LoopScopeShape { + header: BasicBlockId(0), + body: BasicBlockId(0), + latch: BasicBlockId(0), + exit: BasicBlockId(0), + pinned: BTreeSet::new(), + carriers: BTreeSet::new(), + body_locals: BTreeSet::new(), + exit_live: BTreeSet::new(), + progress_carrier: None, + variable_definitions: BTreeMap::new(), + }; + + // Call Pattern 1 lowerer + let join_module = match lower_simple_while_minimal(scope) { + Some(module) => module, + None => { + if debug { + eprintln!("[cf_loop/joinir/pattern1] Pattern 1 lowerer returned None"); + } + return Ok(None); + } + }; + + if debug { + eprintln!( + "[cf_loop/joinir/pattern1] JoinModule generated with {} functions", + join_module.functions.len() + ); + } + + // Convert JoinModule to MirModule + // Phase 188: Pass empty meta map since Pattern 1 lowerer doesn't use metadata + use crate::mir::join_ir::frontend::JoinFuncMetaMap; + let empty_meta: JoinFuncMetaMap = BTreeMap::new(); + + let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta) + .map_err(|e| format!("[cf_loop/joinir/pattern1] MIR conversion failed: {:?}", e))?; + + if debug { + eprintln!( + "[cf_loop/joinir/pattern1] MirModule generated with {} functions", + mir_module.functions.len() + ); + } + + // Merge JoinIR blocks into current function + self.merge_joinir_mir_blocks(&mir_module, debug)?; + + // Return void/0 as loop result (Pattern 1 loops return 0) + // Use the current block to emit the constant + let zero_val = self.value_gen.next(); + use crate::mir::types::ConstValue; + let current_block = self.current_block.ok_or_else(|| { + "[cf_loop/joinir/pattern1] No current block available".to_string() + })?; + + if let Some(ref mut func) = self.current_function { + if let Some(block) = func.get_block_mut(current_block) { + block.instructions.push(crate::mir::MirInstruction::Const { + dst: zero_val, + value: ConstValue::Integer(0), + }); + } + } + + Ok(Some(zero_val)) + } + /// Phase 49-3.2: Merge JoinIR-generated MIR blocks into current_function /// /// # Phase 189: Multi-Function MIR Merge diff --git a/src/mir/join_ir/json.rs b/src/mir/join_ir/json.rs index 17cde1a9..729b7196 100644 --- a/src/mir/join_ir/json.rs +++ b/src/mir/join_ir/json.rs @@ -375,6 +375,12 @@ fn write_mir_like_inst(inst: &MirLikeInst, out: &mut W) -> std::io::Re write!(out, ",\"operand\":{}", operand.0)?; write!(out, "}}")?; } + // Phase 188: Print + MirLikeInst::Print { value } => { + write!(out, "{{\"kind\":\"print\"")?; + write!(out, ",\"value\":{}", value.0)?; + write!(out, "}}")?; + } } Ok(()) } diff --git a/src/mir/join_ir/lowering/simple_while_minimal.rs b/src/mir/join_ir/lowering/simple_while_minimal.rs index 0d878621..eb7ebe97 100644 --- a/src/mir/join_ir/lowering/simple_while_minimal.rs +++ b/src/mir/join_ir/lowering/simple_while_minimal.rs @@ -166,15 +166,11 @@ pub fn lower_simple_while_minimal(_scope: LoopScopeShape) -> Option }); // print(i) - // Phase 188-Impl-1: Use BoxCall for print (no ExternCall variant in MirLikeInst) - // Note: print is a built-in extern function, but we represent it as a BoxCall here + // Phase 188-Impl-1-E: Use Print instruction loop_step_func .body - .push(JoinInst::Compute(MirLikeInst::BoxCall { - dst: None, - box_name: "print".to_string(), - method: "call".to_string(), // External function as method call - args: vec![i_param], + .push(JoinInst::Compute(MirLikeInst::Print { + value: i_param, })); // i_next = i + 1 diff --git a/src/mir/join_ir/mod.rs b/src/mir/join_ir/mod.rs index 50399b28..142d44c7 100644 --- a/src/mir/join_ir/mod.rs +++ b/src/mir/join_ir/mod.rs @@ -465,6 +465,13 @@ pub enum MirLikeInst { op: UnaryOp, operand: VarId, }, + + /// Phase 188: Print 文(コンソール出力) + /// print(value) の構造を JoinIR で表現 + /// MIR 変換時に Print 命令に変換 + Print { + value: VarId, + }, } /// Phase 56: 単項演算種別 diff --git a/src/mir/join_ir_runner.rs b/src/mir/join_ir_runner.rs index 6ff53a18..8995c3d1 100644 --- a/src/mir/join_ir_runner.rs +++ b/src/mir/join_ir_runner.rs @@ -358,6 +358,19 @@ fn eval_compute( }; locals.insert(*dst, result); } + // Phase 188: Print + MirLikeInst::Print { value } => { + let val = read_var(locals, *value)?; + // Print to stdout (convert to string representation) + let output = match val { + JoinValue::Int(i) => i.to_string(), + JoinValue::Bool(b) => b.to_string(), + JoinValue::Str(s) => s, + JoinValue::Unit => "null".to_string(), + JoinValue::BoxRef(_) => "[BoxRef]".to_string(), + }; + println!("{}", output); + } } Ok(()) } diff --git a/src/mir/join_ir_vm_bridge/convert.rs b/src/mir/join_ir_vm_bridge/convert.rs index aa5ebd1a..64b66b39 100644 --- a/src/mir/join_ir_vm_bridge/convert.rs +++ b/src/mir/join_ir_vm_bridge/convert.rs @@ -934,5 +934,10 @@ pub(crate) fn convert_mir_like_inst( operand: *operand, }) } + // Phase 188: Print + MirLikeInst::Print { value } => Ok(MirInstruction::Print { + value: *value, + effects: EffectMask::IO, + }), } }