This commit is contained in:
2026-02-21 13:44:34 -06:00
parent 700b640cf1
commit 7d0c96f328
15 changed files with 1372 additions and 3 deletions

115
mcode.cm
View File

@@ -38,6 +38,11 @@ var mcode = function(ast) {
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",
is_blob: "is_blob", is_data: "is_data",
is_true: "is_true", is_false: "is_false", is_fit: "is_fit",
is_character: "is_char", is_digit: "is_digit", is_letter: "is_letter",
is_lower: "is_lower", is_upper: "is_upper", is_whitespace: "is_ws",
is_actor: "is_actor",
length: "length"
}
@@ -873,6 +878,7 @@ var mcode = function(ast) {
var inline_every = true
var inline_some = true
var inline_reduce = true
var inline_map = true
// --- Helper: emit a reduce loop body ---
// r = {acc, i, arr, fn, len, fn_arity}; emits loop updating acc in-place.
@@ -1162,6 +1168,96 @@ var mcode = function(ast) {
return dest
}
// --- Inline expansion: array(arr, fn) → map ---
var expand_inline_map = function(dest, arr_slot, fn_slot) {
var result = alloc_slot()
var len = alloc_slot()
var i = alloc_slot()
var check = alloc_slot()
var item = alloc_slot()
var fn_arity = alloc_slot()
var arity_is_zero = alloc_slot()
var arity_is_one = alloc_slot()
var null_s = alloc_slot()
var zero = alloc_slot()
var one = alloc_slot()
var f = alloc_slot()
var val = alloc_slot()
var loop_label = gen_label("map_loop")
var call_one_label = gen_label("map_call_one")
var call_two_label = gen_label("map_call_two")
var call_done_label = gen_label("map_call_done")
var done_label = gen_label("map_done")
add_instr(["array", result, 0])
emit_2("length", len, arr_slot)
emit_2("int", i, 0)
emit_2("int", zero, 0)
emit_2("int", one, 1)
emit_1("null", null_s)
emit_2("length", fn_arity, fn_slot)
emit_label(loop_label)
emit_3("lt", check, i, len)
emit_jump_cond("jump_false", check, done_label)
emit_3("load_index", item, arr_slot, i)
emit_3("eq", arity_is_zero, fn_arity, zero)
emit_jump_cond("jump_false", arity_is_zero, call_one_label)
emit_3("frame", f, fn_slot, 0)
emit_3("setarg", f, 0, null_s)
emit_2("invoke", f, val)
emit_jump(call_done_label)
emit_label(call_one_label)
emit_3("eq", arity_is_one, fn_arity, one)
emit_jump_cond("jump_false", arity_is_one, call_two_label)
emit_3("frame", f, fn_slot, 1)
emit_3("setarg", f, 0, null_s)
emit_3("setarg", f, 1, item)
emit_2("invoke", f, val)
emit_jump(call_done_label)
emit_label(call_two_label)
emit_3("frame", f, fn_slot, 2)
emit_3("setarg", f, 0, null_s)
emit_3("setarg", f, 1, item)
emit_3("setarg", f, 2, i)
emit_2("invoke", f, val)
emit_label(call_done_label)
emit_2("push", result, val)
emit_3("add", i, i, one)
emit_jump(loop_label)
emit_label(done_label)
emit_2("move", dest, result)
return dest
}
// --- Inline expansion: array(arr, intrinsic_op) → map with direct opcode ---
var expand_inline_map_intrinsic = function(dest, arr_slot, opcode) {
var result = alloc_slot()
var len = alloc_slot()
var i = alloc_slot()
var check = alloc_slot()
var item = alloc_slot()
var val = alloc_slot()
var zero = alloc_slot()
var one = alloc_slot()
var loop_label = gen_label("mapi_loop")
var done_label = gen_label("mapi_done")
add_instr(["array", result, 0])
emit_2("length", len, arr_slot)
emit_2("int", i, 0)
emit_2("int", zero, 0)
emit_2("int", one, 1)
emit_label(loop_label)
emit_3("lt", check, i, len)
emit_jump_cond("jump_false", check, done_label)
emit_3("load_index", item, arr_slot, i)
emit_2(opcode, val, item)
emit_2("push", result, val)
emit_3("add", i, i, one)
emit_jump(loop_label)
emit_label(done_label)
emit_2("move", dest, result)
return dest
}
// --- Inline expansion: reduce(arr, fn[, initial[, reverse]]) ---
var expand_inline_reduce = function(dest, args, nargs) {
var arr_slot = args.arr
@@ -1929,6 +2025,25 @@ var mcode = function(ast) {
d = alloc_slot()
return expand_inline_reduce(d, {arr: a0, fn: a1, init: a2, rev: a3}, nargs)
}
// array(arr, fn) → inline map expansion
// Skip when first arg is a number literal (that's array(N, fn) — creation, not map)
if (nargs == 2 && fname == "array" && inline_map
&& args_list[0].kind != "number") {
// Specialized: array(arr, known_sensory_intrinsic) → direct opcode loop
if (args_list[1].kind == "name" && args_list[1].intrinsic == true
&& sensory_ops[args_list[1].name] != null) {
a0 = gen_expr(args_list[0], -1)
d = alloc_slot()
return expand_inline_map_intrinsic(d, a0, sensory_ops[args_list[1].name])
}
// General: array(arr, fn_literal) → map loop with arity dispatch
if (args_list[1].kind == "function") {
a0 = gen_expr(args_list[0], -1)
a1 = gen_expr(args_list[1], -1)
d = alloc_slot()
return expand_inline_map(d, a0, a1)
}
}
}
// Collect arg slots