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,
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);
}
}
}