refactor(joinir): Phase 33-12 Large module modularization complete

Task 1: Split mod.rs into if/loop routers
- Created if_lowering_router.rs (172 lines): If-expression routing
- Created loop_pattern_router.rs (149 lines): Loop pattern routing
- Refactored mod.rs (511 → 221 lines): Thin re-export module

Task 2: Modularize loop_patterns per-pattern
- Created loop_patterns/ directory with 4 pattern files:
  - simple_while.rs (225 lines): Pattern 1 implementation
  - with_break.rs (129 lines): Pattern 2 implementation
  - with_if_phi.rs (123 lines): Pattern 3 implementation
  - with_continue.rs (129 lines): Pattern 4 stub
- Created mod.rs (178 lines): Dispatcher + shared utilities
- Removed old loop_patterns.rs (735 lines → directory)

Line count changes:
- mod.rs: 511 → 221 lines (57% reduction)
- loop_patterns: 735 → 784 lines (modularized)
- Total: Net +80 lines for better organization

Benefits:
- Single responsibility per file
- Clear pattern boundaries
- Improved testability
- Better maintainability
- Backward compatibility maintained

Testing:
- cargo build --release:  Success (0 errors)
- Regression test:  Pass (RC: 0)
This commit is contained in:
nyash-codex
2025-12-07 03:26:06 +09:00
parent 192c29efb1
commit adccfe5a4e
9 changed files with 1113 additions and 1033 deletions

View File

