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:
nyash-codex
2025-10-31 20:45:46 +09:00
parent dbc285f2b1
commit e5f697eb22
244 changed files with 16915 additions and 47 deletions

View 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。失敗時は入力パスを返すFailFastは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 }
// Phase1: 文字列正規化(安定化)
// いまは canonicalize は恒等将来はHostBridgeでキー順安定化
local canon = MirIoBox.normalize(src)
// Phase2: 安全な単一ブロック const/binop(+,-,*)/ret の畳み込み(最小実装)
// 備考: まずは main 関数を優先対象とし、成立時のみ最小 JSON に置換(今後は inplace 置換へ段階移行)。
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
}
}