feat(joinir): Phase 247-EX - DigitPos dual-value architecture
Extends DigitPos promotion to generate TWO carriers for Pattern A/B support: - Boolean carrier (is_digit_pos) for break conditions - Integer carrier (digit_value) for NumberAccumulation ## Implementation 1. **DigitPosPromoter** (loop_body_digitpos_promoter.rs) - Generates dual carriers: is_<var> (bool) + <base>_value (int) - Smart naming: "digit_pos" → "digit" (removes "_pos" suffix) 2. **UpdateEnv** (update_env.rs) - Context-aware promoted variable resolution - Priority: <base>_value (int) → is_<var> (bool) → standard - Pass promoted_loopbodylocals from CarrierInfo 3. **Integration** (loop_with_break_minimal.rs) - UpdateEnv constructor updated to pass promoted list ## Test Results - **Before**: 925 tests PASS - **After**: 931 tests PASS (+6 new tests, 0 failures) ## New Tests - test_promoted_variable_resolution_digit_pos - Full dual-value - test_promoted_variable_resolution_fallback_to_bool - Fallback - test_promoted_variable_not_a_carrier - Error handling ## Impact | Pattern | Before | After | |---------|--------|-------| | _parse_number | ✅ Works (bool only) | ✅ Works (bool used, int unused) | | _atoi | ❌ Failed (missing int) | ✅ READY (int carrier available!) | 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -739,4 +739,53 @@ mod tests {
|
||||
"Pattern2 lowerer should accept JsonParser-like break loop"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_atoi_loop_routed_to_pattern2() {
|
||||
// Phase 246-EX Step 2: _atoi loop router integration test
|
||||
// loop(i < len) {
|
||||
// if digit_pos < 0 { break }
|
||||
// result = result * 10 + digit_pos // NumberAccumulation
|
||||
// i = i + 1
|
||||
// }
|
||||
|
||||
let condition = bin(BinaryOperator::Less, var("i"), var("len"));
|
||||
let break_cond = bin(BinaryOperator::Less, var("digit_pos"), lit_i(0));
|
||||
|
||||
// result = result * 10 + digit_pos (NumberAccumulation pattern)
|
||||
let mul_expr = bin(BinaryOperator::Multiply, var("result"), lit_i(10));
|
||||
let result_update_value = bin(BinaryOperator::Add, mul_expr, var("digit_pos"));
|
||||
|
||||
let body = vec![
|
||||
ASTNode::If {
|
||||
condition: Box::new(break_cond),
|
||||
then_body: vec![ASTNode::Break { span: span() }],
|
||||
else_body: None,
|
||||
span: span(),
|
||||
},
|
||||
ASTNode::Assignment {
|
||||
target: Box::new(var("result")),
|
||||
value: Box::new(result_update_value),
|
||||
span: span(),
|
||||
},
|
||||
ASTNode::Assignment {
|
||||
target: Box::new(var("i")),
|
||||
value: Box::new(bin(BinaryOperator::Add, var("i"), lit_i(1))),
|
||||
span: span(),
|
||||
},
|
||||
];
|
||||
|
||||
let ctx = LoopPatternContext::new(&condition, &body, "_atoi", true);
|
||||
let builder = MirBuilder::new();
|
||||
|
||||
// Verify pattern classification
|
||||
assert_eq!(ctx.pattern_kind, LoopPatternKind::Pattern2Break,
|
||||
"_atoi loop should be classified as Pattern2Break");
|
||||
|
||||
// Verify Pattern2 lowerer accepts it
|
||||
assert!(
|
||||
can_lower(&builder, &ctx),
|
||||
"Pattern2 lowerer should accept _atoi loop with NumberAccumulation"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user