feat(joinir): Phase 224 - DigitPosPromoter for A-4 pattern (core complete)

- New DigitPosPromoter Box for cascading indexOf pattern detection
- Two-tier promotion strategy: A-3 Trim → A-4 DigitPos fallback
- Unit tests 6/6 PASS (comparison operators, cascading dependency)
- Promotion verified: digit_pos → is_digit_pos carrier

⚠️ Lowerer integration gap: lower_loop_with_break_minimal doesn't
recognize promoted variables yet (Phase 224-continuation)

🤖 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 16:21:01 +09:00
parent b5661c1915
commit 00d1ec7cc5
8 changed files with 1704 additions and 33 deletions

View File

@ -35,6 +35,7 @@ use crate::ast::ASTNode;
use crate::mir::builder::MirBuilder;
use crate::mir::ValueId;
use super::super::trace;
use crate::mir::loop_pattern_detection::error_messages;
/// Phase 194+: Detection function for Pattern 4
///
@ -279,9 +280,8 @@ impl MirBuilder {
);
// Continue with Pattern4 lowering (fall through)
} else {
return Err(format!(
"[cf_loop/pattern4] Trim pattern detected but not safe: carrier='{}', whitespace_count={}",
helper.carrier_name,
return Err(error_messages::format_error_pattern4_trim_not_safe(
&helper.carrier_name,
helper.whitespace_count()
));
}
@ -290,10 +290,7 @@ impl MirBuilder {
}
ConditionPromotionResult::CannotPromote { reason, vars } => {
// Fail-Fast on promotion failure
return Err(format!(
"[cf_loop/pattern4] Cannot promote LoopBodyLocal variables {:?}: {}",
vars, reason
));
return Err(error_messages::format_error_pattern4_promotion_failed(&vars, &reason));
}
}
}
@ -316,7 +313,7 @@ impl MirBuilder {
Err(e) => {
// Phase 195: Use unified trace
trace::trace().debug("pattern4", &format!("Pattern 4 lowerer failed: {}", e));
return Err(format!("[cf_loop/pattern4] Lowering failed: {}", e));
return Err(error_messages::format_error_pattern4_lowering_failed(&e));
}
};
@ -344,10 +341,7 @@ impl MirBuilder {
// (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
));
return Err(error_messages::format_error_pattern4_carrier_not_found(&carrier.name));
}
}