Files
hakorune/docs/development/current/main/joinir-architecture-overview.md
nyash-codex 69ce196fb4 feat(joinir): Phase 33-23 Stage 2 - Pattern-specific analyzers (Issue 2, Issue 6)
Implements Stage 2 of the JoinIR refactoring roadmap, extracting specialized
analyzer logic from pattern implementations.

## Issue 2: Continue Analysis Extraction (80-100 lines reduction)

**New Module**: `pattern4_carrier_analyzer.rs` (346 lines)
- `analyze_carriers()` - Filter carriers based on loop body updates
- `analyze_carrier_updates()` - Delegate to LoopUpdateAnalyzer
- `normalize_continue_branches()` - Delegate to ContinueBranchNormalizer
- `validate_continue_structure()` - Verify continue pattern validity
- **6 unit tests** covering validation, filtering, normalization

**Updated**: `pattern4_with_continue.rs`
- Removed direct ContinueBranchNormalizer usage (24 lines)
- Removed carrier filtering logic (replaced with analyzer call)
- Cleaner delegation to Pattern4CarrierAnalyzer

**Line Reduction**: 24 lines direct removal from pattern4

## Issue 6: Break Condition Analysis Extraction (60-80 lines reduction)

**New Module**: `break_condition_analyzer.rs` (466 lines)
- `extract_break_condition()` - Extract break condition from if-else-break
- `has_break_in_else_clause()` - Check for else-break pattern
- `validate_break_structure()` - Validate condition well-formedness
- `extract_condition_variables()` - Collect variable dependencies
- `negate_condition()` - Helper for condition negation
- **10 unit tests** covering all analyzer functions

**Updated**: `ast_feature_extractor.rs`
- Delegated `has_break_in_else_clause()` to BreakConditionAnalyzer (40 lines)
- Delegated `extract_break_condition()` to BreakConditionAnalyzer
- Added Phase 33-23 documentation
- Cleaner separation of concerns

**Line Reduction**: 40 lines direct removal from feature extractor

## Module Structure Updates

**Updated**: `src/mir/builder/control_flow/joinir/patterns/mod.rs`
- Added pattern4_carrier_analyzer module export
- Phase 33-23 documentation

**Updated**: `src/mir/loop_pattern_detection/mod.rs`
- Added break_condition_analyzer module export
- Phase 33-23 documentation

## Test Results

 **cargo build --release**: Success (0 errors, warnings only)
 **New tests**: 16/16 PASS
  - pattern4_carrier_analyzer: 6/6 PASS
  - break_condition_analyzer: 10/10 PASS
 **No regressions**: All new analyzer tests pass

## Stage 2 Summary

**Total Implementation**:
- 2 new analyzer modules (812 lines)
- 16 comprehensive unit tests
- 4 files updated
- 2 mod.rs exports added

**Total Line Reduction**: 64 lines direct removal
- pattern4_with_continue.rs: -24 lines
- ast_feature_extractor.rs: -40 lines

**Combined with Stage 1**: 130 lines total reduction (66 + 64)
**Progress**: 130/630 lines (21% of 30% goal achieved)

## Design Benefits

**Pattern4CarrierAnalyzer**:
- Single responsibility: Continue pattern analysis only
- Reusable for future continue-based patterns
- Independent testability
- Clear delegation hierarchy

**BreakConditionAnalyzer**:
- Generic break pattern analysis
- Used by Pattern 2 and future patterns
- No MirBuilder dependencies
- Pure function design

## Box Theory Compliance

 Single responsibility per module
 Clear public API boundaries
 Appropriate visibility (pub(in control_flow::joinir::patterns))
 No cross-module leakage
 Testable units

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-08 04:00:44 +09:00

