union Error [src]
Fields
zoir: Zoir.CompileError
type_check: Error.TypeCheckFailure
Members
- fmtMessage (Function)
- getLocation (Function)
- iterateNotes (Function)
- Iterator (struct)
- Note (union)
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,
diag: *const Diagnostics,
pub fn next(self: *@This()) ?Note {
switch (self.err) {
.zoir => |err| {
if (self.index >= err.note_count) return null;
const note = err.getNotes(self.diag.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, w: *std.Io.Writer) std.Io.Writer.Error!void {
// 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 w.writeAll(self);
}
pub fn fmtMessage(self: Note, diag: *const Diagnostics) std.fmt.Alt([]const u8, Note.formatMessage) {
return .{ .data = switch (self) {
.zoir => |note| note.msg.get(diag.zoir),
.type_check => |note| note.msg,
} };
}
pub fn getLocation(self: Note, diag: *const Diagnostics) Ast.Location {
switch (self) {
.zoir => |note| return zoirErrorLocation(diag.ast, note.token, note.node_or_offset),
.type_check => |note| return diag.ast.tokenLocation(note.offset, note.token),
}
}
};
pub const Iterator = struct {
index: usize = 0,
diag: *const Diagnostics,
pub fn next(self: *@This()) ?Error {
if (self.index < self.diag.zoir.compile_errors.len) {
const result: Error = .{ .zoir = self.diag.zoir.compile_errors[self.index] };
self.index += 1;
return result;
}
if (self.diag.type_check) |err| {
if (self.index == self.diag.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,
diag: *const Diagnostics,
};
fn formatMessage(self: FormatMessage, w: *std.Io.Writer) std.Io.Writer.Error!void {
switch (self.err) {
.zoir => |err| try w.writeAll(err.msg.get(self.diag.zoir)),
.type_check => |tc| try w.writeAll(tc.message),
}
}
pub fn fmtMessage(self: @This(), diag: *const Diagnostics) std.fmt.Alt(FormatMessage, formatMessage) {
return .{ .data = .{
.err = self,
.diag = diag,
} };
}
pub fn getLocation(self: @This(), diag: *const Diagnostics) Ast.Location {
return switch (self) {
.zoir => |err| return zoirErrorLocation(
diag.ast,
err.token,
err.node_or_offset,
),
.type_check => |err| return diag.ast.tokenLocation(err.offset, err.token),
};
}
pub fn iterateNotes(self: @This(), diag: *const Diagnostics) Note.Iterator {
return .{ .err = self, .diag = diag };
}
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);
}
}
}