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:
439
lang/src/shared/json/mir_builder_min.hako
Normal file
439
lang/src/shared/json/mir_builder_min.hako
Normal file
@ -0,0 +1,439 @@
|
||||
// mir_builder_min.nyash — Minimal MIR(JSON v0) builder for selfhost tests
|
||||
// Scope: selfhost only (apps/selfhost/...); no core/runtime changes.
|
||||
|
||||
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
using "lang/src/shared/common/box_helpers.hako" as BoxHelpers
|
||||
using lang.compiler.emit.common.json_emit as JsonEmitBox
|
||||
using lang.compiler.emit.common.mir_emit as MirEmitBox
|
||||
using lang.compiler.emit.common.call_emit as CallEmitBox
|
||||
using lang.compiler.emit.common.newbox_emit as NewBoxEmitBox
|
||||
using "lang/src/shared/json/json_inst_encode_box.hako" as JsonInstEncodeBox
|
||||
|
||||
box MirJsonBuilderMin {
|
||||
buf: StringBox
|
||||
phase: IntegerBox
|
||||
first_inst: IntegerBox
|
||||
blocks: ArrayBox
|
||||
cur_block_index: IntegerBox
|
||||
fn_name: StringBox
|
||||
trace: IntegerBox
|
||||
verify: IntegerBox
|
||||
|
||||
birth() {
|
||||
me.buf = ""
|
||||
me.phase = 0
|
||||
me.first_inst = 1
|
||||
me.blocks = new ArrayBox()
|
||||
me.cur_block_index = -1
|
||||
me.fn_name = ""
|
||||
me.trace = 0
|
||||
me.verify = 0
|
||||
}
|
||||
|
||||
// Internal helpers
|
||||
_get_buf() { return me.buf }
|
||||
_set_buf(s) { me.buf = s return me }
|
||||
_append(s) {
|
||||
me.buf = me.buf + s
|
||||
return me
|
||||
}
|
||||
_int_to_str(n) { return StringHelpers.int_to_str(n) }
|
||||
_to_i64(x) { return StringHelpers.to_i64(x) }
|
||||
|
||||
_quote(s) { return StringHelpers.json_quote(s) }
|
||||
|
||||
_ids_range_json(start, count) {
|
||||
local i = 0
|
||||
local out = "["
|
||||
loop (i < count) {
|
||||
if i > 0 { out = out + "," }
|
||||
out = out + me._int_to_str(start + i)
|
||||
i = i + 1
|
||||
}
|
||||
out = out + "]"
|
||||
return out
|
||||
}
|
||||
|
||||
_ids_array_from_json_text(arr_text) {
|
||||
local out = new ArrayBox()
|
||||
if arr_text == null { return out }
|
||||
local s = "" + arr_text
|
||||
local i = 0
|
||||
loop (i < s.size()) {
|
||||
local ch = s.substring(i, i+1)
|
||||
if ch >= "0" && ch <= "9" {
|
||||
local j = i
|
||||
loop (j < s.size()) {
|
||||
local cj = s.substring(j, j+1)
|
||||
if !(cj >= "0" && cj <= "9") { break }
|
||||
j = j + 1
|
||||
}
|
||||
local num = me._to_i64(s.substring(i, j))
|
||||
out.push(num)
|
||||
i = j
|
||||
} else {
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
_ensure_phase(want) {
|
||||
if me.phase + 1 < want { return me }
|
||||
return me
|
||||
}
|
||||
|
||||
// Public builder steps
|
||||
start_module() {
|
||||
if me.trace == 1 { print("[DEBUG start_module] starting") }
|
||||
me.phase = 1
|
||||
return me._append("{\"functions\":[")
|
||||
}
|
||||
|
||||
start_function(name) {
|
||||
if me.trace == 1 { print("[DEBUG start_function] name=" + name) }
|
||||
me.phase = 2
|
||||
me.fn_name = name
|
||||
me.blocks = new ArrayBox()
|
||||
me.cur_block_index = -1
|
||||
if me.trace == 1 { print("[DEBUG start_function] after set, fn_name=" + me.fn_name) }
|
||||
local b = "{\"name\":" + me._quote(name) + ",\"params\":[],\"blocks\":["
|
||||
return me._append(b)
|
||||
}
|
||||
|
||||
start_block(id) {
|
||||
me.phase = 3
|
||||
me.first_inst = 1
|
||||
local blk = map({ id: id, instructions: new ArrayBox() })
|
||||
me.blocks.push(blk)
|
||||
me.cur_block_index = me.blocks.size() - 1
|
||||
local b = "{\"id\":" + me._int_to_str(id) + ",\"instructions\":["
|
||||
return me._append(b)
|
||||
}
|
||||
|
||||
end_block_continue() {
|
||||
return me._append("]},")
|
||||
}
|
||||
|
||||
_comma_if_needed() {
|
||||
if me.first_inst == 1 {
|
||||
me.first_inst = 0
|
||||
return me
|
||||
}
|
||||
return me._append(",")
|
||||
}
|
||||
|
||||
add_const(dst, val) {
|
||||
me._comma_if_needed()
|
||||
local node = MirEmitBox.make_const(dst, val)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_compare(kind, lhs, rhs, dst) {
|
||||
me._comma_if_needed()
|
||||
local node = MirEmitBox.make_compare(kind, lhs, rhs, dst)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_binop(kind, lhs, rhs, dst) {
|
||||
me._comma_if_needed()
|
||||
local node = { op:"binop", op_kind:kind, lhs:lhs, rhs:rhs, dst:dst }
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_ret(val) {
|
||||
me._comma_if_needed()
|
||||
local node = MirEmitBox.make_ret(val)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_call_ids(name, args_json_text, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = me._ids_array_from_json_text(args_json_text)
|
||||
local node = CallEmitBox.make_call(name, args, dst)
|
||||
node.set("args_text", args_json_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_call_range(name, start, count, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = new ArrayBox()
|
||||
local i = 0
|
||||
loop(i < count) {
|
||||
args.push(start + i)
|
||||
i = i + 1
|
||||
}
|
||||
local args_text = me._ids_range_json(start, count)
|
||||
local node = CallEmitBox.make_call(name, args, dst)
|
||||
node.set("args_text", args_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_boxcall_range(method, recv_id, args_start, count, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = new ArrayBox()
|
||||
local i = 0
|
||||
loop(i < count) {
|
||||
args.push(args_start + i)
|
||||
i = i + 1
|
||||
}
|
||||
local args_text = me._ids_range_json(args_start, count)
|
||||
local node = CallEmitBox.make_boxcall(method, recv_id, args, dst)
|
||||
node.set("args_text", args_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_newbox_range(box_type, args_start, count, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = new ArrayBox()
|
||||
local i = 0
|
||||
loop(i < count) {
|
||||
args.push(args_start + i)
|
||||
i = i + 1
|
||||
}
|
||||
local node = NewBoxEmitBox.with_args_array(NewBoxEmitBox.make_new(box_type, args, dst), args)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_newbox_ids(box_type, args_json_text, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = me._ids_array_from_json_text(args_json_text)
|
||||
local node = NewBoxEmitBox.make_new(box_type, args, dst)
|
||||
node = NewBoxEmitBox.with_args_text(node, args_json_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
_args_array_json_from_ids(ids_start, count) {
|
||||
return me._ids_range_json(ids_start, count)
|
||||
}
|
||||
|
||||
add_mir_call_global_ids(name, args_json_text, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = me._ids_array_from_json_text(args_json_text)
|
||||
local node = CallEmitBox.make_mir_call_global(name, args, dst)
|
||||
node.set("args_text", args_json_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_mir_call_extern_ids(name, args_json_text, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = me._ids_array_from_json_text(args_json_text)
|
||||
local node = CallEmitBox.make_mir_call_extern(name, args, dst)
|
||||
node.set("args_text", args_json_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_mir_call_method_ids(method, recv_id, args_json_text, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = me._ids_array_from_json_text(args_json_text)
|
||||
local node = CallEmitBox.make_mir_call_method(method, recv_id, args, dst)
|
||||
node.set("args_text", args_json_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_mir_call_constructor_ids(box_type, args_json_text, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = me._ids_array_from_json_text(args_json_text)
|
||||
local node = CallEmitBox.make_mir_call_constructor(box_type, args, dst)
|
||||
node.set("args_text", args_json_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_mir_call_global_range(name, start, count, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = new ArrayBox()
|
||||
local i = 0
|
||||
loop(i < count) {
|
||||
args.push(start + i)
|
||||
i = i + 1
|
||||
}
|
||||
local args_text = me._ids_range_json(start, count)
|
||||
local node = CallEmitBox.make_mir_call_global(name, args, dst)
|
||||
node.set("args_text", args_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_mir_call_extern_range(name, start, count, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = new ArrayBox()
|
||||
local i = 0
|
||||
loop(i < count) { args.push(start + i) i = i + 1 }
|
||||
local args_text = me._ids_range_json(start, count)
|
||||
local node = CallEmitBox.make_mir_call_extern(name, args, dst)
|
||||
node.set("args_text", args_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_mir_call_method_range(method, recv_id, args_start, count, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = new ArrayBox()
|
||||
local i = 0
|
||||
loop(i < count) {
|
||||
args.push(args_start + i)
|
||||
i = i + 1
|
||||
}
|
||||
local args_text = me._ids_range_json(args_start, count)
|
||||
local node = CallEmitBox.make_mir_call_method(method, recv_id, args, dst)
|
||||
node.set("args_text", args_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_mir_call_constructor_range(box_type, args_start, count, dst) {
|
||||
me._comma_if_needed()
|
||||
local args = new ArrayBox()
|
||||
local i = 0
|
||||
loop(i < count) {
|
||||
args.push(args_start + i)
|
||||
i = i + 1
|
||||
}
|
||||
local args_text = me._ids_range_json(args_start, count)
|
||||
local node = CallEmitBox.make_mir_call_constructor(box_type, args, dst)
|
||||
node.set("args_text", args_text)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_branch(cond, then_id, else_id) {
|
||||
me._comma_if_needed()
|
||||
local node = MirEmitBox.make_branch(cond, then_id, else_id)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_jump(target) {
|
||||
me._comma_if_needed()
|
||||
local node = MirEmitBox.make_jump(target)
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
add_copy(dst, src) {
|
||||
me._comma_if_needed()
|
||||
local node = { op:"copy", dst:dst, src:src }
|
||||
me._push_inst_map(node)
|
||||
return me._append(JsonEmitBox.to_json(node))
|
||||
}
|
||||
|
||||
end_all() {
|
||||
me.phase = 5
|
||||
return me._append("]}]}]}")
|
||||
}
|
||||
|
||||
to_string() { return me._get_buf() }
|
||||
|
||||
_cur_insts() {
|
||||
local blks = me.blocks
|
||||
if blks == null { return null }
|
||||
local n = 0
|
||||
n = BoxHelpers.array_len(blks)
|
||||
if n <= 0 { return null }
|
||||
local idx = me.cur_block_index
|
||||
if idx == null { idx = -1 }
|
||||
if idx < 0 || idx >= n { idx = n - 1 }
|
||||
local blk = BoxHelpers.array_get(blks, idx)
|
||||
if blk == null { return null }
|
||||
return BoxHelpers.map_get(blk, "instructions")
|
||||
}
|
||||
|
||||
verify_builder_state() { return 0 }
|
||||
|
||||
_verify_enabled() {
|
||||
return me.verify
|
||||
}
|
||||
|
||||
_trace_enabled() {
|
||||
return me.trace
|
||||
}
|
||||
|
||||
_push_inst(node) {
|
||||
local before = 0
|
||||
local insts0 = me._cur_insts()
|
||||
before = BoxHelpers.array_len(insts0)
|
||||
if insts0 == null || insts0.push == null { return }
|
||||
insts0.push(node)
|
||||
if me._verify_enabled() == 1 {
|
||||
local insts1 = me._cur_insts()
|
||||
local after = BoxHelpers.array_len(insts1)
|
||||
local op_str = BoxHelpers.map_get(node, "op")
|
||||
if after != before + 1 { print("[builder-verify] size mismatch before=" + before + " after=" + after + " op=" + op_str) }
|
||||
}
|
||||
if me._trace_enabled() == 1 {
|
||||
local op_str_trace = BoxHelpers.map_get(node, "op")
|
||||
print("[builder-trace] push op=" + op_str_trace)
|
||||
}
|
||||
}
|
||||
|
||||
_push_inst_map(node) { return me._push_inst(node) }
|
||||
|
||||
enable_trace(on) {
|
||||
if on == null { on = 1 }
|
||||
me.trace = on
|
||||
return me
|
||||
}
|
||||
|
||||
enable_verify(on) {
|
||||
if on == null { on = 1 }
|
||||
me.verify = on
|
||||
return me
|
||||
}
|
||||
|
||||
get_current_instructions() { return me._cur_insts() }
|
||||
|
||||
get_blocks_array() { return me.blocks }
|
||||
|
||||
get_function_structure() {
|
||||
local blks = me.get_blocks_array()
|
||||
return map({ name: me.fn_name, params: new ArrayBox(), blocks: blks })
|
||||
}
|
||||
|
||||
emit_to_string() { return me.to_string() }
|
||||
|
||||
_inst_json(node) { return JsonInstEncodeBox.encode(node) }
|
||||
|
||||
to_string_rebuild() {
|
||||
local name = me.fn_name
|
||||
local blks = me.get_blocks_array()
|
||||
local blks_size_str = "null"
|
||||
local blks_len = BoxHelpers.array_len(blks)
|
||||
if blks_len >= 0 { blks_size_str = me._int_to_str(blks_len) }
|
||||
print("[DEBUG rebuild] fn_name=" + name + " blks.size()=" + blks_size_str)
|
||||
local out = "{\"functions\":[{\"name\":" + me._quote(name) + ",\"params\":[],\"blocks\":["
|
||||
local n = blks_len
|
||||
print("[DEBUG rebuild] n=" + me._int_to_str(n))
|
||||
local i = 0
|
||||
loop (i < n) {
|
||||
if i > 0 { out = out + "," }
|
||||
local blk = BoxHelpers.array_get(blks, i)
|
||||
local bid = BoxHelpers.map_get(blk, "id")
|
||||
out = out + "{\"id\":" + me._int_to_str(bid) + ",\"instructions\":["
|
||||
local insts = BoxHelpers.map_get(blk, "instructions")
|
||||
local m = BoxHelpers.array_len(insts)
|
||||
local j = 0
|
||||
loop (j < m) {
|
||||
if j > 0 { out = out + "," }
|
||||
out = out + me._inst_json(BoxHelpers.array_get(insts, j))
|
||||
j = j + 1
|
||||
}
|
||||
out = out + "]}"
|
||||
i = i + 1
|
||||
}
|
||||
out = out + "]}]}"
|
||||
return out
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user