@ -0,0 +1,178 @@
//! Phase 33-12: Loop Pattern Lowering Module
//!
//! Implements JoinIR lowering for different loop patterns:
//! - Pattern 1: Simple while loops (no break/continue)
//! - Pattern 2: Loops with break statements
//! - Pattern 3: Loops with if expressions + PHI merging
//! - Pattern 4: Loops with continue statements (stub)
//!
//! # Module Structure
//!
//! Each pattern is implemented in its own file:
//! - `simple_while.rs`: Pattern 1 implementation
//! - `with_break.rs`: Pattern 2 implementation
//! - `with_if_phi.rs`: Pattern 3 implementation
//! - `with_continue.rs`: Pattern 4 stub
//!
//! # Design Philosophy
//!
//! Pattern lowering functions are "thin boxes":
//! - Takes input (LoopForm, builder)
//! - Returns Result (success/error)
//! - No side effects outside the builder
//!
//! # Reference
//!
//! Design document: `docs/private/roadmap2/phases/phase-188-joinir-loop-pattern-expansion/design.md`
pub mod simple_while;
pub mod with_break;
pub mod with_if_phi;
pub mod with_continue;
pub use simple_while::lower_simple_while_to_joinir;
pub use with_break::lower_loop_with_break_to_joinir;
pub use with_if_phi::lower_loop_with_conditional_phi_to_joinir;
pub use with_continue::lower_loop_with_continue_to_joinir;
// ============================================================================
// Helper Functions (Shared Utilities)
// ============================================================================
// TODO: Implement helper functions for extraction and translation
// These will be shared across all 4 patterns:
//
// 1. extract_carriers_from_header_phi(loop_form) -> Vec<CarrierVar>
// 2. extract_loop_condition_from_header(loop_form) -> ValueId
// 3. extract_body_instructions(loop_form) -> Vec<MirInstruction>
// 4. translate_mir_inst_to_joinir(inst, lowerer) -> JoinInst
// 5. find_break_block(loop_form) -> BasicBlockId
// 6. extract_break_condition(block) -> ValueId
// 7. find_if_else_block(loop_form) -> BasicBlockId
// 8. extract_if_condition(block) -> ValueId
// 9. extract_then_value(block) -> ValueId
// 10. extract_else_value(block) -> ValueId
#[cfg(test)]
mod tests {
use super::*;
// ========================================================================
// Pattern 1: Simple While Loop Tests
// ========================================================================
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern1_lowering_success() {
// TODO: Add integration test for simple while pattern lowering
// Step 1: Create mock LoopForm for simple while pattern
// Step 2: Create mock LoopToJoinLowerer
// Step 3: Call lower_simple_while_to_joinir()
// Step 4: Assert returns Some(JoinInst)
// Step 5: Verify generated JoinIR structure
}
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern1_rejects_break() {
// TODO: Add test that rejects loop with break
// Step 1: Create mock LoopForm with break
// Step 2: Call lower_simple_while_to_joinir()
// Step 3: Assert returns None (unsupported pattern)
}
// ========================================================================
// Pattern 2: Loop with Break Tests
// ========================================================================
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern2_lowering_success() {
// TODO: Add integration test for break pattern lowering
// Step 1: Create mock LoopForm for break pattern
// Step 2: Create mock LoopToJoinLowerer
// Step 3: Call lower_loop_with_break_to_joinir()
// Step 4: Assert returns Some(JoinInst)
// Step 5: Verify generated JoinIR structure (two Jumps to k_exit)
}
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern2_exit_phi_correct() {
// TODO: Add test that verifies k_exit receives correct exit values
// Step 1: Create mock LoopForm for break pattern
// Step 2: Call lower_loop_with_break_to_joinir()
// Step 3: Verify k_exit params = [i_exit]
// Step 4: Verify both Jumps pass current i as argument
}
// ========================================================================
// Pattern 3: Loop with If-Else PHI Tests
// ========================================================================
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern3_lowering_success() {
// TODO: Add integration test for if-else phi pattern lowering
// Step 1: Create mock LoopForm for if-else phi pattern
// Step 2: Create mock LoopToJoinLowerer
// Step 3: Call lower_loop_with_conditional_phi_to_joinir()
// Step 4: Assert returns Some(JoinInst)
// Step 5: Verify generated JoinIR structure (Select instruction)
}
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern3_multiple_carriers() {
// TODO: Add test that verifies multiple carrier variables
// Step 1: Create mock LoopForm with i + sum carriers
// Step 2: Call lower_loop_with_conditional_phi_to_joinir()
// Step 3: Verify loop_step params = [i, sum]
// Step 4: Verify tail Call args = [i_next, sum_new]
}
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern3_if_lowering_integration() {
// TODO: Add test that verifies If lowering integration
// Step 1: Create mock LoopForm with if-else
// Step 2: Call lower_loop_with_conditional_phi_to_joinir()
// Step 3: Verify Select instruction is generated
// Step 4: Verify Select has correct cond/then_val/else_val
}
// ========================================================================
// Pattern 4: Loop with Continue Tests
// ========================================================================
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern4_lowering_success() {
// TODO: Add integration test for continue pattern lowering
// Step 1: Create mock LoopForm for continue pattern
// Step 2: Create mock LoopToJoinLowerer
// Step 3: Call lower_loop_with_continue_to_joinir()
// Step 4: Assert returns Some(JoinInst)
// Step 5: Verify generated JoinIR structure (Jump to loop_step on continue)
}
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern4_continue_jump_correct() {
// TODO: Add test that verifies continue jumps to loop_step
// Step 1: Create mock LoopForm for continue pattern
// Step 2: Call lower_loop_with_continue_to_joinir()
// Step 3: Verify conditional Jump targets loop_step
// Step 4: Verify Jump passes current carrier values as arguments
}
#[test]
#[ignore] // TODO: Implement test after lowering logic is complete
fn test_pattern4_multiple_carriers() {
// TODO: Add test that verifies multiple carrier variables
// Step 1: Create mock LoopForm with i + sum carriers
// Step 2: Call lower_loop_with_continue_to_joinir()
// Step 3: Verify loop_step params = [i, sum]
// Step 4: Verify both tail Call and continue Jump use [i_next, sum_next]
}
}

View File

