refactor(joinir): Unify exit binding generation using ExitMetaCollector
Phase 179 Task 2: Modular exit binding generation Changes: - Pattern 4 (pattern4_with_continue.rs): - REPLACED: Manual exit_bindings loop (28 lines deleted) - WITH: ExitMetaCollector::collect() call (10 lines added) - ADDED: Validation that all carriers have bindings - Net reduction: 10 lines, improved modularity - Pattern 3 (pattern3_with_if_phi.rs): - DOCUMENTED: Why hardcoded ValueId(18) exists - ADDED: TODO with migration path to ExitMeta-based approach - DEFERRED: Actual migration (requires lowerer return type change) - Impact: Low priority - Pattern 3 is test-only Benefits: - Unified approach: Pattern 4 now uses same ExitMetaCollector as other patterns - Reusability: ExitMetaCollector is pattern-agnostic Box - Maintainability: Less duplicate code, clearer responsibilities - Testability: ExitMetaCollector has independent unit tests Notes: - Pattern 3 migration deferred (lowerer doesn't return ExitMeta yet) - Comprehensive TODO comment documents migration path - Pre-existing test failure (stage1_usingresolver) unrelated to this change
This commit is contained in:
@ -7,6 +7,23 @@ use super::super::trace;
|
||||
|
||||
/// Phase 179-A: Expected ValueId for k_exit parameter (sum_final) in Pattern 3
|
||||
/// This corresponds to the exit PHI input in the JoinIR lowering for loop_with_if_phi_minimal
|
||||
///
|
||||
/// # TODO (Phase 179 Task 2): Convert to ExitMeta-based exit binding generation
|
||||
///
|
||||
/// **Current State**: Hardcoded ValueId(18) - fragile and non-reusable
|
||||
///
|
||||
/// **Why it's hardcoded**:
|
||||
/// - Pattern 3's lowerer (`lower_loop_with_if_phi_pattern`) returns `Option<JoinModule>`
|
||||
/// - Unlike Pattern 4 which returns `(JoinModule, JoinFragmentMeta)`
|
||||
/// - No ExitMeta available to dynamically look up exit PHI ValueIds
|
||||
///
|
||||
/// **Migration Path** (when Pattern 3 lowerer is updated):
|
||||
/// 1. Change `lower_loop_with_if_phi_pattern` to return `(JoinModule, JoinFragmentMeta)`
|
||||
/// 2. Remove this constant
|
||||
/// 3. Use ExitMeta loop (like Pattern 4 lines 350-378) to generate exit_bindings dynamically
|
||||
/// 4. See: pattern4_with_continue.rs lines 350-378 for reference implementation
|
||||
///
|
||||
/// **Impact**: Low priority - Pattern 3 is test-only and works correctly with hardcoded value
|
||||
const PATTERN3_K_EXIT_SUM_FINAL_ID: ValueId = ValueId(18);
|
||||
|
||||
/// Phase 194: Detection function for Pattern 3
|
||||
|
||||
@ -347,34 +347,24 @@ impl MirBuilder {
|
||||
);
|
||||
}
|
||||
|
||||
// Phase 196: Dynamically generate exit_bindings from ExitMeta and CarrierInfo
|
||||
let mut exit_bindings = Vec::new();
|
||||
for (carrier_name, join_exit_value) in &exit_meta.exit_values {
|
||||
// Find the host_slot for this carrier
|
||||
let host_slot = carrier_info
|
||||
.carriers
|
||||
.iter()
|
||||
.find(|c| &c.name == carrier_name)
|
||||
.map(|c| c.host_id)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"[cf_loop/pattern4] Carrier '{}' not found in CarrierInfo",
|
||||
carrier_name
|
||||
)
|
||||
})?;
|
||||
|
||||
exit_bindings.push(
|
||||
crate::mir::join_ir::lowering::inline_boundary::LoopExitBinding {
|
||||
carrier_name: carrier_name.clone(),
|
||||
join_exit_value: *join_exit_value,
|
||||
host_slot,
|
||||
},
|
||||
// Phase 179 Task 2: Use ExitMetaCollector for unified exit binding generation
|
||||
// Replaces manual loop (Phase 196 implementation) with modular Box approach
|
||||
use super::super::merge::exit_line::meta_collector::ExitMetaCollector;
|
||||
let exit_bindings = ExitMetaCollector::collect(
|
||||
self,
|
||||
&exit_meta,
|
||||
debug,
|
||||
);
|
||||
|
||||
trace::trace().debug(
|
||||
"pattern4",
|
||||
&format!("Generated binding: {} → JoinIR={} Host={}", carrier_name, join_exit_value.0, host_slot.0)
|
||||
);
|
||||
// Validate that all expected carriers have bindings
|
||||
// (ExitMetaCollector silently skips missing carriers, but Pattern 4 expects all)
|
||||
for carrier in &carrier_info.carriers {
|
||||
if !exit_bindings.iter().any(|b| b.carrier_name == carrier.name) {
|
||||
return Err(format!(
|
||||
"[cf_loop/pattern4] Carrier '{}' not found in variable_map - exit binding missing",
|
||||
carrier.name
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 196: Build host_inputs dynamically
|
||||
|
||||
Reference in New Issue
Block a user