Files
hakorune/docs/development/current/main/phase33-18-continue-pattern-inventory.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

210 lines
8.0 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-18: continue+if/else ループパターン設計フェーズ
**Goal**: 「if (cond) { … } else { continue }」型のループを JoinIR で扱う方法を箱理論ベースで設計する
---
## Task 33-18-1: continue+if/else パターンのインベントリ
### 検出方法
- `rg "continue" apps/tests/ tools/selfhost/ --glob "*.hako"`
### パターン一覧表
| ファイル | ループ条件 | continue位置 | if構造 | carrier数 | 更新式 |
|---------|-----------|-------------|--------|----------|--------|
| **Pattern A: if (cond) { continue } - then側continue** |||||||
| `loop_continue_pattern4.hako` | `i < 10` | then | `if (i % 2 == 0) { continue }` | 2 (i, sum) | `i = i + 1`, `sum = sum + i` |
| `test_pattern4_simple_continue.hako` | `i < n` | then | `if is_even == 1 { continue }` | 3 (i, sum, is_even) | `i = i + 1`, `sum = sum + i` |
| `parser_box_minimal.hako:skip_ws` | `i < n` | then | `if ch == " " \|\| ... { continue }` | 1 (i) | `i = i + 1` |
| `llvm_phi_mix.hako` | `i < 10` | then | `if (i == 2 \|\| i == 4) { continue }` | 2 (i, sum) | 条件付き更新 |
| `llvm_stage3_break_continue.hako` | `i < 10` | then | `if (i < 5) { continue }` | 1 (i) | `i = i + 1` |
| **Pattern B: if (cond) { ... } else { continue } - else側continue** |||||||
| `loop_if_phi_continue.hako` | `i < 6` | else | `if (i % 2 == 0) { i++; printed++; continue } else { i+=2 }` | 2 (i, printed) | 両分岐で更新 |
| `失敗テストmirbuilder...` | `i < 5` | else | `if (i != M) { sum += i } else { continue }` | 3 (i, s, M) | then側のみ更新 |
| **Pattern C: 複雑パターンnested/mixed** |||||||
| `loopform_continue_break_scan.hako` | `true` | then | continue + break 混在 | 2 (i, sum) | 複数分岐 |
| `try_finally_continue_inner_loop.hako` | `j < 3` | then | `if (j == 1) { mark = 1; continue }` | 2 (j, mark) | try/finally内 |
| `nested_loop_inner_continue_isolated.hako` | `j < 3` | then | `if (j == 1) { continue }` | 1 (j) | 内側ループ |
### パターン分類
#### Pattern A: then側continue単純
```nyash
loop(cond) {
if (skip_condition) {
i = i + 1
continue
}
// main processing
i = i + 1
}
```
- **特徴**: continue が条件成立時に実行される「スキップ」パターン
- **既存対応**: Pattern4 で処理可能な形式
- **問題なし**: 現在動作している
#### Pattern B: else側continue問題あり
```nyash
loop(cond) {
if (process_condition) {
// main processing
} else {
continue
}
i = i + 1
}
```
- **特徴**: continue が条件不成立時に実行される
- **論理的同等**: `if (!process_condition) { continue } else { ... }` と等価
- **問題**: 現在 JoinIR では対応できず失敗する
- **失敗例**: `mirbuilder_loop_varvar_ne_else_continue_desc_core_exec_canary_vm`
---
## Task 33-18-2: LoopFeatures / PatternKind から見た分類
### 現在の classify() ロジック
```rust
pub fn classify(features: &LoopFeatures) -> LoopPatternKind {
// Pattern 4: Continue (highest priority)
if features.has_continue {
return LoopPatternKind::Pattern4Continue;
}
// ...
}
```
**問題点**: `has_continue == true` だけで Pattern4 に分類するが、
- Pattern Belse側continueは if-else 構造を持つ
- `has_if_else_phi == true``has_continue == true` が同時に成立する可能性
- 現在のロジックでは continue 優先のため、Pattern4 に分類されるが lowering できない
### 設計案
#### 案 A: Pattern4 に統合BoolExprLowerer で正規化)
**アイデア**:
- `if (!cond) { ... } else { continue }``if (cond) { continue } else { ... }` に変換
- BoolExprLowerer に「条件反転 + 分岐入れ替え」ロジックを追加
- Pattern4 lowerer はそのまま使える
**メリット**:
- 新しい Pattern を追加しなくて良い
- 既存の Pattern4 lowerer を再利用
- 箱の数が増えない
**デメリット**:
- BoolExprLowerer の責務が増える
- 反転ロジックが複雑になる可能性
#### 案 B: 新規 Pattern5 として独立
**アイデア**:
- `Pattern5ContinueIfElse` を新設
- `has_continue && has_if_else_phi` の組み合わせを検出
- 専用 lowerer を実装
**メリット**:
- 責務が明確に分離
- Pattern4 と独立して実装・テスト可能
**デメリット**:
- 新しい箱が増える
- 重複コードが発生する可能性
### 選択基準
| 基準 | 案 A (統合) | 案 B (新設) |
|-----|------------|------------|
| 箱の数 | 増えない | +1 (Pattern5) |
| 既存コード変更 | BoolExprLowerer | classify() のみ |
| 実装難易度 | 中(反転ロジック) | 中新規lowerer |
| テスト容易性 | 既存テスト再利用 | 新規テスト必要 |
**推奨**: **案 APattern4 統合)**
- 理由: `if (cond) { continue }``if (!cond) { ... } else { continue }` は論理的に同型
- 「continue がどちらの分岐にあっても、最終的に同じ CFG 骨格になる」ことを活用
---
## Task 33-18-3: JoinIR 箱との責務マッピング
### 既存箱との関係
| 箱 | 現在の責務 | Pattern B での役割 |
|---|-----------|------------------|
| **LoopFeatures** | break/continue/if_else_phi 検出 | 変更なし(情報収集のみ) |
| **classify()** | Pattern 1-4 振り分け | 案Aなら変更なし |
| **BoolExprLowerer** | 条件式の SSA 化 | **拡張**: continue 分岐の正規化 |
| **Pattern4 lowerer** | continue ブロック生成 | 変更なし |
| **Header PHI** | ループヘッダの PHI 生成 | 変更なし |
| **ExitLine** | carrier / expr 出口処理 | 変更なし |
### 変更が必要な箇所
1. **BoolExprLowerer** (or 新規 ContinueBranchNormalizer Box)
- `if (cond) { ... } else { continue }` を検出
- `if (!cond) { continue } else { ... }` に変換
- 変換後の AST を Pattern4 lowerer に渡す
2. **router.rs** (optional)
- else 側 continue の検出を追加
- BoolExprLowerer への委譲を追加
### joinir-architecture-overview.md への追記案
```markdown
### Continue パターンの分類ルール (Phase 33-18)
- Pattern4_WithContinue は以下の条件で適用:
- `has_continue == true` AND `has_break == false`
- continue の位置then/elseは問わない正規化で吸収
- else 側 continue の処理:
- BoolExprLowerer で条件反転 → then 側 continue 形式に正規化
- 正規化後は通常の Pattern4 として処理
```
---
## Task 33-18-4: 完了条件と次フェーズへの橋渡し
### Phase 33-18 完了条件チェックリスト
- [x] continue+if/else パターンのインベントリが docs に揃っている
- [x] Pattern4 に畳めるかPattern5 新設かの方針が決まっている(案 A: 統合)
- [x] JoinIR の箱たちFeatures / BoolExprLowerer / Header PHI / ExitLineのどこを触るかが決まっている
- [ ] 実装フェーズ33-19のタスクリストが 3〜5 個に落ちている
### 実装フェーズ (Phase 33-19) タスクリスト案
1. **Task 33-19-1**: ContinueBranchNormalizer Box 作成
- else 側 continue を then 側に移動する AST 変換
- 単体テスト付き
2. **Task 33-19-2**: router.rs への統合
- Pattern B 検出時に正規化を呼び出す
- 正規化後 Pattern4 lowerer に委譲
3. **Task 33-19-3**: 失敗テスト修正
- `mirbuilder_loop_varvar_ne_else_continue_desc_core_exec_canary_vm` が PASS になることを確認
4. **Task 33-19-4**: 追加スモークテスト
- Pattern B の各バリエーション単一carrier、複数carrier
5. **Task 33-19-5**: ドキュメント更新
- joinir-architecture-overview.md に正式追記
---
## 備考
- 失敗テストの直接原因は「JoinIR does not support this pattern」エラー
- LoopBuilder は既に削除されているため、JoinIR での対応が必須
- CFG reachability の問題も別途ありRust CLI 経由では MIR 生成されるが reachable=false
**作成日**: 2025-12-07
**Phase**: 33-18 (Design Only)