From 6b15ba1e5f4d70044288406b59c35536e3b20ab1 Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Tue, 14 May 2024 15:27:27 +0200 Subject: [PATCH] feat(vm): std.panic/buzz_panic/vm.panic show buzz stack trace before panicking --- CHANGELOG.md | 1 + src/Jit.zig | 80 +++++-- src/Parser.zig | 2 - src/builtin/list.zig | 92 ++++++-- src/builtin/map.zig | 97 ++++++-- src/builtin/pattern.zig | 60 ++++- src/builtin/range.zig | 20 +- src/builtin/str.zig | 161 +++++++++++--- src/buzz_api.zig | 114 ++++++++-- src/lib/buzz_api.zig | 1 + src/lib/buzz_buffer.zig | 52 ++++- src/lib/buzz_ffi.zig | 10 +- src/lib/buzz_fs.zig | 8 +- src/lib/buzz_http.zig | 82 +++++-- src/lib/buzz_io.zig | 32 ++- src/lib/buzz_os.zig | 55 +++-- src/lib/buzz_std.zig | 8 +- src/vm.zig | 483 ++++++++++++++++++++++------------------ 18 files changed, 951 insertions(+), 407 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53c370ac..3b1ca908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ var value = from { - works with `foreach` - Tracing JIT (https://github.com/buzz-language/buzz/issues/134): will look for hot loops and compile them - `list.fill` +- `std.panic` will panic and print current stack trace ## Changed - Map type notation has changed from `{K, V}` to `{K: V}`. Similarly map expression with specified typed went from `{, ...}` to `{, ...}` (https://github.com/buzz-language/buzz/issues/253) diff --git a/src/Jit.zig b/src/Jit.zig index 2b49e0db..bffadde7 100644 --- a/src/Jit.zig +++ b/src/Jit.zig @@ -4214,7 +4214,10 @@ fn generateFunction(self: *Self, node: Ast.Node.Index) Error!?m.MIR_op_t { } // FIXME: I don't get why we need this: a simple constant becomes rubbish as soon as we enter MIR_new_func_arr if we don't - const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch @panic("Out of memory"); + const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(ctx_name); const function = m.MIR_new_func_arr( self.ctx, @@ -4295,7 +4298,10 @@ fn generateHotspotFunction(self: *Self, node: Ast.Node.Index) Error!?m.MIR_op_t var qualified_name = try self.getQualifiedName(node, false); defer qualified_name.deinit(); - const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch @panic("Out of memory"); + const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(ctx_name); const function = m.MIR_new_func_arr( self.ctx, @@ -4383,7 +4389,10 @@ fn generateNativeFn(self: *Self, node: Ast.Node.Index, raw_fn: m.MIR_item_t) !m. defer nativefn_qualified_name.deinit(); // FIXME: I don't get why we need this: a simple constant becomes rubbish as soon as we enter MIR_new_func_arr if we don't - const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch @panic("Out of memory"); + const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(ctx_name); const function = m.MIR_new_func_arr( self.ctx, @@ -4894,7 +4903,10 @@ pub fn compileZdef(self: *Self, buzz_ast: Ast, zdef: Ast.Zdef.ZdefElement) Error try wrapper_name.writer().print("zdef_{s}\x00", .{zdef.zdef.name}); - const dupped_symbol = self.vm.gc.allocator.dupeZ(u8, zdef.zdef.name) catch @panic("Out of memory"); + const dupped_symbol = self.vm.gc.allocator.dupeZ(u8, zdef.zdef.name) catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(dupped_symbol); const module = m.MIR_new_module(self.ctx, @ptrCast(wrapper_name.items.ptr)); @@ -5026,11 +5038,17 @@ fn buildZdefWrapper(self: *Self, zdef_element: Ast.Zdef.ZdefElement) Error!m.MIR try wrapper_protocol_name.writer().print("p_zdef_{s}\x00", .{zdef_element.zdef.name}); - const dupped_symbol = self.vm.gc.allocator.dupeZ(u8, zdef_element.zdef.name) catch @panic("Out of memory"); + const dupped_symbol = self.vm.gc.allocator.dupeZ(u8, zdef_element.zdef.name) catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(dupped_symbol); // FIXME: I don't get why we need this: a simple constant becomes rubbish as soon as we enter MIR_new_func_arr if we don't - const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch @panic("Out of memory"); + const ctx_name = self.vm.gc.allocator.dupeZ(u8, "ctx") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(ctx_name); const function = m.MIR_new_func_arr( self.ctx, @@ -5235,9 +5253,15 @@ fn buildZdefUnionGetter( ); // FIXME: I don't get why we need this: a simple constant becomes rubbish as soon as we enter MIR_new_func_arr if we don't - const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch @panic("Out of memory"); + const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(vm_name); - const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch @panic("Out of memory"); + const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(data_name); const function = m.MIR_new_func_arr( self.ctx, @@ -5339,11 +5363,20 @@ fn buildZdefUnionSetter( ); // FIXME: I don't get why we need this: a simple constant becomes rubbish as soon as we enter MIR_new_func_arr if we don't - const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch @panic("Out of memory"); + const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(vm_name); - const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch @panic("Out of memory"); + const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(data_name); - const new_value_name = self.vm.gc.allocator.dupeZ(u8, "new_value") catch @panic("Out of memory"); + const new_value_name = self.vm.gc.allocator.dupeZ(u8, "new_value") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(new_value_name); const function = m.MIR_new_func_arr( self.ctx, @@ -5446,9 +5479,15 @@ fn buildZdefContainerGetter( ); // FIXME: I don't get why we need this: a simple constant becomes rubbish as soon as we enter MIR_new_func_arr if we don't - const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch @panic("Out of memory"); + const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(vm_name); - const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch @panic("Out of memory"); + const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(data_name); const function = m.MIR_new_func_arr( self.ctx, @@ -5534,11 +5573,20 @@ fn buildZdefContainerSetter( ); // FIXME: I don't get why we need this: a simple constant becomes rubbish as soon as we enter MIR_new_func_arr if we don't - const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch @panic("Out of memory"); + const vm_name = self.vm.gc.allocator.dupeZ(u8, "vm") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(vm_name); - const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch @panic("Out of memory"); + const data_name = self.vm.gc.allocator.dupeZ(u8, "data") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(data_name); - const new_value_name = self.vm.gc.allocator.dupeZ(u8, "new_value") catch @panic("Out of memory"); + const new_value_name = self.vm.gc.allocator.dupeZ(u8, "new_value") catch { + self.vm.panic("Out of memory"); + unreachable; + }; defer self.vm.gc.allocator.free(new_value_name); const function = m.MIR_new_func_arr( self.ctx, diff --git a/src/Parser.zig b/src/Parser.zig index dbd743fd..51aad46b 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -6971,8 +6971,6 @@ fn searchPaths(self: *Self, file_name: []const u8) ![][]const u8 { try buzzLibPath(), ); - std.debug.print("> {s}\n", .{prefixed}); - try paths.append(prefixed); } diff --git a/src/builtin/list.zig b/src/builtin/list.zig index 11106201..0bb21c64 100644 --- a/src/builtin/list.zig +++ b/src/builtin/list.zig @@ -19,7 +19,10 @@ pub fn append(ctx: *NativeCtx) c_int { list.rawAppend( ctx.vm.gc, value, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; return 0; } @@ -40,7 +43,10 @@ pub fn insert(ctx: *NativeCtx) c_int { ctx.vm.gc, @as(usize, @intCast(index)), value, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(value); @@ -61,9 +67,15 @@ pub fn reverse(ctx: *NativeCtx) c_int { var new_list = ctx.vm.gc.allocateObject( ObjList, ObjList.init(ctx.vm.gc.allocator, list.type_def), - ) catch @panic("Out of memory"); - - new_list.items.appendSlice(list.items.items) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; + + new_list.items.appendSlice(list.items.items) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; std.mem.reverse(Value, new_list.items.items); ctx.vm.push(new_list.toValue()); @@ -94,7 +106,10 @@ pub fn remove(ctx: *NativeCtx) c_int { } ctx.vm.push(list.items.orderedRemove(@as(usize, @intCast(list_index)))); - ctx.vm.gc.markObjDirty(&list.obj) catch @panic("Out of memory"); + ctx.vm.gc.markObjDirty(&list.obj) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; return 1; } @@ -167,8 +182,14 @@ pub fn clone(ctx: *NativeCtx) c_int { var new_list = ctx.vm.gc.allocateObject( ObjList, ObjList.init(ctx.vm.gc.allocator, self.type_def), - ) catch @panic("Out of memory"); - new_list.items.appendSlice(self.items.items) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; + new_list.items.appendSlice(self.items.items) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(new_list.toValue()); @@ -183,15 +204,24 @@ pub fn join(ctx: *NativeCtx) c_int { var writer = result.writer(); defer result.deinit(); for (self.items.items, 0..) |item, i| { - item.toString(&writer) catch @panic("Out of memory"); + item.toString(&writer) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; if (i + 1 < self.items.items.len) { - writer.writeAll(separator.string) catch @panic("Out of memory"); + writer.writeAll(separator.string) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } ctx.vm.push( - (ctx.vm.gc.copyString(result.items) catch @panic("Out of memory")).toValue(), + (ctx.vm.gc.copyString(result.items) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue(), ); return 1; @@ -221,14 +251,23 @@ pub fn sub(ctx: *NativeCtx) c_int { ObjList, .{ .type_def = self.type_def, - .methods = self.methods.clone() catch @panic("Out of memory"), + .methods = self.methods.clone() catch { + ctx.vm.panic("Out of memory"); + unreachable; + }, .items = std.ArrayList(Value).init(ctx.vm.gc.allocator), }, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(list.toValue()); - list.items.appendSlice(substr) catch @panic("Out of memory"); + list.items.appendSlice(substr) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; return 1; } @@ -241,7 +280,10 @@ pub fn next(ctx: *NativeCtx) c_int { const next_index: ?i32 = list.rawNext( ctx.vm, list_index.integerOrNull(), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push( if (next_index) |unext_index| @@ -314,7 +356,10 @@ pub fn filter(ctx: *NativeCtx) c_int { ctx.vm.gc.allocator, list.type_def, ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; for (list.items.items, 0..) |item, index| { const index_value = Value.fromInteger(@as(i32, @intCast(index))); @@ -329,7 +374,10 @@ pub fn filter(ctx: *NativeCtx) c_int { ); if (ctx.vm.pop().boolean()) { - new_list.rawAppend(ctx.vm.gc, item) catch @panic("Out of memory"); + new_list.rawAppend(ctx.vm.gc, item) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } @@ -349,7 +397,10 @@ pub fn map(ctx: *NativeCtx) c_int { ctx.vm.gc.allocator, mapped_type, ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; for (list.items.items, 0..) |item, index| { const index_value = Value.fromInteger(@as(i32, @intCast(index))); @@ -363,7 +414,10 @@ pub fn map(ctx: *NativeCtx) c_int { null, ); - new_list.rawAppend(ctx.vm.gc, ctx.vm.pop()) catch @panic("Out of memory"); + new_list.rawAppend(ctx.vm.gc, ctx.vm.pop()) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } ctx.vm.push(new_list.toValue()); diff --git a/src/builtin/map.zig b/src/builtin/map.zig index 8aeebc57..fff03960 100644 --- a/src/builtin/map.zig +++ b/src/builtin/map.zig @@ -21,9 +21,15 @@ pub fn clone(ctx: *NativeCtx) c_int { var new_map = ctx.vm.gc.allocateObject( ObjMap, ObjMap.init(ctx.vm.gc.allocator, self.type_def), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; new_map.map.deinit(); - new_map.map = self.map.clone() catch @panic("Out of memory"); + new_map.map = self.map.clone() catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(new_map.toValue()); @@ -65,7 +71,10 @@ pub fn filter(ctx: *NativeCtx) c_int { ctx.vm.gc.allocator, self.type_def, ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; var it = self.map.iterator(); while (it.next()) |kv| { @@ -80,7 +89,10 @@ pub fn filter(ctx: *NativeCtx) c_int { ); if (ctx.vm.pop().boolean()) { - new_map.set(ctx.vm.gc, kv.key_ptr.*, kv.value_ptr.*) catch @panic("Out of memory"); + new_map.set(ctx.vm.gc, kv.key_ptr.*, kv.value_ptr.*) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } @@ -131,12 +143,24 @@ pub fn map(ctx: *NativeCtx) c_int { ), }, }, - ) catch @panic("Out of memory"), + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }, ), - ) catch @panic("Out of memory"); - - const key_str = ctx.vm.gc.copyString("key") catch @panic("Out of memory"); - const value_str = ctx.vm.gc.copyString("value") catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; + + const key_str = ctx.vm.gc.copyString("key") catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; + const value_str = ctx.vm.gc.copyString("value") catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; var it = self.map.iterator(); while (it.next()) |kv| { var args = [_]*const Value{ kv.key_ptr, kv.value_ptr }; @@ -153,7 +177,10 @@ pub fn map(ctx: *NativeCtx) c_int { const key = entry.fields.get(key_str).?; const value = entry.fields.get(value_str).?; - new_map.set(ctx.vm.gc, key, value) catch @panic("Out of memory"); + new_map.set(ctx.vm.gc, key, value) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } ctx.vm.push(new_map.toValue()); @@ -212,7 +239,10 @@ pub fn diff(ctx: *NativeCtx) c_int { ctx.vm.gc.allocator, lhs.type_def, ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; var it = lhs.map.iterator(); while (it.next()) |kv| { @@ -222,7 +252,10 @@ pub fn diff(ctx: *NativeCtx) c_int { ctx.vm.gc, kv.key_ptr.*, kv.value_ptr.*, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } @@ -241,7 +274,10 @@ pub fn intersect(ctx: *NativeCtx) c_int { ctx.vm.gc.allocator, lhs.type_def, ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; var it = lhs.map.iterator(); while (it.next()) |kv| { @@ -251,7 +287,10 @@ pub fn intersect(ctx: *NativeCtx) c_int { ctx.vm.gc, kv.key_ptr.*, kv.value_ptr.*, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } @@ -287,7 +326,10 @@ pub fn keys(ctx: *NativeCtx) c_int { const map_keys = self.map.keys(); var result = std.ArrayList(Value).init(ctx.vm.gc.allocator); for (map_keys) |key| { - result.append(key) catch @panic("Out of memory"); + result.append(key) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } var list_def_type: *ObjTypeDef = ctx.vm.gc.type_registry.getTypeDef( @@ -301,7 +343,10 @@ pub fn keys(ctx: *NativeCtx) c_int { ), }, }, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; // Prevent collection ctx.vm.push(list_def_type.toValue()); @@ -309,7 +354,10 @@ pub fn keys(ctx: *NativeCtx) c_int { var list = ctx.vm.gc.allocateObject( ObjList, ObjList.init(ctx.vm.gc.allocator, list_def_type), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; list.items.deinit(); list.items = result; @@ -325,7 +373,10 @@ pub fn values(ctx: *NativeCtx) c_int { const map_values: []Value = self.map.values(); var result = std.ArrayList(Value).init(ctx.vm.gc.allocator); - result.appendSlice(map_values) catch @panic("Out of memory"); + result.appendSlice(map_values) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; const list_def_type = ctx.vm.gc.type_registry.getTypeDef( ObjTypeDef{ @@ -338,12 +389,18 @@ pub fn values(ctx: *NativeCtx) c_int { ), }, }, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; var list = ctx.vm.gc.allocateObject( ObjList, ObjList.init(ctx.vm.gc.allocator, list_def_type), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; list.items.deinit(); list.items = result; diff --git a/src/builtin/pattern.zig b/src/builtin/pattern.zig index b323d5bb..ac3ba0b8 100644 --- a/src/builtin/pattern.zig +++ b/src/builtin/pattern.zig @@ -60,7 +60,10 @@ fn rawMatch(self: *ObjPattern, vm: *VM, subject: *ObjString, offset: *usize) !?* } var results: ?*ObjList = null; - var match_data = self.pattern.createMatchData(null) orelse @panic("Out of memory"); + var match_data = self.pattern.createMatchData(null) orelse { + vm.panic("Out of memory"); + unreachable; + }; defer match_data.free(); const rc = self.pattern.match( @@ -75,7 +78,10 @@ fn rawMatch(self: *ObjPattern, vm: *VM, subject: *ObjString, offset: *usize) !?* switch (rc) { @intFromEnum(pcre.MatchingError.DFA_UINVALID_UTF)...@intFromEnum(pcre.MatchingError.NOMATCH) => {}, // TODO: handle ouptut_vector too small - 0 => @panic("Could not match pattern"), + 0 => { + vm.panic("Could not match pattern"); + unreachable; + }, else => { const output_vector = match_data.getOVectorPointer(); @@ -152,7 +158,10 @@ fn rawReplace(self: *ObjPattern, vm: *VM, subject: *ObjString, replacement: *Obj var result = std.ArrayList(u8).init(vm.gc.allocator); defer result.deinit(); - var match_data = self.pattern.createMatchData(null) orelse @panic("Out of memory"); + var match_data = self.pattern.createMatchData(null) orelse { + vm.panic("Out of memory"); + unreachable; + }; defer match_data.free(); const rc = self.pattern.match( @@ -167,7 +176,10 @@ fn rawReplace(self: *ObjPattern, vm: *VM, subject: *ObjString, replacement: *Obj switch (rc) { @intFromEnum(pcre.MatchingError.DFA_UINVALID_UTF)...@intFromEnum(pcre.MatchingError.NOMATCH) => return subject, // TODO: handle ouptut_vector too small - 0 => @panic("Could not match pattern"), + 0 => { + vm.panic("Could not match pattern"); + unreachable; + }, else => { const output_vector = match_data.getOVectorPointer(); @@ -218,7 +230,10 @@ pub fn match(ctx: *NativeCtx) c_int { ctx.vm, subject, &offset, - ) catch @panic("Out of memory")) |results| { + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }) |results| { ctx.vm.push(results.toValue()); } else { ctx.vm.push(Value.Null); @@ -240,7 +255,10 @@ pub fn replace(ctx: *NativeCtx) c_int { subject, replacement, &offset, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(result.toValue()); } else { @@ -256,7 +274,10 @@ pub fn replace(ctx: *NativeCtx) c_int { @intCast(self.source.len), ), ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; defer ctx.vm.gc.allocator.free(buffer); patternReplace( @@ -271,7 +292,10 @@ pub fn replace(ctx: *NativeCtx) c_int { ); ctx.vm.push( - (ctx.vm.gc.copyString(buffer) catch @panic("Out of memory")).toValue(), + (ctx.vm.gc.copyString(buffer) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue(), ); } @@ -286,7 +310,10 @@ pub fn matchAll(ctx: *NativeCtx) c_int { self, ctx.vm, subject, - ) catch @panic("Out of memory")) |results| { + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }) |results| { ctx.vm.push(results.toValue()); } else { ctx.vm.push(Value.Null); @@ -306,7 +333,10 @@ pub fn replaceAll(ctx: *NativeCtx) c_int { ctx.vm, subject, replacement, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(result.toValue()); } else { @@ -322,7 +352,10 @@ pub fn replaceAll(ctx: *NativeCtx) c_int { @intCast(self.source.len), ), ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; defer ctx.vm.gc.allocator.free(buffer); patternReplaceAll( @@ -337,7 +370,10 @@ pub fn replaceAll(ctx: *NativeCtx) c_int { ); ctx.vm.push( - (ctx.vm.gc.copyString(buffer) catch @panic("Out of memory")).toValue(), + (ctx.vm.gc.copyString(buffer) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue(), ); } diff --git a/src/builtin/range.zig b/src/builtin/range.zig index d7f13ae1..0fe30cba 100644 --- a/src/builtin/range.zig +++ b/src/builtin/range.zig @@ -10,19 +10,28 @@ pub fn toList(ctx: *obj.NativeCtx) c_int { ctx.vm.gc.allocator, ctx.vm.gc.type_registry.int_type, ), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(Value.fromObj(list.toObj())); if (range.low < range.high) { var i: i32 = range.low; while (i < range.high) : (i += 1) { - list.rawAppend(ctx.vm.gc, Value.fromInteger(i)) catch @panic("Out of memory"); + list.rawAppend(ctx.vm.gc, Value.fromInteger(i)) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } else { var i: i32 = range.low; while (i > range.high) : (i -= 1) { - list.rawAppend(ctx.vm.gc, Value.fromInteger(i)) catch @panic("Out of memory"); + list.rawAppend(ctx.vm.gc, Value.fromInteger(i)) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } @@ -54,7 +63,10 @@ pub fn invert(ctx: *obj.NativeCtx) c_int { .high = range.low, .low = range.high, }, - ) catch @panic("Out of memory")).toObj()), + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toObj()), ); return 1; diff --git a/src/builtin/str.zig b/src/builtin/str.zig index 3fa0a409..45b6c7fe 100644 --- a/src/builtin/str.zig +++ b/src/builtin/str.zig @@ -13,7 +13,10 @@ pub fn trim(ctx: *NativeCtx) c_int { const trimmed = std.mem.trim(u8, str.string, " \t\r\n"); - ctx.vm.push((ctx.vm.gc.copyString(trimmed) catch @panic("Out of memory")).toValue()); + ctx.vm.push((ctx.vm.gc.copyString(trimmed) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue()); return 1; } @@ -68,20 +71,32 @@ pub fn utf8Codepoints(ctx: *NativeCtx) c_int { ), }, }, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; var list = (ctx.vm.gc.allocateObject( ObjList, ObjList.init(ctx.vm.gc.allocator, list_def_type), - ) catch @panic("Out of memory")); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }); if (std.unicode.utf8ValidateSlice(str.string)) { const view = std.unicode.Utf8View.init(str.string) catch unreachable; var it = view.iterator(); while (it.nextCodepointSlice()) |codepoint| { - const codepoint_str = ctx.vm.gc.copyString(codepoint) catch @panic("Out of memory"); - - list.rawAppend(ctx.vm.gc, codepoint_str.toValue()) catch @panic("Out of memory"); + const codepoint_str = ctx.vm.gc.copyString(codepoint) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; + + list.rawAppend(ctx.vm.gc, codepoint_str.toValue()) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } @@ -97,10 +112,16 @@ pub fn repeat(ctx: *NativeCtx) c_int { var new_string: std.ArrayList(u8) = std.ArrayList(u8).init(ctx.vm.gc.allocator); var i: usize = 0; while (i < n) : (i += 1) { - new_string.appendSlice(str.string) catch @panic("Out of memory"); + new_string.appendSlice(str.string) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } - const new_objstring = ctx.vm.gc.copyString(new_string.items) catch @panic("Out of memory"); + const new_objstring = ctx.vm.gc.copyString(new_string.items) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(new_objstring.toValue()); @@ -179,10 +200,16 @@ pub fn replace(ctx: *NativeCtx) c_int { self.string, needle.string, replacement.string, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push( - (ctx.vm.gc.copyString(new_string) catch @panic("Out of memory")).toValue(), + (ctx.vm.gc.copyString(new_string) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue(), ); return 1; @@ -209,7 +236,10 @@ pub fn sub(ctx: *NativeCtx) c_int { const substr = self.string[@intCast(start)..limit]; ctx.vm.push( - (ctx.vm.gc.copyString(substr) catch @panic("Out of memory")).toValue(), + (ctx.vm.gc.copyString(substr) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue(), ); return 1; @@ -230,12 +260,18 @@ pub fn split(ctx: *NativeCtx) c_int { ), }, }, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; var list = ctx.vm.gc.allocateObject( ObjList, ObjList.init(ctx.vm.gc.allocator, list_def_type), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; // Prevent gc & is result ctx.vm.push(list.toValue()); @@ -243,15 +279,27 @@ pub fn split(ctx: *NativeCtx) c_int { if (separator.string.len > 0) { var it = std.mem.splitSequence(u8, self.string, separator.string); while (it.next()) |fragment| { - const fragment_str = ctx.vm.gc.copyString(fragment) catch @panic("Out of memory"); - - list.rawAppend(ctx.vm.gc, fragment_str.toValue()) catch @panic("Out of memory"); + const fragment_str = ctx.vm.gc.copyString(fragment) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; + + list.rawAppend(ctx.vm.gc, fragment_str.toValue()) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } else { for (self.string) |char| { - const fragment_str = ctx.vm.gc.copyString(&([_]u8{char})) catch @panic("Out of memory"); - - list.rawAppend(ctx.vm.gc, fragment_str.toValue()) catch @panic("Out of memory"); + const fragment_str = ctx.vm.gc.copyString(&([_]u8{char})) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; + + list.rawAppend(ctx.vm.gc, fragment_str.toValue()) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } } @@ -264,12 +312,18 @@ pub fn encodeBase64(ctx: *NativeCtx) c_int { const encoded = ctx.vm.gc.allocator.alloc( u8, std.base64.standard.Encoder.calcSize(str.string.len), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; defer ctx.vm.gc.allocator.free(encoded); var new_string = ctx.vm.gc.copyString( std.base64.standard.Encoder.encode(encoded, str.string), - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(new_string.toValue()); @@ -281,20 +335,32 @@ pub fn decodeBase64(ctx: *NativeCtx) c_int { const str = ObjString.cast(ctx.vm.peek(0).obj()).?; const size = std.base64.standard.Decoder.calcSizeForSlice(str.string) catch { - ctx.vm.push((ctx.vm.gc.copyString("Could not decode string") catch @panic("Out of memory")).toValue()); + ctx.vm.push((ctx.vm.gc.copyString("Could not decode string") catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue()); return -1; }; - const decoded = ctx.vm.gc.allocator.alloc(u8, size) catch @panic("Out of memory"); + const decoded = ctx.vm.gc.allocator.alloc(u8, size) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; defer ctx.vm.gc.allocator.free(decoded); std.base64.standard.Decoder.decode(decoded, str.string) catch { - ctx.vm.push((ctx.vm.gc.copyString("Could not decode string") catch @panic("Out of memory")).toValue()); + ctx.vm.push((ctx.vm.gc.copyString("Could not decode string") catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue()); return -1; }; - var new_string = ctx.vm.gc.copyString(decoded) catch @panic("Out of memory"); + var new_string = ctx.vm.gc.copyString(decoded) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(new_string.toValue()); @@ -310,7 +376,10 @@ pub fn upper(ctx: *NativeCtx) c_int { return 1; } - var new_str = ctx.vm.gc.allocator.alloc(u8, str.string.len) catch @panic("Out of memory"); + var new_str = ctx.vm.gc.allocator.alloc(u8, str.string.len) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; defer ctx.vm.gc.allocator.free(new_str); for (str.string, 0..) |char, index| { @@ -320,7 +389,10 @@ pub fn upper(ctx: *NativeCtx) c_int { } } - var obj_string = ctx.vm.gc.copyString(new_str) catch @panic("Out of memory"); + var obj_string = ctx.vm.gc.copyString(new_str) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(obj_string.toValue()); @@ -336,7 +408,10 @@ pub fn lower(ctx: *NativeCtx) c_int { return 1; } - var new_str = ctx.vm.gc.allocator.alloc(u8, str.string.len) catch @panic("Out of memory"); + var new_str = ctx.vm.gc.allocator.alloc(u8, str.string.len) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; defer ctx.vm.gc.allocator.free(new_str); for (str.string, 0..) |char, index| { @@ -346,7 +421,10 @@ pub fn lower(ctx: *NativeCtx) c_int { } } - var obj_string = ctx.vm.gc.copyString(new_str) catch @panic("Out of memory"); + var obj_string = ctx.vm.gc.copyString(new_str) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(obj_string.toValue()); @@ -367,10 +445,16 @@ pub fn hex(ctx: *NativeCtx) c_int { var writer = result.writer(); for (str.string) |char| { - writer.print("{x:0>2}", .{char}) catch @panic("Out of memory"); + writer.print("{x:0>2}", .{char}) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; } - var obj_string = ctx.vm.gc.copyString(result.items) catch @panic("Out of memory"); + var obj_string = ctx.vm.gc.copyString(result.items) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(obj_string.toValue()); @@ -386,20 +470,29 @@ pub fn bin(ctx: *NativeCtx) c_int { return 1; } - var result = ctx.vm.gc.allocator.alloc(u8, str.string.len / 2) catch @panic("Out of memory"); + var result = ctx.vm.gc.allocator.alloc(u8, str.string.len / 2) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; defer ctx.vm.gc.allocator.free(result); for (0..result.len) |i| { result[i] = std.fmt.parseInt(u8, str.string[(i * 2)..(i * 2 + 2)], 16) catch { ctx.vm.push( - (ctx.vm.gc.copyString("String does not contain valid hex values") catch @panic("Out of memory")).toValue(), + (ctx.vm.gc.copyString("String does not contain valid hex values") catch { + ctx.vm.panic("Out of memory"); + unreachable; + }).toValue(), ); return -1; }; } - var obj_string = ctx.vm.gc.copyString(result) catch @panic("Out of memory"); + var obj_string = ctx.vm.gc.copyString(result) catch { + ctx.vm.panic("Out of memory"); + unreachable; + }; ctx.vm.push(obj_string.toValue()); diff --git a/src/buzz_api.zig b/src/buzz_api.zig index aa938e0e..33323205 100644 --- a/src/buzz_api.zig +++ b/src/buzz_api.zig @@ -380,7 +380,10 @@ export fn bz_string(vm: *VM, string: ?[*]const u8, len: usize) ?*ObjString { export fn bz_stringZ(vm: *VM, string: [*:0]const u8) Value { // Keeping the sentinel - return (vm.gc.copyString(string[0..(std.mem.len(string) + 1)]) catch @panic("Out of memory")).toValue(); + return (vm.gc.copyString(string[0..(std.mem.len(string) + 1)]) catch { + vm.panic("Out of memory"); + unreachable; + }).toValue(); } export fn bz_valueToObjString(value: Value) *ObjString { @@ -476,7 +479,10 @@ export fn bz_mapType(vm: *VM, key_type: Value, value_type: Value) Value { .optional = false, .resolved_type = resolved_type, }, - ) catch @panic("Out of memory"); + ) catch { + vm.panic("Out of memory"); + unreachable; + }; return typedef.toValue(); } @@ -622,7 +628,10 @@ export fn bz_newVM(self: *VM) ?*VM { }; // FIXME: should share strings between gc gc.* = GarbageCollector.init(self.gc.allocator); - gc.type_registry = TypeRegistry.init(gc) catch @panic("Out of memory"); + gc.type_registry = TypeRegistry.init(gc) catch { + vm.panic("Out of memory"); + unreachable; + }; // FIXME: give reference to JIT? vm.* = VM.init(gc, self.import_registry, self.flavor) catch { @@ -636,6 +645,10 @@ export fn bz_deinitVM(_: *VM) void { // self.deinit(); } +export fn bz_panic(vm: *VM, msg: [*]const u8, len: usize) void { + vm.panic(msg[0..len]); +} + export fn bz_compile( self: *VM, source: ?[*]const u8, @@ -819,7 +832,10 @@ export fn bz_instanceQualified(self: *VM, qualified_name: [*]const u8, len: usiz ObjObjectInstance.init( self, object, - object.type_def.toInstance(self.gc.allocator, &self.gc.type_registry) catch @panic("Out of memory"), + object.type_def.toInstance(self.gc.allocator, &self.gc.type_registry) catch { + self.panic("Out of memory"); + unreachable; + }, ), ) catch { @panic("Could not create error"); @@ -854,8 +870,14 @@ fn instanciateError( if (obj_instance.fields.get(message_key) != null) { obj_instance.fields.put( message_key, - (vm.gc.copyString(msg[0..mlen]) catch @panic("Out of memory")).toValue(), - ) catch @panic("Out of memory"); + (vm.gc.copyString(msg[0..mlen]) catch { + vm.panic("Out of memory"); + unreachable; + }).toValue(), + ) catch { + vm.panic("Out of memory"); + unreachable; + }; } } @@ -1092,7 +1114,10 @@ export fn bz_valueEqual(self: Value, other: Value) Value { } export fn bz_valueTypeOf(self: Value, vm: *VM) Value { - return (self.typeOf(vm.gc) catch @panic("Out of memory")).toValue(); + return (self.typeOf(vm.gc) catch { + vm.panic("Out of memory"); + unreachable; + }).toValue(); } export fn bz_newMap(vm: *VM, map_type: Value) Value { @@ -1518,7 +1543,10 @@ export fn bz_checkBuzzType( var err = std.ArrayList(u8).init(vm.gc.allocator); defer err.deinit(); - const typedef = ObjTypeDef.cast(btype.obj()).?.toStringAlloc(vm.gc.allocator) catch @panic("Out of memory"); + const typedef = ObjTypeDef.cast(btype.obj()).?.toStringAlloc(vm.gc.allocator) catch { + vm.panic("Out of memory"); + unreachable; + }; defer typedef.deinit(); err.writer().print( @@ -1527,7 +1555,10 @@ export fn bz_checkBuzzType( typedef.items, ztype.*, }, - ) catch @panic("Out of memory"); + ) catch { + vm.panic("Out of memory"); + unreachable; + }; bz_pushError( vm, @@ -1593,7 +1624,10 @@ export fn bz_readZigValueFromBuffer( ), ), }, - ) catch @panic("Out of memory"); + ) catch { + vm.panic("Out of memory"); + unreachable; + }; break :integer userdata.toValue(); }, @@ -1679,7 +1713,10 @@ export fn bz_readZigValueFromBuffer( .{ .userdata = std.mem.bytesToValue(u64, bytes[0..8]), }, - ) catch @panic("Out of memory"); + ) catch { + vm.panic("Out of memory"); + unreachable; + }; break :ptr userdata.toValue(); }, @@ -1709,7 +1746,10 @@ export fn bz_writeZigValueToBuffer( @as(u8, 0)); const bytes = std.mem.asBytes(&unwrapped); - buffer.replaceRange(at, bytes.len, bytes) catch @panic("Out of memory"); + buffer.replaceRange(at, bytes.len, bytes) catch { + vm.panic("Out of memory"); + unreachable; + }; }, // Integer can just be truncated .Int => { @@ -1718,13 +1758,19 @@ export fn bz_writeZigValueToBuffer( const unwrapped = ObjUserData.cast(value.obj()).?.userdata; const bytes = std.mem.asBytes(&unwrapped); - buffer.replaceRange(at, bytes.len, bytes) catch @panic("Out of memory"); + buffer.replaceRange(at, bytes.len, bytes) catch { + vm.panic("Out of memory"); + unreachable; + }; }, 1...32 => { const unwrapped = value.integer(); const bytes = std.mem.asBytes(&unwrapped)[0..(ztype.Int.bits / 8)]; - buffer.replaceRange(at, bytes.len, bytes) catch @panic("Out of memory"); + buffer.replaceRange(at, bytes.len, bytes) catch { + vm.panic("Out of memory"); + unreachable; + }; }, else => {}, } @@ -1734,13 +1780,19 @@ export fn bz_writeZigValueToBuffer( const unwrapped = @as(f32, @floatCast(value.float())); const bytes = std.mem.asBytes(&unwrapped); - buffer.replaceRange(at, bytes.len, bytes) catch @panic("Out of memory"); + buffer.replaceRange(at, bytes.len, bytes) catch { + vm.panic("Out of memory"); + unreachable; + }; }, 64 => { const unwrapped = value.float(); const bytes = std.mem.asBytes(&unwrapped); - buffer.replaceRange(at, bytes.len, bytes) catch @panic("Out of memory"); + buffer.replaceRange(at, bytes.len, bytes) catch { + vm.panic("Out of memory"); + unreachable; + }; }, else => {}, }, @@ -1762,7 +1814,10 @@ export fn bz_writeZigValueToBuffer( const unwrapped = ObjUserData.cast(value.obj()).?.userdata; const bytes = std.mem.asBytes(&unwrapped); - buffer.replaceRange(at, bytes.len, bytes) catch @panic("Out of memory"); + buffer.replaceRange(at, bytes.len, bytes) catch { + vm.panic("Out of memory"); + unreachable; + }; }, else => {}, } @@ -1793,8 +1848,14 @@ export fn bz_containerInstance(vm: *VM, typedef_value: Value) Value { ObjForeignContainer.init( vm, ObjTypeDef.cast(typedef_value.obj()).?, - ) catch @panic("Out of memory"), - ) catch @panic("Out of memory")).toValue(); + ) catch { + vm.panic("Out of memory"); + unreachable; + }, + ) catch { + vm.panic("Out of memory"); + unreachable; + }).toValue(); } export fn bz_memcpy(dest: [*]u8, dest_len: usize, source: [*]u8, source_len: usize) void { @@ -1816,7 +1877,10 @@ export fn bz_containerFromSlice(vm: *VM, type_def: *ObjTypeDef, ptr: [*]u8, len: .type_def = type_def, .data = ptr[0..len], }, - ) catch @panic("Out of memory")); + ) catch { + vm.panic("Out of memory"); + unreachable; + }); return container.toValue(); } @@ -1856,7 +1920,10 @@ export fn bz_serialize(vm: *VM, value: Value, error_value: *Value) Value { ); break :s Value.Void; }, - else => @panic("Out of memory"), + else => { + vm.panic("Out of memory"); + unreachable; + }, } }; } @@ -1867,5 +1934,8 @@ export fn bz_currentFiber(vm: *VM) Value { .{ .fiber = vm.current_fiber, }, - ) catch @panic("Out of memory")).toValue(); + ) catch { + vm.panic("Out of memory"); + unreachable; + }).toValue(); } diff --git a/src/lib/buzz_api.zig b/src/lib/buzz_api.zig index 584b6e4f..6fcf7a7d 100644 --- a/src/lib/buzz_api.zig +++ b/src/lib/buzz_api.zig @@ -59,6 +59,7 @@ pub const VM = opaque { pub extern fn bz_newVM(self: *VM) *VM; pub extern fn bz_deinitVM(self: *VM) void; + pub extern fn bz_panic(vm: *VM, msg: [*]const u8, len: usize) void; pub extern fn bz_compile( self: *VM, source: ?[*]const u8, diff --git a/src/lib/buzz_buffer.zig b/src/lib/buzz_buffer.zig index c9d0c82c..bf2a9c08 100644 --- a/src/lib/buzz_buffer.zig +++ b/src/lib/buzz_buffer.zig @@ -14,10 +14,12 @@ pub export fn BufferNew(ctx: *api.NativeCtx) c_int { const capacity = ctx.vm.bz_peek(0).integer(); const buffer = api.VM.allocator.create(Buffer) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; buffer.* = Buffer.init(api.VM.allocator, @intCast(capacity)) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; if (api.ObjUserData.bz_newUserData(ctx.vm, @intFromPtr(buffer))) |userdata| { @@ -25,7 +27,8 @@ pub export fn BufferNew(ctx: *api.NativeCtx) c_int { return 1; } else { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } } @@ -254,7 +257,10 @@ pub export fn BufferWrite(ctx: *api.NativeCtx) c_int { buffer.write(bytes.?[0..len]) catch |err| { switch (err) { Buffer.Error.WriteWhileReading => ctx.vm.pushError("buffer.WriteWhileReadingError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, } return -1; @@ -298,7 +304,10 @@ pub export fn BufferWriteBoolean(ctx: *api.NativeCtx) c_int { buffer.writeBool(value) catch |err| { switch (err) { Buffer.Error.WriteWhileReading => ctx.vm.pushError("buffer.WriteWhileReadingError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, } return -1; @@ -377,7 +386,10 @@ pub export fn BufferWriteInt(ctx: *api.NativeCtx) c_int { buffer.writeInteger(number.integer()) catch |err| { switch (err) { Buffer.Error.WriteWhileReading => ctx.vm.pushError("buffer.WriteWhileReadingError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, } return -1; @@ -393,7 +405,10 @@ pub export fn BufferWriteUserData(ctx: *api.NativeCtx) c_int { buffer.writeUserData(userdata.bz_valueToObjUserData()) catch |err| { switch (err) { Buffer.Error.WriteWhileReading => ctx.vm.pushError("buffer.WriteWhileReadingError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, } return -1; @@ -409,7 +424,10 @@ pub export fn BufferWriteFloat(ctx: *api.NativeCtx) c_int { buffer.writeFloat(number.float()) catch |err| { switch (err) { Buffer.Error.WriteWhileReading => ctx.vm.pushError("buffer.WriteWhileReadingError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, } return -1; @@ -452,7 +470,8 @@ pub export fn BufferBuffer(ctx: *api.NativeCtx) c_int { ) else null, buffer.buffer.items.len)) |objstring| { ctx.vm.bz_pushString(objstring); } else { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } return 1; @@ -508,7 +527,10 @@ inline fn rawWriteZ( const len = api.VM.bz_zigValueSize(zig_type.?); - buffer.buffer.ensureTotalCapacityPrecise(buffer.buffer.items.len + len) catch @panic("Out of memory"); + buffer.buffer.ensureTotalCapacityPrecise(buffer.buffer.items.len + len) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; buffer.buffer.expandToCapacity(); std.debug.assert(buffer.buffer.capacity == buffer.buffer.items.len); @@ -588,12 +610,18 @@ inline fn rawWriteStruct( var len: usize = 0; const ptr = api.ObjForeignContainer.bz_containerSlice(value, &len); - buffer.buffer.ensureTotalCapacityPrecise(buffer.buffer.items.len + len) catch @panic("Out of memory"); + buffer.buffer.ensureTotalCapacityPrecise(buffer.buffer.items.len + len) catch { + vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; buffer.buffer.expandToCapacity(); std.debug.assert(buffer.buffer.capacity == buffer.buffer.items.len); - buffer.buffer.replaceRange(index, len, ptr[0..len]) catch @panic("Out of memory"); + buffer.buffer.replaceRange(index, len, ptr[0..len]) catch { + vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; index += len; } diff --git a/src/lib/buzz_ffi.zig b/src/lib/buzz_ffi.zig index e5f5b14a..6dadb29a 100644 --- a/src/lib/buzz_ffi.zig +++ b/src/lib/buzz_ffi.zig @@ -19,7 +19,10 @@ pub export fn alignOf(ctx: *api.NativeCtx) c_int { .{ zig_type_str[0..len], }, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; ctx.vm.pushError("ffi.FFIZigTypeParseError", msg.items); @@ -47,7 +50,10 @@ pub export fn sizeOf(ctx: *api.NativeCtx) c_int { .{ zig_type_str[0..len], }, - ) catch @panic("Out of memory"); + ) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; ctx.vm.pushError("ffi.FFIZigTypeParseError", msg.items); diff --git a/src/lib/buzz_fs.zig b/src/lib/buzz_fs.zig index cf235d27..3df2e546 100644 --- a/src/lib/buzz_fs.zig +++ b/src/lib/buzz_fs.zig @@ -150,7 +150,10 @@ fn handleRealpathError(ctx: *api.NativeCtx, err: anytype) void { => ctx.vm.pushErrorEnum("errors.FileSystemError", @errorName(err)), error.Unexpected => ctx.vm.pushError("errors.UnexpectedError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, } } @@ -318,7 +321,8 @@ pub export fn list(ctx: *api.NativeCtx) c_int { if (element.name.len > 0) @as([*]const u8, @ptrCast(element.name)) else null, element.name.len, ) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); api.ObjList.bz_listAppend(ctx.vm, file_list, ctx.vm.bz_pop()); diff --git a/src/lib/buzz_http.zig b/src/lib/buzz_http.zig index 111e323c..964ed049 100644 --- a/src/lib/buzz_http.zig +++ b/src/lib/buzz_http.zig @@ -3,20 +3,27 @@ const api = @import("buzz_api.zig"); const http = std.http; pub export fn HttpClientNew(ctx: *api.NativeCtx) c_int { - const client = api.VM.allocator.create(http.Client) catch @panic("Out of memory"); + const client = api.VM.allocator.create(http.Client) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; client.* = http.Client{ .allocator = api.VM.allocator, }; - client.initDefaultProxies(api.VM.allocator) catch @panic("Out of memory"); + client.initDefaultProxies(api.VM.allocator) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; if (api.ObjUserData.bz_newUserData(ctx.vm, @intFromPtr(client))) |userdata| { ctx.vm.bz_pushUserData(userdata); return 1; } else { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } } @@ -41,7 +48,8 @@ pub export fn HttpClientSend(ctx: *api.NativeCtx) c_int { var uri_len: usize = 0; const uri = ctx.vm.bz_peek(1).bz_valueToObjString().bz_objStringToString(&uri_len); if (uri == null) { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } const header_values = ctx.vm.bz_peek(0); @@ -55,7 +63,8 @@ pub export fn HttpClientSend(ctx: *api.NativeCtx) c_int { const value = next_header_value.bz_valueToString(&value_len); if (key == null or value == null) { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } headers.append( @@ -63,11 +72,20 @@ pub export fn HttpClientSend(ctx: *api.NativeCtx) c_int { .name = key.?[0..key_len], .value = value.?[0..value_len], }, - ) catch @panic("Could not send request"); + ) catch { + ctx.vm.bz_panic("Could not send request", "Could not send request".len); + unreachable; + }; } - const request = api.VM.allocator.create(http.Client.Request) catch @panic("Out of memory"); - const server_header_buffer = api.VM.allocator.alloc(u8, 16 * 1024) catch @panic("Out of memory"); + const request = api.VM.allocator.create(http.Client.Request) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; + const server_header_buffer = api.VM.allocator.alloc(u8, 16 * 1024) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; request.* = client.open( method, @@ -97,7 +115,8 @@ pub export fn HttpClientSend(ctx: *api.NativeCtx) c_int { return 1; } else { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } } @@ -180,7 +199,10 @@ pub export fn HttpRequestRead(ctx: *api.NativeCtx) c_int { ctx.vm, "body".ptr, "body".len, - ) orelse @panic("Out of memory"), + ) orelse { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, ), if (body_raw.items.len == 0) api.Value.Null @@ -190,7 +212,10 @@ pub export fn HttpRequestRead(ctx: *api.NativeCtx) c_int { ctx.vm, body_raw.items.ptr, body_raw.items.len, - ) orelse @panic("Out of memory"), + ) orelse { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, ), ); @@ -203,7 +228,10 @@ pub export fn HttpRequestRead(ctx: *api.NativeCtx) c_int { ctx.vm, "status".ptr, "status".len, - ) orelse @panic("Out of memory"), + ) orelse { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, ), api.Value.fromInteger(@intFromEnum(request.response.status)), ); @@ -227,7 +255,10 @@ pub export fn HttpRequestRead(ctx: *api.NativeCtx) c_int { ctx.vm, "headers".ptr, "headers".len, - ) orelse @panic("Out of memory"), + ) orelse { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, ), headers, ); @@ -242,14 +273,20 @@ pub export fn HttpRequestRead(ctx: *api.NativeCtx) c_int { ctx.vm, header.name.ptr, header.name.len, - ) orelse @panic("Out of memory"), + ) orelse { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, ), api.ObjString.bz_objStringToValue( api.ObjString.bz_string( ctx.vm, header.value.ptr, header.value.len, - ) orelse @panic("Out of memory"), + ) orelse { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, ), ); } @@ -261,7 +298,10 @@ pub export fn HttpRequestRead(ctx: *api.NativeCtx) c_int { fn handleWaitError(ctx: *api.NativeCtx, err: anytype) void { switch (err) { - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, error.CertificateBundleLoadFailure, error.CompressionInitializationFailed, @@ -313,7 +353,10 @@ fn handleStartError(ctx: *api.NativeCtx, err: anytype) void { fn handleError(ctx: *api.NativeCtx, err: anytype) void { switch (err) { - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, error.CertificateBundleLoadFailure, error.ConnectionRefused, @@ -339,7 +382,10 @@ fn handleError(ctx: *api.NativeCtx, err: anytype) void { fn handleResponseError(ctx: *api.NativeCtx, err: anytype) void { switch (err) { - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, error.TlsFailure, error.TlsAlert, diff --git a/src/lib/buzz_io.zig b/src/lib/buzz_io.zig index fe1b1bd5..4ee196cb 100644 --- a/src/lib/buzz_io.zig +++ b/src/lib/buzz_io.zig @@ -128,7 +128,10 @@ fn handleFileReadWriteError(ctx: *api.NativeCtx, err: anytype) void { => ctx.vm.pushErrorEnum("errors.ReadWriteError", @errorName(err)), error.Unexpected => ctx.vm.pushError("errors.UnexpectedError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, } } @@ -156,7 +159,8 @@ pub export fn FileReadAll(ctx: *api.NativeCtx) c_int { }; ctx.vm.bz_pushString(api.ObjString.bz_string(ctx.vm, if (content.len > 0) @as([*]const u8, @ptrCast(content)) else null, content.len) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); return 1; @@ -180,7 +184,10 @@ fn handleFileReadLineError(ctx: *api.NativeCtx, err: anytype) void { error.StreamTooLong, => ctx.vm.pushErrorEnum("errors.ReadWriteError", @errorName(err)), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, error.Unexpected => ctx.vm.pushError("errors.UnexpectedError", null), } @@ -215,7 +222,8 @@ pub export fn FileReadLine(ctx: *api.NativeCtx) c_int { if (ubuffer.len > 0) @as([*]const u8, @ptrCast(ubuffer)) else null, ubuffer.len, ) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }, ); } else { @@ -262,7 +270,8 @@ pub export fn FileRead(ctx: *api.NativeCtx) c_int { const reader = file.reader(); var buffer = api.VM.allocator.alloc(u8, @as(usize, @intCast(n))) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; // bz_string will copy it @@ -278,7 +287,8 @@ pub export fn FileRead(ctx: *api.NativeCtx) c_int { ctx.vm.bz_pushNull(); } else { ctx.vm.bz_pushString(api.ObjString.bz_string(ctx.vm, if (buffer[0..read].len > 0) @as([*]const u8, @ptrCast(buffer[0..read])) else null, read) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); } @@ -347,8 +357,14 @@ pub export fn runFile(ctx: *api.NativeCtx) c_int { const source = api.VM.allocator.alloc( u8, - (file.stat() catch @panic("Out of memory")).size, - ) catch @panic("Out of memory"); + (file.stat() catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }).size, + ) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; _ = file.readAll(source) catch |err| { handleFileReadAllError(ctx, err); diff --git a/src/lib/buzz_os.zig b/src/lib/buzz_os.zig index 74eaed8e..9651479f 100644 --- a/src/lib/buzz_os.zig +++ b/src/lib/buzz_os.zig @@ -24,13 +24,17 @@ pub export fn env(ctx: *api.NativeCtx) c_int { return 1; } - const key_slice = api.VM.allocator.dupeZ(u8, key.?[0..len]) catch @panic("Out of memory"); + const key_slice = api.VM.allocator.dupeZ(u8, key.?[0..len]) catch { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }; defer api.VM.allocator.free(key_slice); // FIXME: don't use std.posix directly if (std.posix.getenv(key_slice)) |value| { ctx.vm.bz_pushString(api.ObjString.bz_string(ctx.vm, if (value.len > 0) @as([*]const u8, @ptrCast(value)) else null, value.len) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); return 1; @@ -52,7 +56,8 @@ pub export fn tmpDir(ctx: *api.NativeCtx) c_int { const tmp_dir: []const u8 = sysTempDir(); ctx.vm.bz_pushString(api.ObjString.bz_string(ctx.vm, if (tmp_dir.len > 0) @as([*]const u8, @ptrCast(tmp_dir)) else null, tmp_dir.len) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); return 1; @@ -68,11 +73,13 @@ pub export fn tmpFilename(ctx: *api.NativeCtx) c_int { var random_part = std.ArrayList(u8).init(api.VM.allocator); defer random_part.deinit(); random_part.writer().print("{x}", .{std.crypto.random.int(i32)}) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; var random_part_b64 = std.ArrayList(u8).initCapacity(api.VM.allocator, std.base64.standard.Encoder.calcSize(random_part.items.len)) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; random_part_b64.expandToCapacity(); defer random_part_b64.deinit(); @@ -83,11 +90,13 @@ pub export fn tmpFilename(ctx: *api.NativeCtx) c_int { defer final.deinit(); final.writer().print("{s}{s}-{s}", .{ sysTempDir(), prefix_slice, random_part_b64.items }) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; ctx.vm.bz_pushString(api.ObjString.bz_string(ctx.vm, if (final.items.len > 0) @as([*]const u8, @ptrCast(final.items)) else null, final.items.len) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); return 1; @@ -133,7 +142,10 @@ fn handleSpawnError(ctx: *api.NativeCtx, err: anytype) void { error.WaitTimeOut, => ctx.vm.pushErrorEnum("errors.ExecError", @errorName(err)), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, error.Unexpected => ctx.vm.pushError("errors.UnexpectedError", null), } } @@ -154,7 +166,8 @@ pub export fn execute(ctx: *api.NativeCtx) c_int { std.debug.assert(arg_len > 0); command.append(arg_str.?[0..arg_len]) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; } @@ -247,7 +260,10 @@ fn handleConnectError(ctx: *api.NativeCtx, err: anytype) void { error.OperationAborted, => ctx.vm.pushErrorEnum("errors.ReadWriteError", @errorName(err)), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, error.Unexpected => ctx.vm.pushError("errors.UnexpectedError", null), error.Overflow => ctx.vm.pushError("errors.OverflowError", null), } @@ -363,7 +379,7 @@ fn handleReadAllError(ctx: *api.NativeCtx, err: anytype) void { => ctx.vm.pushErrorEnum("errors.SocketError", @errorName(err)), error.Unexpected => ctx.vm.pushError("errors.UnexpectedError", null), - // error.OutOfMemory => @panic("Out of memory"), + // error.OutOfMemory => {ctx.vm.bz_panic("Out of memory");unreachable;, f memory");unreachable;.len}, // TODO: bug in zig compiler that complains about StreamTooLong and OutOfMemory errors missing when not there, but complains also if they're there else => unreachable, @@ -386,7 +402,8 @@ pub export fn SocketRead(ctx: *api.NativeCtx) c_int { const reader = stream.reader(); var buffer = api.VM.allocator.alloc(u8, @as(usize, @intCast(n))) catch { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }; // bz_string will copy it @@ -402,7 +419,8 @@ pub export fn SocketRead(ctx: *api.NativeCtx) c_int { ctx.vm.bz_pushNull(); } else { ctx.vm.bz_pushString(api.ObjString.bz_string(ctx.vm, if (buffer[0..read].len > 0) @as([*]const u8, @ptrCast(buffer[0..read])) else null, read) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); } @@ -429,7 +447,10 @@ fn handleReadLineError(ctx: *api.NativeCtx, err: anytype) void { error.Unexpected => ctx.vm.pushError("errors.UnexpectedError", null), - error.OutOfMemory => @panic("Out of memory"), + error.OutOfMemory => { + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; + }, error.EndOfStream => {}, } @@ -473,7 +494,8 @@ pub export fn SocketReadLine(ctx: *api.NativeCtx) c_int { null, buffer.len, ) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); } @@ -517,7 +539,8 @@ pub export fn SocketReadAll(ctx: *api.NativeCtx) c_int { null, buffer.len, ) orelse { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; }); } diff --git a/src/lib/buzz_std.zig b/src/lib/buzz_std.zig index d1a20bda..9c6e66a6 100644 --- a/src/lib/buzz_std.zig +++ b/src/lib/buzz_std.zig @@ -149,7 +149,8 @@ pub export fn parseUd(ctx: *api.NativeCtx) c_int { return 1; } else { - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } } @@ -197,7 +198,8 @@ pub export fn char(ctx: *api.NativeCtx) c_int { return 1; } - @panic("Out of memory"); + ctx.vm.bz_panic("Out of memory", "Out of memory".len); + unreachable; } pub export fn assert(ctx: *api.NativeCtx) c_int { @@ -236,7 +238,7 @@ pub export fn buzzPanic(ctx: *api.NativeCtx) c_int { var len: usize = 0; const message = api.Value.bz_valueToString(ctx.vm.bz_peek(0), &len).?; - std.debug.print("{s}\n", .{message[0..len]}); + ctx.vm.bz_panic(message, len); unreachable; } diff --git a/src/vm.zig b/src/vm.zig index d27bc6a8..fb4e6b91 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -120,6 +120,7 @@ pub const Fiber = struct { method: ?*ObjString, frames: std.ArrayList(CallFrame), + // FIXME: this is useless since we actually pop items from the frames list frame_count: usize = 0, recursive_count: u32 = 0, current_compiled_function: ?*ObjFunction = null, @@ -780,11 +781,12 @@ pub const VM = struct { ); } - fn vmPanic(e: anytype) void { - std.debug.print("{}\n", .{e}); - if (!is_wasm) { - std.process.exit(1); - } + pub fn panic(self: *Self, msg: []const u8) void { + @setCold(true); + + self.reportRuntimeErrorWithCurrentStack(msg); + + unreachable; } fn OP_NULL(self: *Self, _: *CallFrame, _: u32, _: OpCode, _: u24) void { @@ -890,8 +892,8 @@ pub const VM = struct { } fn OP_CLONE(self: *Self, _: *CallFrame, _: u32, _: OpCode, _: u24) void { - self.clone() catch |e| { - vmPanic(e); + self.clone() catch { + self.panic("Out of memory"); unreachable; }; @@ -927,8 +929,8 @@ pub const VM = struct { } fn OP_DEFINE_GLOBAL(self: *Self, _: *CallFrame, _: u32, _: OpCode, arg: u24) void { - self.globals.ensureTotalCapacity(arg + 1) catch |e| { - vmPanic(e); + self.globals.ensureTotalCapacity(arg + 1) catch { + self.panic("Out of memory"); unreachable; }; self.globals.expandToCapacity(); @@ -1070,14 +1072,14 @@ pub const VM = struct { } fn OP_TO_STRING(self: *Self, _: *CallFrame, _: u32, _: OpCode, _: u24) void { - const str = self.pop().toStringAlloc(self.gc.allocator) catch |e| { - vmPanic(e); + const str = self.pop().toStringAlloc(self.gc.allocator) catch { + self.panic("Out of memory"); unreachable; }; self.push( Value.fromObj( - (self.gc.copyString(str.items) catch |e| { - vmPanic(e); + (self.gc.copyString(str.items) catch { + self.panic("Out of memory"); unreachable; }).toObj(), ), @@ -1125,12 +1127,12 @@ pub const VM = struct { const function: *ObjFunction = self.readConstant(arg).obj().access(ObjFunction, .Function, self.gc).?; var closure: *ObjClosure = self.gc.allocateObject( ObjClosure, - ObjClosure.init(self.gc.allocator, self, function) catch |e| { - vmPanic(e); + ObjClosure.init(self.gc.allocator, self, function) catch { + self.panic("Out of memory"); unreachable; }, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -1142,16 +1144,16 @@ pub const VM = struct { const index: u8 = self.readByte(); if (is_local) { - closure.upvalues.append(self.captureUpvalue(&(current_frame.slots[index])) catch |e| { - vmPanic(e); + closure.upvalues.append(self.captureUpvalue(&(current_frame.slots[index])) catch { + self.panic("Out of memory"); unreachable; - }) catch |e| { - vmPanic(e); + }) catch { + self.panic("Out of memory"); unreachable; }; } else { - closure.upvalues.append(current_frame.closure.upvalues.items[index]) catch |e| { - vmPanic(e); + closure.upvalues.append(current_frame.closure.upvalues.items[index]) catch { + self.panic("Out of memory"); unreachable; }; } @@ -1197,8 +1199,8 @@ pub const VM = struct { const stack_len = arg_count + catch_count + 1; const stack_slice = stack_ptr[0..stack_len]; - var fiber = self.gc.allocator.create(Fiber) catch |e| { - vmPanic(e); + var fiber = self.gc.allocator.create(Fiber) catch { + self.panic("Out of memory"); unreachable; }; fiber.* = Fiber.init( @@ -1210,8 +1212,8 @@ pub const VM = struct { arg_count, catch_count > 0, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -1223,8 +1225,8 @@ pub const VM = struct { // Put new fiber on the stack var obj_fiber = self.gc.allocateObject(ObjFiber, ObjFiber{ .fiber = fiber, - }) catch |e| { - vmPanic(e); + }) catch { + self.panic("Out of memory"); unreachable; }; @@ -1254,8 +1256,8 @@ pub const VM = struct { const stack_len = arg_count + catch_count + 1; const stack_slice = stack_ptr[0..stack_len]; - var fiber = self.gc.allocator.create(Fiber) catch |e| { - vmPanic(e); + var fiber = self.gc.allocator.create(Fiber) catch { + self.panic("Out of memory"); unreachable; }; fiber.* = Fiber.init( @@ -1267,8 +1269,8 @@ pub const VM = struct { arg_count, catch_count > 0, method, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -1280,8 +1282,8 @@ pub const VM = struct { // Push new fiber on the stack var obj_fiber = self.gc.allocateObject(ObjFiber, ObjFiber{ .fiber = fiber, - }) catch |e| { - vmPanic(e); + }) catch { + self.panic("Out of memory"); unreachable; }; @@ -1303,8 +1305,8 @@ pub const VM = struct { fn OP_RESUME(self: *Self, _: *CallFrame, _: u32, _: OpCode, _: u24) void { const obj_fiber = self.pop().obj().access(ObjFiber, .Fiber, self.gc).?; - obj_fiber.fiber.@"resume"(self) catch |e| { - vmPanic(e); + obj_fiber.fiber.@"resume"(self) catch { + self.panic("Out of memory"); unreachable; }; @@ -1324,8 +1326,8 @@ pub const VM = struct { fn OP_RESOLVE(self: *Self, _: *CallFrame, _: u32, _: OpCode, _: u24) void { const obj_fiber = self.pop().obj().access(ObjFiber, .Fiber, self.gc).?; - obj_fiber.fiber.resolve_(self) catch |e| { - vmPanic(e); + obj_fiber.fiber.resolve_(self) catch { + self.panic("Out of memory"); unreachable; }; @@ -1372,8 +1374,8 @@ pub const VM = struct { arg_count, catch_value, false, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -1403,8 +1405,8 @@ pub const VM = struct { arg_count, catch_value, false, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -1436,8 +1438,8 @@ pub const VM = struct { if (instance.fields.get(method)) |field| { (self.current_fiber.stack_top - arg_count - 1)[0] = field; - self.callValue(field, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.callValue(field, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -1448,8 +1450,8 @@ pub const VM = struct { catch_value, false, false, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -1482,8 +1484,8 @@ pub const VM = struct { if (instance.fields.get(method)) |field| { (self.current_fiber.stack_top - arg_count - 1)[0] = field; - self.tailCall(field, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.tailCall(field, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -1494,8 +1496,8 @@ pub const VM = struct { catch_value, false, true, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -1521,15 +1523,15 @@ pub const VM = struct { const catch_count: u24 = @intCast(0x00ffffff & arg_instruction); const catch_value = if (catch_count > 0) self.pop() else null; - const member = (ObjString.member(self, method) catch |e| { - vmPanic(e); + const member = (ObjString.member(self, method) catch { + self.panic("Out of memory"); unreachable; }).?; const member_value: Value = member.toValue(); (self.current_fiber.stack_top - arg_count - 1)[0] = member_value; - self.callValue(member_value, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.callValue(member_value, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; @@ -1554,15 +1556,15 @@ pub const VM = struct { const catch_count: u24 = @intCast(0x00ffffff & arg_instruction); const catch_value = if (catch_count > 0) self.pop() else null; - const member = (ObjRange.member(self, method) catch |e| { - vmPanic(e); + const member = (ObjRange.member(self, method) catch { + self.panic("Out of memory"); unreachable; }).?; const member_value: Value = member.toValue(); (self.current_fiber.stack_top - arg_count - 1)[0] = member_value; - self.callValue(member_value, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.callValue(member_value, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; @@ -1587,15 +1589,15 @@ pub const VM = struct { const catch_count: u24 = @intCast(0x00ffffff & arg_instruction); const catch_value = if (catch_count > 0) self.pop() else null; - const member = (ObjPattern.member(self, method) catch |e| { - vmPanic(e); + const member = (ObjPattern.member(self, method) catch { + self.panic("Out of memory"); unreachable; }).?; const member_value: Value = member.toValue(); (self.current_fiber.stack_top - arg_count - 1)[0] = member_value; - self.callValue(member_value, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.callValue(member_value, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; @@ -1620,14 +1622,14 @@ pub const VM = struct { const catch_count: u24 = @intCast(0x00ffffff & arg_instruction); const catch_value = if (catch_count > 0) self.pop() else null; - const member = (ObjFiber.member(self, method) catch |e| { - vmPanic(e); + const member = (ObjFiber.member(self, method) catch { + self.panic("Out of memory"); unreachable; }).?; const member_value: Value = member.toValue(); (self.current_fiber.stack_top - arg_count - 1)[0] = member_value; - self.callValue(member_value, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.callValue(member_value, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; @@ -1653,15 +1655,15 @@ pub const VM = struct { const catch_value = if (catch_count > 0) self.pop() else null; const list = self.peek(arg_count).obj().access(ObjList, .List, self.gc).?; - const member = (list.member(self, method) catch |e| { - vmPanic(e); + const member = (list.member(self, method) catch { + self.panic("Out of memory"); unreachable; }).?; const member_value: Value = member.toValue(); (self.current_fiber.stack_top - arg_count - 1)[0] = member_value; - self.callValue(member_value, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.callValue(member_value, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; @@ -1687,15 +1689,15 @@ pub const VM = struct { const catch_value = if (catch_count > 0) self.pop() else null; const map = self.peek(arg_count).obj().access(ObjMap, .Map, self.gc).?; - const member = (map.member(self, method) catch |e| { - vmPanic(e); + const member = (map.member(self, method) catch { + self.panic("Out of memory"); unreachable; }).?; const member_value: Value = member.toValue(); (self.current_fiber.stack_top - arg_count - 1)[0] = member_value; - self.callValue(member_value, arg_count, catch_value, false) catch |e| { - vmPanic(e); + self.callValue(member_value, arg_count, catch_value, false) catch { + self.panic("Out of memory"); unreachable; }; @@ -1728,8 +1730,8 @@ pub const VM = struct { if (self.current_fiber.frame_count == 0) { // We're in a fiber if (self.current_fiber.parent_fiber != null) { - self.current_fiber.finish(self, result) catch |e| { - vmPanic(e); + self.current_fiber.finish(self, result) catch { + self.panic("Out of memory"); unreachable; }; @@ -1812,19 +1814,19 @@ pub const VM = struct { if (self.import_registry.get(fullpath)) |globals| { for (globals.items) |global| { - self.globals.append(global) catch |e| { - vmPanic(e); + self.globals.append(global) catch { + self.panic("Out of memory"); unreachable; }; } } else { - var vm = self.gc.allocator.create(VM) catch |e| { - vmPanic(e); + var vm = self.gc.allocator.create(VM) catch { + self.panic("Out of memory"); unreachable; }; // FIXME: give reference to JIT? - vm.* = VM.init(self.gc, self.import_registry, self.flavor) catch |e| { - vmPanic(e); + vm.* = VM.init(self.gc, self.import_registry, self.flavor) catch { + self.panic("Out of memory"); unreachable; }; // TODO: how to free this since we copy things to new vm, also fails anyway @@ -1833,8 +1835,8 @@ pub const VM = struct { // defer gn.deinit(); // } - vm.interpret(self.current_ast, closure.function, null) catch |e| { - vmPanic(e); + vm.interpret(self.current_ast, closure.function, null) catch { + self.panic("Out of memory"); unreachable; }; @@ -1847,19 +1849,19 @@ pub const VM = struct { var i = exported_count; while (i > 0) : (i -= 1) { const global = vm.peek(@intCast(i)); - self.globals.append(global) catch |e| { - vmPanic(e); + self.globals.append(global) catch { + self.panic("Out of memory"); unreachable; }; - import_cache.append(global) catch |e| { - vmPanic(e); + import_cache.append(global) catch { + self.panic("Out of memory"); unreachable; }; } } - self.import_registry.put(fullpath, import_cache) catch |e| { - vmPanic(e); + self.import_registry.put(fullpath, import_cache) catch { + self.panic("Out of memory"); unreachable; }; } @@ -1925,8 +1927,8 @@ pub const VM = struct { self.pop(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -1955,8 +1957,8 @@ pub const VM = struct { self.gc, ).?, ), - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -1987,8 +1989,8 @@ pub const VM = struct { .high = high, .low = low, }, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }).toObj()), ); @@ -2011,8 +2013,8 @@ pub const VM = struct { var list = self.peek(1).obj().access(ObjList, .List, self.gc).?; const list_value = self.peek(0); - list.rawAppend(self.gc, list_value) catch |e| { - vmPanic(e); + list.rawAppend(self.gc, list_value) catch { + self.panic("Out of memory"); unreachable; }; @@ -2036,8 +2038,8 @@ pub const VM = struct { var map: *ObjMap = self.gc.allocateObject(ObjMap, ObjMap.init( self.gc.allocator, self.readConstant(arg).obj().access(ObjTypeDef, .Type, self.gc).?, - )) catch |e| { - vmPanic(e); + )) catch { + self.panic("Out of memory"); unreachable; }; @@ -2062,8 +2064,8 @@ pub const VM = struct { const key = self.peek(1); const value = self.peek(0); - map.set(self.gc, key, value) catch |e| { - vmPanic(e); + map.set(self.gc, key, value) catch { + self.panic("Out of memory"); unreachable; }; @@ -2091,14 +2093,14 @@ pub const VM = struct { if (index < 0) { self.throw( Error.OutOfBound, - (self.gc.copyString("Out of bound list access.") catch |e| { - vmPanic(e); + (self.gc.copyString("Out of bound list access.") catch { + self.panic("Out of memory"); unreachable; }).toValue(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -2108,14 +2110,14 @@ pub const VM = struct { if (list_index >= list.items.items.len) { self.throw( Error.OutOfBound, - (self.gc.copyString("Out of bound list access.") catch |e| { - vmPanic(e); + (self.gc.copyString("Out of bound list access.") catch { + self.panic("Out of memory"); unreachable; }).toValue(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -2181,14 +2183,14 @@ pub const VM = struct { if (index < 0) { self.throw( Error.OutOfBound, - (self.gc.copyString("Out of bound string access.") catch |e| { - vmPanic(e); + (self.gc.copyString("Out of bound string access.") catch { + self.panic("Out of memory"); unreachable; }).toValue(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -2196,8 +2198,8 @@ pub const VM = struct { const str_index: usize = @intCast(index); if (str_index < str.string.len) { - const str_item = (self.gc.copyString(&([_]u8{str.string[str_index]})) catch |e| { - vmPanic(e); + const str_item = (self.gc.copyString(&([_]u8{str.string[str_index]})) catch { + self.panic("Out of memory"); unreachable; }).toValue(); @@ -2210,14 +2212,14 @@ pub const VM = struct { } else { self.throw( Error.OutOfBound, - (self.gc.copyString("Out of bound str access.") catch |e| { - vmPanic(e); + (self.gc.copyString("Out of bound str access.") catch { + self.panic("Out of memory"); unreachable; }).toValue(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -2244,14 +2246,14 @@ pub const VM = struct { if (index.integer() < 0) { self.throw( Error.OutOfBound, - (self.gc.copyString("Out of bound list access.") catch |e| { - vmPanic(e); + (self.gc.copyString("Out of bound list access.") catch { + self.panic("Out of memory"); unreachable; }).toValue(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -2259,8 +2261,8 @@ pub const VM = struct { const list_index: usize = @intCast(index.integer()); if (list_index < list.items.items.len) { - list.set(self.gc, list_index, value) catch |e| { - vmPanic(e); + list.set(self.gc, list_index, value) catch { + self.panic("Out of memory"); unreachable; }; @@ -2274,14 +2276,14 @@ pub const VM = struct { } else { self.throw( Error.OutOfBound, - (self.gc.copyString("Out of bound list access.") catch |e| { - vmPanic(e); + (self.gc.copyString("Out of bound list access.") catch { + self.panic("Out of memory"); unreachable; }).toValue(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -2305,8 +2307,8 @@ pub const VM = struct { const index = self.peek(1); const value = self.peek(0); - map.set(self.gc, index, value) catch |e| { - vmPanic(e); + map.set(self.gc, index, value) catch { + self.panic("Out of memory"); unreachable; }; @@ -2343,8 +2345,8 @@ pub const VM = struct { .enum_ref = enum_, .case = @intCast(arg), }, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -2394,8 +2396,8 @@ pub const VM = struct { var enum_case: *ObjEnumInstance = self.gc.allocateObject(ObjEnumInstance, ObjEnumInstance{ .enum_ref = enum_, .case = @intCast(index), - }) catch |e| { - vmPanic(e); + }) catch { + self.panic("Out of memory"); unreachable; }; @@ -2432,8 +2434,8 @@ pub const VM = struct { self.readConstant(arg).obj().access(ObjString, .String, self.gc).?, self.readConstant(@as(u24, @intCast(self.readInstruction()))).obj().access(ObjTypeDef, .Type, self.gc).?, ), - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -2460,8 +2462,14 @@ pub const VM = struct { ObjForeignContainer.init( self, typedef.?, - ) catch @panic("Out of memory"), - ) catch @panic("Out of memory")).toValue(); + ) catch { + self.panic("Out of memory"); + unreachable; + }, + ) catch { + self.panic("Out of memory"); + unreachable; + }).toValue(); self.push(instance); @@ -2494,7 +2502,10 @@ pub const VM = struct { object, typedef, ), - ) catch @panic("Out of memory"); + ) catch { + self.panic("Out of memory"); + unreachable; + }; // If not anonymous, set default fields if (object) |obj| { @@ -2504,12 +2515,12 @@ pub const VM = struct { obj_instance.setField( self.gc, kv.key_ptr.*, - self.cloneValue(kv.value_ptr.*) catch |e| { - vmPanic(e); + self.cloneValue(kv.value_ptr.*) catch { + self.panic("Out of memory"); unreachable; }, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -2539,8 +2550,8 @@ pub const VM = struct { object.methods.put( name, method.obj().access(ObjClosure, .Closure, self.gc).?, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; @@ -2566,14 +2577,14 @@ pub const VM = struct { var object = self.peek(1).obj().access(ObjObject, .Object, self.gc).?; if (object.type_def.resolved_type.?.Object.fields.contains(name.string)) { - object.setField(self.gc, name, property) catch |e| { - vmPanic(e); + object.setField(self.gc, name, property) catch { + self.panic("Out of memory"); unreachable; }; } else { assert(object.type_def.resolved_type.?.Object.static_fields.contains(name.string)); - object.setStaticField(self.gc, name, property) catch |e| { - vmPanic(e); + object.setStaticField(self.gc, name, property) catch { + self.panic("Out of memory"); unreachable; }; } @@ -2652,8 +2663,8 @@ pub const VM = struct { self.push(field); } else if (obj_instance.object) |object| { if (object.methods.get(name)) |method| { - self.bindMethod(method, null) catch |e| { - vmPanic(e); + self.bindMethod(method, null) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -2679,12 +2690,12 @@ pub const VM = struct { const list = self.peek(0).obj().access(ObjList, .List, self.gc).?; const name: *ObjString = self.readString(arg); - if (list.member(self, name) catch |e| { - vmPanic(e); + if (list.member(self, name) catch { + self.panic("Out of memory"); unreachable; }) |member| { - self.bindMethod(null, member) catch |e| { - vmPanic(e); + self.bindMethod(null, member) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -2708,12 +2719,12 @@ pub const VM = struct { const map = self.peek(0).obj().access(ObjMap, .Map, self.gc).?; const name: *ObjString = self.readString(arg); - if (map.member(self, name) catch |e| { - vmPanic(e); + if (map.member(self, name) catch { + self.panic("Out of memory"); unreachable; }) |member| { - self.bindMethod(null, member) catch |e| { - vmPanic(e); + self.bindMethod(null, member) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -2737,12 +2748,12 @@ pub const VM = struct { fn OP_GET_STRING_PROPERTY(self: *Self, _: *CallFrame, _: u32, _: OpCode, arg: u24) void { const name: *ObjString = self.readString(arg); - if (ObjString.member(self, name) catch |e| { - vmPanic(e); + if (ObjString.member(self, name) catch { + self.panic("Out of memory"); unreachable; }) |member| { - self.bindMethod(null, member) catch |e| { - vmPanic(e); + self.bindMethod(null, member) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -2766,12 +2777,12 @@ pub const VM = struct { fn OP_GET_PATTERN_PROPERTY(self: *Self, _: *CallFrame, _: u32, _: OpCode, arg: u24) void { const name: *ObjString = self.readString(arg); - if (ObjPattern.member(self, name) catch |e| { - vmPanic(e); + if (ObjPattern.member(self, name) catch { + self.panic("Out of memory"); unreachable; }) |member| { - self.bindMethod(null, member) catch |e| { - vmPanic(e); + self.bindMethod(null, member) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -2795,12 +2806,12 @@ pub const VM = struct { fn OP_GET_FIBER_PROPERTY(self: *Self, _: *CallFrame, _: u32, _: OpCode, arg: u24) void { const name: *ObjString = self.readString(arg); - if (ObjFiber.member(self, name) catch |e| { - vmPanic(e); + if (ObjFiber.member(self, name) catch { + self.panic("Out of memory"); unreachable; }) |member| { - self.bindMethod(null, member) catch |e| { - vmPanic(e); + self.bindMethod(null, member) catch { + self.panic("Out of memory"); unreachable; }; } else { @@ -2825,12 +2836,12 @@ pub const VM = struct { const range = self.peek(0).obj().access(ObjRange, .Range, self.gc).?; const name: *ObjString = self.readString(arg); - if (ObjRange.member(self, name) catch |e| { - vmPanic(e); + if (ObjRange.member(self, name) catch { + self.panic("Out of memory"); unreachable; }) |member| { - self.bindMethod(null, member) catch |e| { - vmPanic(e); + self.bindMethod(null, member) catch { + self.panic("Out of memory"); unreachable; }; } else if (std.mem.eql(u8, "high", name.string)) { @@ -2860,8 +2871,8 @@ pub const VM = struct { const name: *ObjString = self.readString(arg); // Set new value - object.setStaticField(self.gc, name, self.peek(0)) catch |e| { - vmPanic(e); + object.setStaticField(self.gc, name, self.peek(0)) catch { + self.panic("Out of memory"); unreachable; }; @@ -2898,7 +2909,10 @@ pub const VM = struct { self, name.string, self.peek(0), - ) catch @panic("Out of memory"); + ) catch { + self.panic("Out of memory"); + unreachable; + }; // Get the new value from stack, pop the instance and push value again const value: Value = self.pop(); @@ -2932,7 +2946,10 @@ pub const VM = struct { self.gc, name, self.peek(0), - ) catch @panic("Out of memory"); + ) catch { + self.panic("Out of memory"); + unreachable; + }; // Get the new value from stack, pop the instance and push value again const value: Value = self.pop(); @@ -3067,8 +3084,8 @@ pub const VM = struct { const right: *ObjString = self.pop().obj().access(ObjString, .String, self.gc).?; const left: *ObjString = self.pop().obj().access(ObjString, .String, self.gc).?; - self.push(Value.fromObj((left.concat(self, right) catch |e| { - vmPanic(e); + self.push(Value.fromObj((left.concat(self, right) catch { + self.panic("Out of memory"); unreachable; }).toObj())); @@ -3091,12 +3108,12 @@ pub const VM = struct { const left: *ObjList = self.pop().obj().access(ObjList, .List, self.gc).?; var new_list = std.ArrayList(Value).init(self.gc.allocator); - new_list.appendSlice(left.items.items) catch |e| { - vmPanic(e); + new_list.appendSlice(left.items.items) catch { + self.panic("Out of memory"); unreachable; }; - new_list.appendSlice(right.items.items) catch |e| { - vmPanic(e); + new_list.appendSlice(right.items.items) catch { + self.panic("Out of memory"); unreachable; }; @@ -3105,8 +3122,8 @@ pub const VM = struct { .type_def = left.type_def, .methods = left.methods, .items = new_list, - }) catch |e| { - vmPanic(e); + }) catch { + self.panic("Out of memory"); unreachable; }).toValue(), ); @@ -3129,14 +3146,14 @@ pub const VM = struct { const right: *ObjMap = self.pop().obj().access(ObjMap, .Map, self.gc).?; const left: *ObjMap = self.pop().obj().access(ObjMap, .Map, self.gc).?; - var new_map = left.map.clone() catch |e| { - vmPanic(e); + var new_map = left.map.clone() catch { + self.panic("Out of memory"); unreachable; }; var it = right.map.iterator(); while (it.next()) |entry| { - new_map.put(entry.key_ptr.*, entry.value_ptr.*) catch |e| { - vmPanic(e); + new_map.put(entry.key_ptr.*, entry.value_ptr.*) catch { + self.panic("Out of memory"); unreachable; }; } @@ -3146,8 +3163,8 @@ pub const VM = struct { .type_def = left.type_def, .methods = left.methods, .map = new_map, - }) catch |e| { - vmPanic(e); + }) catch { + self.panic("Out of memory"); unreachable; }).toValue(), ); @@ -3589,8 +3606,8 @@ pub const VM = struct { const value_slot: *Value = @ptrCast(self.current_fiber.stack_top - 2); const str: *ObjString = self.peek(0).obj().access(ObjString, .String, self.gc).?; - key_slot.* = if (str.next(self, if (key_slot.*.isNull()) null else key_slot.integer()) catch |e| { - vmPanic(e); + key_slot.* = if (str.next(self, if (key_slot.*.isNull()) null else key_slot.integer()) catch { + self.panic("Out of memory"); unreachable; }) |new_index| Value.fromInteger(new_index) @@ -3599,8 +3616,8 @@ pub const VM = struct { // Set new value if (key_slot.*.isInteger()) { - value_slot.* = (self.gc.copyString(&([_]u8{str.string[@as(usize, @intCast(key_slot.integer()))]})) catch |e| { - vmPanic(e); + value_slot.* = (self.gc.copyString(&([_]u8{str.string[@as(usize, @intCast(key_slot.integer()))]})) catch { + self.panic("Out of memory"); unreachable; }).toValue(); } @@ -3628,8 +3645,8 @@ pub const VM = struct { key_slot.* = if (list.rawNext( self, if (key_slot.*.isNull()) null else key_slot.integer(), - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }) |new_index| Value.fromInteger(new_index) @@ -3698,8 +3715,8 @@ pub const VM = struct { var enum_: *ObjEnum = self.peek(0).obj().access(ObjEnum, .Enum, self.gc).?; // Get next enum case - const next_case = enum_.rawNext(self, enum_case) catch |e| { - vmPanic(e); + const next_case = enum_.rawNext(self, enum_case) catch { + self.panic("Out of memory"); unreachable; }; value_slot.* = (if (next_case) |new_case| Value.fromObj(new_case.toObj()) else Value.Null); @@ -3752,8 +3769,8 @@ pub const VM = struct { if (fiber.fiber.status == .Over) { value_slot.* = Value.Null; } else { - fiber.fiber.@"resume"(self) catch |e| { - vmPanic(e); + fiber.fiber.@"resume"(self) catch { + self.panic("Out of memory"); unreachable; }; } @@ -3777,14 +3794,14 @@ pub const VM = struct { // TODO: Should we throw or @panic? self.throw( Error.UnwrappedNull, - (self.gc.copyString("Force unwrapped optional is null") catch |e| { - vmPanic(e); + (self.gc.copyString("Force unwrapped optional is null") catch { + self.panic("Out of memory"); unreachable; }).toValue(), null, null, - ) catch |e| { - vmPanic(e); + ) catch { + self.panic("Out of memory"); unreachable; }; } @@ -3804,7 +3821,10 @@ pub const VM = struct { } fn OP_TYPEOF(self: *Self, _: *CallFrame, _: u32, _: OpCode, _: u24) void { - self.push((Value.typeOf(self.pop(), self.gc) catch @panic("Out of memory")).toValue()); + self.push((Value.typeOf(self.pop(), self.gc) catch { + self.panic("Out of memory"); + unreachable; + }).toValue()); const next_full_instruction: u32 = self.readInstruction(); @call( @@ -3828,7 +3848,10 @@ pub const VM = struct { self.hotspots.put( node, count, - ) catch @panic("Out of memory"); + ) catch { + self.panic("Out of memory"); + unreachable; + }; self.hotspots_count += 1; @@ -3841,10 +3864,16 @@ pub const VM = struct { .{ .native = native, }, - ) catch @panic("Out of memory"); + ) catch { + self.panic("Out of memory"); + unreachable; + }; // Prevent collection - self.gc.markObj(obj_native.toObj()) catch @panic("Out of memory"); + self.gc.markObj(obj_native.toObj()) catch { + self.panic("Out of memory"); + unreachable; + }; obj_native.mark(self.gc); if (BuildOptions.jit_debug) { @@ -3861,17 +3890,26 @@ pub const VM = struct { // The now compile hotspot must be a new constant for the current function self.currentFrame().?.closure.function.chunk.constants.append( obj_native.toValue(), - ) catch @panic("Out of memory"); + ) catch { + self.panic("Out of memory"); + unreachable; + }; // Patch bytecode to replace hotspot with function call self.patchHotspot( self.current_ast.nodes.items(.location)[node], self.currentFrame().?.closure.function.chunk.constants.items.len - 1, end_ip, - ) catch @panic("Out of memory"); + ) catch { + self.panic("Out of memory"); + unreachable; + }; } else { // Blacklist the node - self.jit.?.blacklisted_hotspots.put(node, {}) catch @panic("Out of memory"); + self.jit.?.blacklisted_hotspots.put(node, {}) catch { + self.panic("Out of memory"); + unreachable; + }; } self.jit.?.jit_time += timer.read(); @@ -4044,6 +4082,17 @@ pub const VM = struct { } } + inline fn reportRuntimeErrorWithCurrentStack(self: *Self, message: []const u8) void { + self.reportRuntimeError( + message, + if (self.currentFrame()) |frame| + frame.closure.function.chunk.lines.items[frame.ip - 1] + else + null, + self.current_fiber.frames.items, + ); + } + fn reportRuntimeError(self: *Self, message: []const u8, error_site: ?Ast.TokenIndex, stack: []const CallFrame) void { var notes = std.ArrayList(Reporter.Note).init(self.gc.allocator); defer {