fix errors with mcode

This commit is contained in:
2026-02-09 18:45:55 -06:00
parent c0b4e70eb2
commit 66a44595c8
4 changed files with 270 additions and 178 deletions

352
mcode.cm
View File

@@ -1142,31 +1142,87 @@ var mcode = function(ast) {
// Statement compilation
gen_statement = function(stmt) {
var kind = null
var left = null
var right = null
var name = null
var local_slot = 0
var arr_expr = null
var arr_slot = 0
var val_slot = 0
var list = null
var _i = 0
var stmts = null
var cond = null
var then_stmts = null
var else_stmts = null
var else_label = null
var end_label = null
var cond_slot = 0
var start_label = null
var old_break = null
var old_continue = null
var cond_label = null
var init = null
var test = null
var update = null
var update_label = null
var init_kind = null
var test_slot = 0
var expr = null
var slot = 0
var null_slot = 0
var call_expr = null
var callee = null
var args_list = null
var arg_slots = null
var nargs = 0
var callee_kind = null
var obj_node = null
var prop = null
var obj_slot = 0
var func_slot = 0
var cases = null
var switch_val = 0
var default_label = null
var case_labels = null
var case_node = null
var case_kind = null
var case_label = null
var case_expr = null
var case_val = 0
var cmp_slot = 0
var case_stmts = null
var _j = 0
var func = null
var func_id = 0
var dest = 0
if (stmt == null) {
return null
}
set_pos(stmt)
var kind = stmt.kind
kind = stmt.kind
if (kind == null) {
return null
}
if (kind == "var" || kind == "def") {
var left = stmt.left
var right = stmt.right
var name = left.name
var local_slot = find_var(name)
left = stmt.left
right = stmt.right
name = left.name
local_slot = find_var(name)
// Pop: var val = arr[]
if (stmt.pop == true && right != null) {
var arr_expr = right.left
var arr_slot = gen_expr(arr_expr, -1)
arr_expr = right.left
arr_slot = gen_expr(arr_expr, -1)
if (local_slot >= 0) {
emit_2("pop", local_slot, arr_slot)
}
return null
}
if (right != null) {
var val_slot = gen_expr(right, local_slot)
val_slot = gen_expr(right, local_slot)
if (local_slot >= 0 && val_slot != local_slot) {
emit_2("move", local_slot, val_slot)
}
@@ -1177,8 +1233,8 @@ var mcode = function(ast) {
}
if (kind == "var_list" || kind == "def_list") {
var list = stmt.list
var _i = 0
list = stmt.list
_i = 0
while (_i < length(list)) {
gen_statement(list[_i])
_i = _i + 1
@@ -1187,8 +1243,8 @@ var mcode = function(ast) {
}
if (kind == "block") {
var stmts = stmt.statements
var _i = 0
stmts = stmt.statements
_i = 0
while (_i < length(stmts)) {
gen_statement(stmts[_i])
_i = _i + 1
@@ -1197,17 +1253,17 @@ var mcode = function(ast) {
}
if (kind == "if") {
var cond = stmt.expression
var then_stmts = stmt.then
var else_stmts = stmt["else"]
cond = stmt.expression
then_stmts = stmt.then
else_stmts = stmt["else"]
if (else_stmts == null) {
else_stmts = stmt.list
}
var else_label = gen_label("if_else")
var end_label = gen_label("if_end")
var cond_slot = gen_expr(cond, -1)
else_label = gen_label("if_else")
end_label = gen_label("if_end")
cond_slot = gen_expr(cond, -1)
emit_jump_cond("jump_false", cond_slot, else_label)
var _i = 0
_i = 0
while (_i < length(then_stmts)) {
gen_statement(then_stmts[_i])
_i = _i + 1
@@ -1226,18 +1282,18 @@ var mcode = function(ast) {
}
if (kind == "while") {
var cond = stmt.expression
var stmts = stmt.statements
var start_label = gen_label("while_start")
var end_label = gen_label("while_end")
var old_break = s_loop_break
var old_continue = s_loop_continue
cond = stmt.expression
stmts = stmt.statements
start_label = gen_label("while_start")
end_label = gen_label("while_end")
old_break = s_loop_break
old_continue = s_loop_continue
s_loop_break = end_label
s_loop_continue = start_label
emit_label(start_label)
var cond_slot = gen_expr(cond, -1)
cond_slot = gen_expr(cond, -1)
emit_jump_cond("jump_false", cond_slot, end_label)
var _i = 0
_i = 0
while (_i < length(stmts)) {
gen_statement(stmts[_i])
_i = _i + 1
@@ -1250,23 +1306,23 @@ var mcode = function(ast) {
}
if (kind == "do") {
var cond = stmt.expression
var stmts = stmt.statements
var start_label = gen_label("do_start")
var cond_label = gen_label("do_cond")
var end_label = gen_label("do_end")
var old_break = s_loop_break
var old_continue = s_loop_continue
cond = stmt.expression
stmts = stmt.statements
start_label = gen_label("do_start")
cond_label = gen_label("do_cond")
end_label = gen_label("do_end")
old_break = s_loop_break
old_continue = s_loop_continue
s_loop_break = end_label
s_loop_continue = cond_label
emit_label(start_label)
var _i = 0
_i = 0
while (_i < length(stmts)) {
gen_statement(stmts[_i])
_i = _i + 1
}
emit_label(cond_label)
var cond_slot = gen_expr(cond, -1)
cond_slot = gen_expr(cond, -1)
emit_jump_cond("jump_true", cond_slot, start_label)
emit_label(end_label)
s_loop_break = old_break
@@ -1275,19 +1331,19 @@ var mcode = function(ast) {
}
if (kind == "for") {
var init = stmt.init
var test = stmt.test
var update = stmt.update
var stmts = stmt.statements
var start_label = gen_label("for_start")
var update_label = gen_label("for_update")
var end_label = gen_label("for_end")
var old_break = s_loop_break
var old_continue = s_loop_continue
init = stmt.init
test = stmt.test
update = stmt.update
stmts = stmt.statements
start_label = gen_label("for_start")
update_label = gen_label("for_update")
end_label = gen_label("for_end")
old_break = s_loop_break
old_continue = s_loop_continue
s_loop_break = end_label
s_loop_continue = update_label
if (init != null) {
var init_kind = init.kind
init_kind = init.kind
if (init_kind == "var" || init_kind == "def") {
gen_statement(init)
} else {
@@ -1296,10 +1352,10 @@ var mcode = function(ast) {
}
emit_label(start_label)
if (test != null) {
var test_slot = gen_expr(test, -1)
test_slot = gen_expr(test, -1)
emit_jump_cond("jump_false", test_slot, end_label)
}
var _i = 0
_i = 0
while (_i < length(stmts)) {
gen_statement(stmts[_i])
_i = _i + 1
@@ -1316,12 +1372,12 @@ var mcode = function(ast) {
}
if (kind == "return") {
var expr = stmt.expression
expr = stmt.expression
if (expr != null) {
var slot = gen_expr(expr, -1)
slot = gen_expr(expr, -1)
emit_1("return", slot)
} else {
var null_slot = alloc_slot()
null_slot = alloc_slot()
emit_1("null", null_slot)
emit_1("return", null_slot)
}
@@ -1329,27 +1385,27 @@ var mcode = function(ast) {
}
if (kind == "go") {
var call_expr = stmt.expression
call_expr = stmt.expression
if (call_expr == null || call_expr.kind != "(") {
return null
}
var callee = call_expr.expression
var args_list = call_expr.list
var arg_slots = []
var _i = 0
var nargs = args_list != null ? length(args_list) : 0
callee = call_expr.expression
args_list = call_expr.list
arg_slots = []
_i = 0
nargs = args_list != null ? length(args_list) : 0
while (_i < nargs) {
push(arg_slots, gen_expr(args_list[_i], -1))
_i = _i + 1
}
var callee_kind = callee.kind
callee_kind = callee.kind
if (callee_kind == ".") {
var obj_node = callee.left
var prop = callee.right
var obj_slot = gen_expr(obj_node, -1)
obj_node = callee.left
prop = callee.right
obj_slot = gen_expr(obj_node, -1)
emit_go_call_method(obj_slot, prop, arg_slots)
} else {
var func_slot = gen_expr(callee, -1)
func_slot = gen_expr(callee, -1)
emit_go_call(func_slot, arg_slots)
}
return null
@@ -1375,27 +1431,27 @@ var mcode = function(ast) {
}
if (kind == "switch") {
var expr = stmt.expression
var cases = stmt.cases
var switch_val = gen_expr(expr, -1)
var end_label = gen_label("switch_end")
var default_label = null
var old_break = s_loop_break
expr = stmt.expression
cases = stmt.cases
switch_val = gen_expr(expr, -1)
end_label = gen_label("switch_end")
default_label = null
old_break = s_loop_break
s_loop_break = end_label
// Phase 1: emit comparisons, collect labels
var case_labels = []
var _i = 0
case_labels = []
_i = 0
while (_i < length(cases)) {
var case_node = cases[_i]
var case_kind = case_node.kind
case_node = cases[_i]
case_kind = case_node.kind
if (case_kind == "default") {
default_label = gen_label("switch_default")
push(case_labels, default_label)
} else {
var case_label = gen_label("switch_case")
var case_expr = case_node.expression
var case_val = gen_expr(case_expr, -1)
var cmp_slot = alloc_slot()
case_label = gen_label("switch_case")
case_expr = case_node.expression
case_val = gen_expr(case_expr, -1)
cmp_slot = alloc_slot()
emit_3("eq", cmp_slot, switch_val, case_val)
emit_jump_cond("jump_true", cmp_slot, case_label)
push(case_labels, case_label)
@@ -1411,8 +1467,8 @@ var mcode = function(ast) {
_i = 0
while (_i < length(cases)) {
emit_label(case_labels[_i])
var case_stmts = cases[_i].statements
var _j = 0
case_stmts = cases[_i].statements
_j = 0
while (_j < length(case_stmts)) {
gen_statement(case_stmts[_j])
_j = _j + 1
@@ -1425,14 +1481,14 @@ var mcode = function(ast) {
}
if (kind == "function") {
var name = stmt.name
name = stmt.name
if (name != null) {
var func = gen_function(stmt)
var func_id = s_func_counter
func = gen_function(stmt)
func_id = s_func_counter
s_func_counter = s_func_counter + 1
push(s_functions, func)
var local_slot = find_var(name)
var dest = alloc_slot()
local_slot = find_var(name)
dest = alloc_slot()
emit_2("function", dest, func_id)
if (local_slot >= 0) {
emit_2("move", local_slot, dest)
@@ -1453,6 +1509,38 @@ var mcode = function(ast) {
// Function compilation
gen_function = function(func_node) {
var saved = save_state()
var is_arrow = func_node.arrow == true
var fn_nr_node = func_node.function_nr
var params = func_node.list
var nr_params = 0
var param_slot = 1
var _i = 0
var param = null
var param_name = null
var ps = 1
var default_expr = null
var end_label = null
var default_slot = 0
var hoisted = null
var fn = null
var fname = null
var compiled = null
var func_id = 0
var local_slot = 0
var dest = 0
var stmts = null
var body = null
var null_slot = 0
var disruption_start = 0
var disrupt_clause = func_node.disruption
var null_slot2 = null
var fn_name = func_node.name
var fn_scope = null
var nr_cs = 0
var result = null
var saved_label = 0
var saved_func = 0
push(parent_states, saved)
s_instructions = []
@@ -1461,28 +1549,25 @@ var mcode = function(ast) {
s_loop_break = null
s_loop_continue = null
var is_arrow = func_node.arrow == true
s_is_arrow = is_arrow
var fn_nr_node = func_node.function_nr
s_function_nr = fn_nr_node != null ? fn_nr_node : 0
// Parameters
var params = func_node.list
if (params == null) {
params = func_node.parameters
}
var nr_params = params != null ? length(params) : 0
nr_params = params != null ? length(params) : 0
s_nr_args = nr_params
s_this_slot = 0
s_nr_close_slots = 0
s_nr_local_slots = 0
var param_slot = 1
var _i = 0
param_slot = 1
_i = 0
while (_i < nr_params) {
var param = params[_i]
var param_name = param.name
param = params[_i]
param_name = param.name
if (param_name == null && is_text(param)) {
param_name = param
}
@@ -1505,15 +1590,15 @@ var mcode = function(ast) {
}
// Default parameter initialization
var ps = 1
ps = 1
_i = 0
while (_i < nr_params) {
var param = params[_i]
var default_expr = param.expression
param = params[_i]
default_expr = param.expression
if (default_expr != null) {
var end_label = gen_label("default_end")
end_label = gen_label("default_end")
emit_jump_cond("jump_not_null", ps, end_label)
var default_slot = gen_expr(default_expr, -1)
default_slot = gen_expr(default_expr, -1)
emit_2("move", ps, default_slot)
emit_label(end_label)
}
@@ -1525,19 +1610,19 @@ var mcode = function(ast) {
load_intrinsics(func_node.intrinsics)
// Compile hoisted function declarations
var hoisted = func_node.functions
hoisted = func_node.functions
if (hoisted != null) {
_i = 0
while (_i < length(hoisted)) {
var fn = hoisted[_i]
var fname = fn.name
fn = hoisted[_i]
fname = fn.name
if (fname != null) {
var compiled = gen_function(fn)
var func_id = s_func_counter
compiled = gen_function(fn)
func_id = s_func_counter
s_func_counter = s_func_counter + 1
push(s_functions, compiled)
var local_slot = find_var(fname)
var dest = alloc_slot()
local_slot = find_var(fname)
dest = alloc_slot()
emit_2("function", dest, func_id)
if (local_slot >= 0) {
emit_2("move", local_slot, dest)
@@ -1548,9 +1633,9 @@ var mcode = function(ast) {
}
// Compile body
var stmts = func_node.statements
stmts = func_node.statements
if (stmts == null) {
var body = func_node.body
body = func_node.body
if (body != null) {
stmts = body.statements
if (stmts == null) {
@@ -1567,14 +1652,11 @@ var mcode = function(ast) {
}
// Implicit return null
var null_slot = alloc_slot()
null_slot = alloc_slot()
emit_1("null", null_slot)
emit_1("return", null_slot)
// Compile disruption clause
var disruption_start = 0
var disrupt_clause = func_node.disruption
var null_slot2 = null
if (disrupt_clause != null && is_array(disrupt_clause)) {
disruption_start = length(s_instructions)
_i = 0
@@ -1588,18 +1670,16 @@ var mcode = function(ast) {
}
// Build result
var fn_name = func_node.name
if (fn_name == null) {
fn_name = "<anonymous>"
}
var fn_scope = find_scope_record(s_function_nr)
var nr_cs = 0
fn_scope = find_scope_record(s_function_nr)
if (fn_scope != null && fn_scope.nr_close_slots != null) {
nr_cs = fn_scope.nr_close_slots
}
var result = {
result = {
name: fn_name,
nr_args: nr_params,
nr_close_slots: nr_cs,
@@ -1613,8 +1693,8 @@ var mcode = function(ast) {
}
// Propagate counters back
var saved_label = s_label_counter
var saved_func = s_func_counter
saved_label = s_label_counter
saved_func = s_func_counter
// Pop parent state
pop(parent_states)
@@ -1628,6 +1708,21 @@ var mcode = function(ast) {
// Program compilation (top-level entry)
var gen_program = function(ast) {
var filename = ast.filename
var hoisted = ast.functions
var _i = 0
var fn = null
var name = null
var compiled = null
var func_id = 0
var local_slot = 0
var dest = 0
var statements = ast.statements
var last_expr_slot = -1
var stmt = null
var kind = null
var null_slot = 0
var result = null
s_filename = filename
s_instructions = []
@@ -1657,19 +1752,18 @@ var mcode = function(ast) {
}
// Compile hoisted function declarations from ast.functions
var hoisted = ast.functions
if (hoisted != null) {
var _i = 0
_i = 0
while (_i < length(hoisted)) {
var fn = hoisted[_i]
var name = fn.name
fn = hoisted[_i]
name = fn.name
if (name != null) {
var compiled = gen_function(fn)
var func_id = s_func_counter
compiled = gen_function(fn)
func_id = s_func_counter
s_func_counter = s_func_counter + 1
push(s_functions, compiled)
var local_slot = find_var(name)
var dest = alloc_slot()
local_slot = find_var(name)
dest = alloc_slot()
emit_2("function", dest, func_id)
if (local_slot >= 0) {
emit_2("move", local_slot, dest)
@@ -1680,12 +1774,10 @@ var mcode = function(ast) {
}
// Generate main code
var statements = ast.statements
var last_expr_slot = -1
var _i = 0
_i = 0
while (_i < length(statements)) {
var stmt = statements[_i]
var kind = stmt.kind
stmt = statements[_i]
kind = stmt.kind
if (kind != null) {
if (kind == "call") {
last_expr_slot = gen_expr(stmt.expression, -1)
@@ -1713,12 +1805,12 @@ var mcode = function(ast) {
if (last_expr_slot >= 0) {
emit_1("return", last_expr_slot)
} else {
var null_slot = alloc_slot()
null_slot = alloc_slot()
emit_1("null", null_slot)
emit_1("return", null_slot)
}
var result = {}
result = {}
result.name = filename != null ? filename : "<eval>"
result.data = s_data
result.functions = s_functions