241 lines
13 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 (20251208)
このドキュメントは、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. **LoopHeader PHI を SSA の単一源泉にする**
- ループ変数とキャリアは **LoopHeaderPhiBuilder/LoopHeaderPhiInfo** でヘッダ PHI を作り、これを「現在値」の SSOT にする。
- exit 用の PHI も組むが、変数再接続や expr_result 収集はヘッダ PHI を経由して行うSSAundef 防止)。
4. **式としての戻り値とキャリア更新を分離する**
- 「ループが式として値を返す」ケース(例: `let r = loop_min_while(...)`)の出口は **exit_phi_builder** が扱う。
- 「ループが状態更新だけする」ケース(例: `trim``start/end`)の出口は **ExitLineExitMeta / ExitBinding / ExitLineReconnector** だけが扱う。
5. **ループ制御 vs 条件式の分離**
- ループの「形」Pattern14, LoopFeaturesは control-flow 専用の箱が担当。
- 条件式(`i < len && (ch == " " || ch == "\t")` 等)は **BoolExprLowerer / condition_to_joinir** が担当し、
ループパターンは boolean ValueId だけを受け取る。
6. **FailFast**
- JoinIR が対応していないループパターン / if パターンは、必ず `[joinir/freeze]` 等で明示的にエラーにする。
- LoopBuilder 等へのサイレントフォールバックは禁止。
---
## 2. 主な箱と責務
### 2.1 Loop 構造・検出ライン
- **LoopFeatures / LoopPatternKind / router**
- ファイル:
- `src/mir/loop_pattern_detection.rs`
- `src/mir/builder/control_flow/joinir/patterns/router.rs`
- `src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs`
- 責務:
- AST から break/continue/ifelse PHI などの特徴を抽出ast_feature_extractor
- `classify(&LoopFeatures)` で Pattern14 に分類し、テーブル駆動の `LOOP_PATTERNS` でルーティング。
- ルータ順序は P4(continue) → P3(ifphi) → P1(simple) → P2(break) で固定(優先度フィールドはデバッグ用)。
- **Pattern Lowerers (Pattern14)**
- ファイル例:
- `pattern1_minimal.rs`Simple while
- `pattern2_with_break.rs`break 付き / Trim 昇格パスを含む)
- `pattern3_with_if_phi.rs`ifphi キャリア)
- `pattern4_with_continue.rs`continue を Select で表現)
- 責務:
- LoopScopeShape / AST / LoopFeatures を入力として JoinIR の `JoinModule` を構築。
- `JoinFragmentMeta{ expr_result, exit_meta }` を返し、出口情報を ExitLine に渡す。
- host/MIR の ValueId は一切扱わないJoinIR ローカルの ValueId のみ)。
- **Scope / Env Builders**
- `loop_scope_shape_builder.rs`: ループ本体ローカルの収集、LoopScopeShape 統一生成。
- `condition_env_builder.rs`: 条件専用変数の環境と ConditionBinding を一括構築。
- **CommonPatternInitializer** (Phase 33-22)
- ファイル: `src/mir/builder/control_flow/joinir/patterns/common_init.rs`
- 責務:
- 全 Pattern 共通の初期化ロジック統一化(ループ変数抽出 + CarrierInfo 構築)。
- 全パターンで boundary.loop_var_name を確実に設定し、SSAundef を防ぐ。
- **JoinIRConversionPipeline** (Phase 33-22)
- ファイル: `src/mir/builder/control_flow/joinir/patterns/conversion_pipeline.rs`
- 責務:
- JoinIR → MIR 変換フロー統一化JoinModule → MirModule → merge_joinir_mir_blocks
- JoinIR/MIR の関数数・ブロック数をログ出力し、全パターンが同じ入口でマージする。
### 2.2 条件式ライン(式の箱)
- **BoolExprLowerer / condition_to_joinir**
- ファイル:
- `src/mir/join_ir/lowering/bool_expr_lowerer.rs`
- `src/mir/join_ir/lowering/condition_to_joinir.rs`
- 責務:
- 通常の if/while 条件を MIR Compare/BinOp/UnaryOp へ lowering。
- ループ lowerer 用の「AST 条件 → JoinIR Compute 命令列」を ConditionEnv とセットで構築。
- **ConditionEnv/ConditionBinding + ConditionEnvBuilder**
- ファイル:
- `src/mir/join_ir/lowering/condition_env.rs`
- `src/mir/builder/control_flow/joinir/patterns/condition_env_builder.rs`
- 責務:
- 変数名→JoinIR ValueId の環境を組み立て、host↔join の橋渡しを ConditionBinding に明示する。
- Pattern 2 では break 条件の全変数をスキャンし、JoinInlineBoundary.condition_bindings に渡す。
- **LoopConditionScopeBoxPhase 170-D 実装済み)**
- ファイル: `src/mir/loop_pattern_detection/loop_condition_scope.rs`
- 責務:
- 条件式の各変数を LoopParam / OuterLocal / LoopBodyLocal に分類。
- 関数パラメータ誤分類バグは `condition_var_analyzer.rs` の修正で解消済みOuterLocal として扱う)。
- **LoopBodyCarrierPromoterPhase 171-C-2 実装済み)**
- ファイル: `src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs`
- 責務:
- LoopBodyLocal を Trim パターンとして bool キャリアへ昇格substring + equality 連鎖を検出)。
- 昇格成功 → CarrierInfo に統合し Pattern 2/4 へ橋渡し。昇格失敗は FailFast。
- Pattern 2 は安全な Trim なら実際に前処理substring 生成 + 空白比較の初期化)を emit してから JoinIR lowering。
- Pattern 4 は Trim 昇格が起きた場合はガード付きでエラーにし、未実装を明示FailFast
- **ContinueBranchNormalizer / LoopUpdateAnalyzer**
- ファイル:
- `src/mir/join_ir/lowering/continue_branch_normalizer.rs`
- `src/mir/join_ir/lowering/loop_update_analyzer.rs`
- 責務:
- else-continue を then-continue へ正規化し、Select ベースの continue を簡潔にする。
- ループ本体で実際に更新されるキャリアだけを抽出Pattern 4 で不要キャリアを排除)。
### 2.3 キャリア / Exit / Boundary ライン
- **CarrierInfo / LoopUpdateAnalyzer**
- ファイル:
- `src/mir/join_ir/lowering/carrier_info.rs`
- `src/mir/join_ir/lowering/loop_update_analyzer.rs`
- 責務:
- ループで更新される変数carrierを検出し、UpdateExpr を保持。
- Pattern 4 では実際に更新されるキャリアだけを残す。
- **ExitMeta / JoinFragmentMeta**
- ファイル: `carrier_info.rs`
- 責務:
- JoinIR lowerer が出口の JoinIR ValueId を記録expr_result とキャリアを明確に分離)。
- **LoopHeader PHI Builder**
- ファイル:
- `src/mir/builder/control_flow/joinir/merge/loop_header_phi_info.rs`
- `loop_header_phi_builder.rs`
- 責務:
- ループ変数とキャリアの PHI をヘッダブロックに生成し、entry/latch の 2 入力で SSA を確立。
- instruction_rewriter が latch 側を埋めた後に finalize して挿入する。
- **JoinInlineBoundary**
- ファイル: `src/mir/join_ir/lowering/inline_boundary.rs`
- 主フィールド:
- `join_inputs / host_inputs`:ループパラメータの橋渡し
- `condition_bindings`条件専用変数の橋渡しJoinIR ValueId を明示)
- `exit_bindings`キャリア出口の橋渡しcarrier 名を明示)
- `expr_result` / `loop_var_name`expr result / ヘッダ PHI 生成用のメタ情報
- 責務:
- 「host ↔ JoinIR」の境界情報の SSOT。各パターン lowerer がここに全て詰めてから merge する。
- **BoundaryInjector**
- ファイル: `src/mir/builder/joinir_inline_boundary_injector.rs`
- 責務:
- `join_inputs``condition_bindings` を entry block に Copy で注入し、JoinIR ローカル ID と host ID を接続。
- **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
- 変数再接続はヘッダ PHI の dst を使って `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` を持つときに exit ブロックへ PHI を生成。
- carrier_inputs も受け取り exit ブロックに PHI を作るが、再接続の SSOT は LoopHeader PHIExitLine はヘッダ PHI を使用)。
- **InstructionRewriter**
- ファイル: `instruction_rewriter.rs`
- 責務:
- continuation 関数k_exitをスキップし、Return → exit ブロック Jump に変換。
- `JoinFragmentMeta.expr_result` と exit_bindings をヘッダ PHI 経由で収集し、`exit_phi_inputs` / `carrier_inputs` を復活させたSSAundef 修正済み)。
- tail call を Branch/Jump に書き換えつつ、LoopHeaderPhiInfo に latch 入力を記録する。
---
## 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 を再割り当てblock_allocatorし、ValueId はパラメータを除外して収集。
- Boundary の condition/exit Bindings の JoinIR ValueId も remap 対象に追加。
- LoopHeader PHI を生成loop_header_phi_builderし、latch 側は instruction_rewriter が埋める。
- instruction_rewriter で関数をマージしつつ Call→Jump に変換、k_exit 関数はスキップ。
- BoundaryInjector で entry block に Copy を注入join_inputs + condition_bindings
- Header PHI を finalize → exit_phi_builder で expr_result/carrier の exit PHI を構築。
- ExitLineOrchestrator がヘッダ PHI dst を使って variable_map を更新。
- host の現在ブロックから JoinIR entry へ jump を張り、exit ブロックに切り替える。
この全体フローの詳細は `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 等
- `docs/development/current/main/loop_pattern_space.md`
- JoinIR ループパターン空間の整理メモ。
どの軸(継続条件 / break / continue / PHI / 条件変数スコープ / 更新パターン)でパターンを分けるか、
そして P1P4 / Trim(P5) の位置づけと、今後追加候補のパターン一覧がまとまっている。