feat(joinir): Phase 227 - CarrierRole separation (LoopState vs ConditionOnly)

- Add CarrierRole enum to distinguish state carriers from condition-only carriers
- ConditionOnly carriers (is_digit_pos) skip exit PHI but keep header PHI
- Update all test struct literals with role field
- 877/884 tests PASS (7 pre-existing failures unrelated)

Remaining: ValueId(0) undefined - header PHI initialization for ConditionOnly

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-10 20:07:30 +09:00
parent d28e54ba06
commit 478cc0012e
20 changed files with 163 additions and 6 deletions

View File

@ -162,6 +162,7 @@ impl CommonPatternInitializer {
name: name.clone(),
host_id: ValueId(0), // Dummy
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, // Phase 227: Default
})
} else {
None

View File

@ -142,6 +142,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -181,11 +182,13 @@ mod tests {
name: "printed".to_string(),
host_id: ValueId(11),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
],
);
@ -228,6 +231,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -256,6 +260,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -284,6 +289,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -315,6 +321,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);

View File

@ -52,6 +52,7 @@ pub fn apply_exit_bindings_to_boundary(
carrier_name: carrier.name.clone(),
host_slot: post_loop_id,
join_exit_value: join_exit_id,
role: carrier.role, // Phase 227: Propagate role from CarrierInfo
});
join_outputs.push(join_exit_id);
@ -83,10 +84,12 @@ pub fn apply_exit_bindings_to_boundary(
///
/// LoopExitBinding for the loop variable
pub fn create_loop_var_exit_binding(carrier_info: &CarrierInfo) -> LoopExitBinding {
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
LoopExitBinding {
carrier_name: carrier_info.loop_var_name.clone(),
join_exit_value: carrier_info.loop_var_id, // Loop var maps to itself
host_slot: carrier_info.loop_var_id,
role: CarrierRole::LoopState, // Phase 227: Loop var is always LoopState
}
}
@ -104,6 +107,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);

View File

@ -40,6 +40,7 @@ pub fn build_loop_exit_bindings(
carrier_name: carrier.name.clone(),
join_exit_value: join_exit_id,
host_slot: carrier.host_id,
role: carrier.role, // Phase 227: Propagate role from CarrierInfo
});
// Allocate new ValueId for post-loop carrier value
@ -90,6 +91,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -127,11 +129,13 @@ mod tests {
name: "printed".to_string(),
host_id: ValueId(11),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
],
);

View File

@ -69,6 +69,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -88,11 +89,13 @@ mod tests {
name: "printed".to_string(),
host_id: ValueId(11),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
CarrierVar {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
],
);
@ -115,6 +118,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -135,6 +139,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);
@ -155,6 +160,7 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
}],
);

View File

@ -475,9 +475,13 @@ impl MirBuilder {
// Issue: CommonPatternInitializer includes all variables in variable_map as carriers,
// but only variables with updates in the loop body are true carriers.
// Condition-only variables (like 'len', 's') should be excluded.
//
// Phase 227: Keep ConditionOnly carriers even if they don't have updates
// (they're used in loop/break conditions, not updated)
let original_carrier_count = carrier_info.carriers.len();
carrier_info.carriers.retain(|carrier| {
carrier_updates.contains_key(&carrier.name)
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
carrier_updates.contains_key(&carrier.name) || carrier.role == CarrierRole::ConditionOnly
});
eprintln!(

View File

@ -276,16 +276,19 @@ mod tests {
name: "i".to_string(),
host_id: ValueId(1),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
CarrierVar {
name: "sum".to_string(),
host_id: ValueId(2),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
CarrierVar {
name: "M".to_string(),
host_id: ValueId(3),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
],
trim_helper: None,

View File

@ -396,11 +396,13 @@ mod tests {
name: "sum".to_string(),
host_id: ValueId(10),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
CarrierVar {
name: "count".to_string(),
host_id: ValueId(11),
join_id: None,
role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState,
},
],
trim_helper: None,