diff --git a/src/mir/join_ir/lowering/skip_ws.rs b/src/mir/join_ir/lowering/skip_ws.rs index f67d3933..91ac307a 100644 --- a/src/mir/join_ir/lowering/skip_ws.rs +++ b/src/mir/join_ir/lowering/skip_ws.rs @@ -45,16 +45,17 @@ use crate::mir::join_ir::{ JoinInst, JoinModule, LoopExitShape, LoopHeaderShape, MirLikeInst, }; -/// Phase 27.8: Main.skip/1 の JoinIR lowering(手書き版) +/// Phase 27.11.1: Common JoinIR builder for Main.skip/1 /// -/// Phase 27.1-27.7 で実装された hand-written JoinIR 生成。 -/// Phase 27.8 以降は `lower_skip_ws_from_mir()` に移行予定。 -fn lower_skip_ws_handwritten(module: &crate::mir::MirModule) -> Option { +/// This function generates the JoinIR for skip/1, shared by both: +/// - lower_skip_ws_handwritten (always uses this) +/// - lower_skip_ws_from_mir (uses this after CFG sanity checks pass) +fn build_skip_ws_joinir(module: &crate::mir::MirModule) -> Option { // Step 1: "Main.skip/1" を探す let target_func = module.functions.get("Main.skip/1")?; - eprintln!("[joinir/skip_ws] Found Main.skip/1"); - eprintln!("[joinir/skip_ws] MIR blocks: {}", target_func.blocks.len()); + eprintln!("[joinir/skip_ws/build] Found Main.skip/1"); + eprintln!("[joinir/skip_ws/build] MIR blocks: {}", target_func.blocks.len()); // Step 2: JoinModule を構築 let mut join_module = JoinModule::new(); @@ -267,144 +268,19 @@ fn lower_skip_ws_from_mir(module: &crate::mir::MirModule) -> Option eprintln!("[joinir/skip_ws/mir] CFG sanity checks passed ✅"); - // JoinIR の ValueId は手書き版と同じレンジを使い、既存テストと互換にする - let skip_id = JoinFuncId::new(0); - let loop_step_id = JoinFuncId::new(1); + // Phase 27.11.1: Generate JoinIR using shared builder + // CFG checks passed, so we can use build_skip_ws_joinir() directly + eprintln!("[joinir/skip_ws/mir] Calling build_skip_ws_joinir() after CFG validation"); + return build_skip_ws_joinir(module); +} - // -------- skip 関数(入口) -------- - let s_param = ValueId(3000); - let mut skip_func = JoinFunction::new(skip_id, "skip".to_string(), vec![s_param]); - - let i_init = ValueId(3001); - let n = ValueId(3002); - - // i_init = 0 - skip_func.body.push(JoinInst::Compute(MirLikeInst::Const { - dst: i_init, - value: ConstValue::Integer(0), - })); - - // n = s.length() - skip_func.body.push(JoinInst::Compute(MirLikeInst::BoxCall { - dst: Some(n), - box_name: "StringBox".to_string(), - method: "length".to_string(), - args: vec![s_param], - })); - - // loop_step(s, i_init, n) - skip_func.body.push(JoinInst::Call { - func: loop_step_id, - args: vec![s_param, i_init, n], - k_next: None, - dst: None, - }); - - // -------- loop_step 関数 -------- - // Header 形: pinned = [s, n], carrier = [i] - let s_loop = ValueId(4000); // pinned - let i_loop = ValueId(4001); // carrier - let n_loop = ValueId(4002); // pinned - - let _header_shape = LoopHeaderShape::new_manual(vec![s_loop, n_loop], vec![i_loop]); - let _exit_shape = LoopExitShape::new_manual(vec![i_loop]); // exit_args = [i] - - let mut loop_step_func = JoinFunction::new( - loop_step_id, - "loop_step".to_string(), - vec![s_loop, i_loop, n_loop], - ); - - let cmp1_result = ValueId(4003); - let ch = ValueId(4004); - let cmp2_result = ValueId(4005); - let i_plus_1 = ValueId(4006); - let const_1 = ValueId(4007); - let const_space = ValueId(4010); - let bool_false = ValueId(4011); - let cmp2_is_false = ValueId(4012); - - // if i >= n { k_exit(i) } - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Compare { - dst: cmp1_result, - op: CompareOp::Ge, - lhs: i_loop, - rhs: n_loop, - })); - loop_step_func.body.push(JoinInst::Jump { - cont: JoinContId::new(0), - args: vec![i_loop], - cond: Some(cmp1_result), - }); - - // const 1 - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Const { - dst: const_1, - value: ConstValue::Integer(1), - })); - - // i_plus_1 = i + 1 - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::BinOp { - dst: i_plus_1, - op: BinOpKind::Add, - lhs: i_loop, - rhs: const_1, - })); - - // ch = s.substring(i, i+1) - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::BoxCall { - dst: Some(ch), - box_name: "StringBox".to_string(), - method: "substring".to_string(), - args: vec![s_loop, i_loop, i_plus_1], - })); - - // cmp2 = (ch == " ") - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Const { - dst: const_space, - value: ConstValue::String(" ".to_string()), - })); - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Compare { - dst: cmp2_result, - op: CompareOp::Eq, - lhs: ch, - rhs: const_space, - })); - - // cmp2_is_false = (cmp2 == false) - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Const { - dst: bool_false, - value: ConstValue::Bool(false), - })); - loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Compare { - dst: cmp2_is_false, - op: CompareOp::Eq, - lhs: cmp2_result, - rhs: bool_false, - })); - - // if ch != " " { k_exit(i) } - loop_step_func.body.push(JoinInst::Jump { - cont: JoinContId::new(1), - args: vec![i_loop], - cond: Some(cmp2_is_false), - }); - - // continue: loop_step(s, i+1, n) - loop_step_func.body.push(JoinInst::Call { - func: loop_step_id, - args: vec![s_loop, i_plus_1, n_loop], - k_next: None, - dst: None, - }); - - // -------- JoinModule 完成 -------- - let mut join_module = JoinModule::new(); - join_module.entry = Some(skip_id); - join_module.add_function(skip_func); - join_module.add_function(loop_step_func); - - Some(join_module) +/// Phase 27.11.1: Handwritten lowering wrapper for Main.skip/1 +/// +/// This is a thin wrapper that calls the shared build_skip_ws_joinir() function. +/// Maintains the handwritten lowering path as the baseline reference. +fn lower_skip_ws_handwritten(module: &crate::mir::MirModule) -> Option { + eprintln!("[joinir/skip_ws/handwritten] Using handwritten lowering path"); + build_skip_ws_joinir(module) } /// Phase 27.8: Main.skip/1 の JoinIR lowering(トグル対応ディスパッチャー)