joinir: clean pattern visibility and refactor pattern2 pipeline
This commit is contained in:
@ -1032,3 +1032,110 @@ JoinIR は Rust 側だけでなく、将来的に .hako selfhost コンパイラ
|
||||
- 根本原因: carrier 検出ロジックの name heuristic が脆弱
|
||||
- **次フェーズ**: Carrier 検出修正(Phase 219)
|
||||
- 詳細: phase218-jsonparser-if-sum-min.md
|
||||
|
||||
---
|
||||
|
||||
## 3. JoinIR → JoinIR 正規化レイヤ(構想 / Phase 26-H ライン)
|
||||
|
||||
### 3.1 Structured JoinIR と Normalized JoinIR(概念レベル)
|
||||
|
||||
JoinIR ラインは、今後は「同じ JoinIR をフェーズごとに正規化していく」二段構成で扱う想定だよ:
|
||||
|
||||
- **Structured JoinIR(現行層)**
|
||||
- Pattern1–5 / CarrierInfo / ConditionEnv / UpdateEnv / Boundary / ExitLine までを終えた状態。
|
||||
- while/if/break/continue/return がまだ「構造」として残っていてよい層。
|
||||
- いまの JoinIR lowering(Pattern lowerer 群)が出力しているものはここ。
|
||||
|
||||
- **Normalized JoinIR(JoinIR’ / CPS 風層)**
|
||||
- 制御構造をすべて「関数+継続+ Env」の形に正規化した状態。
|
||||
- ループは `loop_step(env, k_exit)` と exit 継続のペア、if は `if_branch(env, k_then, k_else)` + join 継続で表現。
|
||||
- while/break/continue/return は **TailCallFn/TailCallKont + If** だけに還元され、goto/生の branch は現れない。
|
||||
- Env は「ループキャリア + DigitPos/num_str などの Derived + captured 変数」を 1 つの struct としてまとめる。
|
||||
|
||||
パイプラインのイメージ:
|
||||
|
||||
```text
|
||||
AST
|
||||
↓
|
||||
JoinIR(Structured) // Pattern1–5, CarrierInfo, ConditionEnv/UpdateEnv, Boundary/ExitLine
|
||||
↓ JoinIR パス A: 正規化(JoinIR → JoinIR)
|
||||
JoinIR(Normalized) // 関数 + 継続 + Env のみ(TailCall-only)
|
||||
↓ JoinIR→MIR bridge
|
||||
MIR
|
||||
```
|
||||
|
||||
型レベルでは、次の二案のどちらかで扱う想定だよ(詳細は今後の Phase で選択):
|
||||
|
||||
- **案① 型を分ける**
|
||||
- `JoinModuleRaw`(Structured)、`JoinModuleCps`(Normalized)を別型にする。
|
||||
- Bridge(JoinIR→MIR)は `JoinModuleCps` だけを受け取る。
|
||||
- **案② 型は 1 つ+フェーズフラグ**
|
||||
- `JoinModule { phase: JoinIrPhase, ... }` として、`phase = Structured / Normalized` をメタデータで持つ。
|
||||
- JoinIR パスはすべて `fn run(&mut JoinModule)`(= joinir→joinir)で構成し、
|
||||
Verifier が「phase=Normalized なら while/if/break/continue/return 禁止」などの不変条件をチェックする。
|
||||
|
||||
どちらの案でも本質は同じで、「JoinIR の下に JoinIR’(= 正規形フェーズ)を 1 段挟む」という設計、というのがポイントだよ。
|
||||
|
||||
### 3.2 Normalized JoinIR の基本モデル(ラフスケッチ)
|
||||
|
||||
Normalized JoinIR では、制御構造を次の 3 要素だけで表現する想定だよ:
|
||||
|
||||
- **Env(環境)**
|
||||
- そのループ/if に必要な情報を 1 つにまとめた struct。
|
||||
- フィールド種別の例:
|
||||
- `Carrier`(LoopState キャリア: i, sum, result, num_state 等)
|
||||
- `Derived`(DigitPos 二重値, NumberAccumulation 等)
|
||||
- `Captured`(外側のローカルや関数パラメータ: s, len 等)
|
||||
|
||||
- **Fn(通常の関数)**
|
||||
- 典型例: `loop_step(env, k_exit)` / `loop_body(env, k_exit)`。
|
||||
- 末尾は常に `TailCallFn` または `TailCallKont`。
|
||||
|
||||
- **Kont(継続)**
|
||||
- 典型例: ループ exit 後の処理、if 後の join、関数 return など。
|
||||
- 末尾は別の Fn/Kont への tail-call。
|
||||
|
||||
制御の不変条件(Normalized フェーズ):
|
||||
|
||||
1. 制御フローは `TailCallFn` / `TailCallKont` / `If(cond, then_k, else_k, env)` のみで表現する。
|
||||
2. 各ループは「`loop_step(env, k_exit)` 関数 + `k_exit(env)` 継続」のペアとして現れる(break は必ず k_exit へ TailCall)。
|
||||
3. continue は `loop_step` への TailCall として現れる(ヘッダ PHI 相当は Env の書き込み順で表現)。
|
||||
4. return は専用の `return_kont(env)` への TailCall で表現される。
|
||||
5. EnvLayoutVerifier(検証箱)が、常に正しい EnvLayout が使われていることをチェックする。
|
||||
|
||||
これにより、現在 JoinIR 層で苦労している「PHI 配線」「exit_bindings/jump_args 整合性」「評価順のねじれ」は、
|
||||
Normalized JoinIR 側では「Env フィールドの更新順」と「どの継続を呼ぶか」に還元される想定だよ。
|
||||
|
||||
### 3.3 Phase 26-H のフェーズ分割(案)
|
||||
|
||||
この正規化レイヤを一度に入れるのは重いので、Phase 26-H ラインとして小さく段階分けして進める方針だよ。
|
||||
(番号は仮で、実際の Phase 番号は current の進行に合わせて調整する想定)
|
||||
|
||||
1. **Phase 26-H.A – モデル定義と Doc 固定(コード変更最小)**
|
||||
- JoinIR Architecture Overview(このファイル)に Structured / Normalized の二層構造を明文化(本節)。
|
||||
- `JoinIrPhase` などのメタ情報だけを追加し、既存 lowering / Bridge の挙動は変えない。
|
||||
- Normalized JoinIR の不変条件(TailCall-only / EnvLayout 整合性)を Verifier の設計として書き出す。
|
||||
|
||||
2. **Phase 26-H.B – 最小サブセットでの JoinIR→JoinIR パス導入**
|
||||
- Pattern1(単純 while, break/continue なし)だけを対象にした Normalized パスを実装。
|
||||
- パイプライン:
|
||||
- 既存: `JoinIR(Structured) → MIR`
|
||||
- 新規: `JoinIR(Structured) → JoinIR(Normalized, small subset) → MIR`
|
||||
- 新規パスは dev フラグの裏側で比較用にのみ使い、E2E で結果が一致することを確認(既定経路は従来のまま)。
|
||||
|
||||
3. **Phase 26-H.C – Pattern2–4 / DigitPos / JsonParser への拡張**
|
||||
- Pattern2/3/4 と DigitPos / NumberAccumulation / Trim を Normalized パスの対象に広げる。
|
||||
- JsonParser `_parse_number` / `_atoi` を優先対象にし、JoinIR(Normalized) 経由での実行を dev フラグ付きで有効化。
|
||||
- JoinIR(Structured) → JoinIR(Normalized) の各ステップに構造テストを追加し、「Env の更新」「継続の呼び出し順」が期待どおりかを固定。
|
||||
|
||||
4. **Phase 26-H.D – Normalized JoinIR を canonical route に昇格**
|
||||
- JoinIR→MIR Bridge が「Normalized フェーズの JoinIR だけ」を受け取るように変更。
|
||||
- Structured JoinIR → MIR の直接パスは「比較テスト専用」として残すか、段階的に削除。
|
||||
- selfhost / JsonParser / hako_check の代表ループはすべて Normalized JoinIR 経由で通ることを確認。
|
||||
|
||||
各サブフェーズでは「既存意味論を変えない」「Fail-Fast 原則を維持する」「新旧経路の比較テストを先に用意する」をガードとして運用するよ。
|
||||
詳細な API/型設計は、Phase 26-H.A/B の中で `EnvLayoutBox` / `LoopStepSynthesizer` / `JpVerifier` 等の箱として段階的に固めていく想定。
|
||||
|
||||
### 3.4 Phase 27-CLEAN – Pattern2–4 の軽量整理
|
||||
|
||||
- Pattern2〜4/loop_with_break_minimal まわりで可視性・ログ・補助関数を整理し、joinir_dev フラグ配下のデバッグログに寄せる。意味論は変えずに「読みやすさ」「追いやすさ」を優先するクリーンアップフェーズだよ。
|
||||
|
||||
Reference in New Issue
Block a user