# JoinIR Plan/Frag SSOT Documentation

**Status**: Active (2025-12-25)
**Phase**: Phase 286 P0 (docs-only)
**Purpose**: Single Source of Truth for Plan/Frag responsibilities, prohibitions, and freeze points

---

## 目標

JoinIR line を Plan/Frag に吸収する前提で、**責務・禁止事項・凍結点（freeze points）**をSSOTとして1ページに固定する。

「2本コンパイラ根治（VM/LLVM）」の合流点が明文化されていること。

---

## 1. Scope / Non-goals

### 対象（Scope）
- JoinIR line（Pattern1-9）における Plan → Frag → MIR merge の限定されたパイプライン
- Plan と Frag の境界における責務分離
- VM/LLVM 両コンパイラでの共通契約

### 対象外（Non-goals）
- MIR実行・VM/LLVM固有の最適化
- JoinIR外のlowering（AST → MIR 全体ではなく、限定されたパイプラインのみ）

---

## 2. 用語（Terms）

| 用語 | 定義 |
|------|------|
| **JoinIR line** | (Pattern detection/Plan) → (Frag+Boundary) → (MIR merge) の限定されたパイプライン |
| **Plan** | パターン抽出・正規化フェーズ（DomainPlan → CorePlan） |
| **Frag** | フラグメント生成・エミットフェーズ（JoinModule + JoinFragmentMeta） |
| **Boundary** | JoinInlineBoundary（host↔JoinIR 変数マッピング） |
| **ExitKind** | 継続の種類（Return/Break/Continue/Kont） |
| **Freeze point** | 以降変更が禁止される確定ポイント |
| **SSOT** | Single Source of Truth（唯一の情報源） |

**注記**: JoinIR line は AST → MIR 全体ではなく、上記の限定された範囲を指す（JoinIR外のloweringは含まない）。

---

## 3. 責務（Responsibilities）

### Planが決めること

Plan 段階では以下を決定する：

- **パターン識別**: どのパターン（Pattern1-9）か
- **制御フロー構造**: ループ/if/try/scan の構造
- **キャリア変数**: ループ間で保持される変数
- **継続構造**: k_exit / k_continue の境界
- **ValueId 割り当て**: JoinIRローカルのValueId（host ValueId と衝突しない領域）

### Planが決めないこと

Plan 段階では以下を決定しない（Frag側の責務）：

- **ホスト変数**: host inputs の ValueId はFrag側で決定
- **最終的な命令列**: Copy命令の注入はFrag側
- **PHI構造**: header/exit PHIの最終構造はFrag側

### Fragが保持すること

Frag 段階では以下を保持する：

- **JoinInlineBoundary**: host↔JoinIR の全マッピング情報
- **JoinFragmentMeta**: expr_result / exit_meta / continuation_funcs
- **terminator SSOT**: emit_frag() を唯一のterminator生成ポイント

### Fragが保持しないこと

Frag 段階では以下を保持しない（Plan側の責務）：

- **パターン知識**: Pattern1-9 の違いを知らない（CorePlanのみ処理）
- **AST情報**: AST構造には直接アクセスしない

---

## 4. 禁止事項（Prohibitions - 最重要）

| 禁止事項 | 理由 |
|----------|------|
| **Planでの実行** | Planは純粋なデータ構造 |
| **Planでの名前解決** | 名前解決はFrag側 |
| **Planでの最適化** | Planは構造のみ記述 |
| **Planでのルール実装** | ルールはFrag側で実装 |
| **Fragでのパターン識別** | パターン知識はPlan側 |
| **明示的でないValueIdマッピング** | 全てBoundary経由 |
| ** terminator の多様な生成ポイント** | emit_frag() SSOT |
| **freeze point 以降の変更** | 不変条件違反 |

### 診断専用の扱い

開発中のデバッグ出力・トレースログは、debugタグ付き（既定OFF）でのみ許可。

### 実装注記（ValueId領域）

現状の実装では JoinIR-local ValueId として 100-999 領域を使用しているが、これは実装詳細であり変更されうる。SSOT としての原則は「host ValueId と衝突しない領域を使う」である。

---

## 5. 凍結点（Freeze Points）

| Stage | 凍結されるもの | 以降禁止される操作 |
|-------|----------------|-------------------|
| **PlanFreeze** (V1-V9) | CorePlanの構造 | Plan構造の変更 |
| **BoundaryFreeze** | JoinInlineBoundaryの全フィールド | Boundaryマッピングの変更 |
| **ValueIdAllocate** | JoinIRローカルValueId（hostと非衝突領域） | 領域の再割り当て |
| **MergeComplete** | MIR block構造 | CFGの変更 |