@ -0,0 +1,225 @@
//! Pattern 1: Simple While Loop Lowering
//!
//! Target: Simple while loops with no break/continue
//! Example: `while(i < 10) { i = i + 1 }`
//!
//! # Transformation
//!
//! ```text
//! fn loop_step(i):
//! exit_cond = !(i < 3)
//! Jump(k_exit, [], cond=exit_cond)
//! print(i)
//! i_next = i + 1
//! Call(loop_step, [i_next])
//! ```
use crate::mir::join_ir::lowering::loop_to_join::LoopToJoinLowerer;
use crate::mir::join_ir::JoinInst;
use crate::mir::loop_form::LoopForm;
/// Lowering for Pattern 1: Simple While Loop
///
/// # Transformation (Pseudocode from design.md)
///
/// ```text
/// fn loop_step(i):
/// exit_cond = !(i < 3)
/// Jump(k_exit, [], cond=exit_cond)
/// print(i)
/// i_next = i + 1
/// Call(loop_step, [i_next])
/// ```
///
/// # Steps (from design.md § Pattern 1 § Step-by-Step Transformation)
///
/// 1. **Extract Loop Variables (Carriers)**
/// - Analyze header PHI nodes
/// - Identify initial values and next values
///
/// 2. **Create loop_step Function Signature**
/// - Parameters: carrier variables + k_exit continuation
///
/// 3. **Create k_exit Continuation**
/// - Handles loop exit (returns final value)
///
/// 4. **Generate Exit Condition Check**
/// - Negate loop condition: `exit_cond = !(i < 3)`
/// - Add Jump to k_exit if exit_cond is true
///
/// 5. **Translate Loop Body**
/// - Copy body instructions to loop_step body
/// - Preserve side effects (print, etc.)
///
/// 6. **Generate Tail Recursion**
/// - Update carrier: `i_next = i + 1`
/// - Tail call: `Call(loop_step, [i_next], k_next: None)`
///
/// 7. **Wire Exit Continuation**
/// - Connect loop_step exit Jump to k_exit
/// - Set k_exit exit_cont to parent continuation
///
/// # Arguments
///
/// * `loop_form` - The loop structure to lower
/// * `lowerer` - The LoopToJoinLowerer builder (provides ValueId allocation, etc.)
///
/// # Returns
///
/// * `Some(JoinInst)` - Lowering succeeded, returns generated JoinIR instruction
/// * `None` - Lowering failed (pattern not matched or unsupported)
///
/// # Errors
///
/// Returns `None` if:
/// - Loop has breaks or continues
/// - Loop has multiple latches
/// - Loop condition is too complex
///
/// # Reference
///
/// See design.md § Pattern 1 for complete transformation details and pseudocode.
///
/// # Example Usage
///
/// ```rust,ignore
/// use crate::mir::loop_pattern_detection::is_simple_while_pattern;
///
/// if is_simple_while_pattern(&loop_form) {
/// lower_simple_while_to_joinir(&loop_form, &mut lowerer)?;
/// }
/// ```
pub fn lower_simple_while_to_joinir(
loop_form: &LoopForm,
lowerer: &mut LoopToJoinLowerer,
) -> Option<JoinInst> {
// TODO: Implement Pattern 1 lowering
//
// Step 1: Extract Loop Variables (Carriers)
// ==========================================
// From header PHI: %2 = phi [%1, bb1], [%6, bb4]
// Extract: (var_name: "i", init_value: ValueId(1), next_value: ValueId(6))
//
// ```rust
// let carriers = extract_carriers_from_header_phi(loop_form)?;
// ```
//
// Step 2: Create loop_step Function Signature
// ============================================
// Signature: fn loop_step(i: ValueId, k_exit: JoinContId) -> ...
//
// ```rust
// let loop_step_id = lowerer.allocate_join_func_id();
// let k_exit_id = lowerer.allocate_join_func_id();
//
// let mut loop_step_params = vec![];
// for carrier in &carriers {
// loop_step_params.push(carrier.param_valueid);
// }
// ```
//
// Step 3: Create k_exit Continuation
// ===================================
// fn k_exit() -> ValueId // Returns final value (0 in this case)
//
// ```rust
// let k_exit_func = JoinFunction {
// id: k_exit_id,
// name: "k_exit".to_string(),
// params: vec![], // No exit values in Pattern 1
// body: vec![
// JoinInst::Compute(MirLikeInst::Const {
// dst: lowerer.fresh_valueid(),
// value: ConstValue::Integer(0),
// }),
// JoinInst::Ret { value: Some(return_val) },
// ],
// exit_cont: None,
// };
// lowerer.register_join_function(k_exit_func);
// ```
//
// Step 4: Generate Exit Condition Check
// ======================================
// exit_cond = !(i < 3)
// Jump(k_exit, [], cond=exit_cond)
//
// ```rust
// let loop_cond = extract_loop_condition_from_header(loop_form)?;
// let exit_cond = lowerer.fresh_valueid();
//
// body.push(JoinInst::Compute(MirLikeInst::UnaryOp {
// dst: exit_cond,
// op: UnaryOp::Not,
// operand: loop_cond,
// }));
//
// body.push(JoinInst::Jump {
// cont: k_exit_id.as_cont(),
// args: vec![],
// cond: Some(exit_cond),
// });
// ```
//
// Step 5: Translate Loop Body
// ===========================
// Copy body instructions to loop_step body
//
// ```rust
// let body_insts = extract_body_instructions(loop_form)?;
// for inst in body_insts {
// body.push(translate_mir_inst_to_joinir(inst, lowerer)?);
// }
// ```
//
// Step 6: Generate Tail Recursion
// ================================
// i_next = i + 1
// Call(loop_step, [i_next], k_next: None)
//
// ```rust
// let const_1 = lowerer.fresh_valueid();
// let i_next = lowerer.fresh_valueid();
//
// body.push(JoinInst::Compute(MirLikeInst::Const {
// dst: const_1,
// value: ConstValue::Integer(1),
// }));
//
// body.push(JoinInst::Compute(MirLikeInst::BinOp {
// dst: i_next,
// op: BinOp::Add,
// lhs: i,
// rhs: const_1,
// }));
//
// body.push(JoinInst::Call {
// func: loop_step_id,
// args: vec![i_next],
// k_next: None, // CRITICAL: Must be None (tail call)
// dst: Some(result_var),
// });
// ```
//
// Step 7: Wire Exit Continuation
// ===============================
// Connect loop_step to k_exit
//
// ```rust
// let loop_step_func = JoinFunction {
// id: loop_step_id,
// name: "loop_step".to_string(),
// params: loop_step_params,
// body: body,
// exit_cont: Some(k_exit_id.as_cont()),
// };
// lowerer.register_join_function(loop_step_func);
// ```
//
// Return success
// ```rust
// Some(JoinInst::Call { ... })
// ```
None
}

