Files
hakorune/docs/development/current/main/phases/phase-259
tomoaki a767f0f3a9 feat(joinir): Phase 259 P0 - Pattern8 BoolPredicateScan + Copy binding fix
Pattern8 (Boolean Predicate Scan) implementation for is_integer/1:
- New pattern detection for `loop + if not predicate() { return false }`
- JoinIR lowerer with main/loop_step/k_exit structure
- Me receiver passed as param (by-name 禁止)

Key fixes:
1. expr_result = Some(join_exit_value) (Pattern7 style)
2. Tail-call: dst: None (no extra Ret instruction)
3. instruction_rewriter: Add `&& is_loop_header_with_phi` check
   - Pattern8 has no carriers → no PHIs → MUST generate Copy bindings
   - Without this, ValueId(103/104/105) were undefined

Status: Copy instructions now generated correctly, but exit block
creation issue remains (next step: Step A-C in指示書).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 02:40:07 +09:00
..

Status: Active
Scope: StringUtils.is_integer/1nested-if + loopを JoinIR で受理して --profile quick を進める。
Related:

  • Now: docs/development/current/main/10-Now.md
  • Phase 258: docs/development/current/main/phases/phase-258/README.md
  • Design goal: docs/development/current/main/design/join-explicit-cfg-construction.md

Phase 259: StringUtils.is_integer/1 (nested-if + loop)

Current Status (SSOT)

  • Current first FAIL: json_lint_vm / StringUtils.is_integer/1
  • Shape summaryログ由来:
    • prelude: nested-if to compute start (handles leading "-")
    • loop: loop(i < s.length()) { if not this.is_digit(s.substring(i, i+1)) { return false } i = i + 1 }
    • post: return true
    • caps: If,Loop,NestedIf,Return

Goal

  • StringUtils.is_integer/1 を JoinIR で受理し、quick の first FAIL を次へ進める

Proposed Approach (P0)

P0 Design Decision: Pattern8新規採用

Why Pattern8?

Pattern6index_of系は "見つける" scan返り値: 整数 i or -1で、is_integer は "全部検証する" predicate scan返り値: 真偽値 true/false。役割が異なるため、Pattern8 として分離した。

Pattern8 vs Pattern6

Pattern6 (index_of系) Pattern8 (is_integer系)
役割 "見つける" scan "全部検証する" predicate scan
Match形 substring(...) == needle not predicate(ch) → early exit
返り値 Integer (i or -1) Boolean (true/false)
Exit PHI i(ループ状態変数) ret_bool(検証結果)
Carriers [i] (LoopState) [] (empty, expr_result のみ)

JoinIR Contract

  • jump_args_layout: ExprResultPlusCarrierscarriers=0
  • expr_result: Some(join_exit_value) - ret_bool from k_exit (pipeline handling)
  • exit_bindings: Emptycarriers なし)
  • SSOT: join_inputs = entry_func.params.clone()
  • Me receiver: Passed as param [i, me, s] (by-name 禁止)

受理形P0固定

loop(i < s.length()) {
    if not this.is_digit(s.substring(i, i + 1)) {
        return false
    }
    i = i + 1
}
return true
  • prelude の start 計算は許可(ただし i_init = start で渡す)
  • predicate は Me method callthis.is_digitのみ
  • step は 1 固定