Phase 259 P0: Pattern8 (BoolPredicateScan) 完全完了 is_integer/1 を Pattern8 で受理し、VM/LLVM EXE 両方で動作確認完了。 次の大工事(block-parameterized CFG への移行)前のマイルストーンとして記録。 ## Key Fixes Applied 1. **skipped_entry_redirects** (instruction_rewriter.rs) - k_exit のスキップ時、entry block 参照を exit_block_id へリダイレクト - BasicBlockId not found エラーを根治 2. **loop_var_name** (pattern8_scan_bool_predicate.rs) - merge_entry_block 選択に使用(`Some(parts.loop_var.clone())`) - 未設定時の誤った entry block 選択を修正 3. **loop_invariants** (pattern8_scan_bool_predicate.rs) - PHI-free 不変量パラメータ(`[(me, me_host), (s, s_host)]`) - loop_var_name 設定時、BoundaryInjector が join_inputs Copy を全スキップするため必要 - Pattern6 と同じ設計(header PHI で不変量を保持) 4. **expr_result** (pattern8_scan_bool_predicate.rs) - k_exit からの返り値を明示設定(`Some(join_exit_value)`) - Pattern7 style(推測ではなく明示) 5. **Smoke test scripts** - set +e パターンで exit code 7 をキャプチャ - LLVM EXE スクリプトにコメント追加(tools/build_llvm.sh 経由の明記) ## Contract Documentation - join-explicit-cfg-construction.md に Pattern8 契約の具体例を追加 - "pattern増でも推測増にしない" の実例として記録 - loop_var_name / loop_invariants / expr_result / jump_args_layout の契約を明示 - 20-Decisions.md に正規化(Semantic/Plumbing)の分離方針を追記 - DOCS_LAYOUT.md に重要ドキュメントへの参照を追加 ## Test Results - ✅ VM smoke test: `[PASS] phase259_p0_is_integer_vm` (exit 7) - ✅ LLVM EXE: tools/build_llvm.sh 経由で exit 7 確認 - ✅ --verify: PASS ## Next FAIL (Phase 260+) - Function: `Main.main/0` in `apps/examples/json_lint/main.hako` - Error: `[cf_loop/pattern2] Failed to extract break condition from loop body` - Pattern: Nested loop(外側 loop + 内側 loop with break) 🚀 次の大工事: block-parameterized CFG への移行を開始します。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
3.7 KiB
3.7 KiB
Status: ✅ P0 Complete
Scope: StringUtils.is_integer/1(nested-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)
P0 Result (2025-12-21)
- is_integer/1: Pattern8 で認識・実行成功 ✅
- VM smoke test:
[PASS] phase259_p0_is_integer_vm✅ - Exit code: 7(is_integer("123") == true)
- json_lint_vm: まだ FAIL(別問題: nested-loop with break / Pattern2)
Key Fixes Applied
expr_result = Some(join_exit_value)- Pattern7 style で明示設定loop_var_name = Some(parts.loop_var.clone())- merge_entry_block 選択用loop_invariants = [(me, me_host), (s, s_host)]- PHI-free 不変量パラメータskipped_entry_redirects- k_exit のスキップ時ブロック参照リダイレクト
Current Status (SSOT)
- ✅ is_integer/1 は Pattern8 で解決
- ❌ json_lint_vm は別の nested-loop with break パターンで失敗中(Phase 260+)
Next FAIL (Phase 260+)
- Function:
Main.main/0inapps/examples/json_lint/main.hako - Error:
[cf_loop/pattern2] Failed to extract break condition from loop body - Pattern: Nested loop(外側
loop(i < cases.length())内で内側loop(j < valid.length())+ break) - AST Structure:
loop(i < cases.length()) { local s = ... local ok = 0 local j = 0 loop(j < valid.length()) { // ← 内側ループ if (s == valid.get(j)) { ok = 1 break // ← Pattern2 が抽出失敗 } j = j + 1 } if (ok == 1) { print("OK") } else { print("ERROR") } i = i + 1 } - Reproduce:
./target/release/hakorune --backend vm apps/examples/json_lint/main.hako - 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
- prelude: nested-if to compute
Goal
StringUtils.is_integer/1を JoinIR で受理し、quick の first FAIL を次へ進める
Proposed Approach (P0)
P0 Design Decision: Pattern8(新規)採用
Why Pattern8?
Pattern6(index_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: ExprResultPlusCarriers(carriers=0)
- expr_result: Some(join_exit_value) - ret_bool from k_exit (pipeline handling)
- exit_bindings: Empty(carriers なし)
- 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 call(this.is_digit)のみ
- step は 1 固定