View File

@ -0,0 +1,129 @@
//! Pattern 2: Loop with Break Lowering
//!
//! Target: Loops with conditional break statements
//! Example: `while(i < 10) { if i >= 5 { break } i = i + 1 }`
//!
//! # Transformation
//!
//! ```text
//! fn loop_step(i):
//! exit_cond = !(i < 3)
//! Jump(k_exit, [i], cond=exit_cond) // Natural exit
//! break_cond = (i >= 2)
//! Jump(k_exit, [i], cond=break_cond) // Break exit
//! i_next = i + 1
//! Call(loop_step, [i_next])
//! ```
use crate::mir::join_ir::lowering::loop_to_join::LoopToJoinLowerer;
use crate::mir::join_ir::JoinInst;
use crate::mir::loop_form::LoopForm;
/// Lowering for Pattern 2: Loop with Conditional Break
///
/// # Transformation (Pseudocode from design.md)
///
/// ```text
/// fn loop_step(i):
/// exit_cond = !(i < 3)
/// Jump(k_exit, [i], cond=exit_cond) // Natural exit
/// break_cond = (i >= 2)
/// Jump(k_exit, [i], cond=break_cond) // Break exit
/// i_next = i + 1
/// Call(loop_step, [i_next])
/// ```
///
/// # Steps (from design.md § Pattern 2 § Step-by-Step Transformation)
///
/// 1. **Extract Loop Variables** (same as Pattern 1)
/// 2. **Create loop_step Function** (same as Pattern 1)
/// 3. **Create k_exit with Exit PHI**
/// - k_exit(i_exit) - receives exit value from both exit paths
/// 4. **Generate Natural Exit Check** (same as Pattern 1)
/// 5. **Generate Break Check**
/// - Extract break condition: `break_cond = (i >= 2)`
/// - Add conditional Jump to k_exit: `Jump(k_exit, [i], cond=break_cond)`
/// 6. **Translate Loop Body** (same as Pattern 1)
/// 7. **Generate Tail Recursion** (same as Pattern 1)
///
/// # Key Difference from Pattern 1
///
/// - **Multiple Exit Paths**: Natural exit + break exit
/// - **Exit PHI**: k_exit receives exit value from both paths
/// - **Sequential Jumps**: Natural exit check → break check → body
///
/// # Arguments
///
/// * `loop_form` - The loop structure to lower (must have break_targets)
/// * `lowerer` - The LoopToJoinLowerer builder
///
/// # Returns
///
/// * `Some(JoinInst)` - Lowering succeeded, returns generated JoinIR instruction
/// * `None` - Lowering failed (pattern not matched or unsupported)
///
/// # Errors
///
/// Returns `None` if:
/// - Loop has no breaks (use Pattern 1 instead)
/// - Loop has multiple break targets (not yet supported)
/// - Break is not in an if statement
///
/// # Reference
///
/// See design.md § Pattern 2 for complete transformation details and pseudocode.
///
/// # Example Usage
///
/// ```rust,ignore
/// use crate::mir::loop_pattern_detection::is_loop_with_break_pattern;
///
/// if is_loop_with_break_pattern(&loop_form) {
/// lower_loop_with_break_to_joinir(&loop_form, &mut lowerer)?;
/// }
/// ```
pub fn lower_loop_with_break_to_joinir(
_loop_form: &LoopForm,
_lowerer: &mut LoopToJoinLowerer,
) -> Option<JoinInst> {
// Phase 188-Impl-2: Delegate to minimal lowerer
// TODO: Extract LoopScopeShape from loop_form for generic implementation
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
use crate::mir::BasicBlockId;
use std::collections::{BTreeMap, BTreeSet};
// For now, use a placeholder LoopScopeShape
// TODO: Build actual LoopScopeShape from loop_form
let _placeholder_scope = LoopScopeShape {
header: BasicBlockId(0),
body: BasicBlockId(0),
latch: BasicBlockId(0),
exit: BasicBlockId(0),
pinned: BTreeSet::new(),
carriers: BTreeSet::new(),
body_locals: BTreeSet::new(),
exit_live: BTreeSet::new(),
progress_carrier: None,
variable_definitions: BTreeMap::new(),
};
// Generate JoinIR module
// Phase 169: lower_loop_with_break_minimal now requires condition AST and builder
// This test stub is not used by the actual router, so commenting out for now
// let _join_module = lower_loop_with_break_minimal(placeholder_scope, condition, builder)?;
// Phase 188-Impl-2: Pattern 2 is now integrated in control_flow.rs via cf_loop_pattern2_with_break()
// This function (lower_loop_with_break_to_joinir) is currently not used by the router.
// The actual lowering happens directly in control_flow.rs which calls loop_with_break_minimal.
//
// TODO: Either:
// 1. Remove this function and rely only on control_flow.rs integration, OR
// 2. Implement JoinModule → JoinInst conversion here (future phase)
eprintln!("[loop_patterns] Pattern 2: Lowering delegated to control_flow.rs");
// Temporary: Return None to trigger fallback
// Pattern 2 currently works via hardcoded route in control_flow.rs
None
}

