Files
hakorune/docs/development/current/main/phase213-progress-checkpoint-1.md
nyash-codex d4f90976da refactor(joinir): Phase 244 - ConditionLoweringBox trait unification
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>
2025-12-11 02:35:31 +09:00

220 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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**:
1. Added new fields for Pattern 3:
- `loop_condition: Option<ASTNode>` - Loop condition AST
- `loop_body: Option<Vec<ASTNode>>` - Loop body AST
- `loop_update_summary: Option<LoopUpdateSummary>` - Update expressions
2. Updated `build_pattern_context()` for Pattern3:
- Stores `condition.clone()` in `loop_condition`
- Stores `body.to_vec()` in `loop_body`
- Placeholder `None` for `loop_update_summary` (TODO: Task 213-2-4)
3. Updated test cases with new fields
### ✅ Task 213-2-3: CarrierUpdateInfo Extension
**File**: `src/mir/join_ir/lowering/loop_update_summary.rs`
**Changes**:
1. Extended `CarrierUpdateInfo` struct:
- `then_expr: Option<ASTNode>` - Then branch update expression
- `else_expr: Option<ASTNode>` - Else branch update expression
2. Updated `analyze_loop_updates()`:
- Default `None` for `then_expr`/`else_expr`
- Comment: "Will be populated by Pattern 3 analyzer"
---
## 📊 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**:
1. Create `Pattern3IfAnalyzer` module
2. Extract if statement from loop body
3. Parse then/else branches for carrier updates
4. Populate `LoopUpdateSummary` with AST expressions
5. Replace hardcoded conditions in lowerer
6. Replace hardcoded updates in lowerer
7. Return `ExitMeta` instead 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**:
1. 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
2. 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**:
1. Focus on condition lowering only (loop + if)
2. Keep update expressions hardcoded for now
3. Use existing `condition_to_joinir` infrastructure
4. 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:
1. Pattern routing works correctly (✅ Pattern 3 detected)
2. MIR PHI generation works (✅ `%31 = phi` created)
3. **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**:
1. **User's 80/20 philosophy**: "完璧より進捗" (progress over perfection)
2. **Fail-Fast principle**: Get `phase212_if_sum_min.hako` working first
3. **Box Theory**: Make minimal, reversible change
4. **Evidence-based**: Phase 212.5 proved the pipeline works
**Implementation Plan**:
1. Extract loop condition from `ctx.loop_condition` AST
2. Extract if condition from `ctx.loop_body` if statement
3. Extract update expression from if-then assignment
4. Replace 3 hardcoded sections in `loop_with_if_phi_minimal.rs`
5. Test with `phase212_if_sum_min.hako` → RC=2 ✅
6. 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)**
```rust
// 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)**
```rust
// 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)**
```rust
// 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
```rust
// 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