From 700b640cf1f07ae02460b51f006e3416bfb47e6d Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 21 Feb 2026 04:13:21 -0600 Subject: [PATCH] type propagation --- mcode.cm | 69 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/mcode.cm b/mcode.cm index beb659f8..c6fae5b3 100644 --- a/mcode.cm +++ b/mcode.cm @@ -89,6 +89,8 @@ var mcode = function(ast) { var s_filename = null var s_has_disruption = false var s_slot_types = {} + var s_num_err_label = null + var s_num_err_emitted = false // Shared closure vars for binop helpers (avoids >4 param functions) var _bp_dest = 0 @@ -118,7 +120,9 @@ var mcode = function(ast) { cur_line: s_cur_line, cur_col: s_cur_col, has_disruption: s_has_disruption, - slot_types: s_slot_types + slot_types: s_slot_types, + num_err_label: s_num_err_label, + num_err_emitted: s_num_err_emitted } } @@ -141,6 +145,8 @@ var mcode = function(ast) { s_cur_col = saved.cur_col s_has_disruption = saved.has_disruption s_slot_types = saved.slot_types + s_num_err_label = saved.num_err_label + s_num_err_emitted = saved.num_err_emitted } // Slot allocation @@ -413,29 +419,37 @@ var mcode = function(ast) { var emit_numeric_binop = function(op_str) { var left_known = is_known_number(_bp_ln) || slot_is_num(_bp_left) var right_known = is_known_number(_bp_rn) || slot_is_num(_bp_right) + var t0 = null + var done = null if (left_known && right_known) { emit_3(op_str, _bp_dest, _bp_left, _bp_right) mark_slot(_bp_dest, "num") return null } - var t0 = alloc_slot() - var err = gen_label("num_err") - var done = gen_label("num_done") + if (s_num_err_label == null) { + s_num_err_label = gen_label("num_err") + } + t0 = alloc_slot() if (!left_known) { emit_2("is_num", t0, _bp_left) - emit_jump_cond("jump_false", t0, err) + emit_jump_cond("jump_false", t0, s_num_err_label) + mark_slot(_bp_left, "num") } if (!right_known) { emit_2("is_num", t0, _bp_right) - emit_jump_cond("jump_false", t0, err) + emit_jump_cond("jump_false", t0, s_num_err_label) + mark_slot(_bp_right, "num") } emit_3(op_str, _bp_dest, _bp_left, _bp_right) - emit_jump(done) - - emit_label(err) - emit_log_error("cannot apply '" + _bp_op_sym + "': operands must be numbers") - emit_0("disrupt") - emit_label(done) + if (!s_num_err_emitted) { + done = gen_label("num_done") + emit_jump(done) + emit_label(s_num_err_label) + emit_log_error("operands must be numbers") + emit_0("disrupt") + emit_label(done) + s_num_err_emitted = true + } mark_slot(_bp_dest, "num") return null } @@ -460,23 +474,30 @@ var mcode = function(ast) { // emit_neg_decomposed: emit type-guarded negate var emit_neg_decomposed = function(dest, src, src_node) { + var t0 = null + var done = null if (is_known_number(src_node) || slot_is_num(src)) { emit_2("negate", dest, src) mark_slot(dest, "num") return null } - var t0 = alloc_slot() - var err = gen_label("neg_err") - var done = gen_label("neg_done") + if (s_num_err_label == null) { + s_num_err_label = gen_label("num_err") + } + t0 = alloc_slot() emit_2("is_num", t0, src) - emit_jump_cond("jump_false", t0, err) + emit_jump_cond("jump_false", t0, s_num_err_label) + mark_slot(src, "num") emit_2("negate", dest, src) - emit_jump(done) - - emit_label(err) - emit_log_error("cannot negate: operand must be a number") - emit_0("disrupt") - emit_label(done) + if (!s_num_err_emitted) { + done = gen_label("num_done") + emit_jump(done) + emit_label(s_num_err_label) + emit_log_error("operands must be numbers") + emit_0("disrupt") + emit_label(done) + s_num_err_emitted = true + } mark_slot(dest, "num") return null } @@ -2605,6 +2626,8 @@ var mcode = function(ast) { s_vars = [] s_intrinsic_cache = [] s_slot_types = {} + s_num_err_label = null + s_num_err_emitted = false s_loop_break = null s_loop_continue = null s_label_map = {} @@ -2804,6 +2827,8 @@ var mcode = function(ast) { s_label_counter = 0 s_func_counter = 0 s_slot_types = {} + s_num_err_label = null + s_num_err_emitted = false s_loop_break = null s_loop_continue = null s_label_map = {}