View File

@ -0,0 +1,129 @@
//! Pattern 4: Loop with Continue - STUB
//!
//! Target: Loops with continue statements
//! Status: Deferred to Phase 195+
//!
//! # Transformation
//!
//! ```text
//! fn loop_step(i, sum):
//! exit_cond = !(i < 10)
//! Jump(k_exit, [sum], cond=exit_cond) // Natural exit
//! i_next = i + 1
//! continue_cond = (i_next % 2 == 0)
//! Jump(loop_step, [i_next, sum], cond=continue_cond) // Continue jumps to loop start
//! sum_next = sum + i_next
//! Call(loop_step, [i_next, sum_next]) // Normal iteration
//! ```
use crate::mir::join_ir::lowering::loop_to_join::LoopToJoinLowerer;
use crate::mir::join_ir::JoinInst;
use crate::mir::loop_form::LoopForm;
/// Lowering for Pattern 4: Loop with Continue
///
/// # Transformation (Pseudocode)
///
/// ```text
/// fn loop_step(i, sum):
/// exit_cond = !(i < 10)
/// Jump(k_exit, [sum], cond=exit_cond) // Natural exit
/// i_next = i + 1
/// continue_cond = (i_next % 2 == 0)
/// Jump(loop_step, [i_next, sum], cond=continue_cond) // Continue jumps to loop start
/// sum_next = sum + i_next
/// Call(loop_step, [i_next, sum_next]) // Normal iteration
/// ```
///
/// # Steps (Pattern 4 Transformation)
///
/// 1. **Extract Loop Variables** (multiple carriers: i + sum)
/// 2. **Create loop_step Function** (params: i, sum, k_exit)
/// 3. **Create k_exit with Exit PHI** (receives sum exit value)
/// 4. **Generate Exit Condition Check** (same as Pattern 1)
/// 5. **Generate Continue Check**
/// - Extract continue condition (if exists)
/// - Add conditional Jump back to loop_step: `Jump(loop_step, [i_next, sum], cond=continue_cond)`
/// 6. **Translate Loop Body** (remaining instructions after continue)
/// 7. **Generate Tail Recursion** (with multiple carriers: i_next, sum_next)
///
/// # Key Difference from Pattern 1/2/3
///
/// - **Continue Jump**: Continue jumps back to loop_step with current carrier values
/// - **Dual Path**: Continue path + normal path (both recursive)
/// - **PHI at Loop Start**: Loop header receives values from both continue and normal paths
///
/// # Arguments
///
/// * `loop_form` - The loop structure to lower (must have continue_targets)
/// * `lowerer` - The LoopToJoinLowerer builder
///
/// # Returns
///
/// * `Some(JoinInst)` - Lowering succeeded, returns generated JoinIR instruction
/// * `None` - Lowering failed (pattern not matched or unsupported)
///
/// # Errors
///
/// Returns `None` if:
/// - Loop has no continues (use Pattern 1 instead)
/// - Loop has break statements (not yet supported)
/// - Continue is not in an if statement
///
/// # Reference
///
/// See design.md § Pattern 4 for complete transformation details and pseudocode.
///
/// # Example Usage
///
/// ```rust,ignore
/// use crate::mir::loop_pattern_detection::is_loop_with_continue_pattern;
///
/// if is_loop_with_continue_pattern(&loop_form) {
/// lower_loop_with_continue_to_joinir(&loop_form, &mut lowerer)?;
/// }
/// ```
pub fn lower_loop_with_continue_to_joinir(
_loop_form: &LoopForm,
_lowerer: &mut LoopToJoinLowerer,
) -> Option<JoinInst> {
// Phase 188-Impl-4: Pattern 4 implementation placeholder
// TODO: Implement Pattern 4 lowering
//
// Step 1: Extract Loop Variables (Carriers)
// ==========================================
// From header PHI: %i = phi [%0, preheader], [%i_next, body]
// %sum = phi [%0, preheader], [%sum_next, body]
// Extract: (var_name: "i", init_value: 0, next_value: i_next)
// (var_name: "sum", init_value: 0, next_value: sum_next)
//
// Step 2: Create loop_step Function Signature
// ============================================
// Signature: fn loop_step(i: ValueId, sum: ValueId, k_exit: JoinContId) -> ...
//
// Step 3: Create k_exit Continuation
// ===================================
// fn k_exit(sum_exit) -> ValueId // Returns final sum value
//
// Step 4: Generate Exit Condition Check
// ======================================
// exit_cond = !(i < 10)
// Jump(k_exit, [sum], cond=exit_cond)
//
// Step 5: Generate Continue Check
// ================================
// i_next = i + 1
// continue_cond = (i_next % 2 == 0)
// Jump(loop_step, [i_next, sum], cond=continue_cond) // Continue to loop start
//
// Step 6: Translate Loop Body (after continue)
// =============================================
// sum_next = sum + i_next
//
// Step 7: Generate Tail Recursion
// ================================
// Call(loop_step, [i_next, sum_next], k_next: None)
eprintln!("[loop_patterns] Pattern 4: Continue lowering not yet implemented");
None
}

