# Phase 256: StringUtils.split/2 Pattern Support Status: Planning Scope: Loop pattern recognition for split/tokenization operations Related: - Phase 255 完了(loop_invariants 導入、Pattern 6 完成) - Phase 254 完了(Pattern 6 index_of 実装) ## 失敗詳細 **テスト**: json_lint_vm (quick profile) **エラー**: `[joinir/freeze] Loop lowering failed: JoinIR does not support this pattern` **関数**: `StringUtils.split/2` ### エラーメッセージ全体 ``` [trace:dev] loop_canonicalizer: Decision: FAIL_FAST [trace:dev] loop_canonicalizer: Missing caps: [ConstStep] [trace:dev] loop_canonicalizer: Reason: Phase 143-P2: Loop does not match read_digits(loop(true)), skip_whitespace, parse_number, continue, parse_string, or parse_array pattern [ERROR] ❌ MIR compilation error: [joinir/freeze] Loop lowering failed: JoinIR does not support this pattern, and LoopBuilder has been removed. Function: StringUtils.split/2 Hint: This loop pattern is not supported. All loops must use JoinIR lowering. ``` ## 期待される動作 `StringUtils.split(s, separator)` が正常にコンパイルされ、文字列分割が動作すること。 ## 実際の動作 Loop canonicalizer が `ConstStep` を要求しているが、このループはステップが複雑で定数ではない。 ## 最小再現コード ```nyash split(s, separator) { local result = new ArrayBox() // Early return for empty separator if separator.length() == 0 { result.push(s) return result } local start = 0 local i = 0 // Main scan loop loop(i <= s.length() - separator.length()) { if s.substring(i, i + separator.length()) == separator { result.push(s.substring(start, i)) start = i + separator.length() i = start // Variable step - moves by separator.length() } else { i = i + 1 // Constant step - moves by 1 } } // Push remaining segment if start <= s.length() { result.push(s.substring(start, s.length())) } return result } ``` ## 分析 ### ループ構造 1. **条件**: `i <= s.length() - separator.length()` 2. **ボディ**: - If branch: マッチング検出時 - `result.push()` でセグメント追加 - `start = i + separator.length()` で次の開始位置更新 - `i = start` で大きくジャンプ(可変ステップ) - Else branch: マッチなし - `i = i + 1` で 1 進む(定数ステップ) 3. **特徴**: - **可変ステップ**: マッチング時は `separator.length()` 分ジャンプ - **複数キャリア**: `i`, `start`, `result` を更新 - **MethodCall**: `substring()`, `push()`, `length()` を使用 ### Canonicalizer の問題 ``` Missing caps: [ConstStep] ``` - 既存の Pattern 1-6 は定数ステップを想定 - このループは条件分岐で異なるステップ幅を使う - Pattern 2 (balanced_depth_scan) に近いが、可変ステップがネック ## 実装計画 ### Option A: Pattern 7 - Split/Tokenization Pattern **新しいパターン追加**: - 可変ステップサポート - 複数キャリア(i, start, accumulator) - If-else での異なるステップ幅処理 **検出条件**: 1. Loop condition: `i <= expr - len` 2. Body has if statement: - Then: `i = something_big` (可変ジャンプ) - Else: `i = i + 1` (定数ステップ) 3. Accumulator への追加操作 (`push` など) ### Option B: Pattern 2 拡張 **既存 Pattern 2 を拡張**: - ConstStep 要件を緩和 - If-else で異なるステップ幅を許可 - balanced_depth_scan_policy を拡張 ### Option C: Normalization 経路 **ループ正規化で対応**: - 可変ステップを定数ステップに変換 - Carrier 追加で状態管理 ## 次のステップ 1. **StepTree 詳細解析**: split ループの完全な AST 構造確認 2. **類似パターン調査**: 他の可変ステップループ(indexOf, contains など) 3. **Option 選択**: Pattern 7 新設 vs Pattern 2 拡張 vs Normalization 4. **実装戦略策定**: 選択した Option の詳細設計 ## 備考 - Phase 255 で loop_invariants が導入されたが、このケースは invariants 以前の問題(可変ステップ) - Phase 254-256 の流れで Pattern 6 → Pattern 7 の自然な進化が期待される - split/tokenization は一般的なパターンなので、汎用的な解決策が望ましい