diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index 1342a13a..c7778898 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -61,6 +61,14 @@ → Task 201-4: 共通ルールチェック & unit test 拡張(2つの新テスト追加)。 → Task 201-5: ドキュメント更新(overview + CURRENT_TASK)。 → **成果**: 全パターン(P1/P2/P3/P4)で Builder 統一完了、フィールド直書き完全排除、挙動不変(テスト全 PASS)。 + - [x] Phase 174: JsonParser 複雑ループ P5 拡張(設計+1本め) ✅ (2025-12-08) + → Task 174-1: 残り JsonParser ループの再チェック(_parse_string/_parse_array/_parse_object 分析)。 + → Task 174-2: 「次に攻める1本」を決定(_parse_string 選定、Trim に最も近い構造)。 + → Task 174-3: 箱の再利用 vs 追加を決定(TrimLoopHelper 再利用可能、最小化版で検証)。 + → Task 174-4: 小さな PoC を 1 本動かす(_parse_string 最小化版で P5 パイプライン成功)。 + → Task 174-5: ドキュメント更新(phase174-jsonparser-p5b-design.md + CURRENT_TASK)。 + → **成果**: Trim P5 パイプラインが `_parse_string` 最小化版でも機能することを実証。 + 文字比較対象が `"\""`(終端クォート)でも Trim と同じ昇格パターンで動作確認。 --- diff --git a/docs/development/current/main/joinir-architecture-overview.md b/docs/development/current/main/joinir-architecture-overview.md index ed5d4f56..2c7e200d 100644 --- a/docs/development/current/main/joinir-architecture-overview.md +++ b/docs/development/current/main/joinir-architecture-overview.md @@ -114,6 +114,10 @@ JoinIR ラインで守るべきルールを先に書いておくよ: - 昇格成功 → CarrierInfo に統合し Pattern 2/4 へ橋渡し。昇格失敗は Fail‑Fast。 - Pattern 2 は安全な Trim なら実際に前処理(substring 生成 + 空白比較の初期化)を emit してから JoinIR lowering。 - Pattern 4 は Trim 昇格が起きた場合はガード付きでエラーにし、未実装を明示(Fail‑Fast)。 + - 汎用性: + - Phase 173 で `_skip_whitespace`(JsonParser)が Trim パターンで動作確認済み。 + - Phase 174 で `_parse_string` 最小化版(終端クォート検出)でも動作確認済み。 + - → 空白文字以外の文字比較ループにも対応可能(TrimLoopHelper の汎用性実証)。 - **ContinueBranchNormalizer / LoopUpdateAnalyzer** - ファイル: diff --git a/docs/development/current/main/phase174-jsonparser-loop-inventory-2.md b/docs/development/current/main/phase174-jsonparser-loop-inventory-2.md new file mode 100644 index 00000000..f8f418ff --- /dev/null +++ b/docs/development/current/main/phase174-jsonparser-loop-inventory-2.md @@ -0,0 +1,345 @@ +# Phase 174-1: JsonParser 複雑ループ再観測 + +**Date**: 2025-12-08 +**Purpose**: Phase 173 で未対応の複雑ループを再分析し、Phase 174 ターゲットを決定 + +--- + +## 未対応ループ分析 + +### 1. _parse_string (lines 150-178) + +**構造**: +```hako +loop(p < s.length()) { + local ch = s.substring(p, p+1) + + if ch == '"' { + // End of string + local result = new MapBox() + result.set("value", me._unescape_string(str)) + result.set("pos", p + 1) + result.set("type", "string") + return result + } + + if ch == "\\" { + // Escape sequence + local has_next = 0 + if p + 1 < s.length() { has_next = 1 } + if has_next == 0 { return null } + + str = str + ch + p = p + 1 + str = str + s.substring(p, p+1) + p = p + 1 + continue + } + + str = str + ch + p = p + 1 +} +``` + +**Pattern 分類**: Pattern4 候補(continue 付き)または Pattern2(基本構造) +**LoopBodyLocal**: `ch` が条件に使用 +**複雑度**: ★★★☆☆(エスケープ処理あり、continue あり) + +**Trim との差分**: +- ✅ **同じ**: LoopBodyLocal `ch` を break 条件に使用 +- ✅ **同じ**: `local ch = s.substring(p, p+1)` パターン +- ✅ **同じ**: 単純な文字比較(`ch == "\""`) +- ⚠️ **追加**: エスケープ処理(`ch == "\\"` の次の文字を読む) +- ⚠️ **追加**: 文字列バッファへの追加処理(`str = str + ch`) +- ⚠️ **追加**: continue 使用(エスケープ処理後) +- ⚠️ **追加**: return による早期終了(成功時) + +**最小化可能性**: ★★★★★(エスケープ処理・continue・return を除外すれば Trim と同型) + +**最小化版**: +```hako +// エスケープ処理・文字列バッファ・continue を除外 +loop(pos < len) { + local ch = s.substring(pos, pos+1) + if ch == "\"" { + break // return の代わりに break + } else { + pos = pos + 1 + } +} +``` + +この構造なら: +- ✅ TrimLoopHelper がそのまま使える +- ✅ Pattern2 Trim 特例経路が使える +- ✅ 単一キャリア `pos` のみ +- ✅ LoopBodyLocal `ch` の昇格パターンが Trim と同じ + +**Phase 174 適性**: ★★★★★(最小化版で Trim に最も近い、第一候補) + +--- + +### 2. _parse_array (lines 203-231) + +**構造**: +```hako +loop(p < s.length()) { + // Parse element + local elem_result = me._parse_value(s, p) + if elem_result == null { return null } + + local elem = elem_result.get("value") + arr.push(elem) + + p = elem_result.get("pos") + p = me._skip_whitespace(s, p) + + if p >= s.length() { return null } + + local ch = s.substring(p, p+1) + if ch == "]" { + // End of array - return result + return result + } + + if ch == "," { + p = p + 1 + p = me._skip_whitespace(s, p) + continue + } + + return null +} +``` + +**Pattern 分類**: Pattern4 候補(continue 付き) +**LoopBodyLocal**: `ch` が条件に使用(ただし複数の他の処理も多い) +**複雑度**: ★★★★☆(複数条件、continue、ネスト、MethodCall 多数) + +**Trim との差分**: +- ⚠️ **追加**: MethodCall 多数(`me._parse_value`, `me._skip_whitespace`) +- ⚠️ **追加**: MapBox/ArrayBox 操作(`elem_result.get()`, `arr.push()`) +- ⚠️ **追加**: 複数の return 文(成功・失敗パス) +- ⚠️ **追加**: continue 使用(区切り文字処理後) +- ✅ **同じ**: `local ch = s.substring(p, p+1)` パターン(限定的) +- ✅ **同じ**: 単純な文字比較(`ch == "]"`, `ch == ","`) + +**最小化可能性**: ★☆☆☆☆(MethodCall と複雑な処理が本質的、最小化困難) + +**Phase 174 適性**: ★★☆☆☆(複雑すぎる、Phase 175+ 推奨) + +--- + +### 3. _parse_object (lines 256-304) + +**構造**: +```hako +loop(p < s.length()) { + p = me._skip_whitespace(s, p) + + // Parse key (must be string) + if s.substring(p, p+1) != '"' { return null } + local key_result = me._parse_string(s, p) + if key_result == null { return null } + + local key = key_result.get("value") + p = key_result.get("pos") + p = me._skip_whitespace(s, p) + + // Expect colon + if p >= s.length() { return null } + if s.substring(p, p+1) != ":" { return null } + p = p + 1 + + p = me._skip_whitespace(s, p) + + // Parse value + local value_result = me._parse_value(s, p) + if value_result == null { return null } + + local value = value_result.get("value") + obj.set(key, value) + + p = value_result.get("pos") + p = me._skip_whitespace(s, p) + + if p >= s.length() { return null } + + local ch = s.substring(p, p+1) + if ch == "}" { + // End of object - return result + return result + } + + if ch == "," { + p = p + 1 + continue + } + + return null +} +``` + +**Pattern 分類**: Pattern4 候補(continue 付き) +**LoopBodyLocal**: `ch` が条件に使用(ただし他の処理も多い) +**複雑度**: ★★★★★(_parse_array と同程度以上、キー・バリューペア処理) + +**Trim との差分**: +- ⚠️ **追加**: _parse_array と同様に MethodCall 多数 +- ⚠️ **追加**: キー・バリューペアの複雑な処理 +- ⚠️ **追加**: 複数の return 文 +- ⚠️ **追加**: continue 使用 +- ✅ **同じ**: `local ch = s.substring(p, p+1)` パターン(限定的) + +**最小化可能性**: ★☆☆☆☆(_parse_array と同様に最小化困難) + +**Phase 174 適性**: ★★☆☆☆(_parse_array と同程度の複雑さ、Phase 175+ 推奨) + +--- + +### 4. _parse_number (lines 121-133) + +**構造**: +```hako +loop(p < s.length()) { + local ch = s.substring(p, p+1) + local digit_pos = digits.indexOf(ch) + + // Exit condition: non-digit character found + if digit_pos < 0 { + break + } + + // Continue parsing: digit found + num_str = num_str + ch + p = p + 1 +} +``` + +**Pattern 分類**: Pattern2(break 付き、continue なし) +**LoopBodyLocal**: `ch`, `digit_pos` が条件に使用 +**複雑度**: ★★☆☆☆(Trim に近いが、indexOf 使用) + +**Trim との差分**: +- ✅ **同じ**: `local ch = s.substring(p, p+1)` パターン +- ✅ **同じ**: break での終了 +- ✅ **同じ**: 単一キャリア `p` の更新 +- ⚠️ **追加**: `digits.indexOf(ch)` による範囲チェック(OR chain の代わり) +- ⚠️ **追加**: 文字列バッファへの追加処理(`num_str = num_str + ch`) + +**最小化可能性**: ★★★★☆(文字列バッファを除外すれば Trim に近い) + +**最小化版**: +```hako +// 文字列バッファを除外 +loop(p < s.length()) { + local ch = s.substring(p, p+1) + local digit_pos = digits.indexOf(ch) + if digit_pos < 0 { + break + } else { + p = p + 1 + } +} +``` + +**Phase 174 適性**: ★★★☆☆(候補だが、_parse_string のほうが Trim に近い) + +--- + +## Phase 174-2 選定結果 + +**選定ループ**: `_parse_string`(最小化版) + +**選定理由**: + +1. ✅ **Trim に最も近い構造**: + - `local ch = s.substring(pos, pos+1)` パターン + - `if ch == "\"" { break }` - 単純な文字比較 + - 単一キャリア `pos` のみ(最小化版) + - LoopBodyLocal `ch` の使用パターンが Trim と同じ + +2. ✅ **最小化可能性が高い**: + - エスケープ処理を除外 → 基本的な文字比較ループ + - 文字列バッファを除外 → 単一キャリア + - continue を除外 → Pattern2 構造維持 + - return を break に置換 → Pattern2 Trim 特例経路利用可能 + +3. ✅ **実用性**: + - JSON 文字列パースの核心部分 + - 成功すれば将来的にエスケープ処理等を追加可能 + +4. ✅ **既存実装で対応可能**: + - `TrimLoopHelper::is_safe_trim()` がそのまま使える + - `LoopBodyCarrierPromoter::try_promote()` で carrier 昇格可能 + - Pattern2 Trim 特例経路で JoinIR 生成可能 + +**構造的類似度**: +- Trim/_skip_whitespace: ★★★★★(100% 一致) +- _parse_string(最小化版): ★★★★★(99% 一致、`"\""`の代わりに空白文字) +- _parse_number(最小化版): ★★★★☆(95% 一致、indexOf 使用が差分) + +**Phase 174 目標**: +- 基本的な文字比較部分を P5 パイプラインで処理(最小化版) +- エスケープ処理・文字列バッファ・continue は Phase 175+ に延期 + +**次点候補**: `_parse_number`(最小化版) +- Trim に近いが、indexOf 使用がやや複雑 +- _parse_string 成功後の次のターゲット候補 + +**Phase 175+ 候補**: `_parse_array`, `_parse_object` +- 複雑すぎる、MethodCall 多数、最小化困難 +- P5 パイプライン拡張後に検討 + +--- + +## Phase 174-3 準備: 最小化版の設計方針 + +**最小化方針**: +1. **エスケープ処理を除外**: `if ch == "\\"` ブロック全体を削除 +2. **文字列バッファを除外**: `str = str + ch` を削除、`str` 変数を削除 +3. **continue を除外**: エスケープ処理がないので continue も不要 +4. **return を break に置換**: 成功時の return を break に変更 + +**最小化版の構造**: +```hako +// Phase 174-4 PoC版(最もシンプルな形) +loop(pos < len) { + local ch = s.substring(pos, pos+1) + if ch == "\"" { + break + } else { + pos = pos + 1 + } +} +``` + +この構造は Trim/_skip_whitespace と **完全に同型**(文字比較の対象が異なるだけ)。 + +**期待される動作**: +1. `LoopConditionScopeBox::analyze()` - `ch` を LoopBodyLocal として検出 +2. `LoopBodyCarrierPromoter::try_promote()` - carrier `is_ch_match` に昇格 +3. `TrimLoopHelper::is_safe_trim()` - true を返す +4. Pattern2 lowerer - Trim 特例経路で JoinIR 生成 + +**Phase 174-4 で実証すべきこと**: +- ✅ Trim パイプラインが文字比較対象が異なるだけで機能すること +- ✅ `"\""`(終端クォート)という異なる文字でも昇格パターンが機能すること +- ✅ TrimLoopHelper の汎用性(空白文字以外にも対応可能) + +--- + +## 結論 + +**Phase 174 戦略**: +- ✅ _parse_string の最小化版をターゲット +- ✅ 既存の TrimLoopHelper をそのまま再利用 +- ✅ Pattern2 Trim 特例経路で JoinIR 生成 +- ❌ エスケープ処理・複数キャリア・continue は Phase 175+ に延期 + +**Phase 175+ への道筋**: +1. Phase 174: _parse_string 最小化版(Trim と同型) +2. Phase 175: 文字列バッファ追加(複数キャリア対応) +3. Phase 176: エスケープ処理追加(continue 対応) +4. Phase 177: _parse_number 対応(indexOf パターン) +5. Phase 178+: _parse_array/_parse_object(複雑ループ) diff --git a/docs/development/current/main/phase174-jsonparser-p5b-design.md b/docs/development/current/main/phase174-jsonparser-p5b-design.md new file mode 100644 index 00000000..d4d174d1 --- /dev/null +++ b/docs/development/current/main/phase174-jsonparser-p5b-design.md @@ -0,0 +1,362 @@ +# Phase 174-3: JsonParser `_parse_string` P5B 設計 + +**Date**: 2025-12-08 +**Target**: `_parse_string` ループ(エスケープ処理付き文字列パース) +**Purpose**: Trim P5 パイプラインを複雑ループに拡張する設計 + +--- + +## ターゲットループ構造 + +### 完全版(Phase 175+ のターゲット) + +```hako +loop(p < s.length()) { + local ch = s.substring(p, p+1) + + if ch == "\"" { // 終端クォート + // End of string + local result = new MapBox() + result.set("value", me._unescape_string(str)) + result.set("pos", p + 1) + result.set("type", "string") + return result + } + + if ch == "\\" { // エスケープ開始 + local has_next = 0 + if p + 1 < s.length() { has_next = 1 } + if has_next == 0 { return null } + + str = str + ch + p = p + 1 + str = str + s.substring(p, p+1) + p = p + 1 + continue + } + + str = str + ch + p = p + 1 +} +``` + +### 最小化版(Phase 174-4 PoC) + +```hako +// エスケープ処理・文字列バッファ・continue・return を除外 +loop(pos < len) { + local ch = s.substring(pos, pos+1) + if ch == "\"" { + break + } else { + pos = pos + 1 + } +} +``` + +--- + +## Pattern Space 分析 + +### 軸 A〜F での分類(最小化版) + +| 軸 | 値 | 説明 | +|----|-----|------| +| **A. 継続条件** | 単純 | `pos < len` | +| **B. 早期終了** | 条件付き break | `if ch == "\"" { break }` | +| **C. スキップ** | なし | continue 使用なし | +| **D. PHI 分岐** | なし | if 分岐あるが PHI 不要 | +| **E. 条件変数のスコープ** | **LoopBodyLocal** | `ch` が条件に使用 | +| **F. キャリア更新** | 単純 | `pos` のみ更新 | + +**Pattern 分類**: **P5**(LoopBodyLocal 条件)+ **Pattern2**(break 付き) + +--- + +## Trim との差分 + +### ✅ 同じ部分(P5 パイプライン再利用可能) + +1. **LoopBodyLocal 変数の使用**: + - Trim: `local ch = s.substring(start, start+1)` + - Parse String: `local ch = s.substring(pos, pos+1)` + - → **完全一致**(変数名が異なるだけ) + +2. **文字比較パターン**: + - Trim: `if ch == " " || ch == "\t" || ch == "\n" || ch == "\r"` + - Parse String: `if ch == "\""` + - → **構造は同じ**(比較対象が異なるだけ) + +3. **Pattern2 構造**: + - Trim: `loop(start < end)` + `{ start = start + 1 } else { break }` + - Parse String: `loop(pos < len)` + `{ pos = pos + 1 } else { break }` + - → **完全同型** + +4. **キャリア更新**: + - Trim: `start = start + 1`(単一キャリア) + - Parse String: `pos = pos + 1`(単一キャリア) + - → **完全一致** + +### ⚠️ 追加部分(完全版、Phase 175+ で必要) + +1. **複数キャリア**: + - `pos`: ループカウンタ + - `str`: 文字列バッファ + - **課題**: 既存の TrimLoopHelper は単一キャリア想定 + +2. **エスケープ処理**: + - `if ch == "\\" { ... }` → 追加の文字読み込み + - **課題**: LoopBodyLocal の多重使用(`ch` と `escaped`) + +3. **continue**: + - エスケープ処理後に continue + - **課題**: Pattern4 対応が必要 + +4. **return による早期終了**: + - 成功時の return + - **課題**: ExitLine とループ外リターンの分離 + +--- + +## 箱の再利用 vs 追加 + +### 再利用可能な既存箱(Phase 174-4) + +| 箱名 | 再利用可能性 | 理由 | +|-----|-----------|------| +| **LoopConditionScopeBox** | ✅ 100% | `ch` を LoopBodyLocal と分類可能 | +| **LoopBodyCarrierPromoter** | ✅ 100% | `ch` の昇格検出(Trim と同じ) | +| **TrimPatternInfo** | ✅ 100% | 基本構造は再利用可能 | +| **TrimLoopHelper** | ✅ 100% | 単一キャリア版で完全対応 | +| **CarrierInfo** | ✅ 100% | `pos` キャリア情報 | +| **ExitLine** | ✅ 100% | break による終了 | +| **Boundary** | ✅ 100% | ループ境界情報 | + +**結論**: 最小化版では**既存の箱をそのまま使える**! + +### 追加が必要な箱(Phase 175+ で検討) + +1. **MultiCarrierTrimHelper**(将来): + - TrimLoopHelper の拡張版 + - 複数キャリア(`pos` + `str`)対応 + - **Phase 175 で設計・実装** + +2. **EscapeSequenceHandler**(将来): + - エスケープ処理の追加ロジック + - `ch == "\\"` 時の特殊処理 + - **Phase 176 で設計・実装** + +3. **ContinuePatternHelper**(将来): + - Pattern4(continue 付き)対応 + - **Phase 176 で設計・実装** + +--- + +## Phase 174 戦略 + +### ステップ1: 最小化版で試験(Phase 174-4) + +**最小化方針**: +- ✅ エスケープ処理を**除外** +- ✅ 文字列バッファ(`str`)を**除外** +- ✅ continue を**除外** +- ✅ return を break に**置換** + +**最小化版**: +```hako +// Phase 174-4 PoC +loop(pos < len) { + local ch = s.substring(pos, pos+1) + if ch == "\"" { + break + } else { + pos = pos + 1 + } +} +``` + +**この構造の利点**: +- ✅ TrimLoopHelper がそのまま使える +- ✅ Pattern2 Trim 特例経路が使える +- ✅ 単一キャリア `pos` のみ +- ✅ 既存コードの変更**ゼロ** + +**期待される動作**: +1. `LoopConditionScopeBox::analyze()` + - `ch`: LoopBodyLocal(substring でループ内定義) + - `pos`, `len`: OuterLocal(ループ外定義) + +2. `LoopBodyCarrierPromoter::try_promote()` + - `ch` を carrier `is_ch_match` に昇格 + - 昇格理由: break 条件に使用 + +3. `TrimLoopHelper::is_safe_trim()` + - true を返す(Trim と完全同型) + +4. Pattern2 lowerer + - Trim 特例経路で JoinIR 生成 + - `[pattern2/trim] Safe Trim pattern detected` + +### ステップ2: エスケープ処理の追加(Phase 175+) + +最小化版が成功したら、段階的に追加: + +1. **Phase 175**: 文字列バッファ追加(複数キャリア対応) + ```hako + loop(pos < len) { + local ch = s.substring(pos, pos+1) + if ch == "\"" { + break + } else { + result = result + ch // ← 追加 + pos = pos + 1 + } + } + ``` + +2. **Phase 176**: エスケープ処理追加(continue 対応) + ```hako + loop(pos < len) { + local ch = s.substring(pos, pos+1) + if ch == "\"" { + break + } else if ch == "\\" { + // エスケープ処理 + pos = pos + 1 + result = result + s.substring(pos, pos+1) + pos = pos + 1 + continue // ← Pattern4 対応が必要 + } else { + result = result + ch + pos = pos + 1 + } + } + ``` + +3. **Phase 177**: return 処理追加(ExitLine 拡張) + ```hako + loop(pos < len) { + local ch = s.substring(pos, pos+1) + if ch == "\"" { + return create_result(result, pos) // ← ExitLine 拡張 + } + // ... 以下同じ + } + ``` + +--- + +## 命名の汎用化(Phase 175+ で検討) + +### 現在の命名(Trim 特化) + +- `TrimLoopHelper` - Trim 専用のような命名 +- `is_safe_trim()` - Trim 専用のような命名 + +### 汎用化案(Phase 175+ で検討) + +**案1: CharComparison** +- `CharComparisonLoopHelper` +- `is_safe_char_comparison()` +- **利点**: 文字比較ループの汎用名 +- **欠点**: やや長い + +**案2: SingleCharBreak** +- `SingleCharBreakLoopHelper` +- `is_safe_single_char_break()` +- **利点**: 構造を正確に表現 +- **欠点**: 長い、やや複雑 + +**案3: P5Pattern(軸E準拠)** +- `P5LoopHelper` +- `is_safe_p5_pattern()` +- **利点**: Pattern Space 軸E と一貫性 +- **欠点**: P5 の意味が不明瞭 + +**Phase 174 での方針**: **命名変更なし**(既存コード保持) +- Phase 175+ で複数キャリア対応時に再検討 +- 既存の TrimLoopHelper は Trim 専用として保持 +- 新しい汎用版を別途作成する可能性 + +--- + +## テスト戦略 + +### Phase 174-4 テストケース + +**ファイル**: `local_tests/test_jsonparser_parse_string_min.hako` + +```hako +static box JsonParserStringTest { + s: StringBox + pos: IntegerBox + len: IntegerBox + + parse_string_min() { + me.s = "hello world\"" // 終端クォート付き + me.pos = 0 + me.len = me.s.length() + + // 最小化版: エスケープ処理なし、終端クォート検出のみ + loop(me.pos < me.len) { + local ch = me.s.charAt(me.pos) + if ch == "\"" { + break + } else { + me.pos = me.pos + 1 + } + } + + print("Found quote at position: ") + print(me.pos) + } + + main() { + me.parse_string_min() + return "OK" + } +} +``` + +**期待される出力**: +``` +[pattern2/check] 'ch': LoopBodyLocal ✅ +[pattern2/promoter] promoted to carrier 'is_ch_match' ✅ +[pattern2/trim] Safe Trim pattern detected ✅ +Found quote at position: 11 +``` + +**実行コマンド**: +```bash +NYASH_JOINIR_CORE=1 NYASH_LEGACY_LOOPBUILDER=0 \ + ./target/release/hakorune local_tests/test_jsonparser_parse_string_min.hako +``` + +--- + +## 結論 + +### Phase 174-4 では + +- ✅ 既存の TrimLoopHelper をそのまま再利用 +- ✅ 最小化版(`ch == "\""`のみ)で P5 パイプライン検証 +- ✅ 既存コードの変更**ゼロ** +- ❌ エスケープ処理・複数キャリア・continue は Phase 175+ に延期 + +### Phase 175+ で検討 + +- **MultiCarrierTrimHelper** の設計 +- **エスケープ処理**の統合(Pattern4 対応) +- **命名の汎用化**(Trim → CharComparison) +- **return 処理**の ExitLine 拡張 + +### 技術的価値 + +**Phase 174-4 で実証すべきこと**: +1. ✅ Trim パイプラインが文字比較対象が異なるだけで機能すること +2. ✅ `"\"`(終端クォート)という異なる文字でも昇格パターンが機能すること +3. ✅ TrimLoopHelper の汎用性(空白文字以外にも対応可能) + +**成功すれば**: +- Trim P5 パイプラインが「Trim 専用」ではなく「文字比較ループ汎用」であることが証明される +- Phase 175+ での拡張(複数キャリア・continue 等)の基盤が確立される diff --git a/src/mir/builder/control_flow/joinir/routing.rs b/src/mir/builder/control_flow/joinir/routing.rs index a3432915..429858ca 100644 --- a/src/mir/builder/control_flow/joinir/routing.rs +++ b/src/mir/builder/control_flow/joinir/routing.rs @@ -91,6 +91,9 @@ impl MirBuilder { // Phase 173: JsonParser P5 expansion test "JsonParserTest._skip_whitespace/3" => true, "JsonParserTest.main/0" => true, + // Phase 174: JsonParser complex loop P5B extension test + "JsonParserStringTest.parse_string_min/0" => true, + "JsonParserStringTest.main/0" => true, _ => false, };