View File

@ -0,0 +1,123 @@
//! Pattern 3: Loop with If-Else PHI Lowering
//!
//! Target: Loops with if expressions inside that merge values
//! Example: `while(i < 10) { if x { y = 1 } else { y = 2 } }`
//!
//! # Transformation
//!
//! ```text
//! fn loop_step(i, sum):
//! exit_cond = !(i <= 5)
//! Jump(k_exit, [sum], cond=exit_cond)
//! sum_new = Select(cond=(i%2==1), then=sum+i, else=sum+0)
//! i_next = i + 1
//! Call(loop_step, [i_next, sum_new])
//! ```
use crate::mir::join_ir::lowering::loop_to_join::LoopToJoinLowerer;
use crate::mir::join_ir::JoinInst;
use crate::mir::loop_form::LoopForm;
/// Lowering for Pattern 3: Loop with If-Else PHI
///
/// # Transformation (Pseudocode from design.md)
///
/// ```text
/// fn loop_step(i, sum):
/// exit_cond = !(i <= 5)
/// Jump(k_exit, [sum], cond=exit_cond)
/// sum_new = Select(cond=(i%2==1), then=sum+i, else=sum+0)
/// i_next = i + 1
/// Call(loop_step, [i_next, sum_new])
/// ```
///
/// # Steps (from design.md § Pattern 3 § Step-by-Step Transformation)
///
/// 1. **Extract Loop Variables** (multiple carriers: i + sum)
/// 2. **Create loop_step Function** (params: i, sum, k_exit)
/// 3. **Create k_exit with Exit PHI** (receives sum exit value)
/// 4. **Generate Exit Condition Check** (same as Pattern 1)
/// 5. **Translate If-Else to Select**
/// - Use existing If lowering (Phase 33: Select/IfMerge)
/// - Generate: `sum_new = Select(cond, then_val, else_val)`
/// 6. **Translate Loop Body** (remaining instructions)
/// 7. **Generate Tail Recursion** (with multiple carriers: i_next, sum_new)
///
/// # Key Difference from Pattern 1
///
/// - **Multiple Carrier Variables**: Loop updates i + sum
/// - **In-Loop If Lowering**: Reuses existing Select/IfMerge lowering
/// - **PHI in Loop Body**: If-else assigns to same variable (becomes Select)
///
/// # Arguments
///
/// * `loop_form` - The loop structure to lower (must have if-else in body)
/// * `lowerer` - The LoopToJoinLowerer builder
///
/// # Returns
///
/// * `Some(JoinInst)` - Lowering succeeded, returns generated JoinIR instruction
/// * `None` - Lowering failed (pattern not matched or unsupported)
///
/// # Errors
///
/// Returns `None` if:
/// - Loop has breaks or continues
/// - If-else does not assign to same variable
/// - If context cannot be resolved
///
/// # Reference
///
/// See design.md § Pattern 3 for complete transformation details and pseudocode.
///
/// # Example Usage
///
/// ```rust,ignore
/// use crate::mir::loop_pattern_detection::is_loop_with_conditional_phi_pattern;
///
/// if is_loop_with_conditional_phi_pattern(&loop_form) {
/// lower_loop_with_conditional_phi_to_joinir(&loop_form, &mut lowerer)?;
/// }
/// ```
pub fn lower_loop_with_conditional_phi_to_joinir(
_loop_form: &LoopForm,
_lowerer: &mut LoopToJoinLowerer,
) -> Option<JoinInst> {
// Phase 188-Impl-3: Delegate to minimal lowerer
// TODO: Extract LoopScopeShape from loop_form for generic implementation
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
use crate::mir::join_ir::lowering::loop_with_if_phi_minimal::lower_loop_with_if_phi_pattern;
use crate::mir::BasicBlockId;
use std::collections::{BTreeMap, BTreeSet};
// For now, use a placeholder LoopScopeShape
// TODO: Build actual LoopScopeShape from loop_form
let placeholder_scope = LoopScopeShape {
header: BasicBlockId(0),
body: BasicBlockId(0),
latch: BasicBlockId(0),
exit: BasicBlockId(0),
pinned: BTreeSet::new(),
carriers: BTreeSet::new(),
body_locals: BTreeSet::new(),
exit_live: BTreeSet::new(),
progress_carrier: None,
variable_definitions: BTreeMap::new(),
};
// Generate JoinIR module
let _join_module = lower_loop_with_if_phi_pattern(placeholder_scope)?;
// Phase 188-Impl-3: Pattern 3 is now integrated via the router
// This function delegates to loop_with_if_phi_minimal which generates JoinModule
//
// TODO: Either:
// 1. Remove this function and rely only on router integration, OR
// 2. Implement JoinModule → JoinInst conversion here (future phase)
eprintln!("[loop_patterns] Pattern 3: Lowering delegated to loop_with_if_phi_minimal");
// Temporary: Return None to trigger fallback
// Pattern 3 currently works via router which calls minimal lowerer directly
None
}