Files
hakorune/docs/development/roadmap/phases/phase-25.1k/README.md
nyash-codex 39f5256c18 📊 Phase 25.1l: Region観測レイヤー骨格 + スコープ契約設計理解
**Region Box統一理論の実装開始**

新規追加:
- src/mir/region/mod.rs: Region/RefSlotKind型定義
- src/mir/region/observer.rs: Region観測レイヤー
- docs/development/roadmap/phases/phase-25.1l/: 設計ドキュメント

主要概念:
- Region Box = Function/Loop/If の統一箱
- RefSlotKind = GC管理用スロット種別(Strong/Weak/Borrowed/NonRef)
- 観測専用(NYASH_REGION_TRACE=1で動作、挙動変更なし)

設計理解の深化:
- ValueId(40)問題 = LoopForm v2スコープ契約違反の症状
- 根本解決 = Region観測で無名一時値のスコープまたぎを検出
- 箱理論3原則: 境界明確化/差し替え可能/段階的移行

関連議論:
- ChatGPT提案: Region統一理論でGC/寿命管理の基盤構築
- SlotRegistry: 変数の単一真実源(SSOT)
- 階層構造: FunctionRegion → LoopRegion → IfRegion

次のステップ:
- Phase 1: Region観測(現在)- 非破壊的追加
- Phase 2: メタデータ出力(MIR JSON拡張)
- Phase 3: GC統合(retain/release挿入)

テスト追加:
- lang/src/compiler/tests/stageb_mini_driver.hako
- tools/test_loopssa_breakfinder_slot.sh

Build:  全警告は既存のもの
Tests: 既存テスト全て緑維持
2025-11-19 02:44:40 +09:00

