Files
hakorune/docs/development/current/main/joinir-architecture-overview.md
nyash-codex 4e32a803a7 feat(joinir): Phase 33-22 CommonPatternInitializer & JoinIRConversionPipeline integration
Unifies initialization and conversion logic across all 4 loop patterns,
eliminating code duplication and establishing single source of truth.

## Changes

### Infrastructure (New)
- CommonPatternInitializer (117 lines): Unified loop var extraction + CarrierInfo building
- JoinIRConversionPipeline (127 lines): Unified JoinIR→MIR→Merge flow

### Pattern Refactoring
- Pattern 1: Uses CommonPatternInitializer + JoinIRConversionPipeline (-25 lines)
- Pattern 2: Uses CommonPatternInitializer + JoinIRConversionPipeline (-25 lines)
- Pattern 3: Uses CommonPatternInitializer + JoinIRConversionPipeline (-25 lines)
- Pattern 4: Uses CommonPatternInitializer + JoinIRConversionPipeline (-40 lines)

### Code Reduction
- Total reduction: ~115 lines across all patterns
- Zero code duplication in initialization/conversion
- Pattern files: 806 lines total (down from ~920)

### Quality Improvements
- Single source of truth for initialization
- Consistent conversion flow across all patterns
- Guaranteed boundary.loop_var_name setting (prevents SSA-undef bugs)
- Improved maintainability and testability

### Testing
- All 4 patterns tested and passing:
  - Pattern 1 (Simple While): 
  - Pattern 2 (With Break): 
  - Pattern 3 (If-Else PHI): 
  - Pattern 4 (With Continue): 

### Documentation
- Phase 33-22 inventory and results document
- Updated joinir-architecture-overview.md with new infrastructure

## Breaking Changes
None - pure refactoring with no API changes

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-07 21:02:20 +09:00

205 lines
10 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.

