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:
nyash-codex
2025-12-08 19:09:06 +09:00
parent 0dc9b838d6
commit 17b9201f96
2 changed files with 34 additions and 27 deletions

View File

@ -7,6 +7,23 @@ use super::super::trace;
/// Phase 179-A: Expected ValueId for k_exit parameter (sum_final) in Pattern 3 /// 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 /// 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); const PATTERN3_K_EXIT_SUM_FINAL_ID: ValueId = ValueId(18);
/// Phase 194: Detection function for Pattern 3 /// Phase 194: Detection function for Pattern 3

View File

@ -347,34 +347,24 @@ impl MirBuilder {
); );
} }
// Phase 196: Dynamically generate exit_bindings from ExitMeta and CarrierInfo // Phase 179 Task 2: Use ExitMetaCollector for unified exit binding generation
let mut exit_bindings = Vec::new(); // Replaces manual loop (Phase 196 implementation) with modular Box approach
for (carrier_name, join_exit_value) in &exit_meta.exit_values { use super::super::merge::exit_line::meta_collector::ExitMetaCollector;
// Find the host_slot for this carrier let exit_bindings = ExitMetaCollector::collect(
let host_slot = carrier_info self,
.carriers &exit_meta,
.iter() debug,
.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( // Validate that all expected carriers have bindings
crate::mir::join_ir::lowering::inline_boundary::LoopExitBinding { // (ExitMetaCollector silently skips missing carriers, but Pattern 4 expects all)
carrier_name: carrier_name.clone(), for carrier in &carrier_info.carriers {
join_exit_value: *join_exit_value, if !exit_bindings.iter().any(|b| b.carrier_name == carrier.name) {
host_slot, return Err(format!(
}, "[cf_loop/pattern4] Carrier '{}' not found in variable_map - exit binding missing",
); carrier.name
));
trace::trace().debug( }
"pattern4",
&format!("Generated binding: {} → JoinIR={} Host={}", carrier_name, join_exit_value.0, host_slot.0)
);
} }
// Phase 196: Build host_inputs dynamically // Phase 196: Build host_inputs dynamically