refactor(joinir): Phase 260 P0.2 - extract select handler

Adds select handler to the handlers/ module:

**handlers/select.rs** (118 lines):
- handle_select() - Select instruction (Phase 256 P1.5)
- Direct instruction emission (no branch/PHI expansion)
- Debug logging support
- Comprehensive unit tests

Pattern: Simple instruction wrapper, no control flow complexity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-21 07:27:18 +09:00
parent 875bfee1ba
commit 666de9d3ec
2 changed files with 118 additions and 0 deletions

View File

@ -9,3 +9,4 @@ pub(super) mod field_access;
pub(super) mod method_call;
pub(super) mod new_box;
pub(super) mod ret;
pub(super) mod select;

View File

@ -0,0 +1,117 @@
//! Select Handler
//!
//! Phase 260 P0.2: Extracted from joinir_block_converter.rs
//! Handles JoinIR Select instruction conversion.
use crate::mir::join_ir_vm_bridge::JoinIrVmBridgeError;
use crate::mir::{MirInstruction, MirType, ValueId};
/// Handle JoinIR Select instruction
///
/// Converts Select to MirInstruction::Select (direct instruction, not control flow expansion).
/// Phase 256 P1.5: Select does not expand to branches/PHI.
///
/// # Arguments
///
/// * `instructions` - Target instruction vector to append to
/// * `dst` - Destination ValueId for selected value
/// * `cond` - Condition ValueId (boolean)
/// * `then_val` - Value if condition is true
/// * `else_val` - Value if condition is false
/// * `type_hint` - Optional type hint (currently unused)
/// * `debug` - Optional debug flag for logging
pub fn handle_select(
instructions: &mut Vec<MirInstruction>,
dst: &ValueId,
cond: &ValueId,
then_val: &ValueId,
else_val: &ValueId,
type_hint: &Option<MirType>,
debug: bool,
) -> Result<(), JoinIrVmBridgeError> {
// Phase 256 P1.5: Select → MirInstruction::Select (direct instruction, not control flow expansion)
if debug {
eprintln!(
"[joinir_block] Converting Select: dst={:?}, cond={:?}, then_val={:?}, else_val={:?}",
dst, cond, then_val, else_val
);
}
// Emit Select instruction directly (no branch/phi expansion)
let select_inst = MirInstruction::Select {
dst: *dst,
cond: *cond,
then_val: *then_val,
else_val: *else_val,
};
instructions.push(select_inst);
let _ = type_hint;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_handle_select() {
let mut instructions = vec![];
let dst = ValueId(100);
let cond = ValueId(200);
let then_val = ValueId(300);
let else_val = ValueId(400);
let result = handle_select(
&mut instructions,
&dst,
&cond,
&then_val,
&else_val,
&None,
false,
);
assert!(result.is_ok());
assert_eq!(instructions.len(), 1);
if let MirInstruction::Select {
dst: inst_dst,
cond: inst_cond,
then_val: inst_then,
else_val: inst_else,
} = &instructions[0]
{
assert_eq!(*inst_dst, ValueId(100));
assert_eq!(*inst_cond, ValueId(200));
assert_eq!(*inst_then, ValueId(300));
assert_eq!(*inst_else, ValueId(400));
} else {
panic!("Expected Select instruction");
}
}
#[test]
fn test_handle_select_with_debug() {
let mut instructions = vec![];
let dst = ValueId(500);
let cond = ValueId(600);
let then_val = ValueId(700);
let else_val = ValueId(800);
// Test with debug enabled (should not panic, just print)
let result = handle_select(
&mut instructions,
&dst,
&cond,
&then_val,
&else_val,
&Some(MirType::Integer),
true,
);
assert!(result.is_ok());
assert_eq!(instructions.len(), 1);
}
}