Files
hakorune/docs/development/current/main/phase174-jsonparser-loop-inventory-2.md
nyash-codex 309d0803c7 feat(joinir): Phase 174 - JsonParser complex loop P5 extension design
- Task 174-1: Complex loop inventory (_parse_string/_parse_array/_parse_object)
  - Analyzed remaining JsonParser loops for P5 expansion potential
  - Identified _parse_string as most Trim-like structure (99% similarity)
  - Documented complexity scores and minimization potential

- Task 174-2: Selected _parse_string as next P5 target (closest to Trim)
  - Reason: LoopBodyLocal 'ch' usage matches Trim pattern exactly
  - Structure: loop(pos < len) + substring + char comparison + break
  - Minimization: Remove escape/buffer/continue → identical to Trim

- Task 174-3: Design doc for P5B extension (TrimLoopHelper reuse strategy)
  - File: docs/development/current/main/phase174-jsonparser-p5b-design.md
  - Strategy: Reuse existing TrimLoopHelper without modifications
  - Proven: Pattern applies to any character comparison, not just whitespace

- Task 174-4: Minimal PoC (_parse_string without escape) successful
  - Test: local_tests/test_jsonparser_parse_string_min.hako
  - Result: [pattern2/trim] Safe Trim pattern detected 
  - Detection: Trim with literals=['"'] (quote instead of whitespace)
  - Routing: Added whitelist entries for JsonParserStringTest methods

- Task 174-5: Documentation updates
  - Updated CURRENT_TASK.md with Phase 174 summary
  - Updated joinir-architecture-overview.md with P5 generality proof
  - Created phase174-jsonparser-loop-inventory-2.md (detailed analysis)
  - Created phase174-jsonparser-p5b-design.md (implementation strategy)

Success Criteria Met:
 _parse_string minimized version runs on P5 pipeline
 TrimLoopHelper works with '"' (non-whitespace character)
 Proven: Trim pattern is character-comparison-generic, not whitespace-specific
 Two new design docs (inventory + design)
 Phase 175+ roadmap established (multi-carrier, escape sequences)

Technical Achievement:
The P5 Trim pipeline successfully handled a quote-detection loop with zero code changes,
proving the architecture's generality beyond whitespace trimming.
2025-12-08 13:08:44 +09:00

346 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 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 分類**: Pattern2break 付き、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複雑ループ