use super::{BasicBlockId, ValueId}; use crate::ast::{ASTNode, LiteralValue}; impl super::MirBuilder { // Peek expression lowering pub(super) fn build_peek_expression( &mut self, scrutinee: ASTNode, arms: Vec<(LiteralValue, ASTNode)>, else_expr: ASTNode, ) -> Result { // Evaluate scrutinee in the current block let scr_val = self.build_expression_impl(scrutinee)?; // Prepare merge and result let merge_block: BasicBlockId = self.block_gen.next(); let result_val = self.value_gen.next(); let mut phi_inputs: Vec<(BasicBlockId, ValueId)> = Vec::new(); // Create dispatch block where we start comparing arms let dispatch_block = self.block_gen.next(); // Jump from current block to dispatch (ensure terminator exists) let need_jump = { let cur = self.current_block; if let (Some(cb), Some(ref func)) = (cur, &self.current_function) { if let Some(bb) = func.blocks.get(&cb) { !bb.is_terminated() } else { true } } else { true } }; if need_jump { self.emit_instruction(super::MirInstruction::Jump { target: dispatch_block, })?; } self.start_new_block(dispatch_block)?; // If there are no arms, fall through to else directly if arms.is_empty() { let else_block = self.block_gen.next(); self.emit_instruction(super::MirInstruction::Jump { target: else_block })?; self.start_new_block(else_block)?; let else_val = self.build_expression_impl(else_expr)?; phi_inputs.push((else_block, else_val)); self.emit_instruction(super::MirInstruction::Jump { target: merge_block, })?; self.start_new_block(merge_block)?; // フェーズM: 常にPHI命令を使用(no_phi_mode撤廃) self.emit_instruction(super::MirInstruction::Phi { dst: result_val, inputs: phi_inputs, })?; return Ok(result_val); } // Else block to handle default case let else_block = self.block_gen.next(); // Chain dispatch blocks for each arm let mut cur_dispatch = dispatch_block; for (i, (label, arm_expr)) in arms.iter().cloned().enumerate() { let then_block = self.block_gen.next(); // Next dispatch (only for non-last arm) let next_dispatch = if i + 1 < arms.len() { Some(self.block_gen.next()) } else { None }; let else_target = next_dispatch.unwrap_or(else_block); // In current dispatch block, compare and branch self.start_new_block(cur_dispatch)?; let lit_id = self.value_gen.next(); let const_value = match label { LiteralValue::String(s) => super::ConstValue::String(s), LiteralValue::Integer(i) => super::ConstValue::Integer(i), LiteralValue::Bool(b) => super::ConstValue::Bool(b), LiteralValue::Float(f) => super::ConstValue::Float(f), LiteralValue::Null => super::ConstValue::Null, LiteralValue::Void => super::ConstValue::Void, }; self.emit_instruction(super::MirInstruction::Const { dst: lit_id, value: const_value, })?; let cond_id = self.value_gen.next(); self.emit_instruction(super::MirInstruction::Compare { dst: cond_id, op: super::CompareOp::Eq, lhs: scr_val, rhs: lit_id, })?; self.emit_instruction(super::MirInstruction::Branch { condition: cond_id, then_bb: then_block, else_bb: else_target, })?; // then arm self.start_new_block(then_block)?; let then_val = self.build_expression_impl(arm_expr)?; phi_inputs.push((then_block, then_val)); self.emit_instruction(super::MirInstruction::Jump { target: merge_block, })?; // Move to next dispatch or else block cur_dispatch = else_target; } // Lower else expression in else_block self.start_new_block(else_block)?; let else_val = self.build_expression_impl(else_expr)?; phi_inputs.push((else_block, else_val)); self.emit_instruction(super::MirInstruction::Jump { target: merge_block, })?; // Merge and yield result self.start_new_block(merge_block)?; // フェーズM: 常にPHI命令を使用(no_phi_mode撤廃) self.emit_instruction(super::MirInstruction::Phi { dst: result_val, inputs: phi_inputs, })?; Ok(result_val) } }