refactor(mir): phase260 p0.1 strangler hardening + smoke fixtures
This commit is contained in:
115
docs/development/current/main/design/exception-cleanup-async.md
Normal file
115
docs/development/current/main/design/exception-cleanup-async.md
Normal file
@ -0,0 +1,115 @@
|
||||
# Catch / Cleanup / Async — Join-Explicit CFG extensions
|
||||
|
||||
Status: Draft(design SSOT candidate)
|
||||
Last updated: 2025-12-20
|
||||
|
||||
Related:
|
||||
- North star: `docs/development/current/main/design/join-explicit-cfg-construction.md`
|
||||
- Phase 260 roadmap: `docs/development/current/main/phases/phase-260/README.md`
|
||||
|
||||
## 目的
|
||||
|
||||
Nyash/Hakorune の表面文法(主に postfix `catch/cleanup`)に合わせて、例外/後始末/中断(async)を追加するときに JoinIR→MIR の暗黙ABI(推測/メタ/例外的分岐)を再増殖させないための設計メモ。
|
||||
|
||||
注: `try { ... }` は言語資料上は legacy/非推奨として扱われることがあるが、この設計は **`try` の存在を前提にしない**(catch/cleanup を正規化の入口にする)。
|
||||
|
||||
ポイントは 2 つだけ:
|
||||
|
||||
1. **制御フローは edge を明示し、値は edge-args(block params)で運ぶ**
|
||||
2. **“意味SSOT” と “配線SSOT” を分離し、Fail-Fast の verify を常設する**
|
||||
|
||||
## 実装タイミング(推奨)
|
||||
|
||||
前提(Phase 260 で固める):
|
||||
|
||||
- MIR で edge-args が terminator operand にあり、`BasicBlock.jump_args` に依存しない(併存→移行→削除の P2 到達が理想)
|
||||
- “読む側” の参照点が `out_edges()`/`edge_args_to(target)` に一本化されている(Branch 含む)
|
||||
- “書く側” の terminator 設定が API で一元化されている(successors キャッシュ同期漏れを構造で潰している)
|
||||
- DCE/verify/printer が terminator operand を SSOT として扱う(メタ追いが不要)
|
||||
|
||||
順序(迷子が減る順):
|
||||
|
||||
1. `catch/cleanup`(例外): `Invoke(ok_edge, err_edge)` を追加(例外 edge を明示)
|
||||
2. `cleanup/defer`(後始末): “脱出 edge 正規化” を追加(Return/Throw/Break/Continue を cleanup に寄せる)
|
||||
3. `async/await`: CFG 語彙に混ぜず **state-machine lowering**(AsyncLowerBox)で分離
|
||||
|
||||
## 用語(この文書の範囲)
|
||||
|
||||
- **edge-args**: branch/jump の edge に紐づく引数。ターゲット block の params と 1:1 で対応する。
|
||||
- **Invoke**: 正常継続(ok)と例外継続(err)を持つ呼び出し terminator。
|
||||
- **cleanup normalizer**: cleanup/defer を実現するために「スコープ外へ出る edge」を cleanup ブロックに集約する正規化箱。
|
||||
- **async lowering**: `await` を state machine に落としてから CFG(MIR)にする箱。
|
||||
|
||||
## catch(最小語彙:例外 edge)
|
||||
|
||||
### 目標
|
||||
|
||||
- 例外経路を “暗黙” にせず、CFG の edge として明示する。
|
||||
- 例外値は catch block の params(edge-args)で受ける。
|
||||
|
||||
### 最小追加語彙(案)
|
||||
|
||||
- `MirTerminator::Invoke { callee, args, ok: (bb_ok, ok_args), err: (bb_err, err_args) }`
|
||||
|
||||
設計ノート:
|
||||
|
||||
- ok/err 両方が必須(片側欠落を許さない)
|
||||
- ok/err の args は “役割付きABI” で解釈する(将来 `JoinAbi`/`ContSigId` へ)
|
||||
|
||||
### throw の扱い(最小)
|
||||
|
||||
MIR で `Throw` を増やさずに済む形:
|
||||
|
||||
- 正規化(Normalizer)が “現在の例外継続” を知っており、`throw e` を `Jump(unwind_bb, [e, ...])` に正規化する
|
||||
|
||||
### verify(Fail-Fast)
|
||||
|
||||
- `Invoke` は terminator(block の最後)であること
|
||||
- ok/err のターゲット block params と args の数が一致すること
|
||||
- err 側の先頭 param は例外値(role=Exception)であること(最低限の役割固定)
|
||||
- “may_throw な呼び出し” を `Call` で表していないこと(暫定: 当面は全部 Invoke に倒しても良い)
|
||||
|
||||
## cleanup(脱出 edge 正規化)
|
||||
|
||||
### 目標(finally の後継としての cleanup)
|
||||
|
||||
- return/break/continue/throw 等の “脱出” を cleanup 経由に統一して、後始末漏れを構造で潰す。
|
||||
- 例外/return の payload は edge-args(block params)で運ぶ(PHI/メタに逃げない)。
|
||||
|
||||
### 最小形(案)
|
||||
|
||||
スコープ S ごとに次の 2 ブロック(または 1 ブロック + dispatch)を作る:
|
||||
|
||||
- `cleanup_entry_S(tag, payload..., carriers...)`
|
||||
- `cleanup_dispatch_S(tag, payload..., carriers...)`
|
||||
|
||||
`ExitTag`(例):
|
||||
|
||||
- `Return`
|
||||
- `Throw`
|
||||
- `Break`
|
||||
- `Continue`
|
||||
- `Cancel`(async の drop/cancel 用に予約)
|
||||
|
||||
### verify(Fail-Fast)
|
||||
|
||||
- S の内部ブロックから “S の外” への edge が存在したら落とす(例外: cleanup_dispatch のみ)
|
||||
- `Invoke.err` など “例外 edge” も漏れなく cleanup に寄せられていること
|
||||
- `ExitTag` の分岐が未処理になっていないこと(Unknown は即死)
|
||||
|
||||
## async/await(state machine lowering)
|
||||
|
||||
### 目標
|
||||
|
||||
- `await` を CFG 語彙に混ぜず、AsyncLowerBox が責務として消す(残ったら verify で即死)。
|
||||
- cancel/drop が必要なら `ExitTag::Cancel` と cleanup を接続して後始末を一貫化する。
|
||||
|
||||
### 最小インターフェース(案)
|
||||
|
||||
- `await` は “前段IR(AsyncPrep)” にのみ存在してよい
|
||||
- AsyncLowerBox で state machine 化した後、MIR は `Jump/Branch/Return/Invoke/Call` の語彙だけにする
|
||||
|
||||
### verify(Fail-Fast)
|
||||
|
||||
- AsyncLowerBox 後に `await` が 1 つでも残っていたら落とす
|
||||
- state dispatch が全 state をカバーしていること(未到達 state は削除可)
|
||||
Reference in New Issue
Block a user