Merge branch 'runtime_rework' into fix_gc

This commit is contained in:
2026-02-14 22:11:31 -06:00
46 changed files with 711117 additions and 120593 deletions

View File

@@ -28,6 +28,13 @@ var mcode = function(ast) {
"<<=": "shl", ">>=": "shr", ">>>=": "ushr"
}
var sensory_ops = {
is_array: "is_array", is_function: "is_func", is_object: "is_record",
is_stone: "is_stone", is_integer: "is_int", is_text: "is_text",
is_number: "is_num", is_logical: "is_bool", is_null: "is_null",
length: "length"
}
// Compiler state
var s_instructions = null
var s_data = null
@@ -584,7 +591,14 @@ var mcode = function(ast) {
// Central router: maps op string to decomposition helper
// Sets _bp_* closure vars then calls helper with reduced args
var relational_ops = {
lt: ["lt_int", "lt_float", "lt_text"],
le: ["le_int", "le_float", "le_text"],
gt: ["gt_int", "gt_float", "gt_text"],
ge: ["ge_int", "ge_float", "ge_text"]
}
var emit_binop = function(op_str, dest, left, right) {
var rel = null
_bp_dest = dest
_bp_left = left
_bp_right = right
@@ -594,20 +608,17 @@ var mcode = function(ast) {
emit_eq_decomposed()
} else if (op_str == "ne") {
emit_ne_decomposed()
} else if (op_str == "lt") {
emit_relational("lt_int", "lt_float", "lt_text")
} else if (op_str == "le") {
emit_relational("le_int", "le_float", "le_text")
} else if (op_str == "gt") {
emit_relational("gt_int", "gt_float", "gt_text")
} else if (op_str == "ge") {
emit_relational("ge_int", "ge_float", "ge_text")
} else if (op_str == "subtract" || op_str == "multiply" ||
op_str == "divide" || op_str == "modulo" || op_str == "pow") {
emit_numeric_binop(op_str)
} else {
// Passthrough for bitwise, in, etc.
emit_3(op_str, dest, left, right)
rel = relational_ops[op_str]
if (rel != null) {
emit_relational(rel[0], rel[1], rel[2])
} else if (op_str == "subtract" || op_str == "multiply" ||
op_str == "divide" || op_str == "modulo" || op_str == "pow") {
emit_numeric_binop(op_str)
} else {
// Passthrough for bitwise, in, etc.
emit_3(op_str, dest, left, right)
}
}
return null
}
@@ -1737,37 +1748,11 @@ var mcode = function(ast) {
fname = callee.name
nargs = args_list != null ? length(args_list) : 0
// 1-arg type check intrinsics → direct opcode
if (nargs == 1) {
if (fname == "is_array" || fname == "is_function" ||
fname == "is_object" || fname == "is_stone" ||
fname == "is_integer" || fname == "is_text" ||
fname == "is_number" || fname == "is_logical" ||
fname == "is_null" || fname == "length") {
if (nargs == 1 && sensory_ops[fname] != null) {
a0 = gen_expr(args_list[0], -1)
d = alloc_slot()
if (fname == "is_array") {
emit_2("is_array", d, a0)
} else if (fname == "is_function") {
emit_2("is_func", d, a0)
} else if (fname == "is_object") {
emit_2("is_record", d, a0)
} else if (fname == "is_stone") {
emit_2("is_stone", d, a0)
} else if (fname == "is_integer") {
emit_2("is_int", d, a0)
} else if (fname == "is_text") {
emit_2("is_text", d, a0)
} else if (fname == "is_number") {
emit_2("is_num", d, a0)
} else if (fname == "is_logical") {
emit_2("is_bool", d, a0)
} else if (fname == "is_null") {
emit_2("is_null", d, a0)
} else if (fname == "length") {
emit_2("length", d, a0)
}
emit_2(sensory_ops[fname], d, a0)
return d
}
}
// 2-arg push: push(arr, val) → guarded direct opcode
if (nargs == 2 && fname == "push") {
@@ -1997,7 +1982,7 @@ var mcode = function(ast) {
_i = _i + 1
}
dest = alloc_slot()
add_instr(["array", dest, 0])
add_instr(["array", dest, count])
_i = 0
while (_i < count) {
emit_2("push", dest, elem_slots[_i])
@@ -2010,7 +1995,7 @@ var mcode = function(ast) {
if (kind == "record") {
list = expr.list
dest = alloc_slot()
push(s_instructions, ["record", dest, 0])
push(s_instructions, ["record", dest, length(list)])
_i = 0
while (_i < length(list)) {
pair = list[_i]