Phase 100: Pinned Read‑Only Captures(設計メモ)
目的
JoinIR lowering のスコープ解決(ConditionEnv → LoopBodyLocalEnv → CapturedEnv)の前提を崩さずに、
「ループ外で定義した local(動的式でも可)」をループ内で receiver として参照できるようにする。
例(問題の形):
local s = "a" + "b" // 条件式とは無関係
loop(i < n) {
local ch = s.substring(i, i + 1) // receiver 解決が必要
}
方針(SSOT)
- “Pinned local” は 新しい Pattern ではなく、ループに入ってくる read‑only 入力として扱う。
- SSOT は増やさず
CapturedEnvに統合し、CapturedKindで区別する:Explicit: 従来の capturePinned: ループ内参照のために必要な read‑only local
Fail‑Fast 契約
Pinnedは loop body 内で 再代入されない(assignment target に現れたら拒否)。- loop entry 時点で host 側 ValueId が存在する(
variable_mapに無い場合は拒否)。 - 初期化が loop より後にある等、支配関係が曖昧な場合は拒否(理由付き)。
- init 式の副作用有無は問わない(評価はホスト側で1回、Pinned は値を渡すだけ)。
Loop Canonicalizer との関係(混ぜない)
- Phase 100 は「ループ外の値が loop 内で見えない」問題(capture/wiring)を解く。
- Loop Canonicalizer は「ループ内の不変式を外に出す」AST 変換であり、別ユースケース。