Files
hakorune/docs/development/current/main/phases/phase-259/README.md

106 lines
3.7 KiB
Markdown
Raw Normal View History

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>
2025-12-21 03:21:22 +09:00
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)
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>
2025-12-21 03:21:22 +09:00
## 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)
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>
2025-12-21 03:21:22 +09:00
- ✅ 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 }`
- 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固定
```nyash
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 固定