restore(lang): full lang tree from ff3ef452 (306 files) — compiler, vm, shared, runner, c-abi, etc.\n\n- Restores lang/ directory (files≈306, dirs≈64) as per historical branch with selfhost sources\n- Keeps our recent parser index changes in compiler/* (merged clean by checkout)\n- Unblocks selfhost development and documentation references
This commit is contained in:
162
lang/src/llvm_ir/boxes/aot_prep.hako
Normal file
162
lang/src/llvm_ir/boxes/aot_prep.hako
Normal file
@ -0,0 +1,162 @@
|
||||
// aot_prep.hako — AotPrepBox (pre-MIR normalizer/optimizer; skeleton)
|
||||
// 入出力(最小仕様)
|
||||
// - AotPrepBox.prep/1(json_in_path: String) -> String (json_out_path)
|
||||
// 責務
|
||||
// - JSON(MIR v0) の軽量正規化(キー順/冗長キー削除)と安全な const/binop(+,-,*)/ret の単一ブロック畳み込み
|
||||
// - 既定ではパススルー(Rust 側 maybe_prepare_mir_json が実体)。段階的にこちらへ移管する
|
||||
|
||||
using "lang/src/shared/mir/mir_io_box.hako" as MirIoBox
|
||||
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
|
||||
static box AotPrepBox {
|
||||
// AotPrepBox.prep
|
||||
// 入力: JSONファイルパス(MIR v0)
|
||||
// 出力: 正規化後のJSONを書き出したパス(<in>.prep.json)。失敗時は入力パスを返す(Fail‑FastはRust側が継続)。
|
||||
prep(json_in_path) {
|
||||
if !json_in_path { return json_in_path }
|
||||
// Read input
|
||||
local fb = new FileBox()
|
||||
fb.open(json_in_path, "r")
|
||||
local src = fb.read()
|
||||
fb.close()
|
||||
if !src { return json_in_path }
|
||||
|
||||
// Phase‑1: 文字列正規化(安定化)
|
||||
// いまは canonicalize は恒等(将来はHostBridgeでキー順安定化)
|
||||
local canon = MirIoBox.normalize(src)
|
||||
|
||||
// Phase‑2: 安全な単一ブロック const/binop(+,-,*)/ret の畳み込み(最小実装)
|
||||
// 備考: まずは main 関数を優先対象とし、成立時のみ最小 JSON に置換(今後は in‑place 置換へ段階移行)。
|
||||
local out = AotPrepBox._try_fold_const_binop_ret(canon)
|
||||
if !out { out = canon }
|
||||
|
||||
// Decide output path
|
||||
local out_path = json_in_path + ".prep.json"
|
||||
fb.open(out_path, "w")
|
||||
fb.write(out)
|
||||
fb.close()
|
||||
return out_path
|
||||
}
|
||||
|
||||
// 内部: 最小の安全畳み込み(JSON文字列ベース)
|
||||
_try_fold_const_binop_ret(json) {
|
||||
if !json { return null }
|
||||
// Helper: find the [ ... ] span of the first block's instructions for the function near `start_from`.
|
||||
local find_instr_span_from = fun(s, start_from) {
|
||||
local key = "\"instructions\":["
|
||||
local pos = s.indexOf(key, start_from)
|
||||
if pos < 0 { return [-1, -1] }
|
||||
local ls = s.indexOf("[", pos)
|
||||
if ls < 0 { return [-1, -1] }
|
||||
local depth = 0
|
||||
local i = ls
|
||||
local L = s.size()
|
||||
local rs = -1
|
||||
loop(i < L) {
|
||||
local ch = s.substring(i, i+1)
|
||||
if ch == "[" { depth = depth + 1 }
|
||||
if ch == "]" { depth = depth - 1; if depth == 0 { rs = i; break } }
|
||||
i = i + 1
|
||||
}
|
||||
return [ls, rs]
|
||||
}
|
||||
// Helper: attempt to fold within a given [arr_start, arr_end] span; return replaced JSON on success
|
||||
local try_fold_in_span = fun(s, arr_start, arr_end) {
|
||||
if arr_start < 0 || arr_end < 0 { return null }
|
||||
local body = s.substring(arr_start, arr_end+1)
|
||||
// Need two const, a binop, and a ret in this span
|
||||
local p1 = body.indexOf("\"op\":\"const\"")
|
||||
local p2 = body.indexOf("\"op\":\"const\"", (p1>=0 ? (p1+1) : 0))
|
||||
local pb = body.indexOf("\"op\":\"binop\"", (p2>=0 ? (p2+1) : 0))
|
||||
local pr = body.indexOf("\"op\":\"ret\"", (pb>=0 ? (pb+1) : 0))
|
||||
if p1 < 0 || p2 < 0 || pb < 0 || pr < 0 { return null }
|
||||
// parse helpers within body
|
||||
local parse_dst = fun(ss, pos) {
|
||||
local k = "\"dst\":"
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return -1 }
|
||||
i = i + k.size()
|
||||
local digs = StringHelpers.read_digits(ss, i)
|
||||
if digs == "" { return -1 }
|
||||
return StringHelpers.to_i64(digs)
|
||||
}
|
||||
local parse_val = fun(ss, pos) {
|
||||
local k = "\"value\":{\"type\":\"i64\",\"value\":"
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return null }
|
||||
i = i + k.size()
|
||||
local digs = StringHelpers.read_digits(ss, i)
|
||||
if digs == "" { return null }
|
||||
return StringHelpers.to_i64(digs)
|
||||
}
|
||||
local d1 = parse_dst(body, p1)
|
||||
local a = parse_val(body, p1)
|
||||
local d2 = parse_dst(body, p2)
|
||||
local b = parse_val(body, p2)
|
||||
if d1 < 0 || d2 < 0 || a == null || b == null { return null }
|
||||
local find_num = fun(ss, key, pos) {
|
||||
local k = key
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return -1 }
|
||||
i = i + k.size()
|
||||
local digs = StringHelpers.read_digits(ss, i)
|
||||
if digs == "" { return -1 }
|
||||
return StringHelpers.to_i64(digs)
|
||||
}
|
||||
local find_op = fun(ss, pos) {
|
||||
local k = "\"operation\":\""
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return "" }
|
||||
i = i + k.size()
|
||||
local j = ss.indexOf("\"", i)
|
||||
if j < 0 { return "" }
|
||||
return ss.substring(i, j)
|
||||
}
|
||||
local lhs = find_num(body, "\"lhs\":", pb)
|
||||
local rhs = find_num(body, "\"rhs\":", pb)
|
||||
local bop = find_op(body, pb)
|
||||
local d3 = find_num(body, "\"dst\":", pb)
|
||||
if lhs != d1 || rhs != d2 || d3 < 0 { return null }
|
||||
local rv = find_num(body, "\"value\":", pr)
|
||||
if rv != d3 { return null }
|
||||
// binop allowed: +,-,* only
|
||||
local res = 0
|
||||
if bop == "+" { res = a + b } else { if bop == "-" { res = a - b } else { if bop == "*" { res = a * b } else { return null } } }
|
||||
// build new array and replace in-place
|
||||
local new_insts = "[" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + StringHelpers.int_to_str(d1) + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + StringHelpers.int_to_str(res) + "}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":" + StringHelpers.int_to_str(d1) + "}]"
|
||||
local head = s.substring(0, arr_start)
|
||||
local tail = s.substring(arr_end + 1, s.size())
|
||||
return head + new_insts + tail
|
||||
}
|
||||
// Pass 1: prefer name:"main"
|
||||
local fn_pos = json.indexOf("\"name\":\"main\"")
|
||||
if fn_pos >= 0 {
|
||||
local span = find_instr_span_from(json, fn_pos)
|
||||
local ls = span[0]; local rs = span[1]
|
||||
local repl = try_fold_in_span(json, ls, rs)
|
||||
if repl { return repl }
|
||||
}
|
||||
// Pass 2: scan functions sequentially and attempt per function
|
||||
local froot = json.indexOf("\"functions\":[")
|
||||
if froot < 0 { return null }
|
||||
local scan = froot
|
||||
local tries = 0
|
||||
loop(tries < 16) {
|
||||
local np = json.indexOf("\"name\":\"", scan+1)
|
||||
if np < 0 { break }
|
||||
local span2 = find_instr_span_from(json, np)
|
||||
local ls2 = span2[0]; local rs2 = span2[1]
|
||||
if ls2 >= 0 && rs2 >= 0 {
|
||||
local repl2 = try_fold_in_span(json, ls2, rs2)
|
||||
if repl2 { return repl2 }
|
||||
scan = rs2 + 1
|
||||
} else {
|
||||
scan = np + 8
|
||||
}
|
||||
tries = tries + 1
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user