Files
hakorune/lang/src/compiler/pipeline_v2/local_ssa_box.hako
nyash-codex 5e3d9e7ae4 restore(lang/compiler): bring back lang/src/compiler from e917d400; add Hako index canaries and docs; implement Rust-side index operator (Array/Map get/set) with Fail‑Fast diagnostics
- restore: lang/src/compiler/** (parser/emit/builder/pipeline_v2) from e917d400
- docs: docs/development/selfhosting/index-operator-hako.md
- smokes(hako): tools/smokes/v2/profiles/quick/core/index_operator_hako.sh (opt-in)
- smokes(vm): adjust index_operator_vm.sh for semicolon gate + stable error text
- rust/parser: allow IndexExpr and assignment LHS=Index; postfix parse LBRACK chain
- rust/builder: lower arr/map index to BoxCall get/set; annotate array/map literals; Fail‑Fast for unsupported types
- CURRENT_TASK: mark Rust side done; add Hako tasks checklist

Note: files disappeared likely due to branch FF to a lineage without lang/src/compiler; no explicit delete commit found. Added anchor checks and suggested CI guard in follow-up.
2025-10-31 20:18:39 +09:00

189 lines
6.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// LocalSSABox — 材化materialize/Copy 挿入の最小ポリシーを集約
// Phase 15.7: 最小実装。将来 PHI/Call 前の規約をここに集約して拡張する。
using "lang/src/shared/common/box_helpers.hako" as BoxHelpers
static box LocalSSABox {
_maybe_unwrap_instructions(insts) {
if insts == null { return null }
local repr = "" + insts
if repr.indexOf("MapBox(") == 0 {
local inner = BoxHelpers.map_get(insts, "instructions")
if inner != null { return inner }
}
return insts
}
// 汎用: copy 命令を instsArrayBox of Map末尾に追加
add_copy(insts, dst, src) {
if insts == null { return 1 }
insts = me._maybe_unwrap_instructions(insts)
if insts == null { return 1 }
call("ArrayBox.push/2", insts, { op:"copy", dst: dst, src: src })
return 0
}
// PHI直後の材化最小: いまは add_copy と同じ。将来 PHI 群スキップを実装
ensure_after_phis_copy(insts, src, dst) {
if insts == null { return 1 }
insts = me._maybe_unwrap_instructions(insts)
if insts == null { return 1 }
if BoxHelpers.is_array(insts) == 0 {
return me.add_copy(insts, dst, src)
}
local n = BoxHelpers.array_len(insts)
local i = 0
loop (i < n) {
local ins = BoxHelpers.array_get(insts, i)
if ins == null { break }
local op = BoxHelpers.map_get(ins, "op")
if op == null || op != "phi" { break }
i = i + 1
}
local insert_at = i // phi 直後
local node = { op:"copy", dst: dst, src: src }
if insert_at >= n {
call("ArrayBox.push/2", insts, node)
return 0
}
if n > 0 {
call("ArrayBox.push/2", insts, BoxHelpers.array_get(insts, n - 1))
local j = n - 1
loop (j >= insert_at) {
call("ArrayBox.set/3", insts, j + 1, BoxHelpers.array_get(insts, j))
j = j - 1
}
call("ArrayBox.set/3", insts, insert_at, node)
return 0
}
call("ArrayBox.push/2", insts, node)
return 0
}
// 新規: 定義直後に copy を挿入(安全・最小)
ensure_after_last_def_copy(insts, src, dst) {
if insts == null { return 1 }
if BoxHelpers.is_array(insts) == 0 { return 1 }
local n = BoxHelpers.array_len(insts)
local insert_at = n
// Find the first terminator index (ret/branch/jump/throw) to ensure block ends with a terminator
local term_at = n
{
local i = 0
loop(i < n) {
local ins = BoxHelpers.array_get(insts, i)
if ins != null {
local op = BoxHelpers.map_get(ins, "op")
if op == "ret" || op == "branch" || op == "jump" || op == "throw" { term_at = i break }
}
i = i + 1
}
}
// 探索: 最後に dst=src を定義した位置
{
local i = 0
loop (i < n) {
local ins = BoxHelpers.array_get(insts, i)
if ins != null {
print("[LS] checking def ins=" + ("" + ins))
local d_raw = BoxHelpers.map_get(ins, "dst")
print("[LS] dst raw=" + ("" + d_raw))
local d = BoxHelpers.value_i64(d_raw)
if d != null && d == src { insert_at = i + 1 }
}
i = i + 1
}
}
// Do not cross terminator: insert before the first terminator if present
if insert_at > term_at { insert_at = term_at }
local node = { op:"copy", dst: dst, src: src }
if insert_at >= n { call("ArrayBox.push/2", insts, node) return 0 }
// 1つ末尾に空きを作る末尾要素を複製して押し出す
if n > 0 {
call("ArrayBox.push/2", insts, BoxHelpers.array_get(insts, n - 1))
local j = n - 1
loop (j >= insert_at) {
call("ArrayBox.set/3", insts, j + 1, BoxHelpers.array_get(insts, j))
j = j - 1
}
call("ArrayBox.set/3", insts, insert_at, node)
return 0
}
call("ArrayBox.push/2", insts, node)
return 0
}
// calls の最小材化: 最後の ret が参照する値 src を探し、src の直後に copy(dst=src+1) を挿入する。
// mod_full: { functions: [ { blocks: [ { instructions: [...] } ] } ] }
ensure_materialize_last_ret(mod_full) {
if mod_full == null { return 1 }
local fns = BoxHelpers.map_get(mod_full, "functions")
if fns == null || BoxHelpers.array_len(fns) == 0 { return 1 }
local blocks = BoxHelpers.map_get(BoxHelpers.array_get(fns, 0), "blocks")
if blocks == null || BoxHelpers.array_len(blocks) == 0 { return 1 }
local insts = BoxHelpers.map_get(BoxHelpers.array_get(blocks, 0), "instructions")
if insts == null || BoxHelpers.array_len(insts) == 0 { return 1 }
// ret の引数を探索
local n = BoxHelpers.array_len(insts)
local src = null
{
local i = 0
loop(i < n) {
local ins = BoxHelpers.array_get(insts, i)
if ins != null {
local op = BoxHelpers.map_get(ins, "op")
if op == "ret" {
src = BoxHelpers.value_i64(BoxHelpers.map_get(ins, "value"))
}
}
i = i + 1
}
}
if src == null { return 1 }
return me.ensure_after_last_def_copy(insts, src, src + 1)
}
// ensure_cond: 最初の branch の cond を検出し、その定義直後に copy を1つ挿入最小
// - 形状期待: いずれかの block.instructions に { op:"branch", cond:<id>, ... }
ensure_cond(mod_full) {
if mod_full == null { return 1 }
local fns = BoxHelpers.map_get(mod_full, "functions")
if fns == null { return 1 }
local bn = BoxHelpers.array_len(fns)
if bn == 0 { return 1 }
local blocks = BoxHelpers.map_get(BoxHelpers.array_get(fns, 0), "blocks")
if blocks == null || BoxHelpers.array_len(blocks) == 0 { return 1 }
// 探索: 各ブロックの instructions から最初の branch を見つけ、そのブロックで材化
local bi = 0
local block_count = BoxHelpers.array_len(blocks)
loop (bi < block_count) {
local insts = BoxHelpers.map_get(BoxHelpers.array_get(blocks, bi), "instructions")
local insts_len = BoxHelpers.array_len(insts)
if insts_len > 0 {
local n = insts_len
local cond = null
{
local i = 0
loop(i < n) {
local ins = BoxHelpers.array_get(insts, i)
if ins != null {
local op = BoxHelpers.map_get(ins, "op")
if op == "branch" {
cond = BoxHelpers.value_i64(BoxHelpers.map_get(ins, "cond"))
break
}
}
i = i + 1
}
}
if cond != null { return me.ensure_after_last_def_copy(insts, cond, cond + 2) }
}
bi = bi + 1
}
return 1
}
}
static box LocalSSAStub { main(args) { return 0 } }