feat(loop-phi): Phase 25.1c/k - continue_merge PHI生成完了

## 実装内容

### 1. continue_merge ブロックで PHI ノード生成
- `src/mir/loop_builder.rs` (422-557行)
- 複数の continue パスからの変数値を PHI でマージ
- 全て同じ値なら PHI 省略(最適化)
- merged_snapshot を seal_phis に渡す構造

### 2. ValueId::INVALID GUARD 修正
- `src/mir/phi_core/loopform_builder.rs` (111行)
- 誤った `value.0 == 0` チェックを `value == ValueId::INVALID` に修正
- ValueId::INVALID は u32::MAX なので、ValueId(0) は有効な値

### 3. test_loopform_builder_separation を構造ベースに改善
- 具体的な ValueId(100..105) を期待するアサーションを削除
- pinned/carrier の分離、ValueId の有効性、衝突チェックに変更
- HashMap の反復順序や内部の割り当て順に依存しないテストに改善

## テスト結果

 **既存テスト全て PASS**:
- `test_loopform_builder_separation` - 構造ベース修正で PASS
- 既存ループ関連テスト15個 - 全て PASS
- `mir_stageb_loop_break_continue::*` - PASS
- `mir_loopform_exit_phi::*` - PASS

 **実行確認**:
- 基本的なループ実行 - 正常動作(sum=10)
- continue を含むループ実行 - 正常動作(sum=8)
- continue_merge ブロック生成確認(BasicBlockId表示)

⚠️ **残存バグ**:
- FuncScannerBox.scan_all_boxes/1: ValueId(1283) undefined
- 13個の continue を持つ複雑なループで発生
- Phase 25.2 リファクタリングで解決予定

## 今後の予定

Phase 25.2 として以下のリファクタリングを実施予定:
1. LoopSnapshotMergeBox 実装(優先度1)
2. LoopVarClassifyBox 実装(優先度2)
3. LoopDebugLogBox 実装(優先度3)
4. TextScanRegionBox 実装(優先度4)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-20 01:41:17 +09:00
parent 7c3f1eafde
commit 7373fa265b
3 changed files with 190 additions and 24 deletions

View File

@ -0,0 +1,57 @@
// funcscanner_fib_min.hako — FuncScannerBox + LoopForm v2 minimal harness
//
// 目的:
// - StageB を経由せず、「FuncScannerBox.scan_all_boxes/1 + LoopForm v2」のみで
// fib 風ソースをスキャンしたときの挙動を固定再現する。
// - Undefined ValueIdloop/continue + PHI 周り)の問題を、この箱単体で観測できるようにする。
//
// 振る舞い:
// - fib サンプルと同等の static box TestBox/Main を src に埋め込む。
// - FuncScannerBox.scan_all_boxes(src) を呼び出し、defs の数と box/name をログに出す。
// - VM 側で NYASH_VM_VERIFY_MIR=1 を付与して実行することで、
// LoopForm v2 / FuncScannerBox 周辺の Undefined Value を構造的に追えるようにする。
using lang.compiler.entry.func_scanner as FuncScannerBox
static box Main {
method main(args) {
// stageb_fib_program_defs_canary_vm.sh と同等の fib 用ソースを組み立てる
local src = ""
src = src + "static box TestBox {\n"
src = src + " method fib(n) {\n"
src = src + " local i = 0\n"
src = src + " local a = 0\n"
src = src + " local b = 1\n"
src = src + " loop(i < n) {\n"
src = src + " local t = a + b\n"
src = src + " a = b\n"
src = src + " b = t\n"
src = src + " i = i + 1\n"
src = src + " }\n"
src = src + " return b\n"
src = src + " }\n"
src = src + "}\n\n"
src = src + "static box Main {\n"
src = src + " method main(args) {\n"
src = src + " local t = new TestBox()\n"
src = src + " return t.fib(6)\n"
src = src + " }\n"
src = src + "}\n"
// FuncScannerBox を直接呼び出して defs を収集
local defs = FuncScannerBox.scan_all_boxes(src)
local n = defs.length()
print("[funcscanner/fib_min] defs.len=" + ("" + n))
// 各定義の box/name をダンプStageB FuncScanner と比較しやすくする)
local i = 0
loop(i < n) {
local d = defs.get(i)
print("[funcscanner/fib_min] def[" + ("" + i) + "] box=" + ("" + d.get("box")) + " name=" + ("" + d.get("name")))
i = i + 1
}
return 0
}
}