## 実装内容(Step 1-3 完全達成) ### Step 1: src/mir/join_ir.rs 型定義追加 - **JoinFuncId / JoinContId**: 関数・継続ID型 - **JoinFunction**: 関数(引数 = φノード) - **JoinInst**: Call/Jump/Ret/Compute 最小命令セット - **MirLikeInst**: 算術・比較命令ラッパー - **JoinModule**: 複数関数保持コンテナ - **単体テスト**: 型サニティチェック追加 ### Step 2: テストケース追加 - **apps/tests/joinir_min_loop.hako**: 最小ループ+breakカナリア - **src/tests/mir_joinir_min.rs**: 手書きJoinIR構築テスト - MIR → JoinIR手動構築で型妥当性確認 - #[ignore] で手動実行専用化 - NYASH_JOINIR_EXPERIMENT=1 トグル制御 ### Step 3: 環境変数トグル実装 - **NYASH_JOINIR_EXPERIMENT=1**: 実験モード有効化 - **デフォルト挙動**: 既存MIR/LoopForm経路のみ(破壊的変更なし) - **トグルON時**: JoinIR手書き構築テスト実行 ## Phase 26-H スコープ遵守 ✅ 型定義のみ(変換ロジックは未実装) ✅ 最小限の命令セット ✅ Debug 出力で妥当性確認 ✅ 既存パイプライン無影響 ## テスト結果 ``` $ NYASH_JOINIR_EXPERIMENT=1 cargo test --release mir_joinir_min_manual_construction -- --ignored --nocapture [joinir/min] MIR module compiled, 3 functions [joinir/min] JoinIR module constructed: [joinir/min] ✅ JoinIR型定義は妥当(Phase 26-H) test result: ok. 1 passed; 0 failed ``` ## JoinIR理論の実証 - **φノード = 関数引数**: `fn loop_step(i, k_exit)` - **merge = join関数**: 分岐後の合流点 - **ループ = 再帰関数**: `loop_step` 自己呼び出し - **break = 継続呼び出し**: `k_exit(i)` ## 次フェーズ (Phase 27.x) - LoopForm v2 → JoinIR 自動変換実装 - break/continue ハンドリング - Exit PHI の JoinIR 引数化 🌟 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com>
4.4 KiB
4.4 KiB
Phase 26-H — JoinIR / 関数正規化 タスクチェックリスト
このフェーズは「設計+ミニ実験」専用だよ。本線のスモーク/CI は既存の MIR/LoopForm 経路のまま維持しつつ、関数正規化(JoinIR/LoopFnIR)の足場を小さく固めることをゴールにする。
A. 設計ドキュメントまわり
-
A-1: join-ir 設計の骨格を固める
docs/development/architecture/join-ir.mdに:- 命令セット(
call,ret, 必要ならjump)の最小定義を明記する - if / loop / break / continue / return → JoinIR の変換規則を列挙する
- φ = 関数引数 / merge = join 関数 / loop = 再帰 + exit 継続 の対応表を書く
- 命令セット(
- 26-H で「実装として本当に増やす箱」と、「概念ラベルとしてだけ残す箱」を分けてコメントしておく
-
A-2: 26-H フェーズ README の整備
docs/development/roadmap/phases/phase-26-H/README.mdに:- 現在の箱群(LoopForm/PHI/解析系)の棚卸し
- 最終的に残したい箱セット(LoopForm 前段 + LoopFnIR/JoinIR + 最小解析箱)を 1 セクションでまとめる
- 「このフェーズでは設計+ミニ実験のみ、本線は既存ルート」というスコープ/制限を明記する
B. JoinIR 型・変換の最小実装
-
B-1: JoinIR 型定義ファイルの追加
src/mir/join_ir.rsを追加し、以下を定義する(最小限でOK):JoinFunction(名前・引数・ブロック一覧)JoinBlock(ラベルと命令列)JoinInst(call/ret などのバリアント)
Debug/Displayなどダンプに必要な実装だけ付ける(最初はDebugだけでも可)
-
B-2: LoopForm→JoinIR ミニ変換関数(1ケース用)
- まずは 汎用変換ではなく、特定の小関数だけを対象にした試験的関数 を 1つ実装する:
- 例:
fn lower_simple_loop_to_joinir(mir: &MirModule, func_name: &str) -> Option<JoinFunction>
- 例:
- ルールは join-ir.md の「Loop→step/k_exit」変換に従って手作業気味でよい(このフェーズでは general solution を目指さない)
- まずは 汎用変換ではなく、特定の小関数だけを対象にした試験的関数 を 1つ実装する:
C. 最小 .hako + テスト(カナリア)
-
C-1: 最小 JoinIR 用 .hako を追加
apps/tests/joinir_min_loop.hako(例)を作成:- 例:
static box JoinIrMin { main() { var i = 0; loop(i < 3) { if i >= 2 { break } i = i + 1 } return i } }
- 例:
-
C-2: Rust テストで MIR→JoinIR ダンプを確認
src/tests/mir_joinir_min.rs(仮ファイル)を追加し:- 上記 .hako を AST→MIR までコンパイル
lower_simple_loop_to_joinirを呼んでJoinFunctionを生成eprintln!("{:?}", join_fn)などで形を確認(当面は assert よりも形の手動確認を重視)
- テストは デフォルト ON でも軽い ことを確認(重ければ
#[ignore]+ 手動実行でもOK)
D. トグル付き実験フック
- D-1: 実験用トグルの追加
NYASH_JOINIR_EXPERIMENT=1のときだけ JoinIR ダンプを有効にするパスを Runner 側に追加する(例:--debug-joinir-minに相乗りでも可)- トグル OFF のときは既存の MIR/LoopForm 経路しか走らないことを確認する
E. ループ/PHI ラインとの関係メモ
-
E-1: 「どの箱が将来 JoinIR に吸収されるか」を一覧にする
loopform_ssot.mdか 26-H README に:- Header/Exit PHI まわりの箱で、JoinIR 導入後に 不要or縮退 するもの
- LoopForm / ControlForm は「前段の構造箱」として残すもの
- 解析系(LoopVarClassBox / LoopExitLivenessBox など)のうち、JoinIR 後も必要なもの
を簡易な表にして残す
-
E-2: 「今はここまで、27.x でここまで」を線引きする
- 26-H のスコープ: 設計+最小 JoinIR ダンプ
- 27.x 候補: JoinIR 経由で 1〜2 個の本番ループ(FuncScanner/Stage-B)を通す、PHI/ExitLiveness の一部を JoinIR 側に移す
このファイルは「26‑H でやることを一覧で見たいときのチェックリスト」として使ってね。
タスクが増えたら、このファイルに A/B/C… の形で足していく想定だよ。