- Task 173-1: JsonParser loop inventory recheck
- Observed 6 loops: _trim (2 loops, already working), _skip_whitespace,
_parse_string, _parse_array, _unescape_string
- Created comprehensive observation report with Trim similarity ratings
- Discovered that JsonParser._trim already uses P5 pipeline successfully
- Task 173-2: Selected _skip_whitespace as Trim-equivalent pattern
- Perfect structural match with Trim (100% identical)
- Independent helper method, easy to test
- Frequently used in JsonParser (7 call sites)
- Task 173-3: Design doc for P5 pipeline extension to JsonParser
- Confirmed existing TrimLoopHelper works without modification
- No charAt() support needed (_skip_whitespace uses substring())
- Documented data flow and risk analysis
- Task 173-4: Successfully converted _skip_whitespace to JoinIR
- Created test case: local_tests/test_jsonparser_skip_whitespace.hako
- Added routing whitelist: JsonParserTest._skip_whitespace/3
- Pattern detection SUCCESS:
* LoopBodyLocal 'ch' detected
* Carrier promotion to 'is_ch_match'
* Trim pattern recognized
* JoinIR generation successful
- Verified P5 pipeline works for both static box methods and helper methods
- Task 173-5: Documentation updates
- phase173-jsonparser-loop-recheck.md: Loop observation report
- phase173-jsonparser-p5-design.md: P5 extension design
- phase173-jsonparser-p5-impl.md: Implementation results
- CURRENT_TASK.md: Phase 173 completion record
Key achievement: Proven that Trim P5 pipeline is fully generic -
works for both TrimTest (static box method) and JsonParser (helper method).
LoopBodyLocal carrier promotion is production-ready for Trim-like patterns.
Changes:
- src/mir/builder/control_flow/joinir/routing.rs: Add JsonParserTest whitelist
- docs/development/current/main/*173*.md: 3 new documentation files
- CURRENT_TASK.md: Phase 173 completion entry
9.6 KiB
Phase 173-3: JsonParser P5 Design
Date: 2025-12-08 Purpose: Trim P5 パイプラインを JsonParser に展開する設計
基本方針
「Trim パターンをそのまま再利用」 - JsonParser の
_skip_whitespaceは Trim と完全同型なので、既存の TrimPatternInfo / TrimLoopHelper をそのまま使用できる。
重要な発見
Phase 173-1 の観測で判明した事実:
✅ JsonParser の _trim メソッドは既に P5 対応済み!
[pattern2/trim] Safe Trim pattern detected, implementing lowering
[pattern2/trim] Carrier: 'is_ch_match', original var: 'ch', whitespace chars: ["\r", "\n", "\t", " "]
[joinir/pattern2] Generated JoinIR for Loop with Break Pattern (Phase 170-B)
これは、Phase 171 で実装した P5 パイプラインが、以下の範囲で既に機能していることを意味する:
- ✅
LoopConditionScopeBox::analyze()- LoopBodyLocal 検出 - ✅
LoopBodyCarrierPromoter::try_promote()- Carrier 昇格 - ✅
TrimLoopHelper::is_safe_trim()- Trim パターン検証 - ✅ Pattern2 lowerer - Trim 特例経路で JoinIR 生成
必要な対応
1. 命名の汎用化(将来対応、今回は不要)
現在の TrimLoopHelper は「Trim」という名前だが、実際は「LoopBodyLocal 変数を bool carrier に昇格する」汎用的なパターン。将来的には以下の名前変更を検討:
TrimPatternInfo→CharComparisonPatternInfoTrimLoopHelper→CharComparisonLoopHelper
ただし Phase 173 では名前変更しない(挙動不変を優先)。
理由:
- 動作実績: Phase 171 で Trim として実装し、既に JsonParser._trim で動作確認済み
- リスク回避: 名前変更は破壊的変更のリスクあり
- 段階的実装: まず JsonParser で動作確認してから、汎用化を検討
2. JsonParser 用のテストケース追加
目的: _skip_whitespace が P5 パイプラインで動作することを確認
ファイル: local_tests/test_jsonparser_skip_whitespace.hako(NEW)
内容:
static box JsonParserTest {
s: StringBox
pos: IntegerBox
len: IntegerBox
skip_whitespace(input_str, start_pos) {
me.s = input_str
me.pos = start_pos
me.len = me.s.length()
local p = me.pos
loop(p < me.len) {
local ch = me.s.substring(p, p+1)
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" {
p = p + 1
} else {
break
}
}
return p
}
main() {
print("=== JsonParser skip_whitespace Test ===")
local result = me.skip_whitespace(" \t\n hello", 0)
print("Skipped to position: ")
print(result)
if result == 5 {
print("PASS: Correctly skipped 5 whitespace characters")
return 0
} else {
print("FAIL: Expected position 5, got ")
print(result)
return 1
}
}
}
期待される動作:
loop(p < me.len)- Pattern2 として検出local ch = me.s.substring(p, p+1)- LoopBodyLocal として検出if ch == " " || ...- Trim パターンとして認識- Carrier
is_ch_matchに昇格 - JoinIR 生成成功
3. Pattern2 での Trim 特例判定拡張(必要なら)
現在の Pattern2 は「Trim」という名前で判定しているが、実際は構造判定なので、JsonParser の _skip_whitespace も同じ経路を通るはず。
確認事項:
- ✅
TrimLoopHelper::is_safe_trim()が JsonParser ループでも true になるか? - ✅
substring()メソッドの検出が機能するか? - ⚠️
charAt()メソッドの検出が必要か?(_skip_whitespaceはsubstring()を使用)
結論: Phase 173-4 で実行時に確認
データフロー(JsonParser 版)
JsonParser._skip_whitespace (AST)
↓
LoopConditionScopeBox::analyze()
↓ has_loop_body_local() == true (ch が LoopBodyLocal)
LoopBodyCarrierPromoter::try_promote()
↓ Promoted { trim_info }
TrimPatternInfo::to_carrier_info()
↓
CarrierInfo::merge_from()
↓
TrimLoopHelper::is_safe_trim() → true
↓
Pattern2 lowerer (Trim 特例経路)
↓
JoinIR 生成(bool carrier: is_ch_match)
Trim との違い: なし(完全同型)
実装方針
Phase 173-4 で確認すべきこと
-
LoopBodyLocal 検出: JsonParser の
_skip_whitespaceがLoopBodyCarrierPromoterで検出されるか?- 期待:
local ch = s.substring(p, p+1)が LoopBodyLocal として認識される
- 期待:
-
Trim パターン認識:
TrimLoopHelper::is_safe_trim()が true になるか?- 期待: 空白文字判定パターンが検出される
-
Trim 特例経路: Pattern2 の Trim 特例経路を通るか?
- 期待:
[pattern2/trim] Safe Trim pattern detectedが出力される
- 期待:
-
JoinIR 生成: JoinIR → MIR lowering が成功するか?
- 期待:
[joinir/pattern2] Generated JoinIR for Loop with Break Patternが出力される
- 期待:
-
実行成功: 生成された MIR が正しく実行されるか?
- 期待:
PASS: Correctly skipped 5 whitespace charactersが出力される
- 期待:
追加実装が必要な場合
可能性のある拡張:
-
charAt() メソッドの検出
- 現在:
substring()のみ検出 - 拡張:
charAt()も検出(JsonParser の一部のコードで使用) - 実装箇所:
src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs - 方法:
is_substring_method_call()をis_char_extraction_method()に拡張
- 現在:
-
メソッド名の汎用化
- 現在: "substring" ハードコード
- 拡張: "charAt", "substring" の両方に対応
- リスク: 低(既存動作を壊さない追加)
Phase 173-4 での判断基準:
- ✅
_skip_whitespaceがsubstring()のみ使用 → 追加実装不要 - ⚠️ 他の JsonParser ループが
charAt()使用 → Phase 174+ で対応
構造比較
Trim (test_trim_main_pattern.hako)
loop(start < end) {
local ch = s.substring(start, start+1)
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" {
start = start + 1
} else {
break
}
}
JsonParser._skip_whitespace
loop(p < s.length()) {
local ch = s.substring(p, p+1)
if ch == " " || ch == "\t" || ch == "\n" || ch == "\r" {
p = p + 1
} else {
break
}
}
構造的一致点
| 要素 | Trim | JsonParser | 一致 |
|---|---|---|---|
| ループ条件 | start < end |
p < s.length() |
✅ (比較演算) |
| LoopBodyLocal | local ch = s.substring(...) |
local ch = s.substring(...) |
✅ (完全一致) |
| 空白判定 | ch == " " || ch == "\t" || ... |
ch == " " || ch == "\t" || ... |
✅ (完全一致) |
| 進行処理 | start = start + 1 |
p = p + 1 |
✅ (加算代入) |
| 終了処理 | break |
break |
✅ (完全一致) |
結論: 100% 構造的に一致 → 既存の P5 パイプラインで完全対応可能
リスク分析
低リスク要因
-
既存実装の活用:
TrimLoopHelperは既に JsonParser._trim で動作確認済みLoopBodyCarrierPromoterは既に Trim で動作確認済み- Pattern2 Trim 特例経路は既に実装済み
-
構造的一致:
_skip_whitespaceと Trim は完全同型- 新しいパターン認識ロジック不要
-
独立性:
_skip_whitespaceは独立した helper method- 他のコードへの影響なし
潜在的リスク
-
MethodCall 検出の差異:
- Trim: static box method 内のループ
- JsonParser: helper method 内のループ
- 影響: 低(AST レベルでは同じ構造)
-
変数スコープの差異:
- Trim:
start,endが method local - JsonParser:
pが method local、sが parameter - 影響: 低(LoopConditionScopeBox は parameter も OuterLocal として扱う)
- Trim:
結論: 既存実装で対応可能、追加実装不要の見込み
次のステップ (Phase 173-4)
実装タスク
-
テストケース作成:
local_tests/test_jsonparser_skip_whitespace.hako作成- Trim と同じ構造、JsonParser の文脈でテスト
-
JoinIR モード実行:
NYASH_JOINIR_CORE=1 NYASH_LEGACY_LOOPBUILDER=0 \ ./target/release/hakorune local_tests/test_jsonparser_skip_whitespace.hako -
期待される出力確認:
[pattern2/check] Analyzing condition scope: 3 variables [pattern2/check] 'ch': LoopBodyLocal [pattern2/promoter] LoopBodyLocal 'ch' promoted to carrier 'is_ch_match' [pattern2/trim] Safe Trim pattern detected, implementing lowering [joinir/pattern2] Generated JoinIR for Loop with Break Pattern PASS: Correctly skipped 5 whitespace characters -
charAt() 対応確認:
- 必要なら
LoopBodyCarrierPromoterを拡張 - Phase 173-4 の実行結果で判断
- 必要なら
-
テスト実行:
cargo test --release --lib loop_body_carrier_promoter cargo test --release --lib pattern2_with_break
成功基準
- ✅
test_jsonparser_skip_whitespace.hakoが JoinIR で成功 - ✅
[pattern2/trim] Safe Trim pattern detected出力 - ✅
PASS: Correctly skipped 5 whitespace characters出力 - ✅ 既存の Trim テストが引き続き PASS
- ✅ ユニットテスト全て PASS
ドキュメント成果物:
phase173-jsonparser-p5-impl.md- 実装結果レポートCURRENT_TASK.md- Phase 173 成果記録