---

## 6. 不変条件（Invariants / Fail-Fast）

### Plan段階の不変条件

- **V1**: 条件のValueIdは有効（pre-generated）
- **V2**: Exitの妥当性（Returnは関数内、Break/Continueはループ内）
- **V3**: Seqは非空
- **V4**: Ifのthen_plansは非空
- **V5**: ループはキャリアを1つ以上持つ
- **V6**: Frag entryはheader_bbを指す
- **V7**: block_effectsにheader_bbが含まれる
- **V10**: body_bbのeffectsはloop_plan.bodyに積む（block_effects[body_bb]は空でなければならない）
  - Phase 286 P2.7 追加: lowererはloop_plan.bodyをbody_bbにemitし、block_effectsのbody_bbは無視する

### Boundary段階の不変条件

- **B1**: join_inputsのValueIdはhost ValueIdと衝突しない領域^1
  - JoinIR lowering では `alloc_join_param()` を使用すること（再発防止）
- **B2**: exit_bindingsは対応するexit PHIを持つ
- **C1**: 同じjoin_valueは同じhost_valueにマッピング
- **C2**: condition bindingのjoin_valueはhost ValueIdと衝突しない領域^1
  - ConditionEnv 経由で割り当てられる

---
^1) 現状の実装では 100-999 の範囲を使用しているが、これは実装詳細であり将来の実装では変わりうる。

### Merge段階の不変条件（debug_assertions）

- **M1**: Header PHI dstは再定義されない
- **M2**: Exit PHI inputsは全て定義されている
- **M3**: terminator targetsは全て存在する
- **M4**: ValueIdは領域を守っている

### 破ったらどこで落とすか

- **Contract違反**: `contract_checks.rs` で早期return
- **Debug assert**: `debug_assert!` / `unreachable!` で即座に落とす
- **検証漏れ**: CIで `cfg(debug_assertions)` テストを実行

---

## 7. 2本コンパイラ根治の合流点

### 共通パス（Shared Path）

```
AST → JoinIR Plan → JoinIR Frag → MIR Merge
```

共通パスでは以下が共有される：

- **Pattern Detection**: 同じパターン認識アルゴリズム
- **Boundary Construction**: 同じ JoinInlineBoundary 構造
- **MIR Merge**: 同じ merge_joinir_mir_blocks() ロジック

### 分岐点（Divergence Point）

```
MIR → [VM: MirInterpreter]
    → [LLVM: llvmlite/inkwell]
```

### 差分が許される場所

- **Method ID injection**: LLVM側のみ
- **Experimental features**: NYASH_JOINIR_VM_BRIDGE vs NYASH_JOINIR_LLVM_EXPERIMENT
- **Execution engines**: MirInterpreter vs llvmlite

### 差分が許されない場所

- **JoinIR structure**: 同じ構造でなければならない
- **PHI nodes**: 同じPHI構造でなければならない
- **ValueId mappings**: 同じマッピングでなければならない

---

## 8. デバッグ導線

詳細は CLAUDE.md へのリンク（重複させない）:

- **NYASH_CLI_VERBOSE=1**: 一般的な詳細ログ
- **HAKO_JOINIR_DEBUG=1**: JoinIR ルーティング・ブロック割り当て
- **NYASH_TRACE_VARMAP=1**: variable_map トレース（PHI接続デバッグ）
- **JoinIR architecture**: docs/development/current/main/joinir-architecture-overview.md

---

## 9. 関連ドキュメント（SSOT）

- Post-PHI final form: `docs/development/current/main/design/post-phi-final-form-ssot.md`

---

## 関連ドキュメント

- **JoinIR Architecture Overview**: [joinir-architecture-overview.md](./joinir-architecture-overview.md) - 全体アーキテクチャのSSOT
- **JoinIR Design Map**: [joinir-design-map.md](./joinir-design-map.md) - 実装導線の地図
- **Phase 286 README**: [../phases/phase-286/README.md](../phases/phase-286/README.md) - フェーズ進捗
- Post-PHI final form: `docs/development/current/main/design/post-phi-final-form-ssot.md`
- Effect classification: `docs/development/current/main/design/effect-classification-ssot.md`

---

## 変更ログ

- **2025-12-26**: Phase 286 P2.7 - V10追加（body_bb effects契約の明文化）
- **2025-12-25**: Phase 286 P0 - 初版作成（docs-only）
