**Region Box統一理論の実装開始**
新規追加:
- src/mir/region/mod.rs: Region/RefSlotKind型定義
- src/mir/region/observer.rs: Region観測レイヤー
- docs/development/roadmap/phases/phase-25.1l/: 設計ドキュメント
主要概念:
- Region Box = Function/Loop/If の統一箱
- RefSlotKind = GC管理用スロット種別(Strong/Weak/Borrowed/NonRef)
- 観測専用(NYASH_REGION_TRACE=1で動作、挙動変更なし)
設計理解の深化:
- ValueId(40)問題 = LoopForm v2スコープ契約違反の症状
- 根本解決 = Region観測で無名一時値のスコープまたぎを検出
- 箱理論3原則: 境界明確化/差し替え可能/段階的移行
関連議論:
- ChatGPT提案: Region統一理論でGC/寿命管理の基盤構築
- SlotRegistry: 変数の単一真実源(SSOT)
- 階層構造: FunctionRegion → LoopRegion → IfRegion
次のステップ:
- Phase 1: Region観測(現在)- 非破壊的追加
- Phase 2: メタデータ出力(MIR JSON拡張)
- Phase 3: GC統合(retain/release挿入)
テスト追加:
- lang/src/compiler/tests/stageb_mini_driver.hako
- tools/test_loopssa_breakfinder_slot.sh
Build: ✅ 全警告は既存のもの
Tests: 既存テスト全て緑維持
75 lines
3.0 KiB
Plaintext
75 lines
3.0 KiB
Plaintext
// LoopSSA - Exit PHI Generation for Loops with Breaks
|
||
// Purpose:
|
||
// - Stage‑1 Program(JSON v0) に対して、loop + break パターンを検出し、
|
||
// exit block に PHI 相当の命令を注入する「SSA 補強フェーズ」の入口だよ。
|
||
// - 自身はオーケストレータ箱として振る舞い、実際の解析/変換は
|
||
// BreakFinderBox / PhiInjectorBox に委譲するよ。
|
||
// Policy:
|
||
// - 入力: Stage‑1 Program(JSON v0)(単一関数 or Program 全体)。
|
||
// - 出力: exit PHI 相当の命令が入った Program(JSON v0)(文字列)。
|
||
// - 解析: BreakFinderBox.find_breaks(json, trace_flag) が JSON を読み取り専用で解析。
|
||
// - 変換: PhiInjectorBox.inject_exit_phis(json, breaks, trace_flag) が exit block をテキストベースで書き換える。
|
||
// - 環境変数/トレース:
|
||
// - HAKO_LOOPSSA_TRACE=1 : LoopSSA/BreakFinder/PhiInjector 専用のトレースON
|
||
// - HAKO_COMPILER_BUILDER_TRACE=1 : (後方互換)未設定時のフォールバックとして扱う
|
||
// LoopSSA 側で trace_flag を 0/1 に正規化し、下流には数値だけを渡す(箱ごとに ENV を直読しない)。
|
||
|
||
using lang.compiler.builder.ssa.exit_phi.break_finder as BreakFinderBox
|
||
using lang.compiler.builder.ssa.exit_phi.phi_injector as PhiInjectorBox
|
||
|
||
static box LoopSSA {
|
||
// Main entry: Guard PHI-like merges at loop headers/exits
|
||
// Phase 2-5 implementation: detect breaks and inject exit PHIs
|
||
stabilize_merges(stage1_json) {
|
||
// Resolve trace flag once at the entry point(0/1 に正規化)
|
||
// 優先: HAKO_LOOPSSA_TRACE / 後方互換: HAKO_COMPILER_BUILDER_TRACE
|
||
local trace_env = env.get("HAKO_LOOPSSA_TRACE")
|
||
if trace_env == null {
|
||
trace_env = env.get("HAKO_COMPILER_BUILDER_TRACE")
|
||
}
|
||
local trace_flag = 0
|
||
if trace_env != null && ("" + trace_env) == "1" { trace_flag = 1 }
|
||
|
||
if trace_flag == 1 {
|
||
print("[loopssa] stabilize_merges start")
|
||
}
|
||
|
||
// Check if exit PHI feature is enabled
|
||
local enable_exit_phi = 1
|
||
{
|
||
local flag = env.get("HAKO_LOOPSSA_EXIT_PHI")
|
||
if flag != null && ("" + flag) == "0" { enable_exit_phi = 0 }
|
||
}
|
||
|
||
if enable_exit_phi == 0 {
|
||
if trace_flag == 1 {
|
||
print("[loopssa] exit PHI disabled, pass-through")
|
||
}
|
||
return stage1_json
|
||
}
|
||
|
||
// Phase 2: Find breaks in loops
|
||
local breaks = BreakFinderBox.find_breaks(stage1_json, trace_flag)
|
||
|
||
if trace_flag == 1 {
|
||
print("[loopssa] found " + breaks.length() + " breaks")
|
||
}
|
||
|
||
if breaks.length() == 0 {
|
||
if trace_flag == 1 {
|
||
print("[loopssa] no breaks found, pass-through")
|
||
}
|
||
return stage1_json
|
||
}
|
||
|
||
// Phase 3: Inject PHI nodes at exit blocks
|
||
local result = PhiInjectorBox.inject_exit_phis(stage1_json, breaks, trace_flag)
|
||
|
||
if trace_flag == 1 {
|
||
print("[loopssa] exit PHIs injected successfully")
|
||
}
|
||
|
||
return result
|
||
}
|
||
}
|