//! Phase 273 P1: PlanLowerer - CorePlan → MIR 生成 (SSOT) //! //! # Responsibilities //! //! - Receive CorePlan from PlanNormalizer //! - Emit MIR instructions using pre-allocated ValueIds //! - No pattern-specific knowledge (pattern-agnostic) //! //! # Key Design Decision //! //! Lowerer processes CorePlan ONLY. It does not know about scan, split, or //! any other pattern-specific semantics. All pattern knowledge is in Normalizer. use super::{CoreEffectPlan, CoreLoopPlan, CorePlan}; use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternContext; use crate::mir::builder::MirBuilder; use crate::mir::{Effect, EffectMask, MirInstruction, ValueId}; /// Phase 273 P1: PlanLowerer - CorePlan → MIR 生成 (SSOT) pub(in crate::mir::builder) struct PlanLowerer; impl PlanLowerer { /// CorePlan を受け取り、MIR を生成 /// /// # Arguments /// /// * `builder` - MIR builder (mutable access for instruction emission) /// * `plan` - CorePlan from Normalizer (pre-allocated ValueIds) /// * `ctx` - Loop pattern context for debug/func_name pub(in crate::mir::builder) fn lower( builder: &mut MirBuilder, plan: CorePlan, ctx: &LoopPatternContext, ) -> Result, String> { match plan { CorePlan::Seq(plans) => Self::lower_seq(builder, plans, ctx), CorePlan::Loop(loop_plan) => Self::lower_loop(builder, loop_plan, ctx), CorePlan::If(_if_plan) => { // P1: If is handled inline in Loop body Err("[lowerer] Standalone CorePlan::If not yet supported".to_string()) } CorePlan::Effect(effect) => { Self::emit_effect(builder, &effect)?; Ok(None) } CorePlan::Exit(_exit) => { // P1: Exit is handled by edge CFG in Loop Err("[lowerer] Standalone CorePlan::Exit not yet supported".to_string()) } } } /// Seq: process plans in order fn lower_seq( builder: &mut MirBuilder, plans: Vec, ctx: &LoopPatternContext, ) -> Result, String> { let mut result = None; for plan in plans { result = Self::lower(builder, plan, ctx)?; } Ok(result) } /// Loop: emit blocks, effects, PHI, and edge CFG /// /// This is pattern-agnostic. All pattern knowledge is in Normalizer. fn lower_loop( builder: &mut MirBuilder, loop_plan: CoreLoopPlan, ctx: &LoopPatternContext, ) -> Result, String> { use crate::mir::builder::control_flow::joinir::trace; let trace_logger = trace::trace(); let debug = ctx.debug; if debug { trace_logger.debug( "lowerer/loop", &format!( "Phase 273 P1: Lowering CoreLoopPlan for {}", ctx.func_name ), ); } // Step 1: Emit Jump from preheader (current block) to header if builder.current_block.is_some() { builder.emit_instruction(MirInstruction::Jump { target: loop_plan.header_bb, edge_args: None, })?; } // Step 2: Start header block and emit header effects builder.start_new_block(loop_plan.header_bb)?; for effect in &loop_plan.header_effects { Self::emit_effect(builder, effect)?; } if debug { trace_logger.debug( "lowerer/loop", &format!("Header effects emitted: {} effects", loop_plan.header_effects.len()), ); } // Step 3: Start body block and emit body plans builder.start_new_block(loop_plan.body_bb)?; for plan in loop_plan.body { match plan { CorePlan::Effect(effect) => { Self::emit_effect(builder, &effect)?; } _ => { // P1: Only Effect plans in body for now return Err("[lowerer] Non-Effect plan in Loop body not yet supported".to_string()); } } } if debug { trace_logger.debug("lowerer/loop", "Body plans emitted"); } // Step 4: Start step block and emit step effects builder.start_new_block(loop_plan.step_bb)?; for effect in &loop_plan.step_effects { Self::emit_effect(builder, effect)?; } if debug { trace_logger.debug( "lowerer/loop", &format!("Step effects emitted: {} effects", loop_plan.step_effects.len()), ); } // Step 5: Ensure found_bb and after_bb exist builder.ensure_block_exists(loop_plan.found_bb)?; builder.ensure_block_exists(loop_plan.after_bb)?; // Step 6: Insert PHI at header for each carrier use crate::mir::builder::emission::phi::insert_loop_phi; for carrier in &loop_plan.carriers { insert_loop_phi( builder, loop_plan.header_bb, carrier.phi_dst, vec![ (loop_plan.preheader_bb, carrier.init_value), (loop_plan.step_bb, carrier.step_value), ], "lowerer/loop_phi", )?; } if debug { trace_logger.debug("lowerer/loop", "PHI inserted at header_bb"); } // Step 7: Emit edge CFG (terminators) use crate::mir::builder::emission::loop_scan_with_init::emit_scan_with_init_edgecfg; emit_scan_with_init_edgecfg( builder, loop_plan.header_bb, loop_plan.body_bb, loop_plan.step_bb, loop_plan.after_bb, loop_plan.found_bb, loop_plan.cond_loop, loop_plan.cond_match, loop_plan.carriers.first().map(|c| c.phi_dst).unwrap_or(ValueId(0)), )?; if debug { trace_logger.debug("lowerer/loop", "Edge CFG emitted"); } // Step 8: Update variable_map for carriers for carrier in &loop_plan.carriers { builder .variable_ctx .variable_map .insert(carrier.name.clone(), carrier.phi_dst); } // Step 9: Setup after_bb for subsequent AST lowering builder.start_new_block(loop_plan.after_bb)?; // Step 10: Return Void (pattern applied successfully) use crate::mir::builder::emission::constant::emit_void; let void_val = emit_void(builder); if debug { trace_logger.debug( "lowerer/loop", &format!("Loop complete, returning Void {:?}", void_val), ); } Ok(Some(void_val)) } /// Emit a single CoreEffectPlan as MirInstruction fn emit_effect(builder: &mut MirBuilder, effect: &CoreEffectPlan) -> Result<(), String> { match effect { CoreEffectPlan::Const { dst, value } => { builder.emit_instruction(MirInstruction::Const { dst: *dst, value: value.clone(), })?; } CoreEffectPlan::MethodCall { dst, object, method, args } => { builder.emit_instruction(MirInstruction::BoxCall { dst: Some(*dst), box_val: *object, method: method.clone(), method_id: None, args: args.clone(), effects: EffectMask::PURE.add(Effect::Io), })?; } CoreEffectPlan::BinOp { dst, lhs, op, rhs } => { builder.emit_instruction(MirInstruction::BinOp { dst: *dst, lhs: *lhs, op: *op, rhs: *rhs, })?; } CoreEffectPlan::Compare { dst, lhs, op, rhs } => { builder.emit_instruction(MirInstruction::Compare { dst: *dst, lhs: *lhs, op: *op, rhs: *rhs, })?; } } Ok(()) } }