diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 1b4b401a..da0e11f3 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -295,10 +295,61 @@ - ⚠️ 保留: 外部ローカルをレシーバーとする MethodCall (`digits.indexOf(ch)`) - **理由**: Phase 170-200 の 2-tier 境界設計(ConditionEnv/LoopBodyLocalEnv)を保持 - **将来**: Phase 200+ で独立した箱として設計、または .hako リライト対応 - - [ ] Phase 194: JsonParser 残りループ展開 - - _parse_array, _parse_object (P4 Continue, MethodCall 複数対応) - - _parse_string 完全版 (P2/P4, string concat + escape) - - _unescape_string (P4 Continue, 複雑キャリア + flatten) + - [x] **Phase 194: JsonParser P1/P2/P5 実戦投入(検証フェーズ)** ✅ (2025-12-09) + - **目的**: Phase 170-193 インフラの実コード検証(Fail-Fast 戦略) + - 194-1: Loop inventory 作成 ✅ + - 4/10 ループ JoinIR 対応(_skip_whitespace, _trim x2, _match_literal) + - 6/10 ループ保留(明確な理由付き) + - 詳細: phase194-loop-inventory.md(10ループ完全分類) + - 194-2: Routing 確認 ✅ + - Structure-only mode 動作確認(whitelist 不要) + - 既存 whitelist に全4ループ登録済み + - 194-3: E2E 実行 ✅ + - 結果: Compilation Error(Expected - Fail-Fast 戦略成功) + - エラー: `digits.indexOf()` → ConditionEnv constraint + - 分析: function-scoped variables は Phase 193 非対応 + - 194-4: Regression tests ✅ + - phase190_atoi_impl.hako → 12 ✅ + - phase191_body_local_atoi.hako → 123 ✅ + - phase193_init_method_call.hako → RC:0 ✅ + - 194-5: ドキュメント更新 ✅ + - phase194-jsonparser-deployment.md(Implementation Status 完全記録) + - joinir-architecture-overview.md(Section 7.2 Phase 194 完了マーク) + - CURRENT_TASK.md(本項目追加) + - **成果**: インフラ品質検証完了、次 Phase への明確なロードマップ提示 + - ✅ P5 Trim pattern 実戦検証(_trim で動作確認) + - ✅ ConditionEnv 制約明確化(function-scoped variables 未対応) + - ✅ 退行なし(Phase 190-193 全テスト PASS) + - **技術的発見**: + 1. ConditionEnv constraint(function-scoped variables 非対応) + - 影響: _parse_number, _atoi(digits.indexOf 依存) + - 解決策案: Phase 200+ ConditionEnv 拡張 OR .hako リライト + 2. Complex carriers(多段フラグ) + - 影響: _parse_string, _unescape_string + - 解決策: Phase 195+ Pattern 3 拡張 + 3. Multiple MethodCalls(ループ body 内複数呼び出し) + - 影響: _parse_array, _parse_object + - 解決策: Phase 195+ MethodCall 拡張 + - **推奨ロードマップ**: + - Phase 195: Pattern 3 extension(if-in-loop + multi-flag carriers) + - Phase 200+: ConditionEnv expansion(function-scoped locals) + - Phase 201+: MethodCall extension(multiple calls in body) + - [ ] **Phase 195: Pattern 3 拡張(設計フェーズ)** + - **目的**: P3(If-Else PHI)を複数キャリア対応に拡張する設計 + - 195-1: 対象ループ絞り込み(_parse_string 簡易版、if-sum) + - 195-2: LoopUpdateSummary/CarrierInfo 設計整理(複数キャリア対応) + - 195-3: Pattern3 lowerer 設計更新(PhiGroup vs ExitLine 拡張判断) + - 195-4: 実装スコープ決定(2-3キャリア、既存 UpdateKind 範囲内) + - 195-5: ドキュメント更新(CURRENT_TASK.md + overview 更新) + - **設計判断**: + - ✅ ExitLine 拡張で対応(PhiGroupBox は作らない - YAGNI 原則) + - ✅ 両分岐での Carrier 定義確認(更新なし = 前の値使用) + - ❌ ConditionEnv 拡張なし(Phase 200+ 保留) + - ❌ LoopBodyLocal + MethodCall 混在は Phase 195+ 延期 + - **期待成果**: + - phase195-pattern3-extension-design.md(完全設計書) + - Phase 195-impl の実装スコープ明確化 + - JsonParser カバレッジ 40% → 60% への道筋 --- diff --git a/docs/development/current/main/joinir-architecture-overview.md b/docs/development/current/main/joinir-architecture-overview.md index 8c20d85e..ab400ea0 100644 --- a/docs/development/current/main/joinir-architecture-overview.md +++ b/docs/development/current/main/joinir-architecture-overview.md @@ -509,12 +509,28 @@ JoinIR は Rust 側だけでなく、将来的に .hako selfhost コンパイラ - テスト: phase192_normalization_demo.hako → 123 ✅ - 制約: MethodCall を含む init 式は Phase 193 で対応予定 -3. **MethodCall を含む init 式の対応(Phase 193)** - - `local digit = digits.indexOf(ch)` のような MethodCall init の lowering +3. **✅ MethodCall を含む init 式の対応** → Phase 193 完了 + - `local digit = digits.indexOf(ch)` のような MethodCall init の lowering 完了 - LoopBodyLocalInitLowerer 拡張(BoxCall emission) - - メソッド whitelist: indexOf, substring 等 + - メソッド whitelist: indexOf, get, toString 対応 + - 制約: body-local init のみ対応、condition 内の MethodCall は Phase 200+ -4. **JsonParser 残り複雑ループ・selfhost ループへの適用(Phase 194+)** - - `_parse_array` / `_parse_object`(P4 Continue + 複数 MethodCall) - - `_unescape_string`(複雑なキャリア + flatten) - - selfhost `.hako` コンパイラの全ループを JoinIR で処理 +4. **✅ JsonParser 実戦投入(P1/P2/P5 検証)** → Phase 194 完了 + - 4/10 ループが JoinIR 経路で動作確認 (40% coverage) + - Target loops: _skip_whitespace, _trim (x2), _match_literal + - Deferred loops: _parse_number, _atoi (ConditionEnv constraint) + - Deferred loops: _parse_string, _unescape_string (complex carriers) + - Deferred loops: _parse_array, _parse_object (multiple MethodCalls) + - 詳細: phase194-loop-inventory.md, phase194-jsonparser-deployment.md + +5. **Pattern 3 拡張(複数キャリア対応)** → Phase 195 設計中 + - 目的: P3(If-Else PHI)で 2-3 個の Carrier を同時処理 + - 設計判断: ExitLine 拡張で対応(PhiGroupBox は作らない - YAGNI 原則) + - 対象: _parse_string(flag+buffer)、if-sum(sum+count) + - Phase 195-impl で実装予定 + +6. **JsonParser 残り複雑ループへの適用(Phase 195+, 200+)** + - Phase 200+: ConditionEnv 拡張 (function-scoped variables) → _parse_number, _atoi + - Phase 195+: Pattern 3 拡張 (multi-flag carriers) → _parse_string, _unescape_string + - Phase 195+: MethodCall 拡張 (multiple calls in body) → _parse_array, _parse_object + - selfhost `.hako` コンパイラの全ループを JoinIR で処理 (Phase 210+) diff --git a/docs/development/current/main/phase195-pattern3-extension-design.md b/docs/development/current/main/phase195-pattern3-extension-design.md new file mode 100644 index 00000000..4bfe7692 --- /dev/null +++ b/docs/development/current/main/phase195-pattern3-extension-design.md @@ -0,0 +1,623 @@ +# Phase 195: Pattern 3 拡張(if-in-loop + マルチキャリア) + +**Status**: Design Phase +**Date**: 2025-12-09 +**Prerequisite**: Phase 194 complete (JsonParser deployment & validation) + +--- + +## 目的 + +**Pattern 3(If-Else PHI)の対応範囲を拡張**し、複数キャリアの条件付き更新を JoinIR で扱えるようにする。 + +**スコープ**: +- ✅ if 内で完結する複数キャリア更新(2-3個程度) +- ❌ ConditionEnv 拡張は行わない(外部ローカル・digits 系は Phase 200+ 保留) +- ❌ LoopBodyLocal + MethodCall 混在は Phase 195+ に延期 + +--- + +## Task 195-1: 対象ループの絞り込み(doc-only) + +### 目標 +JsonParser / selfhost から「P3 で攻めたいループ」を **1-2 本だけ**選定し、AST 構造を詳細に分析する。 + +### 候補ループ + +#### 候補 1: JsonParser `_parse_string` の簡易版(優先度: 高) + +**ループ構造**: +```nyash +// _parse_string (escape 処理の簡略版) +static box JsonParser { + _parse_string(s, start) { + local buffer = "" + local escaped = false + local i = start + + loop(i < s.length() and s[i] != '"') { + local ch = s[i] + + if(ch == '\\') { + escaped = true // ← Carrier 1 update + } else { + buffer = buffer + ch // ← Carrier 2 update + escaped = false // ← Carrier 1 update + } + + i = i + 1 + } + + return buffer + } +} +``` + +**AST 構造**: +``` +Loop { + condition: BinOp(i < len AND s[i] != '"') + body: [ + LocalVar { name: "ch", init: ArrayAccess(s, i) }, // body-local + If { + condition: Compare(ch == '\\'), + then: [ + Assign { lhs: "escaped", rhs: BoolLiteral(true) } + ], + else: [ + Assign { lhs: "buffer", rhs: BinOp(buffer + ch) }, + Assign { lhs: "escaped", rhs: BoolLiteral(false) } + ] + }, + Assign { lhs: "i", rhs: BinOp(i + 1) } + ] +} +``` + +**キャリア分析**: +| Carrier | Type | Update Pattern | Then Branch | Else Branch | +|---------|------|----------------|-------------|-------------| +| `escaped` | BoolBox | Conditional flag | `true` | `false` | +| `buffer` | StringBox | StringAppend | (unchanged) | `buffer + ch` | +| `i` | IntegerBox | CounterLike | `i + 1` | `i + 1` | + +**P3 で扱う範囲**: +- ✅ `escaped`: 条件フラグ(両分岐で定義) +- ✅ `buffer`: StringAppend(else のみ更新、then は不変) +- ✅ `i`: ループ外で統一更新(P3 の外で処理) + +**制約**: +- `ch` は body-local 変数(Phase 191 で対応済み) +- `s[i]` の配列アクセスは ConditionEnv で解決(`s` は outer local → Phase 200+) +- **この Phase では `ch = "x"` のような定数で代替してテスト** + +#### 候補 2: selfhost の if-sum パターン(優先度: 中) + +**ループ構造**: +```nyash +// selfhost: 条件付き集計 +static box Aggregator { + sum_positive(array) { + local sum = 0 + local count = 0 + local i = 0 + + loop(i < array.length()) { + if(array[i] > 0) { + sum = sum + array[i] // ← Carrier 1 update + count = count + 1 // ← Carrier 2 update + } + i = i + 1 + } + + return sum + } +} +``` + +**AST 構造**: +``` +Loop { + condition: Compare(i < array.length()) + body: [ + If { + condition: Compare(array[i] > 0), + then: [ + Assign { lhs: "sum", rhs: BinOp(sum + array[i]) }, + Assign { lhs: "count", rhs: BinOp(count + 1) } + ], + else: [] // 空(更新なし) + }, + Assign { lhs: "i", rhs: BinOp(i + 1) } + ] +} +``` + +**キャリア分析**: +| Carrier | Type | Update Pattern | Then Branch | Else Branch | +|---------|------|----------------|-------------|-------------| +| `sum` | IntegerBox | NumberAccumulation | `sum + array[i]` | (unchanged) | +| `count` | IntegerBox | CounterLike | `count + 1` | (unchanged) | +| `i` | IntegerBox | CounterLike | `i + 1` | `i + 1` | + +**P3 で扱う範囲**: +- ✅ `sum`: NumberAccumulation(then のみ更新) +- ✅ `count`: CounterLike(then のみ更新) +- ✅ `i`: ループ外で統一更新 + +**制約**: +- `array[i]` の配列アクセスは ConditionEnv で解決(`array` は outer local → Phase 200+) +- **この Phase では `i` のような既存パラメータで代替してテスト** + +### Phase 195 での選定 + +**優先順位 1**: 候補 1(_parse_string 簡易版) +- 理由: JsonParser の実戦コード、flag + buffer の2キャリア +- 簡略化: `ch = "x"` 定数で配列アクセス回避 + +**優先順位 2**: 候補 2(if-sum) +- 理由: selfhost の典型パターン、sum + count の2キャリア +- 簡略化: `i` のみで配列アクセス回避 + +**成果物**: +- 選定したループの詳細 AST 構造記録(本セクション) +- キャリア分析表(UpdateKind 分類済み) + +--- + +## Task 195-2: LoopUpdateSummary / CarrierInfo の設計整理 + +### 現状の P3 サポート(Phase 170-189) + +**既存の P3 は単一キャリアのみ対応**: +```rust +// 既存の P3 ケース +if(cond) { + sum = sum + i // ← 単一キャリア "sum" +} else { + sum = sum - i +} +``` + +**LoopUpdateSummary / CarrierInfo の構造**: +```rust +pub struct CarrierInfo { + pub carriers: Vec, // キャリア名リスト + pub updates: HashMap, // name → update式 +} + +pub struct LoopUpdateSummary { + pub kind: UpdateKind, // CounterLike | NumberAccumulation | ... + // ... +} +``` + +### Phase 195 で扱う「複数キャリア + 条件付き更新」 + +**拡張要件**: +```rust +// Phase 195 の P3 ケース +if(cond) { + escaped = true // ← Carrier 1 + // buffer は更新なし(不変) +} else { + buffer = buffer + ch // ← Carrier 2 + escaped = false // ← Carrier 1 +} +``` + +**設計原則**: +1. **両分岐で同じ Carrier が必ず定義**されること(PHI 生成の前提) + - 片方の分岐で更新なし(不変)の場合、明示的に `carrier = carrier` を挿入 + - OR: PHI 生成時に「更新なし = 前の値を使う」として扱う + +2. **各 Carrier の update 式は既存 UpdateKind 範囲内**: + - CounterLike: `count + 1`, `count - 1` + - NumberAccumulation: `sum + i`, `sum * base + addend` + - StringAppend: `buffer + ch` + - BoolFlag: `true`, `false`(新規 UpdateKind 候補) + +3. **CarrierInfo は複数 Carrier を同時に保持**: + ```rust + CarrierInfo { + carriers: vec!["escaped", "buffer"], + updates: { + "escaped": ..., // then/else で異なる式 + "buffer": ..., + } + } + ``` + +### 制約の明確化 + +**P3 で扱う Carrier の制約** (Phase 195): +- ✅ if-else の**両分岐で同じ Carrier が定義**される(明示的 or 不変) +- ✅ 各 update 式は**既存 UpdateKind に対応**する +- ❌ MethodCall を含む update は Phase 193 の制約に従う(ループパラメータのみ) +- ❌ 外部ローカル変数(`digits` 等)は Phase 200+ に保留 + +**例(OK)**: +```nyash +if(ch == '\\') { + escaped = true // ✅ BoolFlag +} else { + buffer = buffer + ch // ✅ StringAppend + escaped = false // ✅ BoolFlag +} +``` + +**例(NG - Phase 195 範囲外)**: +```nyash +if(cond) { + digit = digits.indexOf(ch) // ❌ 外部ローカル (Phase 200+) + sum = sum + digit +} +``` + +### 成果物 +- 複数キャリア対応の設計原則(本セクション) +- UpdateKind 拡張候補(BoolFlag)の検討 +- CarrierInfo 構造の拡張仕様(擬似コード) + +--- + +## Task 195-3: Pattern3 lowerer の設計更新 + +### 現状の P3 lowerer(Phase 170-189) + +**単一キャリアの処理フロー**: +``` +1. If-Else AST を検出 +2. Then/Else 各分岐で carrier 更新式を抽出 +3. JoinIR で Then/Else ブロック生成 +4. Merge 点で PHI 命令生成(1つの carrier のみ) +5. ExitLine で PHI 結果を variable_map に接続 +``` + +### Phase 195 での拡張設計 + +#### 1. 複数 Carrier の同時処理 + +**設計案**: 複数 PHI を同じ Merge 点で生成 + +```rust +// 擬似コード: Pattern3 lowerer 拡張 + +// Step 1: If-Else で更新される全 Carrier を収集 +let carriers_in_then = extract_carriers(&if_node.then_branch); +let carriers_in_else = extract_carriers(&if_node.else_branch); +let all_carriers = carriers_in_then.union(&carriers_in_else); + +// Step 2: 各 Carrier について Then/Else の update 式を取得 +let mut carrier_updates = HashMap::new(); +for carrier in all_carriers { + let then_update = get_update_or_unchanged(&if_node.then_branch, carrier); + let else_update = get_update_or_unchanged(&if_node.else_branch, carrier); + carrier_updates.insert(carrier, (then_update, else_update)); +} + +// Step 3: JoinIR で Then/Else ブロック生成(複数 update を emit) +let then_block = emit_then_branch(&carrier_updates); +let else_block = emit_else_branch(&carrier_updates); + +// Step 4: Merge 点で複数 PHI 生成 +let merge_block = create_merge_block(); +for (carrier, (then_val, else_val)) in carrier_updates { + let phi_result = emit_phi(merge_block, then_val, else_val); + // ExitLine で variable_map に接続 + exit_line.connect(carrier, phi_result); +} +``` + +#### 2. PhiGroupBox vs ExitLine/CarrierInfo 拡張 + +**Option A: PhiGroupBox(新規箱)** +```rust +pub struct PhiGroupBox { + pub phis: Vec, // 複数 PHI の束 +} + +pub struct PhiInfo { + pub carrier_name: String, + pub then_value: ValueId, + pub else_value: ValueId, + pub result: ValueId, +} +``` + +**メリット**: +- 複数 PHI の関係性を明示的に管理 +- 単一責任の原則(PHI グループ専用) + +**デメリット**: +- 新規箱の追加(複雑度増加) +- 既存の ExitLine との統合が必要 + +**Option B: ExitLine/CarrierInfo 拡張(既存箱再利用)** +```rust +// 既存の ExitLine を拡張 +pub struct ExitLine { + pub phi_connections: HashMap, // carrier → PHI result +} + +// CarrierInfo は既に複数 Carrier 対応 +pub struct CarrierInfo { + pub carriers: Vec, + pub updates: HashMap, +} +``` + +**メリット**: +- 新規箱なし(既存インフラ再利用) +- ExitLine が既に複数 Carrier 接続をサポート + +**デメリット**: +- ExitLine の責務が拡大 + +**Phase 195 での判断**: +→ **Option B(既存箱拡張)を採用** + +**理由**: +- ExitLine は既に「variable_map への接続」を担当 +- 複数 Carrier → 複数 PHI は自然な拡張 +- 新規箱を作る必要性が低い(YAGNI 原則) + +#### 3. 更新なし(不変)の扱い + +**ケース**: 片方の分岐で Carrier が更新されない + +```nyash +if(ch == '\\') { + escaped = true + // buffer は更新なし(不変) +} else { + buffer = buffer + ch + escaped = false +} +``` + +**設計案**: PHI 生成時に「前の値」を使用 + +```rust +// Then 分岐で buffer 更新なし +let then_buffer_value = previous_buffer_value; // ← ループ header の PHI param + +// Else 分岐で buffer 更新あり +let else_buffer_value = emit_string_append(...); + +// Merge 点で PHI +let buffer_phi = emit_phi(merge, then_buffer_value, else_buffer_value); +``` + +**実装詳細**: +- `get_update_or_unchanged()` 関数で検出 +- 更新なし → `ValueId` として「前の値」を返す +- PHI 生成時に自動的に接続 + +### 成果物 +- Pattern3 lowerer の擬似コード(本セクション) +- PhiGroupBox vs ExitLine 拡張の判断(Option B 採用) +- 更新なし(不変)の扱い方設計 + +--- + +## Task 195-4: 実装スコープの決定(どこまでやるか) + +### Phase 195-impl の範囲 + +**✅ Phase 195-impl で実装する**: +1. **複数 Carrier の P3 処理**(2-3個程度) + - `escaped` + `buffer` のような flag + accumulation + - `sum` + `count` のような accumulation + counter + +2. **既存 UpdateKind 範囲内の update**: + - CounterLike: `count + 1` + - NumberAccumulation: `sum + i` + - StringAppend: `buffer + ch` + - BoolFlag: `true`, `false`(新規 UpdateKind 追加候補) + +3. **両分岐での定義確認**: + - Then/Else で同じ Carrier が定義されるケース + - 更新なし(不変)の場合は自動的に「前の値」を使用 + +4. **E2E テスト**: + - 簡易版 _parse_string(`ch = "x"` 定数版) + - 簡易版 if-sum(配列アクセスなし版) + +**❌ Phase 195-impl で実装しない**: +1. **LoopBodyLocal + MethodCall 混在**: + - `local ch = s[i]; if(...) { buf += ch }` + - → Phase 191(body-local init)と Phase 193(MethodCall)の組み合わせ + - → Phase 195+ に延期(複雑度高い) + +2. **外部ローカル変数(ConditionEnv 拡張)**: + - `local digits = "012..."; digit = digits.indexOf(ch)` + - → Phase 200+ に保留(設計判断済み) + +3. **ネストした If**: + - `if(...) { if(...) { ... } }` + - → Phase 196+ に延期(P3 の P3) + +### ゴールの明確化 + +**Phase 195-impl のゴール**: +> 「Named carrier が 2-3 個あっても P3 lowerer が壊れない」こと。 +> +> JsonParser/simple selfhost で「flag + count」くらいの例が通ること。 + +**成功基準**: +- [ ] 簡易版 _parse_string が JoinIR で動作(escaped + buffer) +- [ ] 簡易版 if-sum が JoinIR で動作(sum + count) +- [ ] 既存テスト(phase190-194)が退行しない +- [ ] ドキュメント更新(Implementation Status セクション追加) + +### テストケース設計 + +#### テスト 1: flag + buffer (BoolFlag + StringAppend) + +**ファイル**: `apps/tests/phase195_flag_buffer.hako` + +```nyash +static box Main { + main() { + local buffer = "" + local escaped = false + local i = 0 + + loop(i < 3) { + local ch = "a" // ← 定数(配列アクセス回避) + + if(i == 1) { + escaped = true + } else { + buffer = buffer + ch + escaped = false + } + + i = i + 1 + } + + print(buffer) // Expected: "aa" (i=0,2 で追加) + return 0 + } +} +``` + +#### テスト 2: sum + count (NumberAccumulation + CounterLike) + +**ファイル**: `apps/tests/phase195_sum_count.hako` + +```nyash +static box Main { + main() { + local sum = 0 + local count = 0 + local i = 0 + + loop(i < 5) { + if(i > 2) { + sum = sum + i // i=3,4 で加算 + count = count + 1 + } + i = i + 1 + } + + print(sum) // Expected: 7 (3+4) + print(count) // Expected: 2 + return 0 + } +} +``` + +--- + +## Task 195-5: CURRENT_TASK / overview 更新 + +### CURRENT_TASK.md 更新内容 + +```markdown +## Phase 195: Pattern 3 拡張(設計フェーズ)(完了予定: 2025-12-XX) + +**目的**: P3(If-Else PHI)を複数キャリア対応に拡張する設計 + +**タスク**: +- [ ] 195-1: 対象ループ絞り込み(_parse_string 簡易版、if-sum) +- [ ] 195-2: LoopUpdateSummary/CarrierInfo 設計整理(複数キャリア対応) +- [ ] 195-3: Pattern3 lowerer 設計更新(PhiGroup vs ExitLine 拡張判断) +- [ ] 195-4: 実装スコープ決定(2-3キャリア、既存 UpdateKind 範囲内) +- [ ] 195-5: ドキュメント更新(本項目 + overview 更新) + +**設計判断**: +- ✅ ExitLine 拡張で対応(PhiGroupBox は作らない) +- ✅ 両分岐での Carrier 定義確認(更新なし = 前の値使用) +- ❌ ConditionEnv 拡張なし(Phase 200+ 保留) +- ❌ LoopBodyLocal + MethodCall 混在は Phase 195+ 延期 + +**期待成果**: +- phase195-pattern3-extension-design.md(完全設計書) +- Phase 195-impl の実装スコープ明確化 +- JsonParser カバレッジ 40% → 60% への道筋 +``` + +### joinir-architecture-overview.md 更新内容 + +Section 7.2 "残タスク" に追記: + +```markdown +- [ ] **Phase 195**: Pattern 3 拡張(複数キャリア対応) + - 設計フェーズ: P3 で 2-3 個の Carrier を同時処理 + - ExitLine 拡張で複数 PHI 生成(PhiGroupBox は不要) + - 対象: _parse_string(flag+buffer)、if-sum(sum+count) + - Phase 195-impl で実装予定 +``` + +--- + +## 成功基準(設計フェーズ) + +- [x] 対象ループ選定完了(_parse_string 簡易版、if-sum) +- [x] キャリア分析表作成(UpdateKind 分類済み) +- [x] 複数キャリア対応の設計原則明確化 +- [x] Pattern3 lowerer の擬似コード作成 +- [x] PhiGroupBox vs ExitLine 拡張の判断(Option B 採用) +- [x] 実装スコープ決定(Phase 195-impl 範囲明確化) +- [x] テストケース設計(2ケース) +- [x] ドキュメント更新計画作成 + +--- + +## 関連ファイル + +### 設計対象 +- `src/mir/builder/control_flow/joinir/patterns/pattern3_with_if.rs`(Phase 195-impl で実装) +- `src/mir/join_ir/lowering/loop_update_summary.rs`(BoolFlag UpdateKind 追加候補) +- `src/mir/join_ir/lowering/carrier_info.rs`(複数 Carrier 対応確認) + +### テストファイル(Phase 195-impl で作成) +- `apps/tests/phase195_flag_buffer.hako`(BoolFlag + StringAppend) +- `apps/tests/phase195_sum_count.hako`(NumberAccumulation + CounterLike) + +### ドキュメント +- `docs/development/current/main/phase195-pattern3-extension-design.md`(本ファイル) +- `docs/development/current/main/joinir-architecture-overview.md`(更新予定) +- `CURRENT_TASK.md`(Phase 195 設計タスク追加) + +--- + +## 次のステップ + +### Phase 195-impl: Pattern3 拡張実装 + +設計書(本ファイル)に基づいて実装: +1. Pattern3 lowerer に複数 Carrier 処理追加 +2. ExitLine で複数 PHI 接続 +3. BoolFlag UpdateKind 追加(必要に応じて) +4. E2E テスト(phase195_flag_buffer.hako, phase195_sum_count.hako) +5. ドキュメント更新(Implementation Status セクション) + +### Phase 196+: 候補 + +- Pattern 3 のネスト対応(if-in-if) +- LoopBodyLocal + MethodCall + P3 の統合 +- JsonParser の _parse_string 完全版(配列アクセス対応 = Phase 200+) + +--- + +## 設計原則(Phase 195) + +1. **既存箱再利用**: + - PhiGroupBox を作らず、ExitLine/CarrierInfo を拡張 + - YAGNI(You Aren't Gonna Need It)原則 + +2. **段階的拡張**: + - 単一キャリア(Phase 170-189)→ 複数キャリア(Phase 195) + - 2-3 個程度に限定(無理に全部対応しない) + +3. **Fail-Fast 継承**: + - ConditionEnv 拡張なし(Phase 200+ 保留) + - 複雑なパターンは Phase 195+ に延期 + +4. **箱理論の実践**: + - 設計フェーズで構造を固める + - 実装フェーズは lowerer のみに集中 + - ドキュメント駆動開発