Files
hakorune/docs/development/current/main/phase33-duplication-map.md
nyash-codex 4e32a803a7 feat(joinir): Phase 33-22 CommonPatternInitializer & JoinIRConversionPipeline integration
Unifies initialization and conversion logic across all 4 loop patterns,
eliminating code duplication and establishing single source of truth.

## Changes

### Infrastructure (New)
- CommonPatternInitializer (117 lines): Unified loop var extraction + CarrierInfo building
- JoinIRConversionPipeline (127 lines): Unified JoinIR→MIR→Merge flow

### Pattern Refactoring
- Pattern 1: Uses CommonPatternInitializer + JoinIRConversionPipeline (-25 lines)
- Pattern 2: Uses CommonPatternInitializer + JoinIRConversionPipeline (-25 lines)
- Pattern 3: Uses CommonPatternInitializer + JoinIRConversionPipeline (-25 lines)
- Pattern 4: Uses CommonPatternInitializer + JoinIRConversionPipeline (-40 lines)

### Code Reduction
- Total reduction: ~115 lines across all patterns
- Zero code duplication in initialization/conversion
- Pattern files: 806 lines total (down from ~920)

### Quality Improvements
- Single source of truth for initialization
- Consistent conversion flow across all patterns
- Guaranteed boundary.loop_var_name setting (prevents SSA-undef bugs)
- Improved maintainability and testability

### Testing
- All 4 patterns tested and passing:
  - Pattern 1 (Simple While): 
  - Pattern 2 (With Break): 
  - Pattern 3 (If-Else PHI): 
  - Pattern 4 (With Continue): 

### Documentation
- Phase 33-22 inventory and results document
- Updated joinir-architecture-overview.md with new infrastructure

## Breaking Changes
None - pure refactoring with no API changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-07 21:02:20 +09:00

