better fn error

This commit is contained in:
2026-02-20 21:59:17 -06:00
parent 374069ae99
commit 652e8a19f0

View File

@@ -494,6 +494,37 @@ static int mach_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) {
return 1;
}
/* Scan backwards from pc to find what loaded the callee register.
Returns the name in buf, or NULL if unknown. */
static const char *mach_callee_name(JSContext *ctx, JSCodeRegister *code,
uint32_t pc, int reg,
char *buf, size_t buf_size) {
int hops = 4; /* limit move-chain depth */
for (int i = (int)pc - 2; i >= 0 && hops > 0; i--) {
MachInstr32 prev = code->instructions[i];
int prev_op = MACH_GET_OP(prev);
int prev_a = MACH_GET_A(prev);
if (prev_a != reg) continue;
if (prev_op == MACH_GETENV || prev_op == MACH_GETINTRINSIC) {
int bx = MACH_GET_Bx(prev);
if ((uint32_t)bx < code->cpool_count && JS_IsText(code->cpool[bx]))
return JS_KeyGetStr(ctx, buf, buf_size, code->cpool[bx]);
}
if (prev_op == MACH_LOAD_FIELD) {
int ci = MACH_GET_C(prev);
if ((uint32_t)ci < code->cpool_count && JS_IsText(code->cpool[ci]))
return JS_KeyGetStr(ctx, buf, buf_size, code->cpool[ci]);
}
if (prev_op == MACH_MOVE) {
reg = MACH_GET_B(prev);
hops--;
continue;
}
break; /* some other op wrote to this reg — give up */
}
return NULL;
}
/* ---- Link pass: resolve GETNAME to GETINTRINSIC or GETENV ---- */
static void mach_link_code(JSContext *ctx, JSCodeRegister *code, JSValue env) {
@@ -2560,7 +2591,12 @@ vm_dispatch:
/* A=frame_slot, B=func_reg, C=argc */
JSValue func_val = frame->slots[b];
if (!mist_is_function(func_val)) {
JS_RaiseDisrupt(ctx, "not a function");
char nbuf[KEY_GET_STR_BUF_SIZE];
const char *name = mach_callee_name(ctx, code, pc, b, nbuf, sizeof(nbuf));
if (name)
JS_RaiseDisrupt(ctx, "%s is not a function", name);
else
JS_RaiseDisrupt(ctx, "not a function");
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
goto disrupt;
}