feat(joinir): Phase 224-D - ConditionAlias for promoted variable resolution
- Add ConditionAlias type to CarrierInfo (old_name → carrier_name) - Record aliases in DigitPosPromoter and TrimPatternInfo - Resolve aliases in Pattern2 ConditionEnv building - digit_pos now correctly resolves to is_digit_pos carrier Fixes "Variable 'digit_pos' not bound in ConditionEnv" error. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -210,16 +210,6 @@ impl MirBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 201: Allocate carrier ValueIds from Param region and SET join_id
|
||||
// This ensures carriers are also in the safe Param region
|
||||
// CRITICAL: We must set join_id so the lowerer can access it
|
||||
for carrier in &mut carrier_info.carriers {
|
||||
let carrier_join_id = join_value_space.alloc_param();
|
||||
carrier.join_id = Some(carrier_join_id);
|
||||
eprintln!("[pattern2/phase201] Allocated carrier '{}' param ID: {:?}",
|
||||
carrier.name, carrier_join_id);
|
||||
}
|
||||
|
||||
// Phase 191: Create empty body-local environment
|
||||
// LoopBodyLocalInitLowerer will populate it during init lowering
|
||||
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
|
||||
@ -228,10 +218,6 @@ impl MirBuilder {
|
||||
eprintln!("[pattern2/body-local] Phase 201: Created empty body-local environment (param_count={})",
|
||||
join_value_space.param_count());
|
||||
|
||||
// Phase 201: Create alloc_join_value closure using JoinValueSpace
|
||||
// This ensures all param allocations go through the unified space
|
||||
let mut alloc_join_value = || join_value_space.alloc_param();
|
||||
|
||||
// Debug: Log condition bindings
|
||||
eprintln!("[cf_loop/pattern2] Phase 201: ConditionEnv contains {} variables:", env.len());
|
||||
eprintln!(" Loop param '{}' → JoinIR {:?}", loop_var_name, env.get(&loop_var_name));
|
||||
@ -352,6 +338,62 @@ impl MirBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 224-D: Allocate join_ids for ALL carriers (including newly merged ones)
|
||||
// This must happen AFTER promotion/merge to include promoted carriers
|
||||
eprintln!("[pattern2/phase224d] Allocating join_ids for {} carriers", carrier_info.carriers.len());
|
||||
for carrier in &mut carrier_info.carriers {
|
||||
let carrier_join_id = join_value_space.alloc_param();
|
||||
carrier.join_id = Some(carrier_join_id);
|
||||
eprintln!("[pattern2/phase224d] Allocated carrier '{}' param ID: {:?}",
|
||||
carrier.name, carrier_join_id);
|
||||
}
|
||||
|
||||
// Phase 224-D: Save carriers with join_ids BEFORE filtering
|
||||
let carriers_with_join_ids = carrier_info.carriers.clone();
|
||||
|
||||
// Phase 224-D: Add condition aliases to ConditionEnv
|
||||
// This allows promoted variables to be referenced by their original names in conditions
|
||||
for alias in &carrier_info.condition_aliases {
|
||||
// Check if the carrier_name matches the loop_var_name (promoted as main carrier)
|
||||
if alias.carrier_name == carrier_info.loop_var_name {
|
||||
// Use loop variable's join_id from env
|
||||
if let Some(join_id) = env.get(&carrier_info.loop_var_name) {
|
||||
env.insert(alias.old_name.clone(), join_id);
|
||||
eprintln!(
|
||||
"[pattern2/phase224d] Added condition alias '{}' → loop_var '{}' (join_id={:?})",
|
||||
alias.old_name, carrier_info.loop_var_name, join_id
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Find the carrier's join_id in the carriers list (BEFORE filtering, with join_ids)
|
||||
if let Some(carrier) = carriers_with_join_ids.iter().find(|c| c.name == alias.carrier_name) {
|
||||
if let Some(join_id) = carrier.join_id {
|
||||
// Add alias mapping: old_name → carrier's join_id
|
||||
env.insert(alias.old_name.clone(), join_id);
|
||||
eprintln!(
|
||||
"[pattern2/phase224d] Added condition alias '{}' → carrier '{}' (join_id={:?})",
|
||||
alias.old_name, alias.carrier_name, join_id
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
"[pattern2/phase224d] WARNING: Carrier '{}' has no join_id yet!",
|
||||
alias.carrier_name
|
||||
);
|
||||
}
|
||||
} else {
|
||||
eprintln!(
|
||||
"[pattern2/phase224d] WARNING: Carrier '{}' not found in carriers list!",
|
||||
alias.carrier_name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 201: Create alloc_join_value closure using JoinValueSpace
|
||||
// This ensures all param allocations go through the unified space
|
||||
// NOTE: Must be created AFTER all direct join_value_space.alloc_param() calls
|
||||
let mut alloc_join_value = || join_value_space.alloc_param();
|
||||
|
||||
// Phase 180-3: Delegate Trim/P5 processing to TrimLoopLowerer
|
||||
let effective_break_condition = if let Some(trim_result) = super::trim_loop_lowering::TrimLoopLowerer::try_lower_trim_like_loop(
|
||||
self,
|
||||
|
||||
@ -73,6 +73,7 @@ impl Pattern4CarrierAnalyzer {
|
||||
carriers: updated_carriers,
|
||||
trim_helper: all_carriers.trim_helper.clone(),
|
||||
promoted_loopbodylocals: all_carriers.promoted_loopbodylocals.clone(), // Phase 224
|
||||
condition_aliases: all_carriers.condition_aliases.clone(), // Phase 224-D
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,29 @@
|
||||
use crate::mir::ValueId;
|
||||
use std::collections::BTreeMap; // Phase 222.5-D: HashMap → BTreeMap for determinism
|
||||
|
||||
/// Phase 224-D: Alias for promoted LoopBodyLocal in condition expressions
|
||||
///
|
||||
/// When a LoopBodyLocal variable is promoted to a carrier, the original variable
|
||||
/// name must still be resolvable in condition expressions for backward compatibility.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// // Original variable: "digit_pos"
|
||||
/// // Promoted carrier: "is_digit_pos"
|
||||
/// ConditionAlias {
|
||||
/// old_name: "digit_pos".to_string(),
|
||||
/// carrier_name: "is_digit_pos".to_string(),
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConditionAlias {
|
||||
/// Original variable name (e.g., "digit_pos")
|
||||
pub old_name: String,
|
||||
/// Promoted carrier name (e.g., "is_digit_pos")
|
||||
pub carrier_name: String,
|
||||
}
|
||||
|
||||
/// Information about a single carrier variable
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CarrierVar {
|
||||
@ -52,6 +75,12 @@ pub struct CarrierInfo {
|
||||
/// during condition promotion (e.g., DigitPosPromoter). The lowerer should skip
|
||||
/// LoopBodyLocal checks for these variables.
|
||||
pub promoted_loopbodylocals: Vec<String>,
|
||||
/// Phase 224-D: Condition aliases for promoted LoopBodyLocal variables
|
||||
///
|
||||
/// Maps old variable names to their promoted carrier names for condition resolution.
|
||||
/// This allows break/continue conditions to reference promoted variables by their
|
||||
/// original names (e.g., `if digit_pos < 0` still works after promotion to "is_digit_pos").
|
||||
pub condition_aliases: Vec<ConditionAlias>,
|
||||
}
|
||||
|
||||
impl CarrierInfo {
|
||||
@ -113,6 +142,7 @@ impl CarrierInfo {
|
||||
carriers,
|
||||
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
||||
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
||||
condition_aliases: Vec::new(), // Phase 224-D: No aliases by default
|
||||
})
|
||||
}
|
||||
|
||||
@ -171,6 +201,7 @@ impl CarrierInfo {
|
||||
carriers,
|
||||
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
||||
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
||||
condition_aliases: Vec::new(), // Phase 224-D: No aliases by default
|
||||
})
|
||||
}
|
||||
|
||||
@ -198,6 +229,7 @@ impl CarrierInfo {
|
||||
carriers,
|
||||
trim_helper: None, // Phase 171-C-5: No Trim pattern by default
|
||||
promoted_loopbodylocals: Vec::new(), // Phase 224: No promoted variables by default
|
||||
condition_aliases: Vec::new(), // Phase 224-D: No aliases by default
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,6 +290,13 @@ impl CarrierInfo {
|
||||
self.promoted_loopbodylocals.push(promoted_var.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 224-D: Merge condition_aliases (deduplicate by old_name)
|
||||
for alias in &other.condition_aliases {
|
||||
if !self.condition_aliases.iter().any(|a| a.old_name == alias.old_name) {
|
||||
self.condition_aliases.push(alias.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Phase 171-C-5: Get Trim pattern helper
|
||||
|
||||
@ -83,6 +83,12 @@ impl TrimPatternInfo {
|
||||
// Phase 171-C-5: Attach TrimLoopHelper for pattern-specific lowering logic
|
||||
carrier_info.trim_helper = Some(TrimLoopHelper::from_pattern_info(self));
|
||||
|
||||
// Phase 224-D: Record condition alias for promoted variable
|
||||
carrier_info.condition_aliases.push(crate::mir::join_ir::lowering::carrier_info::ConditionAlias {
|
||||
old_name: self.var_name.clone(),
|
||||
carrier_name: self.carrier_name.clone(),
|
||||
});
|
||||
|
||||
carrier_info
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,17 +180,37 @@ impl DigitPosPromoter {
|
||||
);
|
||||
|
||||
// Step 6: Build CarrierInfo
|
||||
// For DigitPos pattern, we add a NEW carrier (not replace loop_var)
|
||||
let carrier_name = format!("is_{}", var_in_cond);
|
||||
let carrier_info = CarrierInfo::with_carriers(
|
||||
carrier_name.clone(),
|
||||
ValueId(0), // Placeholder (will be remapped)
|
||||
vec![],
|
||||
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierVar;
|
||||
let promoted_carrier = CarrierVar {
|
||||
name: carrier_name.clone(),
|
||||
host_id: ValueId(0), // Placeholder (will be remapped)
|
||||
join_id: None, // Will be allocated later
|
||||
};
|
||||
|
||||
// Create CarrierInfo with a dummy loop_var_name (will be ignored during merge)
|
||||
let mut carrier_info = CarrierInfo::with_carriers(
|
||||
"__dummy_loop_var__".to_string(), // Placeholder, not used
|
||||
ValueId(0), // Placeholder
|
||||
vec![promoted_carrier],
|
||||
);
|
||||
|
||||
// Phase 224-D: Record condition alias for promoted variable
|
||||
carrier_info.condition_aliases.push(crate::mir::join_ir::lowering::carrier_info::ConditionAlias {
|
||||
old_name: var_in_cond.clone(),
|
||||
carrier_name: carrier_name.clone(),
|
||||
});
|
||||
|
||||
eprintln!(
|
||||
"[digitpos_promoter] A-4 DigitPos pattern promoted: {} → {}",
|
||||
var_in_cond, carrier_name
|
||||
);
|
||||
eprintln!(
|
||||
"[digitpos_promoter] Phase 224-D: Added condition alias '{}' → '{}'",
|
||||
var_in_cond, carrier_name
|
||||
);
|
||||
|
||||
return DigitPosPromotionResult::Promoted {
|
||||
carrier_info,
|
||||
|
||||
Reference in New Issue
Block a user