//! Phase 33-3: If/Else → Select lowering integration tests //! //! Tests the pattern matching and lowering of if/else to JoinIR Select instruction. #[cfg(test)] mod tests { use crate::mir::join_ir::lowering::try_lower_if_to_joinir; use crate::mir::join_ir::JoinInst; use crate::mir::{ BasicBlock, BasicBlockId, MirFunction, MirInstruction, MirModule, ValueId, }; use std::collections::BTreeMap; /// Helper to create a simple if/else function matching the "simple" pattern fn create_simple_pattern_mir() -> MirFunction { let mut blocks = BTreeMap::new(); // Entry block (bb0): branch on cond let mut entry = BasicBlock::new(BasicBlockId::new(0)); entry.terminator = Some(MirInstruction::Branch { condition: ValueId(0), // cond parameter then_bb: BasicBlockId::new(1), else_bb: BasicBlockId::new(2), }); blocks.insert(BasicBlockId::new(0), entry); // Then block (bb1): return 10 // NOTE: Pattern matcher expects empty blocks (Return only) let mut then_block = BasicBlock::new(BasicBlockId::new(1)); then_block.terminator = Some(MirInstruction::Return { value: Some(ValueId(1)), // Assumes ValueId(1) is const 10 }); blocks.insert(BasicBlockId::new(1), then_block); // Else block (bb2): return 20 // NOTE: Pattern matcher expects empty blocks (Return only) let mut else_block = BasicBlock::new(BasicBlockId::new(2)); else_block.terminator = Some(MirInstruction::Return { value: Some(ValueId(2)), // Assumes ValueId(2) is const 20 }); blocks.insert(BasicBlockId::new(2), else_block); use crate::mir::{EffectMask, MirType}; use crate::mir::function::FunctionMetadata; use std::collections::HashMap; MirFunction { signature: crate::mir::FunctionSignature { name: "IfSelectTest.test/1".to_string(), params: vec![MirType::Unknown], return_type: MirType::Integer, effects: EffectMask::PURE, }, entry_block: BasicBlockId::new(0), blocks: blocks.into_iter().collect(), locals: vec![], params: vec![ValueId(0)], next_value_id: 3, metadata: FunctionMetadata::default(), } } /// Helper to create a local pattern function fn create_local_pattern_mir() -> MirFunction { let mut blocks = BTreeMap::new(); // Entry block (bb0): branch on cond let mut entry = BasicBlock::new(BasicBlockId::new(0)); entry.terminator = Some(MirInstruction::Branch { condition: ValueId(0), // cond then_bb: BasicBlockId::new(1), else_bb: BasicBlockId::new(2), }); blocks.insert(BasicBlockId::new(0), entry); // Then block (bb1): x = 100; jump merge // NOTE: Pattern matcher expects exactly 1 Copy instruction let mut then_block = BasicBlock::new(BasicBlockId::new(1)); then_block.instructions.push(MirInstruction::Copy { dst: ValueId(3), // x src: ValueId(10), // Assumes ValueId(10) is const 100 }); then_block.terminator = Some(MirInstruction::Jump { target: BasicBlockId::new(3), }); blocks.insert(BasicBlockId::new(1), then_block); // Else block (bb2): x = 200; jump merge // NOTE: Pattern matcher expects exactly 1 Copy instruction let mut else_block = BasicBlock::new(BasicBlockId::new(2)); else_block.instructions.push(MirInstruction::Copy { dst: ValueId(3), // x src: ValueId(20), // Assumes ValueId(20) is const 200 }); else_block.terminator = Some(MirInstruction::Jump { target: BasicBlockId::new(3), }); blocks.insert(BasicBlockId::new(2), else_block); // Merge block (bb3): return x let mut merge_block = BasicBlock::new(BasicBlockId::new(3)); merge_block.terminator = Some(MirInstruction::Return { value: Some(ValueId(3)), }); blocks.insert(BasicBlockId::new(3), merge_block); use crate::mir::{EffectMask, MirType}; use crate::mir::function::FunctionMetadata; use std::collections::HashMap; MirFunction { signature: crate::mir::FunctionSignature { name: "IfSelectTest.main/0".to_string(), params: vec![], return_type: MirType::Integer, effects: EffectMask::PURE, }, entry_block: BasicBlockId::new(0), blocks: blocks.into_iter().collect(), locals: vec![], params: vec![], next_value_id: 21, metadata: FunctionMetadata::default(), } } #[test] fn test_if_select_simple_pattern() { // Set environment variable for this test std::env::set_var("NYASH_JOINIR_IF_SELECT", "1"); let func = create_simple_pattern_mir(); let entry_block = func.entry_block; // Try to lower to JoinIR let result = try_lower_if_to_joinir(&func, entry_block, true); assert!( result.is_some(), "Expected simple pattern to be lowered to Select" ); if let Some(JoinInst::Select { dst, cond, then_val, else_val, }) = result { eprintln!("✅ Simple pattern successfully lowered to Select"); eprintln!(" dst: {:?}, cond: {:?}, then: {:?}, else: {:?}", dst, cond, then_val, else_val); } else { panic!("Expected JoinInst::Select, got {:?}", result); } // Clean up std::env::remove_var("NYASH_JOINIR_IF_SELECT"); } #[test] fn test_if_select_local_pattern() { std::env::set_var("NYASH_JOINIR_IF_SELECT", "1"); let func = create_local_pattern_mir(); let entry_block = func.entry_block; // Try to lower to JoinIR let result = try_lower_if_to_joinir(&func, entry_block, true); assert!( result.is_some(), "Expected local pattern to be lowered to Select" ); if let Some(JoinInst::Select { dst, cond, then_val, else_val, }) = result { eprintln!("✅ Local pattern successfully lowered to Select"); eprintln!(" dst: {:?}, cond: {:?}, then: {:?}, else: {:?}", dst, cond, then_val, else_val); } else { panic!("Expected JoinInst::Select, got {:?}", result); } std::env::remove_var("NYASH_JOINIR_IF_SELECT"); } #[test] fn test_if_select_disabled_by_default() { // Ensure environment variable is NOT set std::env::remove_var("NYASH_JOINIR_IF_SELECT"); let func = create_simple_pattern_mir(); let entry_block = func.entry_block; // Should return None when disabled let result = try_lower_if_to_joinir(&func, entry_block, false); assert!( result.is_none(), "Expected None when NYASH_JOINIR_IF_SELECT is not set" ); eprintln!("✅ If/Select lowering correctly disabled by default"); } #[test] fn test_if_select_wrong_function_name() { std::env::set_var("NYASH_JOINIR_IF_SELECT", "1"); // Create function with wrong name (not IfSelectTest.*) let mut func = create_simple_pattern_mir(); func.signature.name = "WrongName.test/1".to_string(); let entry_block = func.entry_block; // Should return None for non-IfSelectTest functions let result = try_lower_if_to_joinir(&func, entry_block, true); assert!( result.is_none(), "Expected None for non-IfSelectTest functions" ); eprintln!("✅ Function name filter working correctly"); std::env::remove_var("NYASH_JOINIR_IF_SELECT"); } }