# Phase 124: Reads Facts SSOT + Return(Variable) 解禁 (dev-only) ## 目的 StepTreeFacts に `reads` フィールドを追加し、Normalized側が「変数return/cond」を再解析なしで扱えるようにする。 ## 背景 現在、Normalized builder は writes のみを env として持ち、`Return(Variable(name))` が来たときに name が env に無いと処理できない。Phase 123 では `Return(Unknown)` を導入したが、これは "値が決まらない" 場合であり、「変数名は分かっているが env に無い」ケースとは異なる。 Phase 124 では、StepTreeFacts に reads を追加し、変数参照を明示的に記録することで、Normalized側が「この変数は読まれている」という情報を持てるようにする。 ## 方針 ### reads の収集範囲 - **Variable(name)**: 式中の変数参照は reads に追加 - **Assign の RHS**: 代入の右辺に出てくる Variable も reads に追加 - **条件式**: cond_ast / cond_sig 内の Variable も reads に追加(式の意味解析は不要、構文木から拾う) ### reads の扱い - reads は「識別できた local 名だけ」でOK - 不明な読み込みは capability/unknown-read に落とす(Phase 125以降で対応) - reads は BTreeSet で決定的にソート - StepTreeContract の signature に含める(basis string に影響) ### Return(Variable) の実装 - Normalized builder で Return(Variable(name)) を処理 - name が env にあるなら env から値を取り `Ret(Some(v))` - env に無いが reads にあるなら Phase 124 では Fail-Fast にする - **dev-only**: `NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1` でのみ動作 - env に無い return var は strict モードで `freeze_with_hint` を呼び出してエラー ## 実装計画 ### P1: StepTreeFacts に reads を追加 - `src/mir/control_tree/step_tree_facts.rs` - `reads: BTreeSet` 追加 - API: `add_read(name)` / `merge_reads()` - `src/mir/control_tree/step_tree.rs`(または facts builder) - Variable(name) を見たら `add_read(name)` - Assign は writes に入れるが、RHS 内の Variable は reads として拾う - 条件式(cond_ast / cond_sig)も "Variable が出たら reads" に入れる ### P2: StepTreeContractBox に reads を反映 - `src/mir/control_tree/step_tree_contract_box.rs` - `StepTreeContract` に reads を追加(順序は決定的) - `signature_basis_string()` に reads を含める(BTreeSet の順で安定) ### P3: Normalized builder で Return(Variable) を実装 - `src/mir/control_tree/normalized_shadow/builder.rs` - Return(Variable(name)): - name が env にあるなら env から値を取り `Ret(Some(v))` - env に無いが reads にあるなら Phase 124 では Fail-Fast にする - **dev-only**: `NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1` でのみ動作 - env に無い return var は strict モードで `freeze_with_hint` を呼び出してエラー - unit test: `x=7; return x` が生成できる ### P4: integration smoke - fixture: `apps/tests/phase124_if_only_return_var_min.hako`(expected 7) - `local x = 7; return x` - smoke: `tools/smokes/v2/profiles/integration/apps/phase124_if_only_return_var_vm.sh` - `NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1` で PASS 固定 ### P5: docs 完了 - `docs/development/current/main/10-Now.md` / INDEX / backlog 更新 ## 受け入れ基準 - [ ] StepTreeFacts に reads が追加される - [ ] StepTreeContract の signature に reads が含まれる - [ ] Normalized builder で Return(Variable) が処理できる(dev-only) - [ ] integration smoke が PASS する - [ ] 既存テストが全て PASS する(signature 変更によるテスト更新は許容) ## 制約事項 - **dev-only**: `NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1` でのみ動作 - **既定挙動は不変**: 環境変数無しでは従来通り(Phase 123 まで) - **Fail-Fast 原則**: env に無い return var は strict モードでエラー ## 次のステップ(Phase 125以降) - unknown-read capability の導入 - reads に基づく環境拡張(env に無い変数を reads から補完) - loop との統合(loop 内の reads を継続的に追跡) ## 参照 - Phase 123: Return(Unknown) 導入 - Phase 121: Shadow If Only 基本実装 - Phase 118: Loop Nested If Merge