Files
hakorune/docs/development/current/main/phases/phase-256
tomoaki 64f679354a fix(joinir): Phase 256 P1 - Carrier PHI wiring and parameter mapping (in progress)
**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>
2025-12-20 01:24:04 +09:00
..

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
}

分析

ループ構造

  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 256 指示書P0

目標

  • StringUtils.split/2 の loop を JoinIR で受理し、json_lint_vm を PASS に戻す。
  • by-name 分岐禁止(StringUtils.split/2 だけを特別扱いしない)。
  • workaround 禁止fallback は作らない)。

推奨方針P0

Option APattern 7 新設)を推奨。

理由:

  • 可変 stepthen: i = start / else: i = i + 1)は既存の ConstStep 前提と相性が悪い。
  • Pattern 2 を膨らませず、tokenization 系の “専用パターン” として箱化した方が責務が綺麗。

P0 タスク

  1. 最小 fixture + v2 smokeintegration
  • apps/tests/phase256_p0_split_min.hako
  • tools/smokes/v2/profiles/integration/apps/phase256_p0_split_vm.sh
  • tools/smokes/v2/profiles/integration/apps/phase256_p0_split_llvm_exe.sh
  1. 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” がある(任意だがあると精度が上がる)
  1. 抽出箱Parts
  • i / start / result / s / separator を抽出
  • then/else の更新式(可変 step と const stepを抽出
  1. JoinIR lowerer専用
  • loop_state: i, start
  • invariants: s, separator, resultresult は更新されるので carrier 扱いが必要なら role を明確に)
  • then/else で異なる i_nextSelect もしくは branch で表現(設計 SSOT は JoinIR 側で決める)
  1. 検証
  • 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 は一般的なパターンなので、汎用的な解決策が望ましい