# JoinIR Architecture Overview (20251206)
このドキュメントは、JoinIR ライン全体Loop/If lowering, ExitLine, Boundary, 条件式 lowering
「箱」と「契約」を横串でまとめた設計図だよ。selfhost / JsonParser / hako_check など、
どの呼び出し元から見てもここを見れば「JoinIR 層の責務と流れ」が分かるようにしておく。
変更があったら、Phase ドキュメントではなく **このファイルを随時更新する** 方針。
---
## 1. 不変条件Invariants
JoinIR ラインで守るべきルールを先に書いておくよ:
1. **JoinIR 内部は JoinIR ValueId だけ**
- JoinIR lowering が発行する `JoinInst``ValueId` は、すべて `alloc_value()` で割り当てるローカル ID。
- Rust/MIR 側の ValueId`builder.variable_map` に入っている IDは、JoinIR には直接持ち込まない。
2. **host ↔ join の橋渡しは JoinInlineBoundary 系だけ**
- host から JoinIR への入力(ループ変数 / 条件専用変数)は
- `JoinInlineBoundary.join_inputs + host_inputs`
- `JoinInlineBoundary.condition_bindings`ConditionBinding
だけで接続する。
- 出力(キャリアの出口)は `JoinInlineBoundary.exit_bindings` に一本化する。
3. **式としての戻り値とキャリア更新を分離する**
- 「ループが式として値を返す」ケース(例: `let r = loop_min_while(...)`)の出口は **exit_phi_builder** が扱う。
- 「ループが状態更新だけする」ケース(例: `trim``start/end`)の出口は **ExitLineExitMeta / ExitBinding / ExitLineReconnector** だけが扱う。
4. **ループ制御 vs 条件式の分離**
- ループの「形」Pattern14, LoopFeaturesは control-flow 専用の箱が担当。
- 条件式(`i < len && (ch == " " || ch == "\t")` 等)は **BoolExprLowerer / condition_to_joinir** が担当し、
ループパターンは boolean ValueId だけを受け取る。
5. **FailFast**
- JoinIR が対応していないループパターン / if パターンは、必ず `[joinir/freeze]` 等で明示的にエラーにする。
- LoopBuilder 等へのサイレントフォールバックは禁止Phase 186187 で完全削除済み)。
---
## 2. 主な箱と責務
### 2.1 Loop 構造・検出ライン
- **LoopFeatures / LoopPatternKind / router**
- ファイル:
- `src/mir/loop_pattern_detection.rs`
- `src/mir/builder/control_flow/joinir/patterns/router.rs`
- 責務:
- AST からループ構造の特徴(`has_break`, `has_continue`, `has_if_else_phi`, `carrier_count` 等)を抽出。
- `classify(&LoopFeatures)` で Pattern14 に分類。
- `LOOP_PATTERNS` テーブルを通じて該当 lowererpattern*_minimal.rsにルーティング。
- Phase 170C 系で `LoopUpdateSummary`(各キャリアの UpdateKind 情報)を統合し、
`CaseALoweringShape` が関数名ではなく構造+更新パターンだけを見て判定できるようにする計画。
- **Pattern Lowerers (Pattern14)**
- ファイル例:
- `simple_while_minimal.rs`Pattern1
- `loop_with_break_minimal.rs`Pattern2
- `loop_with_if_phi_minimal.rs`Pattern3
- `loop_with_continue_minimal.rs`Pattern4
- 責務:
- LoopScopeShape / AST / LoopFeatures を入力として JoinIR の `JoinModule` を構築。
- `JoinFragmentMeta{ expr_result, exit_meta }` を返し、出口情報を ExitLine に渡す。
- host/MIR の ValueId は一切扱わないJoinIR ローカルの ValueId のみ)。
- **CommonPatternInitializer** (Phase 33-22)
- ファイル: `src/mir/builder/control_flow/joinir/patterns/common_init.rs`
- 責務:
- 全 Pattern 共通の初期化ロジック統一化(ループ変数抽出 + CarrierInfo 構築)。
- All 4 loop patterns use this for unified initialization, guaranteeing boundary.loop_var_name is always set and preventing SSA-undef bugs.
- **JoinIRConversionPipeline** (Phase 33-22)
- ファイル: `src/mir/builder/control_flow/joinir/patterns/conversion_pipeline.rs`
- 責務:
- JoinIR → MIR 変換フロー統一化JoinModule → MirModule → merge_joinir_mir_blocks
- Single entry point for JoinIR→MIR conversion, encapsulating phases 1-6 and ensuring consistent transformation across all patterns.
### 2.2 条件式ライン(式の箱)
- **BoolExprLowerer**
- ファイル: `src/mir/join_ir/lowering/bool_expr_lowerer.rs`
- 責務:
- AST の boolean 式 → MIR の Compare/BinOp/UnaryOp に lowering通常の if/while 用)。
- `<, ==, !=, <=, >=, >``&&, ||, !` の組合せを扱う。
- **condition_to_joinir + ConditionEnv/ConditionBinding**
- ファイル: `src/mir/join_ir/lowering/condition_to_joinir.rs`
- 責務:
- ループ lowerer 用の「AST 条件 → JoinIR Compute命令列」。
- `ConditionEnv` 経由で「変数名 → JoinIR ValueId」のみを見る。
- host 側の ValueId は `ConditionBinding { name, host_value, join_value }` として JoinInlineBoundary に記録する。
### 2.3 キャリア / Exit / Boundary ライン
- **CarrierInfo / LoopUpdateAnalyzer**
- ファイル:
- `src/mir/join_ir/lowering/carrier_info.rs`
- `LoopUpdateAnalyzer` 周辺
- 責務:
- ループ内で更新される変数carrierの名前と host ValueId を検出。
- 更新式(`sum = sum + i`, `count = count + 1` 等)を `UpdateExpr` として保持。
- **ExitMeta / JoinFragmentMeta**
- ファイル: `carrier_info.rs`
- 責務:
- JoinIR lowerer が「どの carrier が、どの JoinIR ValueId で出口に出るか」を記録。
- `JoinFragmentMeta` の一部として `expr_result: Option<ValueId>``exit_meta` をまとめる。
- **ExitMetaCollector**
- ファイル: `src/mir/builder/control_flow/joinir/merge/exit_line/meta_collector.rs`
- 責務:
- `ExitMeta + CarrierInfo` から `Vec<LoopExitBinding{ carrier_name, join_exit_value, host_slot }>` を構築。
- 副作用なしの pure function。
- **JoinInlineBoundary**
- ファイル: `src/mir/join_ir/lowering/inline_boundary.rs`
- フィールド(主なもの):
- `join_inputs / host_inputs`:ループパラメータの橋渡し
- `condition_bindings: Vec<ConditionBinding>`:条件専用変数の橋渡し
- `exit_bindings: Vec<LoopExitBinding>`:キャリア出口の橋渡し
- 責務:
- 「host 関数 ↔ JoinIR fragment」の境界情報の SSOT。
- **BoundaryInjector**
- ファイル: `src/mir/builder/joinir_inline_boundary_injector.rs`
- 責務:
- `join_inputs + host_inputs` / `condition_bindings` に基づき、entry block に Copy 命令を挿して host→JoinIR を接続。
- **ExitLine (ExitMetaCollector / ExitLineReconnector / ExitLineOrchestrator)**
- ファイル:
- `src/mir/builder/control_flow/joinir/merge/exit_line/mod.rs`
- `exit_line/meta_collector.rs`
- `exit_line/reconnector.rs`
- 責務:
- ExitMeta から exit_bindings を構築しCollector
remapper と組み合わせて `builder.variable_map` のキャリアスロットを更新Reconnector
- expr 用の PHI には一切触れないcarrier 専用ライン)。
### 2.4 expr result ライン(式としての戻り値)
- **exit_phi_builder**
- ファイル: `src/mir/builder/control_flow/joinir/merge/exit_phi_builder.rs`
- 責務:
- JoinIR fragment が「式としての戻り値expr_result」を持つ場合にだけ、
Return 値を exit block の PHI にまとめて 1 つの `ValueId` を返す※Phase 3316 で正式再実装予定)。
- ループキャリア(`start/end/sum`は扱わないcarrier は ExitLine 専用ライン)。
- **InstructionRewriterexpr_result のみを exit_phi_inputs に流す)**
- ファイル: `instruction_rewriter.rs`
- 責務:
- `JoinFragmentMeta.expr_result``Some` の場合だけ、該当 return 値を exit_phi_inputs に積むのが理想形。
- carrier 用の return/jump は ExitMeta/ExitLine 側で扱う。
- **現状Phase 3315 時点)**:
- SSAundef を避けるため、一時的に `exit_phi_inputs` / `carrier_inputs` の収集を停止している。
- そのため「ループを式として評価する」ケースでは PHI を経由した expr 結果はまだ生成されない。
- これは **一時的な止血措置** であり、Phase 3316 で「Loop ヘッダ PHI を出口値の SSOT とする」設計に差し替える予定。
---
## 3. JoinIR → MIR 統合の全体フロー
1. Pattern router が AST/LoopFeatures から Pattern14 を選択し、各 lowerer が
`(JoinModule, JoinFragmentMeta)` を生成。
2. `JoinInlineBoundary` が:
- ループ入力join_inputs/host_inputs
- 条件変数condition_bindings
- キャリア出口exit_bindings
を保持。
3. `merge_joinir_mir_blocks` が:
- BlockID/ValueID remap
- JoinIR 関数群の inline
- Return→jump の書き換え
- expr result 用 PHIexit_phi_builder
- ExitLineOrchestratorExitMetaCollector + ExitLineReconnector
を順に実行。
この全体フローの詳細は `src/mir/builder/control_flow/joinir/merge/mod.rs`
`phase-189-multi-function-mir-merge/README.md` を参照。
---
## 4. selfhost / .hako JoinIR Frontend との関係
JoinIR は Rust 側だけでなく、将来的に .hako selfhost コンパイラ側でも生成・解析される予定だよ:
- .hako 側の JsonParser/分析箱は、Program JSON / MIR JSON v1 を読んで JoinIR/MIR を解析する。
- Rust 側 JoinIR ラインの設計変更(特に ValueId/ExitLine/Boundary 周り)は、
**必ずこのファイルを更新してから** .hako 側にも段階的に反映する方針。
「JoinIR の仕様」「箱の責務」「境界の契約」は、このファイルを SSOT として運用していく。
---
## 5. 関連ドキュメント
- `docs/development/current/main/10-Now.md`
- 全体の「いまどこ」を短くまとめたダッシュボード。
- `docs/private/roadmap2/phases/phase-180-joinir-unification-before-selfhost/README.md`
- JoinIR 統一フェーズ全体のロードマップと進捗。
- 各 Phase 詳細:
- 185188: Strict mode / LoopBuilder 削除 / Pattern14 基盤
- 189193: Multi-function merge / Select bridge / ExitLine 箱化
- 171172 / 3310/13: ConditionEnv, ConditionBinding, JoinFragmentMeta, ExitLineRefactor 等