feat(joinir): Phase 259 P0 complete - Pattern8 final fixes + docs (pre-block-params migration)

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>
This commit is contained in:
2025-12-21 03:21:22 +09:00
parent a767f0f3a9
commit 4496b6243d
9 changed files with 253 additions and 19 deletions

View File

@ -1,5 +1,5 @@
Status: Active
Scope: `StringUtils.is_integer/1`nested-if + loopを JoinIR で受理して `--profile quick` を進める。
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`
@ -7,9 +7,51 @@ Related:
# 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**: 7is_integer("123") == true
- **json_lint_vm**: まだ FAIL別問題: nested-loop with break / Pattern2
### Key Fixes Applied
1. `expr_result = Some(join_exit_value)` - Pattern7 style で明示設定
2. `loop_var_name = Some(parts.loop_var.clone())` - merge_entry_block 選択用
3. `loop_invariants = [(me, me_host), (s, s_host)]` - PHI-free 不変量パラメータ
4. `skipped_entry_redirects` - k_exit のスキップ時ブロック参照リダイレクト
## Current Status (SSOT)
- Current first FAIL: `json_lint_vm / StringUtils.is_integer/1`
- ✅ is_integer/1 は Pattern8 で解決
- ❌ json_lint_vm は別の nested-loop with break パターンで失敗中Phase 260+
### 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(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**:
```bash
./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 }`