107 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 25.1k — LoopSSA v2 実装 & StageB SSA 安定化(.hako 本体版)
Status: in progress.hako 側 LoopSSA v2 本体実装Rust 側は既存 SSA/PHI を SSOT として維持)
## ゴール
- 25.1j までに固めた LoopSSA/BreakFinderBox/PhiInjectorBox の責務・設計をベースに、
`.hako` 側 LoopSSA v2 の **実装本体** に踏み込むフェーズだよ。
- 具体的には:
- StageB minimal harness`tools/test_stageb_min.sh`)の Test 2/3 で出ている:
- Test 2: `.hako` StageB コンパイラ(`compiler_stageb.hako`)が `stageb_min_sample.hako` をコンパイルする
**「.hako パーサStageB コンパイラ経路FuncScanner / LoopSSA / BreakFinderBox / PhiInjectorBox」** での Rust VM エラー
`BreakFinderBox.find_breaks/2``_find_loops/2` の receiver 未定義 `use of undefined value ValueId(..)`
- Test 3: 同テストファイルを Rust MIR ビルダーで実行したときの `%0` 由来 SSA エラー(`NYASH_VM_VERIFY_MIR=1` 時)
**LoopSSA v2 の改善によって減らす/消す** ことを狙うRust 側 LoopForm v2 / Conservative PHI Box は既に緑で SSOT 済み)。
- 文字列ハードコードベースの `_collect_phi_vars` / synthetic `"r{block}_{var}"` を、
Carrier/Pinned ベースの設計に一歩近づける(完全置き換えまでは行かなくても OK
- Rust 側 LoopForm v2 / Conservative PHI Box は SSOT として維持し、.hako 側 LoopSSA v2 は dev トグルで常時検証しつつ徐々に寄せていく。
## 前提25.1j までで揃っているもの)
- Rust 側:
- LoopForm v2 + Conservative PHI Box + ControlForm が統合済みで、If/Loop の SSA/PHI は緑。
- StageB 風ループRust テスト)も LoopForm v2 / Conservative PHI で安定している。
- `.hako` 側:
- LoopSSA パス:
- `LoopSSA.stabilize_merges(stage1_json)``BreakFinderBox.find_breaks(json, trace_flag)`
`PhiInjectorBox.inject_exit_phis(json, breaks, trace_flag)` の 2 段構成で動作。
- trace/ENV 解釈は LoopSSA に一元化され、下流には 0/1 の `trace_flag` だけ渡す構造に整理済み。
- BreakFinderBox:
- `_find_loops(json_str, trace)``"loop_header":` / `"loop_exit":` から loop を検出。
- `loop_info``{"header", "exit", "body", "control"}` を格納し、`control` に ControlFormBox を添付。
- PhiInjectorBox:
- 現状は `common_vars = ["i","n","item","j","count","val"]` に対する簡易版 `_collect_phi_vars`
- value_id は `"r{block_id}_{var_name}"` 形式の synthetic 値(観測用のダミー)を返している。
- ドキュメント:
- 25.1j の README で LoopSSA/BreakFinderBox/PhiInjectorBox の責務境界と Carrier/Pinned/Invariants 概念を明文化済み。
## 方針25.1k: LoopSSA v2 の「中身」を少し前に進める)
### KA: StageB Test2 の ValueId(50) 問題の最小再現と LoopSSA 切り分け
- 目的:
- `BreakFinderBox._find_loops/2` で発生している `use of undefined value ValueId(50)`(現在は 46→39 と推移中)を、
「LoopSSA / BreakFinderBox が生成した JSON / MIR の問題なのか」「それ以前の StageB パイプラインの問題なのか」切り分ける。
- ステップ:
1. `tools/test_stageb_min.sh` Test2 の Program(JSON v0) 出力を一時ファイルに保存StageB → Program(JSON v0) 直後)。
2. その JSON に対して:
- Rust 側 MirBuilder / LoopForm v2 / Conservative PHI を使って `NYASH_VM_VERIFY_MIR=1` を通し、Rust 側 SSA/PHI の健全性を確認する。
- `.hako` 側 LoopSSA を単独で呼び出す(`LoopSSA.stabilize_merges(json)`最小ハーネスを用意し、BreakFinderBox / PhiInjectorBox の前後で JSON を比較。
3. どの時点で `BreakFinderBox._find_loops/2` の receiver が「定義のない pinned ValueId例: 39/46/50」になるかを特定し、
LoopSSA v2 の変更前後で挙動が悪化していないかを確認する。
### KB: BreakFinderBox の LoopScope 精度の向上(保守的に)
- 目的:
- `_find_loop_body` の「header_id < id < exit_idヒューリスティックが過剰/過少に body を拾っていないかを確認改善する
- ステップ:
- ControlFormBox を活用して LoopScope の妥当性をチェック:
- header/exit/body に対して Rust LoopForm v2 の期待と比較しやすい形でログを出すblock id 範囲など)。
- 必要であれば:
- body 集合をexit から逆到達できる blockなどより保守的な条件に修正文字列ベースの範囲内で)。
- ゴール:
- LoopSSA 本来そのループに属さない block body に含めないようにするValueId(50) のような飛び火を防ぐ)。
### KC: PhiInjectorBox の v2 への一歩Carrier/Pinned の入口だけ作る)
- 目的:
- `_collect_phi_vars` の完全置き換えまでは行かずに今後の移行先となる v2 API の入口を整える
- ステップ:
- `PhiInjectorBox` に新しい内部ヘルパーを追加例: `_collect_phi_vars_v2(json_str, break_list, loop_info)`:
- まだ中身は stub でもよいが、「Carrier/Pinned/Invariants 3 区分を引数/戻り値で表現できる形にする
- 25.1k では v1 実装`_collect_phi_vars`を実際に置き換えずtrace=1 の時だけ v2 の診断ログを出すくらいに留める
- `loop_info.get("control")` ControlFormBox から header/exit/body を読み取り
どの変数が本来の Carrier に相当しそうかをログに出すまだ PHI には使わない)。
### KD: StageB Test3 (%0) の「悪化していない」ことの確認
- 目的:
- LoopSSA v2 の変更がStageB Test3 `%0` SSA 問題を悪化させていないことを確認する
- ステップ:
- `NYASH_VM_VERIFY_MIR=1` Test3 を流したときのエラー位置関数名/ブロック/命令を記録
- 25.1k の差分適用前後で比較しLoopSSA 関連の変更による新規エラーが出ていないことを確認
- 必要ならTest3 から LoopSSA を一時オフ`HAKO_LOOPSSA_EXIT_PHI=0`にした場合のログも取っておき
LoopSSA が原因の部分それ以外を明確に切り分ける
### KE: デバッグ用ハーネス・プリセットの整備
- 目的:
- LoopSSA/BreakFinderBox/PhiInjectorBox 周辺をデバッグしやすくするための共通の足場を用意し
25.1k 以降の作業で毎回同じ ENV/コマンドを手で組み立てなくて済むようにする
- 実装メモ:
- `tools/stageb_loopssa_debug.sh`:
- StageB 最小ハーネス `tools/test_stageb_min.sh` LoopSSA v2 デバッグ向けの ENV プリセット
`HAKO_LOOPSSA_EXIT_PHI=1`, `HAKO_COMPILER_BUILDER_TRACE=1`, `NYASH_VM_TRACE=1`,
`NYASH_LOCAL_SSA_TRACE=1`, `NYASH_BUILDER_TRACE_RECV=1` など付きで実行する小さなラッパ
- `lang/src/compiler/tests/loopssa_breakfinder_slot.hako` + `tools/test_loopssa_breakfinder_slot.sh`:
- Program(JSON v0) を直接文字列として持つ LoopSSA ハーネス現在は最小緑 JSON将来は StageB Test2 から抽出した失敗 JSON を貼り付けるスロットとして運用)。
- `HAKO_LOOPSSA_EXIT_PHI=1` LoopSSA v2 / BreakFinderBox / PhiInjectorBox の経路だけを通しValueId(..) 問題を StageB 抜きで再現できるようにする
## このフェーズで「しない」こと
- PhiInjectorBox `_collect_phi_vars` / `_get_var_value` **完全刷新すること**:
- これは 25.1k の次25.1l 以降の本格 v2 実装のタスクとして分ける
- Rust LoopForm v2 / Conservative PHI の設計を変えること:
- Rust 側はあくまで SSOT であり、.hako 側はそれに追従する形で徐々に近づける