feat(joinir): Phase 200-A ConditionEnv extension infrastructure

Added type and skeleton infrastructure for function-scoped variable
capture, preparing for Phase 200-B integration with ConditionEnv.

New Types:
- CapturedVar: { name, host_id, is_immutable }
- CapturedEnv: Collection of captured variables
- ParamRole: { LoopParam, Condition, Carrier, ExprResult }

New Functions (Skeletons):
- analyze_captured_vars(): Detects function-scoped "constants"
- build_with_captures(): ConditionEnvBuilder v2 entry point
- add_param_with_role(): Role-based parameter routing

New File:
- src/mir/loop_pattern_detection/function_scope_capture.rs

Design Principles:
- Infra only: Types and skeletons, no behavior changes
- Existing behavior maintained: All current loops work identically
- Box-first: New responsibilities in new file
- Documentation: Future implementation plans in code comments

Test Results:
- 6 new unit tests (function_scope_capture: 3, param_role: 3)
- All 804 existing tests PASS (0 regressions)

Next: Phase 200-B (actual capture detection and integration)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-09 16:19:08 +09:00
parent f47fa9a7a8
commit 3a9b44c4e2
7 changed files with 914 additions and 1 deletions

View File

@ -49,10 +49,23 @@ JoinIR ラインで守るべきルールを先に書いておくよ:
- 現状は ConditionBinding/ExitMeta/JoinFragmentMeta で役割を区別しており、将来 ParamRole enum として明示する予定。
8. **LoopHeader PHI dst は予約領域(上書き禁止)**
- LoopHeaderPhiBuilder が生成したヘッダ PHI の dst ValueId は「現在のループ値」の SSOT として扱い、
- LoopHeaderPhiBuilder が生成したヘッダ PHI の dst ValueId は「現在のループ値」の SSOT として扱い、
BoundaryInjector や InstructionRewriter が `Copy` などで二度書きすることを禁止する。
- merge ラインでは「ヘッダ PHI dst に対する新しい定義が出てきたら debug モードで panic する」ことで契約違反を早期検出する。
9. **ParamRole の不変条件Phase 200-A 追加)**
- **Condition 役のパラメータは「PHI dst にしてはいけない」**
- 理由: 条件専用変数はループ内で更新されない(例: `digits` in `_atoi()`
- LoopHeaderPhiBuilder は Condition 役の変数に対して header PHI を生成しない
- **Condition 役のパラメータは「ExitLine の対象にも入れない」**
- 理由: 条件専用変数はループ外で使われない(ループ内でのみ参照)
- ExitLineReconnector は Condition 役の変数を exit_bindings から除外
- **ParamRole の分類**:
- `LoopParam`: ループ制御変数(例: `i` in `loop(i < len)`)→ header PHI + exit_bindings
- `Condition`: 条件専用変数(例: `digits` in `digits.indexOf(ch)`)→ condition_bindings のみ
- `Carrier`: 状態更新変数(例: `sum`, `count`)→ header PHI + exit_bindings
- `ExprResult`: ループ戻り値 → exit_phi_builder で処理
---
## 2. 主な箱と責務
@ -262,6 +275,35 @@ JoinIR ラインで守るべきルールを先に書いておくよ:
- `verify_joinir_contracts()`: merge_joinir_mir_blocks() の最後で全契約を一括チェック。
- release ビルドでは完全に除去される(`#[cfg(debug_assertions)]`)。
- **FunctionScopeCaptureAnalyzer / CapturedEnvPhase 200-A 追加)**
- ファイル: `src/mir/loop_pattern_detection/function_scope_capture.rs`
- 責務:
- 関数スコープで宣言され、ループ内で不変な変数("実質定数")を検出。
- 例: `local digits = "0123456789"` in `JsonParser._atoi()`
- CapturedVar: `{ name, host_id, is_immutable }`
- CapturedEnv: 検出された変数のコレクション
- **Phase 200-A**: 型と空実装のみskeleton
- **Phase 200-B**: 実際の検出ロジックを実装予定AST スキャン + 再代入チェック)。
- **ParamRole enumPhase 200-A 追加)**
- ファイル: `src/mir/join_ir/lowering/inline_boundary_builder.rs`
- 責務:
- JoinInlineBoundary のパラメータ役割を明示的に区別。
- LoopParam / Condition / Carrier / ExprResult の 4 種類。
- **不変条件**:
- **Condition 役**: PHI dst にしてはいけない(ループ内で更新されない)。
- **Condition 役**: ExitLine の対象にも入れない(ループ外で使われない)。
- 理由: 条件専用変数(例: `digits`)はループ内でのみ参照され、不変。
- **Phase 200-A**: enum 定義のみ。
- **Phase 200-B**: ルーティングロジック実装予定CapturedEnv 統合時)。
- **ConditionEnvBuilder::build_with_capturesPhase 200-A 追加)**
- ファイル: `src/mir/builder/control_flow/joinir/patterns/condition_env_builder.rs`
- 責務:
- 将来 CapturedEnv を受け取り、ConditionEnv に統合する v2 入口。
- **Phase 200-A**: 既存実装に委譲する skeleton。
- **Phase 200-B**: CapturedEnv の変数を condition_bindings に追加する実装予定。
### 2.4 expr result ライン(式としての戻り値)
- **exit_phi_builder**