Unify condition lowering logic across Pattern 2/4 with trait-based API. New infrastructure: - condition_lowering_box.rs: ConditionLoweringBox trait + ConditionContext (293 lines) - ExprLowerer implements ConditionLoweringBox trait (+51 lines) Pattern migrations: - Pattern 2 (loop_with_break_minimal.rs): Use trait API - Pattern 4 (loop_with_continue_minimal.rs): Use trait API Benefits: - Unified condition lowering interface - Extensible for future lowering strategies - Clean API boundary between patterns and lowering logic - Zero code duplication Test results: 911/911 PASS (+2 new tests) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
6.5 KiB
Phase 213: Progress Checkpoint 1
Date: 2025-12-09
Status: ✅ Foundation Complete, Ready for Lowerer Refactoring
Commit: d7805e59
🎯 Completed Work
✅ Task 213-2-2: PatternPipelineContext Extension
File: src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs
Changes:
-
Added new fields for Pattern 3:
loop_condition: Option<ASTNode>- Loop condition ASTloop_body: Option<Vec<ASTNode>>- Loop body ASTloop_update_summary: Option<LoopUpdateSummary>- Update expressions
-
Updated
build_pattern_context()for Pattern3:- Stores
condition.clone()inloop_condition - Stores
body.to_vec()inloop_body - Placeholder
Noneforloop_update_summary(TODO: Task 213-2-4)
- Stores
-
Updated test cases with new fields
✅ Task 213-2-3: CarrierUpdateInfo Extension
File: src/mir/join_ir/lowering/loop_update_summary.rs
Changes:
-
Extended
CarrierUpdateInfostruct:then_expr: Option<ASTNode>- Then branch update expressionelse_expr: Option<ASTNode>- Else branch update expression
-
Updated
analyze_loop_updates():- Default
Noneforthen_expr/else_expr - Comment: "Will be populated by Pattern 3 analyzer"
- Default
📊 Current State Analysis
MIR Analysis for phase212_if_sum_min.hako
Expected vs Actual:
| Element | Expected | Actual (Hardcoded) |
|---|---|---|
| Loop limit | i < 3 |
i <= 5 |
| Loop cond | icmp Lt %8, %18 |
icmp Le %8, %18 |
| If cond | i > 0 |
i % 2 == 1 |
| If cond code | icmp Gt %8, %zero |
%8 Mod %2; icmp Eq ... %1 |
| Then update | sum + 1 |
sum + i |
| Then code | %9 Add %const_1 |
%9 Add %8 |
Root Cause: loop_with_if_phi_minimal.rs lines 217-385 are completely hardcoded for loop_if_phi.hako test pattern.
🔄 Next Steps (3 Approaches)
Approach A: Full AST-Based Generalization (Phase 213 Original Plan)
Tasks:
- Create
Pattern3IfAnalyzermodule - Extract if statement from loop body
- Parse then/else branches for carrier updates
- Populate
LoopUpdateSummarywith AST expressions - Replace hardcoded conditions in lowerer
- Replace hardcoded updates in lowerer
- Return
ExitMetainstead of hardcoded ValueIds
Pros: Complete generalization, supports all if-sum patterns Cons: Large scope, ~500-800 lines of new code
Approach B: Minimal Incremental (80/20 Rule)
Tasks:
- Just replace the 3 hardcoded constants:
- Loop limit: 5 → extract from AST condition
- If condition:
i % 2 == 1→ extract from AST if statement - Update value:
i→ extract from AST assignment
- Keep existing structure, minimal changes
Pros: Small scope, fast to implement, gets phase212_if_sum_min.hako working
Cons: Still not fully generic, will need refactoring later
Approach C: Hybrid - BoolExprLowerer First
Tasks:
- Focus on condition lowering only (loop + if)
- Keep update expressions hardcoded for now
- Use existing
condition_to_joinirinfrastructure - Defer update generalization to Phase 214
Pros: Leverages existing infrastructure, cleaner architecture
Cons: phase212_if_sum_min.hako still won't work fully
💭 Analysis & Recommendation
Key Insight from Phase 212.5
Phase 212.5 discovered that:
- Pattern routing works correctly (✅ Pattern 3 detected)
- MIR PHI generation works (✅
%31 = phicreated) - Only the lowerer's hardcoded values are wrong
This means the JoinIR → MIR pipeline is solid. We just need to feed it the right JoinIR.
Recommendation: Approach B (Minimal Incremental)
Rationale:
- User's 80/20 philosophy: "完璧より進捗" (progress over perfection)
- Fail-Fast principle: Get
phase212_if_sum_min.hakoworking first - Box Theory: Make minimal, reversible change
- Evidence-based: Phase 212.5 proved the pipeline works
Implementation Plan:
- Extract loop condition from
ctx.loop_conditionAST - Extract if condition from
ctx.loop_bodyif statement - Extract update expression from if-then assignment
- Replace 3 hardcoded sections in
loop_with_if_phi_minimal.rs - Test with
phase212_if_sum_min.hako→ RC=2 ✅ - Keep existing tests working (backward compatibility)
Estimated effort: 2-3 hours (vs 8-10 hours for Approach A)
🔍 Technical Details for Approach B
What Needs to Change
File: src/mir/join_ir/lowering/loop_with_if_phi_minimal.rs
Section 1: Loop Condition (lines 217-233)
// Before (hardcoded):
loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Const {
dst: const_5,
value: ConstValue::Integer(5), // ← Hardcoded!
}));
loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
dst: cmp_le,
op: CompareOp::Le, // ← Hardcoded!
lhs: i_param,
rhs: const_5,
}));
// After (AST-based):
// Extract from ctx.loop_condition: "i < 3"
// Lower to JoinIR using existing infrastructure
Section 2: If Condition (lines 254-288)
// Before (hardcoded):
// const 2, mod, const 1, eq → (i % 2 == 1)
// After (AST-based):
// Extract from loop_body if statement: "i > 0"
// Lower to JoinIR: const 0, cmp Gt
Section 3: Update Expression (lines 290-298)
// Before (hardcoded):
loop_step_func.body.push(JoinInst::Compute(MirLikeInst::BinOp {
dst: sum_then,
op: BinOpKind::Add,
lhs: sum_param,
rhs: i_param, // ← Hardcoded! Should be const 1
}));
// After (AST-based):
// Extract from then-branch assignment: "sum = sum + 1"
// Lower to JoinIR: sum_param Add const_1
Helper Functions Needed
// Extract loop condition details
fn extract_loop_condition(condition: &ASTNode)
-> Result<(CompareOp, i64), String>
// Extract if statement from loop body
fn extract_if_statement(body: &[ASTNode])
-> Result<&ASTNode, String>
// Extract if condition details
fn extract_if_condition(if_node: &ASTNode)
-> Result<(CompareOp, i64), String>
// Extract update value from assignment
fn extract_update_value(assignment: &ASTNode)
-> Result<i64, String>
📋 Decision Point
Question for user: Which approach should we take?
A. Full AST-based generalization (Approach A) B. Minimal incremental replacement (Approach B) ← Recommended C. Hybrid BoolExprLowerer-first (Approach C) D. Different approach?
Current blockers: None - foundation is complete
Current branch: main (d7805e59)
Build status: ✅ Passing
Status: Active
Scope: If-sum 進捗チェックポイント(JoinIR v2)