lower ops directly
This commit is contained in:
94
mcode.cm
94
mcode.cm
@@ -41,6 +41,28 @@ var mcode = function(ast) {
|
||||
length: "length"
|
||||
}
|
||||
|
||||
// Numeric intrinsic lowering maps (Tier 1 direct mcode).
|
||||
var intrinsic_num_unary_ops = {
|
||||
abs: "abs",
|
||||
sign: "sign",
|
||||
fraction: "fraction",
|
||||
integer: "integer",
|
||||
whole: "integer",
|
||||
neg: "negate"
|
||||
}
|
||||
var intrinsic_num_binary_ops = {
|
||||
modulo: "modulo",
|
||||
remainder: "remainder",
|
||||
max: "max",
|
||||
min: "min"
|
||||
}
|
||||
var intrinsic_num_place_ops = {
|
||||
floor: "floor",
|
||||
ceiling: "ceiling",
|
||||
round: "round",
|
||||
trunc: "trunc"
|
||||
}
|
||||
|
||||
// Compiler state
|
||||
var s_instructions = null
|
||||
var s_data = null
|
||||
@@ -877,6 +899,56 @@ var mcode = function(ast) {
|
||||
}
|
||||
}
|
||||
|
||||
// Intrinsic numeric helpers:
|
||||
// preserve native intrinsic behavior for bad argument types by returning null.
|
||||
var emit_intrinsic_num_unary = function(op, arg_slot) {
|
||||
var dest = alloc_slot()
|
||||
var t = alloc_slot()
|
||||
var bad = gen_label(op + "_arg_bad")
|
||||
var done = gen_label(op + "_arg_done")
|
||||
emit_2("is_num", t, arg_slot)
|
||||
emit_jump_cond("jump_false", t, bad)
|
||||
emit_2(op, dest, arg_slot)
|
||||
emit_jump(done)
|
||||
emit_label(bad)
|
||||
emit_1("null", dest)
|
||||
emit_label(done)
|
||||
return dest
|
||||
}
|
||||
|
||||
var emit_intrinsic_num_binary = function(op, left_slot, right_slot) {
|
||||
var dest = alloc_slot()
|
||||
var t0 = alloc_slot()
|
||||
var t1 = alloc_slot()
|
||||
var bad = gen_label(op + "_arg_bad")
|
||||
var done = gen_label(op + "_arg_done")
|
||||
emit_2("is_num", t0, left_slot)
|
||||
emit_jump_cond("jump_false", t0, bad)
|
||||
emit_2("is_num", t1, right_slot)
|
||||
emit_jump_cond("jump_false", t1, bad)
|
||||
emit_3(op, dest, left_slot, right_slot)
|
||||
emit_jump(done)
|
||||
emit_label(bad)
|
||||
emit_1("null", dest)
|
||||
emit_label(done)
|
||||
return dest
|
||||
}
|
||||
|
||||
var emit_intrinsic_num_place = function(op, value_slot, place_slot) {
|
||||
var dest = alloc_slot()
|
||||
var t = alloc_slot()
|
||||
var bad = gen_label(op + "_arg_bad")
|
||||
var done = gen_label(op + "_arg_done")
|
||||
emit_2("is_num", t, value_slot)
|
||||
emit_jump_cond("jump_false", t, bad)
|
||||
emit_3(op, dest, value_slot, place_slot)
|
||||
emit_jump(done)
|
||||
emit_label(bad)
|
||||
emit_1("null", dest)
|
||||
emit_label(done)
|
||||
return dest
|
||||
}
|
||||
|
||||
// Scan scope record for variable declarations
|
||||
var scan_scope = function() {
|
||||
var scope = find_scope_record(s_function_nr)
|
||||
@@ -1796,6 +1868,28 @@ var mcode = function(ast) {
|
||||
if (callee_kind == "name" && callee.intrinsic == true) {
|
||||
fname = callee.name
|
||||
nargs = args_list != null ? length(args_list) : 0
|
||||
mop = intrinsic_num_unary_ops[fname]
|
||||
if (mop != null && nargs == 1) {
|
||||
a0 = gen_expr(args_list[0], -1)
|
||||
return emit_intrinsic_num_unary(mop, a0)
|
||||
}
|
||||
mop = intrinsic_num_binary_ops[fname]
|
||||
if (mop != null && nargs == 2) {
|
||||
a0 = gen_expr(args_list[0], -1)
|
||||
a1 = gen_expr(args_list[1], -1)
|
||||
return emit_intrinsic_num_binary(mop, a0, a1)
|
||||
}
|
||||
mop = intrinsic_num_place_ops[fname]
|
||||
if (mop != null && (nargs == 1 || nargs == 2)) {
|
||||
a0 = gen_expr(args_list[0], -1)
|
||||
if (nargs == 2) {
|
||||
a1 = gen_expr(args_list[1], -1)
|
||||
} else {
|
||||
a1 = alloc_slot()
|
||||
emit_1("null", a1)
|
||||
}
|
||||
return emit_intrinsic_num_place(mop, a0, a1)
|
||||
}
|
||||
// 1-arg type check intrinsics → direct opcode
|
||||
if (nargs == 1 && sensory_ops[fname] != null) {
|
||||
a0 = gen_expr(args_list[0], -1)
|
||||
|
||||
Reference in New Issue
Block a user