union Error [src]

Fields

zoir: Zoir.CompileError
type_check: Error.TypeCheckFailure

Members

Source

pub const Error = union(enum) { zoir: Zoir.CompileError, type_check: Error.TypeCheckFailure, pub const Note = union(enum) { zoir: Zoir.CompileError.Note, type_check: TypeCheckFailure.Note, pub const Iterator = struct { index: usize = 0, err: Error, status: *const Status, pub fn next(self: *@This()) ?Note { switch (self.err) { .zoir => |err| { if (self.index >= err.note_count) return null; const zoir = self.status.zoir.?; const note = err.getNotes(zoir)[self.index]; self.index += 1; return .{ .zoir = note }; }, .type_check => |err| { if (self.index >= err.getNoteCount()) return null; const note = err.getNote(self.index); self.index += 1; return .{ .type_check = note }; }, } } }; fn formatMessage( self: []const u8, comptime f: []const u8, options: std.fmt.FormatOptions, writer: anytype, ) !void { _ = f; _ = options; // Just writes the string for now, but we're keeping this behind a formatter so we have // the option to extend it in the future to print more advanced messages (like `Error` // does) without breaking the API. try writer.writeAll(self); } pub fn fmtMessage(self: Note, status: *const Status) std.fmt.Formatter(Note.formatMessage) { return .{ .data = switch (self) { .zoir => |note| note.msg.get(status.zoir.?), .type_check => |note| note.msg, } }; } pub fn getLocation(self: Note, status: *const Status) Ast.Location { const ast = status.ast.?; switch (self) { .zoir => |note| return zoirErrorLocation(ast, note.token, note.node_or_offset), .type_check => |note| return ast.tokenLocation(note.offset, note.token), } } }; pub const Iterator = struct { index: usize = 0, status: *const Status, pub fn next(self: *@This()) ?Error { const zoir = self.status.zoir orelse return null; if (self.index < zoir.compile_errors.len) { const result: Error = .{ .zoir = zoir.compile_errors[self.index] }; self.index += 1; return result; } if (self.status.type_check) |err| { if (self.index == zoir.compile_errors.len) { const result: Error = .{ .type_check = err }; self.index += 1; return result; } } return null; } }; const TypeCheckFailure = struct { const Note = struct { token: Ast.TokenIndex, offset: u32, msg: []const u8, owned: bool, fn deinit(self: @This(), gpa: Allocator) void { if (self.owned) gpa.free(self.msg); } }; message: []const u8, owned: bool, token: Ast.TokenIndex, offset: u32, note: ?@This().Note, fn deinit(self: @This(), gpa: Allocator) void { if (self.note) |note| note.deinit(gpa); if (self.owned) gpa.free(self.message); } fn getNoteCount(self: @This()) usize { return @intFromBool(self.note != null); } fn getNote(self: @This(), index: usize) @This().Note { assert(index == 0); return self.note.?; } }; const FormatMessage = struct { err: Error, status: *const Status, }; fn formatMessage( self: FormatMessage, comptime f: []const u8, options: std.fmt.FormatOptions, writer: anytype, ) !void { _ = f; _ = options; switch (self.err) { .zoir => |err| try writer.writeAll(err.msg.get(self.status.zoir.?)), .type_check => |tc| try writer.writeAll(tc.message), } } pub fn fmtMessage(self: @This(), status: *const Status) std.fmt.Formatter(formatMessage) { return .{ .data = .{ .err = self, .status = status, } }; } pub fn getLocation(self: @This(), status: *const Status) Ast.Location { const ast = status.ast.?; return switch (self) { .zoir => |err| return zoirErrorLocation( status.ast.?, err.token, err.node_or_offset, ), .type_check => |err| return ast.tokenLocation(err.offset, err.token), }; } pub fn iterateNotes(self: @This(), status: *const Status) Note.Iterator { return .{ .err = self, .status = status }; } fn zoirErrorLocation(ast: Ast, maybe_token: Ast.OptionalTokenIndex, node_or_offset: u32) Ast.Location { if (maybe_token.unwrap()) |token| { var location = ast.tokenLocation(0, token); location.column += node_or_offset; return location; } else { const ast_node: Ast.Node.Index = @enumFromInt(node_or_offset); const token = ast.nodeMainToken(ast_node); return ast.tokenLocation(0, token); } } }