Skip to content

Commit

Permalink
Simplifies error formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
MasonRemaley committed Jan 8, 2025
1 parent a261da8 commit 058f69b
Show file tree
Hide file tree
Showing 5 changed files with 558 additions and 263 deletions.
16 changes: 14 additions & 2 deletions lib/std/zig/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11518,9 +11518,21 @@ fn parseStrLit(
}
}

fn failWithStrLitError(astgen: *AstGen, err: std.zig.string_literal.Error, token: Ast.TokenIndex, bytes: []const u8, offset: u32) InnerError {
fn failWithStrLitError(
astgen: *AstGen,
err: std.zig.string_literal.Error,
token: Ast.TokenIndex,
bytes: []const u8,
offset: u32,
) InnerError {
const raw_string = bytes[offset..];
return err.lower(raw_string, offset, AstGen.failOff, .{ astgen, token });
return AstGen.failOff(
astgen,
token,
@intCast(offset + err.offset()),
"{}",
.{err.fmt(raw_string)},
);
}

fn failNode(
Expand Down
16 changes: 14 additions & 2 deletions lib/std/zig/ZonGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -741,8 +741,20 @@ fn setNode(zg: *ZonGen, dest: Zoir.Node.Index, repr: Zoir.Node.Repr) void {
zg.nodes.set(@intFromEnum(dest), repr);
}

fn lowerStrLitError(zg: *ZonGen, err: std.zig.string_literal.Error, token: Ast.TokenIndex, raw_string: []const u8, offset: u32) Allocator.Error!void {
return err.lower(raw_string, offset, ZonGen.addErrorTokOff, .{ zg, token });
fn lowerStrLitError(
zg: *ZonGen,
err: std.zig.string_literal.Error,
token: Ast.TokenIndex,
raw_string: []const u8,
offset: u32,
) Allocator.Error!void {
return ZonGen.addErrorTokOff(
zg,
token,
@intCast(offset + err.offset()),
"{}",
.{err.fmt(raw_string)},
);
}

fn lowerNumberError(zg: *ZonGen, err: std.zig.number_literal.Error, token: Ast.TokenIndex, bytes: []const u8) Allocator.Error!void {
Expand Down
86 changes: 56 additions & 30 deletions lib/std/zig/string_literal.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,41 +39,67 @@ pub const Error = union(enum) {
/// `''`. Not returned for string literals.
empty_char_literal,

/// Returns `func(first_args[0], ..., first_args[n], offset + bad_idx, format, args)`.
pub fn lower(
const FormatMessage = struct {
err: Error,
raw_string: []const u8,
index_offset: u32,
comptime func: anytype,
first_args: anytype,
) @typeInfo(@TypeOf(func)).@"fn".return_type.? {
switch (err) {
inline else => |bad_index_or_void, tag| {
const bad_index: u32 = switch (@TypeOf(bad_index_or_void)) {
void => 0,
else => @intCast(bad_index_or_void),
};
const fmt_str: []const u8, const args = switch (tag) {
.invalid_escape_character => .{ "invalid escape character: '{c}'", .{raw_string[bad_index]} },
.expected_hex_digit => .{ "expected hex digit, found '{c}'", .{raw_string[bad_index]} },
.empty_unicode_escape_sequence => .{ "empty unicode escape sequence", .{} },
.expected_hex_digit_or_rbrace => .{ "expected hex digit or '}}', found '{c}'", .{raw_string[bad_index]} },
.invalid_unicode_codepoint => .{ "unicode escape does not correspond to a valid unicode scalar value", .{} },
.expected_lbrace => .{ "expected '{{', found '{c}'", .{raw_string[bad_index]} },
.expected_rbrace => .{ "expected '}}', found '{c}'", .{raw_string[bad_index]} },
.expected_single_quote => .{ "expected single quote ('), found '{c}'", .{raw_string[bad_index]} },
.invalid_character => .{ "invalid byte in string or character literal: '{c}'", .{raw_string[bad_index]} },
.empty_char_literal => .{ "empty character literal", .{} },
};
return @call(.auto, func, first_args ++ .{
index_offset + bad_index,
fmt_str,
args,
});
},
};

fn formatMessage(
self: FormatMessage,
comptime f: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = f;
_ = options;
switch (self.err) {
.invalid_escape_character => |bad_index| try writer.print(
"invalid escape character: '{c}'",
.{self.raw_string[bad_index]},
),
.expected_hex_digit => |bad_index| try writer.print(
"expected hex digit, found '{c}'",
.{self.raw_string[bad_index]},
),
.empty_unicode_escape_sequence => try writer.writeAll(
"empty unicode escape sequence",
),
.expected_hex_digit_or_rbrace => |bad_index| try writer.print(
"expected hex digit or '}}', found '{c}'",
.{self.raw_string[bad_index]},
),
.invalid_unicode_codepoint => try writer.writeAll(
"unicode escape does not correspond to a valid unicode scalar value",
),
.expected_lbrace => |bad_index| try writer.print(
"expected '{{', found '{c}'",
.{self.raw_string[bad_index]},
),
.expected_rbrace => |bad_index| try writer.print(
"expected '}}', found '{c}'",
.{self.raw_string[bad_index]},
),
.expected_single_quote => |bad_index| try writer.print(
"expected single quote ('), found '{c}'",
.{self.raw_string[bad_index]},
),
.invalid_character => |bad_index| try writer.print(
"invalid byte in string or character literal: '{c}'",
.{self.raw_string[bad_index]},
),
.empty_char_literal => try writer.writeAll(
"empty character literal",
),
}
}

pub fn fmt(self: @This(), raw_string: []const u8) std.fmt.Formatter(formatMessage) {
return .{ .data = .{
.err = self,
.raw_string = raw_string,
} };
}

pub fn offset(err: Error) usize {
return switch (err) {
inline .invalid_escape_character,
Expand Down
3 changes: 0 additions & 3 deletions lib/std/zon.zig
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
//! * `parseFromZoir`
//! * `parseFromZoirNode`
//! * `parseFromZoirNode`
//! * `parseFromZoirNodeNoAlloc`
//!
//! If you need lower level control than provided by this module, you can operate directly on the
//! results of `std.zig.Zoir` directly. This module is a good example of how that can be done.
Expand All @@ -69,9 +68,7 @@ pub const ParseOptions = @import("zon/parse.zig").Options;
pub const ParseStatus = @import("zon/parse.zig").Status;
pub const parseFromSlice = @import("zon/parse.zig").parseFromSlice;
pub const parseFromZoir = @import("zon/parse.zig").parseFromZoir;
pub const parseFromZoirNoAlloc = @import("zon/parse.zig").parseFromZoirNoAlloc;
pub const parseFromZoirNode = @import("zon/parse.zig").parseFromZoirNode;
pub const parseFromZoirNodeNoAlloc = @import("zon/parse.zig").parseFromZoirNodeNoAlloc;
pub const parseFree = @import("zon/parse.zig").parseFree;

pub const StringifierOptions = @import("zon/stringify.zig").StringifierOptions;
Expand Down
Loading

0 comments on commit 058f69b

Please sign in to comment.