139 lines
4.4 KiB
Markdown
139 lines
4.4 KiB
Markdown
|
|
# 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 は一般的なパターンなので、汎用的な解決策が望ましい
|