**Status**: Core carrier PHI issue partially resolved, debugging loop body **Progress**: ✅ Task 1: split_scan_minimal.rs Carriers-First ordering (6 locations) ✅ Task 2: pattern7_split_scan.rs boundary configuration (host/join inputs, exit_bindings, expr_result) ✅ Result now flows from k_exit to post-loop code (RC issue resolved) ⚠️ Loop body instruction execution needs review **Key Fixes**: 1. Fixed host_inputs/join_inputs to match main() params Carriers-First order 2. Added result to exit_bindings (CarrierRole::LoopState) 3. Added result back to loop_invariants for variable initialization 4. Added expr_result=join_exit_value_result for loop expression return 5. Fixed jump args to k_exit to include all 4 params [i, start, result, s] **Current Issue**: - Loop body type errors resolved (String vs Integer fixed) - New issue: Loop body computations (sep_len) undefined in certain blocks - Likely cause: JoinIR→MIR conversion of local variables needs review **Next Steps**: - Review JoinValueSpace allocation and ValueId mapping in conversion - Verify loop_step instruction ordering and block structure - May need to refactor bound computation or revisit split algorithm 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
6.3 KiB
6.3 KiB
Phase 256: StringUtils.split/2 Pattern Support
Status: Active 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 を要求しているが、このループはステップが複雑で定数ではない。
最小再現コード
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
}
分析
ループ構造
- 条件:
i <= s.length() - separator.length() - ボディ:
- If branch: マッチング検出時
result.push()でセグメント追加start = i + separator.length()で次の開始位置更新i = startで大きくジャンプ(可変ステップ)
- Else branch: マッチなし
i = i + 1で 1 進む(定数ステップ)
- If branch: マッチング検出時
- 特徴:
- 可変ステップ: マッチング時は
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 での異なるステップ幅処理
検出条件:
- Loop condition:
i <= expr - len - Body has if statement:
- Then:
i = something_big(可変ジャンプ) - Else:
i = i + 1(定数ステップ)
- Then:
- Accumulator への追加操作 (
pushなど)
Option B: Pattern 2 拡張
既存 Pattern 2 を拡張:
- ConstStep 要件を緩和
- If-else で異なるステップ幅を許可
- balanced_depth_scan_policy を拡張
Option C: Normalization 経路
ループ正規化で対応:
- 可変ステップを定数ステップに変換
- Carrier 追加で状態管理
次のステップ
- StepTree 詳細解析: split ループの完全な AST 構造確認
- 類似パターン調査: 他の可変ステップループ(indexOf, contains など)
- Option 選択: Pattern 7 新設 vs Pattern 2 拡張 vs Normalization
- 実装戦略策定: 選択した Option の詳細設計
Phase 256 指示書(P0)
目標
StringUtils.split/2の loop を JoinIR で受理し、json_lint_vmを PASS に戻す。- by-name 分岐禁止(
StringUtils.split/2だけを特別扱いしない)。 - workaround 禁止(fallback は作らない)。
推奨方針(P0)
Option A(Pattern 7 新設)を推奨。
理由:
- 可変 step(then:
i = start/ else:i = i + 1)は既存の ConstStep 前提と相性が悪い。 - Pattern 2 を膨らませず、tokenization 系の “専用パターン” として箱化した方が責務が綺麗。
P0 タスク
- 最小 fixture + v2 smoke(integration)
apps/tests/phase256_p0_split_min.hakotools/smokes/v2/profiles/integration/apps/phase256_p0_split_vm.shtools/smokes/v2/profiles/integration/apps/phase256_p0_split_llvm_exe.sh
- DetectorBox(構造のみ)
- ループ条件が
i <= s.length() - sep.length()形 - body に
if substring(i, i + sep.length()) == sep { ... i = start } else { i = i + 1 } result.push(...)を含む(ArrayBox accumulator)- ループ後に “残り push” がある(任意だがあると精度が上がる)
- 抽出箱(Parts)
i/start/result/s/separatorを抽出- then/else の更新式(可変 step と const step)を抽出
- JoinIR lowerer(専用)
- loop_state:
i,start - invariants:
s,separator,result(result は更新されるので carrier 扱いが必要なら role を明確に) - then/else で異なる
i_nextをSelectもしくは branch で表現(設計 SSOT は JoinIR 側で決める)
- 検証
- integration smokes 2本が PASS
./tools/smokes/v2/run.sh --profile quickの最初の FAIL が次へ進む
注意(P0ではやらない)
- 既存 Pattern の大改造(Pattern 2 の全面拡張)は避ける
- 正規化(Normalization 経路)は P1 以降の検討に回す
備考
- Phase 255 で loop_invariants が導入されたが、このケースは invariants 以前の問題(可変ステップ)
- Phase 254-256 の流れで Pattern 6 → Pattern 7 の自然な進化が期待される
- split/tokenization は一般的なパターンなので、汎用的な解決策が望ましい