fix some rough edges around stack traces

hide irrelevant CallFrames
fix span info for the implicit stack frame
This commit is contained in:
りき萌 2025-06-25 21:10:54 +02:00
parent e49885c83a
commit 7a52dbebd0
4 changed files with 34 additions and 11 deletions

View file

@ -196,27 +196,32 @@ export fn haku2_vm_stackframe_count(vm: *const Vm) usize {
return vm.stackFrameCount();
}
export fn haku2_vm_stackframe_is_return_marker(vm: *const Vm, index: usize) bool {
const stack_frame = vm.stackFrame(index);
return stack_frame.closure == null;
}
export fn haku2_vm_stackframe_is_system(vm: *const Vm, index: usize) bool {
const stack_frame = vm.stackFrame(index);
return stack_frame.closure.impl == .system;
return stack_frame.closure.?.impl == .system;
}
export fn haku2_vm_stackframe_pc(vm: *const Vm, index: usize) i32 {
const stack_frame = vm.stackFrame(index);
if (stack_frame.closure.impl == .bytecode)
if (stack_frame.closure.?.impl == .bytecode)
if (stack_frame.ip) |ip|
return stack_frame.closure.programCounter(ip);
return stack_frame.closure.?.programCounter(ip);
return -1; // no return address
}
export fn haku2_vm_stackframe_function_name_len(vm: *const Vm, index: usize) usize {
const stack_frame = vm.stackFrame(index);
return stack_frame.closure.name.len;
return stack_frame.closure.?.name.len;
}
export fn haku2_vm_stackframe_function_name(vm: *const Vm, index: usize) [*]const u8 {
const stack_frame = vm.stackFrame(index);
return stack_frame.closure.name.ptr;
return stack_frame.closure.?.name.ptr;
}
// Renderer

View file

@ -30,7 +30,7 @@ pub const Limits = struct {
};
pub const CallFrame = struct {
closure: *const value.Closure,
closure: ?*const value.Closure,
return_addr: ?[*]const u8,
bottom: u32,
};
@ -100,7 +100,7 @@ pub fn outOfMemory(vm: *Vm) Error {
// NOTE: Different from CallFrame, this is a helper type for obtaining stack traces.
pub const StackFrame = struct {
closure: *const value.Closure,
closure: ?*const value.Closure,
ip: ?[*]const u8,
};
@ -117,7 +117,17 @@ pub fn stackFrame(vm: *const Vm, index: usize) StackFrame {
if (index == 0) {
return .{
.closure = closure,
.ip = vm.ip,
// Span info hairiness:
// Because call frames place the instruction pointer past the call instruction,
// the frontend subtracts 1 from it to get a position within the chunk that
// has the correct line info.
// This subtracting by one doesn't work for the implicit stack frame though, because
// its ip gets updated at the _start_ of the instruction---meaning that if you
// subtract one from it, it'll point to the _previous_ instruction, while the actual
// error occurred in the current one.
// To alleviate this, add one here to point to either the middle or the end of the
// current instruction.
.ip = if (vm.ip) |ip| ip + 1 else null,
};
} else {
// NOTE: Minus two, because remember index == 0 is occupied by the current stack frame.
@ -269,7 +279,7 @@ pub fn run(
}
try vm.pushCall(.{
.closure = closure,
.closure = null,
.return_addr = null, // nowhere to return to
.bottom = bottom,
});
@ -591,7 +601,7 @@ pub fn run(
try vm.push(result);
if (call_frame.return_addr) |addr| {
closure = call_frame.closure;
closure = call_frame.closure.?;
ip = addr;
bottom = call_frame.bottom;