286 lines
10 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 33 コード重複マップ - 視覚化ガイド
## 🎯 目的
Pattern 1-4の共通コードを視覚的に理解し、箱化の対象を明確にする。
---
## 📊 重複コード分布図
```
Pattern Lowerer Structure (Before Optimization)
================================================
pattern1_minimal.rs (176行) pattern2_with_break.rs (219行)
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ ✅ can_lower() │ │ ✅ can_lower() │
│ ✅ lower() │ │ ✅ lower() │
│ │ │ │
│ ⚠️ DUPLICATE INIT (50行) │ │ ⚠️ DUPLICATE INIT (50行) │
│ - extract_loop_var │ │ - extract_loop_var │
│ - variable_map lookup │ │ - variable_map lookup │
│ - trace::varmap() │ │ - trace::varmap() │
│ │ │ │
│ ⚠️ DUPLICATE CONVERT (30行)│ │ ⚠️ DUPLICATE CONVERT (30行)│
│ - convert_join_to_mir │ │ - convert_join_to_mir │
│ - trace::joinir_stats() │ │ - trace::joinir_stats() │
│ - JoinInlineBoundary │ │ - JoinInlineBoundary │
│ - merge_joinir_blocks │ │ - merge_joinir_blocks │
│ │ │ │
│ ✅ Pattern 1 specific (96行)│ │ ✅ Pattern 2 specific (139行)│
└─────────────────────────────┘ └─────────────────────────────┘
pattern3_with_if_phi.rs (165行) pattern4_with_continue.rs (343行)
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ ✅ can_lower() │ │ ✅ can_lower() │
│ ✅ lower() │ │ ✅ lower() │
│ │ │ │
│ ⚠️ DUPLICATE INIT (50行) │ │ ⚠️ DUPLICATE INIT (50行) │
│ - extract_loop_var │ │ - extract_loop_var │
│ - variable_map lookup │ │ - variable_map lookup │
│ - trace::varmap() │ │ - trace::varmap() │
│ │ │ │
│ ⚠️ DUPLICATE CONVERT (30行)│ │ ⚠️ DUPLICATE CONVERT (30行)│
│ - convert_join_to_mir │ │ - convert_join_to_mir │
│ - trace::joinir_stats() │ │ - trace::joinir_stats() │
│ - JoinInlineBoundary │ │ - JoinInlineBoundary │
│ - merge_joinir_blocks │ │ - merge_joinir_blocks │
│ │ │ │
│ ✅ Pattern 3 specific (85行) │ │ ✅ Pattern 4 specific (263行)│
│ │ │ + LoopUpdateAnalyzer │
│ │ │ + ContinueNormalizer │
└─────────────────────────────┘ └─────────────────────────────┘
⚠️ = 重複コード(削減対象)
✅ = パターン固有ロジック(維持)
```
---
## 🔥 重複コードの詳細内訳
### 重複箇所1: 初期化ロジック4箇所×50行 = 200行
**Pattern 1の例**:
```rust
// src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs:64-79
let loop_var_name = self.extract_loop_variable_from_condition(condition)?;
let loop_var_id = self
.variable_map
.get(&loop_var_name)
.copied()
.ok_or_else(|| {
format!(
"[cf_loop/pattern1] Loop variable '{}' not found in variable_map",
loop_var_name
)
})?;
trace::trace().varmap("pattern1_start", &self.variable_map);
// Pattern 2, 3, 4でも同一コード
```
**重複パターン**:
- Pattern 1: `pattern1_minimal.rs:64-79` (16行)
- Pattern 2: `pattern2_with_break.rs:56-71` (16行)
- Pattern 3: `pattern3_with_if_phi.rs:56-71` (16行)
- Pattern 4: `pattern4_with_continue.rs:115-130` (16行)
**合計**: 4箇所 × 16行 = **64行重複**
---
### 重複箇所2: JoinIR変換パイプライン4箇所×30行 = 120行
**Pattern 1の例**:
```rust
// src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs:100-130
let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta)
.map_err(|e| format!("[cf_loop/joinir/pattern1] MIR conversion failed: {:?}", e))?;
trace::trace().joinir_stats(
"pattern1",
join_module.functions.len(),
mir_module.blocks.len(),
);
let boundary = JoinInlineBoundary::new_inputs_only(
vec![ValueId(0)],
vec![loop_var_id],
);
let _ = self.merge_joinir_mir_blocks(&mir_module, Some(&boundary), debug)?;
// Pattern 2, 3, 4でも同一フロー細部のみ異なる
```
**重複パターン**:
- Pattern 1: `pattern1_minimal.rs:100-130` (31行)
- Pattern 2: `pattern2_with_break.rs:120-150` (31行)
- Pattern 3: `pattern3_with_if_phi.rs:105-135` (31行)
- Pattern 4: `pattern4_with_continue.rs:200-230` (31行)
**合計**: 4箇所 × 31行 = **124行重複**
---
## 🎯 箱化後の理想構造
```
After Optimization (CommonPatternInitializer + JoinIRConversionPipeline)
=========================================================================
pattern1_minimal.rs (126行 → 28%削減)
┌─────────────────────────────┐
│ ✅ can_lower() │
│ ✅ lower() │
│ │
│ 📦 CommonPatternInitializer │ ← 新しい箱!
│ .extract_loop_context() │ ← 1行で50行分の処理
│ │
│ 📦 JoinIRConversionPipeline │ ← 新しい箱!
│ .convert_and_merge() │ ← 1行で30行分の処理
│ │
│ ✅ Pattern 1 specific (96行)│ ← 変更なし
└─────────────────────────────┘
pattern2_with_break.rs (169行 → 23%削減)
pattern3_with_if_phi.rs (115行 → 30%削減)
pattern4_with_continue.rs (293行 → 15%削減)
全パターン同様に削減!
```
---
## 📊 削減インパクト分析
### Before / After 比較表
| ファイル | Before | After | 削減行数 | 削減率 |
|---------|-------|-------|---------|-------|
| pattern1_minimal.rs | 176行 | 126行 | -50行 | 28% |
| pattern2_with_break.rs | 219行 | 169行 | -50行 | 23% |
| pattern3_with_if_phi.rs | 165行 | 115行 | -50行 | 30% |
| pattern4_with_continue.rs | 343行 | 293行 | -50行 | 15% |
| **patterns/ 合計** | **1,801行** | **1,601行** | **-200行** | **11%** |
### 新規追加ファイル
| ファイル | 行数 | 役割 |
|---------|-----|-----|
| common_init.rs | 60行 | CommonPatternInitializer実装 |
| conversion_pipeline.rs | 50行 | JoinIRConversionPipeline実装 |
**実質削減**: 200行 - 110行 = **90行削減** + 保守性大幅向上
---
## 🔍 コード重複検出コマンド
```bash
# 重複箇所1: Loop variable extraction
grep -A 10 "extract_loop_variable_from_condition" \
src/mir/builder/control_flow/joinir/patterns/pattern*.rs
# 重複箇所2: JoinIR conversion
grep -A 15 "convert_join_module_to_mir_with_meta" \
src/mir/builder/control_flow/joinir/patterns/pattern*.rs
# 重複箇所3: Merge call
grep -A 5 "merge_joinir_mir_blocks" \
src/mir/builder/control_flow/joinir/patterns/pattern*.rs
```
---
## 🎯 実装順序(推奨)
### Phase 1: CommonPatternInitializer (1時間)
```bash
# Step 1: 新規ファイル作成
touch src/mir/builder/control_flow/joinir/patterns/common_init.rs
# Step 2: Pattern 1で動作確認
cargo test --release loop_min_while
# Step 3: Pattern 2, 3, 4に適用
# 各10分
# Step 4: 全体テスト
cargo test --release loop_min_while loop_with_break \
loop_with_if_phi_sum loop_with_continue
```
### Phase 2: JoinIRConversionPipeline (1時間)
```bash
# Step 1: 新規ファイル作成
touch src/mir/builder/control_flow/joinir/patterns/conversion_pipeline.rs
# Step 2: Pattern 1で動作確認
cargo test --release loop_min_while
# Step 3: Pattern 2, 3, 4に適用
# 各10分
# Step 4: 全体テスト
cargo test --release
```
---
## ✅ 成功基準
1. **ビルド成功**: 0エラー・0警告
2. **テスト全PASS**: Pattern 1-4の既存テスト全て通過
3. **SSA-undefゼロ**: MIRレベルのエラーなし
4. **削減達成**: patterns/モジュール全体で200行削減
5. **保守性向上**: 重複コードゼロ、単一責任の原則適用
---
## 🚨 リスク管理
### 潜在的リスク
1. **テスト失敗**: 初期化ロジックの微妙な差異を見落とす可能性
- **対策**: Pattern毎に個別テスト実行、段階的移行
2. **デバッグ困難化**: エラー時のスタックトレースが深くなる
- **対策**: 適切なエラーメッセージ、pattern_name引数の維持
3. **将来の拡張性**: Pattern 5/6で異なる初期化が必要になる可能性
- **対策**: CommonPatternInitializerを柔軟に設計オプション引数
### 緊急時のロールバック手順
```bash
# Step 1: 変更前のコミットに戻る
git revert HEAD
# Step 2: テスト確認
cargo test --release
# Step 3: 原因分析
# → phase33-post-analysis.md の「テスト計画」を参照
```
---
## 📚 関連ドキュメント
- [Phase 33-19 実装完了レポート](phase33-17-implementation-complete.md)
- [Phase 33-21 Parameter remapping fix](../../../private/) (未作成)
- [JoinIRアーキテクチャ概要](joinir-architecture-overview.md)
- [Pattern Router設計](phase33-16-INDEX.md)
---
## 📝 変更履歴
- 2025-12-07: 初版作成Phase 33-21完了後の調査結果