feat(joinir): Phase 246-EX Part 2 - Exit PHI & step scheduling fixes

Phase 246-EX Part 2 completes the _atoi JoinIR integration:

Key fixes:
- Exit PHI connection: ExitLineReconnector now correctly uses exit PHI dsts
- Jump args preservation: BasicBlock.jump_args field stores JoinIR exit values
- instruction_rewriter: Reads jump_args, remaps JoinIR→HOST values by carrier order
- step_schedule.rs: New module for body-local init step ordering

Files changed:
- reconnector.rs: Exit PHI connection improvements
- instruction_rewriter.rs: Jump args reading & carrier value mapping
- loop_with_break_minimal.rs: Refactored step scheduling
- step_schedule.rs: NEW - Step ordering logic extracted

Tests: 931/931 PASS (no regression)

🤖 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-11 16:46:53 +09:00
parent e356524b0a
commit eb00d97fdb
16 changed files with 802 additions and 219 deletions

View File

@ -140,14 +140,36 @@ impl<'a> UpdateEnv<'a> {
/// env.resolve("digit_pos") → env.get("digit_value") → Some(ValueId(X))
/// ```
pub fn resolve(&self, name: &str) -> Option<ValueId> {
// Phase 247-EX: Check if this is a promoted variable
if self.promoted_loopbodylocals.iter().any(|v| v == name) {
// Phase 247-EX: Check if this is a promoted variable (digit_pos) or its derived carrier name (digit_value)
let promoted_key = if self.promoted_loopbodylocals.iter().any(|v| v == name) {
Some(name.to_string())
} else if let Some(base) = name.strip_suffix("_value") {
let candidate = format!("{}_pos", base);
if self.promoted_loopbodylocals.iter().any(|v| v == &candidate) {
Some(candidate)
} else {
None
}
} else {
None
};
if let Some(promoted_name) = promoted_key {
// Prefer the freshly computed body-local value if it exists (digit_pos)
if let Some(val) = self.body_local_env.get(&promoted_name) {
eprintln!(
"[update_env/phase247ex] Resolved promoted '{}' from body-local env: {:?}",
name, val
);
return Some(val);
}
// Phase 247-EX: Naming convention - "digit_pos" → "digit_value" (not "digit_pos_value")
// Extract base name: "digit_pos" → "digit", "pos" → "pos"
let base_name = if name.ends_with("_pos") {
&name[..name.len() - 4] // Remove "_pos" suffix
let base_name = if promoted_name.ends_with("_pos") {
&promoted_name[..promoted_name.len() - 4] // Remove "_pos" suffix
} else {
name
promoted_name.as_str()
};
// Priority 1a: Try <base>_value (integer carrier for NumberAccumulation)