| author | |
| committer | |
| log | 7e2a26c0c441a902968726442114e3590820433b |
| tree | 90035e47e0208afa7d1bcd3484e30d22d2a24f4e |
| parent | 5378fdb153bc76990105e3640e7725e434e8cdee |
Alignment and fill options only apply to numbers.
Rework the implementation to mainly branch on the format string rather
than the type information. This is more straightforward to maintain and
more straightforward for comptime evaluation.
Enums support being printed as decimal, hexadecimal, octal, and binary.
`formatInteger` is another possible format method that is
unconditionally called when the value type is struct and one of the
integer-printing format specifiers are used.29 files changed, 636 insertions(+), 452 deletions(-)
lib/compiler/aro/aro/Diagnostics.zig+2-2| ... | @@ -461,10 +461,10 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void { | ... | @@ -461,10 +461,10 @@ pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void { |
| 461 | try writer.writeByte(@intCast(codepoint)); | 461 | try writer.writeByte(@intCast(codepoint)); |
| 462 | } else if (codepoint < 0xFFFF) { | 462 | } else if (codepoint < 0xFFFF) { |
| 463 | try writer.writeAll("\\u"); | 463 | try writer.writeAll("\\u"); |
| 464 | try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 4 }); | 464 | try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 4 }); |
| 465 | } else { | 465 | } else { |
| 466 | try writer.writeAll("\\U"); | 466 | try writer.writeAll("\\U"); |
| 467 | try writer.printIntOptions(codepoint, 16, .upper, .{ .fill = '0', .width = 8 }); | 467 | try writer.printInt(codepoint, 16, .upper, .{ .fill = '0', .width = 8 }); |
| 468 | } | 468 | } |
| 469 | } | 469 | } |
| 470 | } | 470 | } |
lib/compiler/aro/aro/Preprocessor.zig+1-1| ... | @@ -3262,7 +3262,7 @@ fn printLinemarker( | ... | @@ -3262,7 +3262,7 @@ fn printLinemarker( |
| 3262 | // containing the same bytes as the input regardless of encoding. | 3262 | // containing the same bytes as the input regardless of encoding. |
| 3263 | else => { | 3263 | else => { |
| 3264 | try w.writeAll("\\x"); | 3264 | try w.writeAll("\\x"); |
| 3265 | // TODO try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' }); | 3265 | // TODO try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); |
| 3266 | try w.print("{x:0>2}", .{byte}); | 3266 | try w.print("{x:0>2}", .{byte}); |
| 3267 | }, | 3267 | }, |
| 3268 | }; | 3268 | }; |
lib/compiler/aro/aro/Value.zig+1-2| ... | @@ -961,8 +961,7 @@ pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w | ... | @@ -961,8 +961,7 @@ pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w |
| 961 | switch (key) { | 961 | switch (key) { |
| 962 | .null => return w.writeAll("nullptr_t"), | 962 | .null => return w.writeAll("nullptr_t"), |
| 963 | .int => |repr| switch (repr) { | 963 | .int => |repr| switch (repr) { |
| 964 | inline .u64, .i64 => |x| return w.print("{d}", .{x}), | 964 | inline .u64, .i64, .big_int => |x| return w.print("{d}", .{x}), |
| 965 | .big_int => |x| return w.print("{fd}", .{x}), | ||
| 966 | }, | 965 | }, |
| 967 | .float => |repr| switch (repr) { | 966 | .float => |repr| switch (repr) { |
| 968 | .f16 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000) / 1000}), | 967 | .f16 => |x| return w.print("{d}", .{@round(@as(f64, @floatCast(x)) * 1000) / 1000}), |
lib/std/Build/Step/CheckObject.zig+4-7| ... | @@ -230,12 +230,7 @@ const ComputeCompareExpected = struct { | ... | @@ -230,12 +230,7 @@ const ComputeCompareExpected = struct { |
| 230 | literal: u64, | 230 | literal: u64, |
| 231 | }, | 231 | }, |
| 232 | 232 | ||
| 233 | pub fn format( | 233 | pub fn format(value: ComputeCompareExpected, bw: *Writer) Writer.Error!void { |
| 234 | value: ComputeCompareExpected, | ||
| 235 | bw: *Writer, | ||
| 236 | comptime fmt: []const u8, | ||
| 237 | ) !void { | ||
| 238 | if (fmt.len != 0) std.fmt.invalidFmtError(fmt, value); | ||
| 239 | try bw.print("{s} ", .{@tagName(value.op)}); | 234 | try bw.print("{s} ", .{@tagName(value.op)}); |
| 240 | switch (value.value) { | 235 | switch (value.value) { |
| 241 | .variable => |name| try bw.writeAll(name), | 236 | .variable => |name| try bw.writeAll(name), |
| ... | @@ -571,7 +566,9 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { | ... | @@ -571,7 +566,9 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { |
| 571 | null, | 566 | null, |
| 572 | .of(u64), | 567 | .of(u64), |
| 573 | null, | 568 | null, |
| 574 | ) catch |err| return step.fail("unable to read '{f'}': {s}", .{ src_path, @errorName(err) }); | 569 | ) catch |err| return step.fail("unable to read '{f}': {s}", .{ |
| 570 | std.fmt.alt(src_path, .formatEscapeChar), @errorName(err), | ||
| 571 | }); | ||
| 575 | 572 | ||
| 576 | var vars: std.StringHashMap(u64) = .init(gpa); | 573 | var vars: std.StringHashMap(u64) = .init(gpa); |
| 577 | for (check_object.checks.items) |chk| { | 574 | for (check_object.checks.items) |chk| { |
lib/std/Target.zig+7-18| ... | @@ -301,24 +301,13 @@ pub const Os = struct { | ... | @@ -301,24 +301,13 @@ pub const Os = struct { |
| 301 | 301 | ||
| 302 | /// This function is defined to serialize a Zig source code representation of this | 302 | /// This function is defined to serialize a Zig source code representation of this |
| 303 | /// type, that, when parsed, will deserialize into the same data. | 303 | /// type, that, when parsed, will deserialize into the same data. |
| 304 | pub fn format(ver: WindowsVersion, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { | 304 | pub fn format(wv: WindowsVersion, w: *std.io.Writer) std.io.Writer.Error!void { |
| 305 | const maybe_name = std.enums.tagName(WindowsVersion, ver); | 305 | if (std.enums.tagName(WindowsVersion, wv)) |name| { |
| 306 | if (comptime std.mem.eql(u8, f, "s")) { | 306 | var vecs: [2][]const u8 = .{ ".", name }; |
| 307 | if (maybe_name) |name| | 307 | return w.writeVecAll(&vecs); |
| 308 | try w.print(".{s}", .{name}) | 308 | } else { |
| 309 | else | 309 | return w.print("@enumFromInt(0x{X:0>8})", .{wv}); |
| 310 | try w.print(".{d}", .{@intFromEnum(ver)}); | 310 | } |
| 311 | } else if (comptime std.mem.eql(u8, f, "c")) { | ||
| 312 | if (maybe_name) |name| | ||
| 313 | try w.print(".{s}", .{name}) | ||
| 314 | else | ||
| 315 | try w.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)}); | ||
| 316 | } else if (f.len == 0) { | ||
| 317 | if (maybe_name) |name| | ||
| 318 | try w.print("WindowsVersion.{s}", .{name}) | ||
| 319 | else | ||
| 320 | try w.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)}); | ||
| 321 | } else std.fmt.invalidFmtError(f, ver); | ||
| 322 | } | 311 | } |
| 323 | }; | 312 | }; |
| 324 | 313 |
lib/std/Uri.zig+14| ... | @@ -240,6 +240,10 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { | ... | @@ -240,6 +240,10 @@ pub fn parseAfterScheme(scheme: []const u8, text: []const u8) ParseError!Uri { |
| 240 | return uri; | 240 | return uri; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | pub fn format(uri: *const Uri, writer: *std.io.Writer) std.io.Writer.Error!void { | ||
| 244 | return writeToStream(uri, writer, .all); | ||
| 245 | } | ||
| 246 | |||
| 243 | pub fn writeToStream(uri: *const Uri, writer: *std.io.Writer, flags: Format.Flags) std.io.Writer.Error!void { | 247 | pub fn writeToStream(uri: *const Uri, writer: *std.io.Writer, flags: Format.Flags) std.io.Writer.Error!void { |
| 244 | if (flags.scheme) { | 248 | if (flags.scheme) { |
| 245 | try writer.print("{s}:", .{uri.scheme}); | 249 | try writer.print("{s}:", .{uri.scheme}); |
| ... | @@ -302,6 +306,16 @@ pub const Format = struct { | ... | @@ -302,6 +306,16 @@ pub const Format = struct { |
| 302 | fragment: bool = false, | 306 | fragment: bool = false, |
| 303 | /// When true, include the port part of the URI. Ignored when `port` is null. | 307 | /// When true, include the port part of the URI. Ignored when `port` is null. |
| 304 | port: bool = true, | 308 | port: bool = true, |
| 309 | |||
| 310 | pub const all: Flags = .{ | ||
| 311 | .scheme = true, | ||
| 312 | .authentication = true, | ||
| 313 | .authority = true, | ||
| 314 | .path = true, | ||
| 315 | .query = true, | ||
| 316 | .fragment = true, | ||
| 317 | .port = true, | ||
| 318 | }; | ||
| 305 | }; | 319 | }; |
| 306 | 320 | ||
| 307 | pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { | 321 | pub fn default(f: Format, writer: *std.io.Writer) std.io.Writer.Error!void { |
lib/std/fmt.zig+40-62| ... | @@ -53,16 +53,20 @@ pub const Options = struct { | ... | @@ -53,16 +53,20 @@ pub const Options = struct { |
| 53 | /// - when using a field name, you are required to enclose the field name (an identifier) in square | 53 | /// - when using a field name, you are required to enclose the field name (an identifier) in square |
| 54 | /// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...} | 54 | /// brackets, e.g. {[score]...} as opposed to the numeric index form which can be written e.g. {2...} |
| 55 | /// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below) | 55 | /// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below) |
| 56 | /// - *fill* is a single byte which is used to pad the formatted text | 56 | /// - *fill* is a single byte which is used to pad formatted numbers. |
| 57 | /// - *alignment* is one of the three bytes '<', '^', or '>' to make the text left-, center-, or right-aligned, respectively | 57 | /// - *alignment* is one of the three bytes '<', '^', or '>' to make numbers |
| 58 | /// - *width* is the total width of the field in bytes. This is generally only | 58 | /// left, center, or right-aligned, respectively. |
| 59 | /// useful for ASCII text, such as numbers. | 59 | /// - *width* is the total width of the field in bytes. This only applies to number formatting. |
| 60 | /// - *precision* specifies how many decimals a formatted number should have | 60 | /// - *precision* specifies how many decimals a formatted number should have. |
| 61 | /// | 61 | /// |
| 62 | /// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when | 62 | /// Note that most of the parameters are optional and may be omitted. Also you |
| 63 | /// all parameters after the separator are omitted. | 63 | /// can leave out separators like `:` and `.` when all parameters after the |
| 64 | /// Only exception is the *fill* parameter. If a non-zero *fill* character is required at the same time as *width* is specified, | 64 | /// separator are omitted. |
| 65 | /// one has to specify *alignment* as well, as otherwise the digit following `:` is interpreted as *width*, not *fill*. | 65 | /// |
| 66 | /// Only exception is the *fill* parameter. If a non-zero *fill* character is | ||
| 67 | /// required at the same time as *width* is specified, one has to specify | ||
| 68 | /// *alignment* as well, as otherwise the digit following `:` is interpreted as | ||
| 69 | /// *width*, not *fill*. | ||
| 66 | /// | 70 | /// |
| 67 | /// The *specifier* has several options for types: | 71 | /// The *specifier* has several options for types: |
| 68 | /// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes | 72 | /// - `x` and `X`: output numeric value in hexadecimal notation, or string in hexadecimal bytes |
| ... | @@ -405,9 +409,9 @@ pub const ArgState = struct { | ... | @@ -405,9 +409,9 @@ pub const ArgState = struct { |
| 405 | /// Asserts the rendered integer value fits in `buffer`. | 409 | /// Asserts the rendered integer value fits in `buffer`. |
| 406 | /// Returns the end index within `buffer`. | 410 | /// Returns the end index within `buffer`. |
| 407 | pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize { | 411 | pub fn printInt(buffer: []u8, value: anytype, base: u8, case: Case, options: Options) usize { |
| 408 | var bw: Writer = .fixed(buffer); | 412 | var w: Writer = .fixed(buffer); |
| 409 | bw.printIntOptions(value, base, case, options) catch unreachable; | 413 | w.printInt(value, base, case, options) catch unreachable; |
| 410 | return bw.end; | 414 | return w.end; |
| 411 | } | 415 | } |
| 412 | 416 | ||
| 413 | /// Converts values in the range [0, 100) to a base 10 string. | 417 | /// Converts values in the range [0, 100) to a base 10 string. |
| ... | @@ -956,35 +960,23 @@ fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime | ... | @@ -956,35 +960,23 @@ fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime |
| 956 | } | 960 | } |
| 957 | 961 | ||
| 958 | test "array" { | 962 | test "array" { |
| 959 | { | 963 | const value: [3]u8 = "abc".*; |
| 960 | const value: [3]u8 = "abc".*; | 964 | try expectArrayFmt("array: abc\n", "array: {s}\n", value); |
| 961 | try expectArrayFmt("array: abc\n", "array: {s}\n", value); | 965 | try expectArrayFmt("array: 616263\n", "array: {x}\n", value); |
| 962 | try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {d}\n", value); | 966 | try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value); |
| 963 | try expectArrayFmt("array: 616263\n", "array: {x}\n", value); | ||
| 964 | try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value); | ||
| 965 | |||
| 966 | var buf: [100]u8 = undefined; | ||
| 967 | try expectFmt( | ||
| 968 | try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}), | ||
| 969 | "array: {*}\n", | ||
| 970 | .{&value}, | ||
| 971 | ); | ||
| 972 | } | ||
| 973 | 967 | ||
| 974 | { | 968 | var buf: [100]u8 = undefined; |
| 975 | const value = [2][3]u8{ "abc".*, "def".* }; | 969 | try expectFmt( |
| 976 | 970 | try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@intFromPtr(&value)}), | |
| 977 | try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value); | 971 | "array: {*}\n", |
| 978 | try expectArrayFmt("array: { { 97, 98, 99 }, { 100, 101, 102 } }\n", "array: {d}\n", value); | 972 | .{&value}, |
| 979 | try expectArrayFmt("array: { 616263, 646566 }\n", "array: {x}\n", value); | 973 | ); |
| 980 | } | ||
| 981 | } | 974 | } |
| 982 | 975 | ||
| 983 | test "slice" { | 976 | test "slice" { |
| 984 | { | 977 | { |
| 985 | const value: []const u8 = "abc"; | 978 | const value: []const u8 = "abc"; |
| 986 | try expectFmt("slice: abc\n", "slice: {s}\n", .{value}); | 979 | try expectFmt("slice: abc\n", "slice: {s}\n", .{value}); |
| 987 | try expectFmt("slice: { 97, 98, 99 }\n", "slice: {d}\n", .{value}); | ||
| 988 | try expectFmt("slice: 616263\n", "slice: {x}\n", .{value}); | 980 | try expectFmt("slice: 616263\n", "slice: {x}\n", .{value}); |
| 989 | try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value}); | 981 | try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value}); |
| 990 | } | 982 | } |
| ... | @@ -999,17 +991,12 @@ test "slice" { | ... | @@ -999,17 +991,12 @@ test "slice" { |
| 999 | try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice}); | 991 | try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice}); |
| 1000 | } | 992 | } |
| 1001 | 993 | ||
| 1002 | try expectFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"}); | ||
| 1003 | try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); | 994 | try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); |
| 1004 | 995 | ||
| 1005 | { | 996 | { |
| 1006 | var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 }; | 997 | var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 }; |
| 1007 | var runtime_zero: usize = 0; | 998 | const input: []const u32 = &int_slice; |
| 1008 | _ = &runtime_zero; | 999 | try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{input}); |
| 1009 | try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {any}", .{int_slice[runtime_zero..]}); | ||
| 1010 | try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]}); | ||
| 1011 | try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]}); | ||
| 1012 | try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]}); | ||
| 1013 | } | 1000 | } |
| 1014 | { | 1001 | { |
| 1015 | const S1 = struct { | 1002 | const S1 = struct { |
| ... | @@ -1054,11 +1041,6 @@ test "cstr" { | ... | @@ -1054,11 +1041,6 @@ test "cstr" { |
| 1054 | "cstr: {s}\n", | 1041 | "cstr: {s}\n", |
| 1055 | .{@as([*c]const u8, @ptrCast("Test C"))}, | 1042 | .{@as([*c]const u8, @ptrCast("Test C"))}, |
| 1056 | ); | 1043 | ); |
| 1057 | try expectFmt( | ||
| 1058 | "cstr: Test C\n", | ||
| 1059 | "cstr: {s:10}\n", | ||
| 1060 | .{@as([*c]const u8, @ptrCast("Test C"))}, | ||
| 1061 | ); | ||
| 1062 | } | 1044 | } |
| 1063 | 1045 | ||
| 1064 | test "struct" { | 1046 | test "struct" { |
| ... | @@ -1428,16 +1410,12 @@ test "enum-literal" { | ... | @@ -1428,16 +1410,12 @@ test "enum-literal" { |
| 1428 | 1410 | ||
| 1429 | test "padding" { | 1411 | test "padding" { |
| 1430 | try expectFmt("Simple", "{s}", .{"Simple"}); | 1412 | try expectFmt("Simple", "{s}", .{"Simple"}); |
| 1431 | try expectFmt(" true", "{:10}", .{true}); | 1413 | try expectFmt(" 1234", "{:10}", .{1234}); |
| 1432 | try expectFmt(" true", "{:>10}", .{true}); | 1414 | try expectFmt(" 1234", "{:>10}", .{1234}); |
| 1433 | try expectFmt("======true", "{:=>10}", .{true}); | 1415 | try expectFmt("======1234", "{:=>10}", .{1234}); |
| 1434 | try expectFmt("true======", "{:=<10}", .{true}); | 1416 | try expectFmt("1234======", "{:=<10}", .{1234}); |
| 1435 | try expectFmt(" true ", "{:^10}", .{true}); | 1417 | try expectFmt(" 1234 ", "{:^10}", .{1234}); |
| 1436 | try expectFmt("===true===", "{:=^10}", .{true}); | 1418 | try expectFmt("===1234===", "{:=^10}", .{1234}); |
| 1437 | try expectFmt(" Minimum width", "{s:18} width", .{"Minimum"}); | ||
| 1438 | try expectFmt("==================Filled", "{s:=>24}", .{"Filled"}); | ||
| 1439 | try expectFmt(" Centered ", "{s:^24}", .{"Centered"}); | ||
| 1440 | try expectFmt("-", "{s:-^1}", .{""}); | ||
| 1441 | try expectFmt("====a", "{c:=>5}", .{'a'}); | 1419 | try expectFmt("====a", "{c:=>5}", .{'a'}); |
| 1442 | try expectFmt("==a==", "{c:=^5}", .{'a'}); | 1420 | try expectFmt("==a==", "{c:=^5}", .{'a'}); |
| 1443 | try expectFmt("a====", "{c:=<5}", .{'a'}); | 1421 | try expectFmt("a====", "{c:=<5}", .{'a'}); |
| ... | @@ -1485,17 +1463,17 @@ test "named arguments" { | ... | @@ -1485,17 +1463,17 @@ test "named arguments" { |
| 1485 | 1463 | ||
| 1486 | test "runtime width specifier" { | 1464 | test "runtime width specifier" { |
| 1487 | const width: usize = 9; | 1465 | const width: usize = 9; |
| 1488 | try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width }); | 1466 | try expectFmt("~~12345~~", "{d:~^[1]}", .{ 12345, width }); |
| 1489 | try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width }); | 1467 | try expectFmt("~~12345~~", "{d:~^[width]}", .{ .string = 12345, .width = width }); |
| 1490 | try expectFmt(" hello", "{s:[1]}", .{ "hello", width }); | 1468 | try expectFmt(" 12345", "{d:[1]}", .{ 12345, width }); |
| 1491 | try expectFmt("42 hello", "{d} {s:[2]}", .{ 42, "hello", width }); | 1469 | try expectFmt("42 12345", "{d} {d:[2]}", .{ 42, 12345, width }); |
| 1492 | } | 1470 | } |
| 1493 | 1471 | ||
| 1494 | test "runtime precision specifier" { | 1472 | test "runtime precision specifier" { |
| 1495 | const number: f32 = 3.1415; | 1473 | const number: f32 = 3.1415; |
| 1496 | const precision: usize = 2; | 1474 | const precision: usize = 2; |
| 1497 | try expectFmt("3.14e0", "{:1.[1]}", .{ number, precision }); | 1475 | try expectFmt("3.14e0", "{e:1.[1]}", .{ number, precision }); |
| 1498 | try expectFmt("3.14e0", "{:1.[precision]}", .{ .number = number, .precision = precision }); | 1476 | try expectFmt("3.14e0", "{e:1.[precision]}", .{ .number = number, .precision = precision }); |
| 1499 | } | 1477 | } |
| 1500 | 1478 | ||
| 1501 | test "recursive format function" { | 1479 | test "recursive format function" { |
lib/std/io/Writer.zig+284-207| ... | @@ -777,15 +777,15 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void { | ... | @@ -777,15 +777,15 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void { |
| 777 | .pointer => |info| { | 777 | .pointer => |info| { |
| 778 | try w.writeAll(@typeName(info.child) ++ "@"); | 778 | try w.writeAll(@typeName(info.child) ++ "@"); |
| 779 | if (info.size == .slice) | 779 | if (info.size == .slice) |
| 780 | try w.printIntOptions(@intFromPtr(value.ptr), 16, .lower, .{}) | 780 | try w.printInt(@intFromPtr(value.ptr), 16, .lower, .{}) |
| 781 | else | 781 | else |
| 782 | try w.printIntOptions(@intFromPtr(value), 16, .lower, .{}); | 782 | try w.printInt(@intFromPtr(value), 16, .lower, .{}); |
| 783 | return; | 783 | return; |
| 784 | }, | 784 | }, |
| 785 | .optional => |info| { | 785 | .optional => |info| { |
| 786 | if (@typeInfo(info.child) == .pointer) { | 786 | if (@typeInfo(info.child) == .pointer) { |
| 787 | try w.writeAll(@typeName(info.child) ++ "@"); | 787 | try w.writeAll(@typeName(info.child) ++ "@"); |
| 788 | try w.printIntOptions(@intFromPtr(value), 16, .lower, .{}); | 788 | try w.printInt(@intFromPtr(value), 16, .lower, .{}); |
| 789 | return; | 789 | return; |
| 790 | } | 790 | } |
| 791 | }, | 791 | }, |
| ... | @@ -804,11 +804,147 @@ pub fn printValue( | ... | @@ -804,11 +804,147 @@ pub fn printValue( |
| 804 | ) Error!void { | 804 | ) Error!void { |
| 805 | const T = @TypeOf(value); | 805 | const T = @TypeOf(value); |
| 806 | 806 | ||
| 807 | if (fmt.len == 1) switch (fmt[0]) { | 807 | switch (fmt.len) { |
| 808 | '*' => return w.printAddress(value), | 808 | 1 => switch (fmt[0]) { |
| 809 | 'f' => return value.format(w), | 809 | '*' => return w.printAddress(value), |
| 810 | 'f' => return value.format(w), | ||
| 811 | 'd' => switch (@typeInfo(T)) { | ||
| 812 | .float, .comptime_float => return printFloat(w, value, .decimal, options), | ||
| 813 | .int, .comptime_int => return printInt(w, value, 10, .lower, options), | ||
| 814 | .@"struct" => return value.formatInteger(w, 10, .lower), | ||
| 815 | .@"enum" => return printInt(w, @intFromEnum(value), 10, .lower, options), | ||
| 816 | .vector => return printVector(w, fmt, options, value, max_depth), | ||
| 817 | else => invalidFmtError(fmt, value), | ||
| 818 | }, | ||
| 819 | 'c' => return w.printAsciiChar(value, options), | ||
| 820 | 'u' => return w.printUnicodeCodepoint(value), | ||
| 821 | 'b' => switch (@typeInfo(T)) { | ||
| 822 | .int, .comptime_int => return printInt(w, value, 2, .lower, options), | ||
| 823 | .@"enum" => return printInt(w, @intFromEnum(value), 2, .lower, options), | ||
| 824 | .@"struct" => return value.formatInteger(w, 2, .lower), | ||
| 825 | .vector => return printVector(w, fmt, options, value, max_depth), | ||
| 826 | else => invalidFmtError(fmt, value), | ||
| 827 | }, | ||
| 828 | 'o' => switch (@typeInfo(T)) { | ||
| 829 | .int, .comptime_int => return printInt(w, value, 8, .lower, options), | ||
| 830 | .@"enum" => return printInt(w, @intFromEnum(value), 8, .lower, options), | ||
| 831 | .@"struct" => return value.formatInteger(w, 8, .lower), | ||
| 832 | .vector => return printVector(w, fmt, options, value, max_depth), | ||
| 833 | else => invalidFmtError(fmt, value), | ||
| 834 | }, | ||
| 835 | 'x' => switch (@typeInfo(T)) { | ||
| 836 | .float, .comptime_float => return printFloatHexOptions(w, value, .lower, options), | ||
| 837 | .int, .comptime_int => return printInt(w, value, 16, .lower, options), | ||
| 838 | .@"enum" => return printInt(w, @intFromEnum(value), 16, .lower, options), | ||
| 839 | .@"struct" => return value.formatInteger(w, 16, .lower), | ||
| 840 | .pointer => |info| switch (info.size) { | ||
| 841 | .one, .slice => { | ||
| 842 | const slice: []const u8 = value; | ||
| 843 | return printHex(w, slice, .lower); | ||
| 844 | }, | ||
| 845 | .many, .c => { | ||
| 846 | const slice: [:0]const u8 = std.mem.span(value); | ||
| 847 | return printHex(w, slice, .lower); | ||
| 848 | }, | ||
| 849 | }, | ||
| 850 | .array => { | ||
| 851 | const slice: []const u8 = &value; | ||
| 852 | return printHex(w, slice, .lower); | ||
| 853 | }, | ||
| 854 | .vector => return printVector(w, fmt, options, value, max_depth), | ||
| 855 | else => invalidFmtError(fmt, value), | ||
| 856 | }, | ||
| 857 | 'X' => switch (@typeInfo(T)) { | ||
| 858 | .float, .comptime_float => return printFloatHexOptions(w, value, .lower, options), | ||
| 859 | .int, .comptime_int => return printInt(w, value, 16, .upper, options), | ||
| 860 | .@"enum" => return printInt(w, @intFromEnum(value), 16, .upper, options), | ||
| 861 | .@"struct" => return value.formatInteger(w, 16, .upper), | ||
| 862 | .pointer => |info| switch (info.size) { | ||
| 863 | .one, .slice => { | ||
| 864 | const slice: []const u8 = value; | ||
| 865 | return printHex(w, slice, .upper); | ||
| 866 | }, | ||
| 867 | .many, .c => { | ||
| 868 | const slice: [:0]const u8 = std.mem.span(value); | ||
| 869 | return printHex(w, slice, .upper); | ||
| 870 | }, | ||
| 871 | }, | ||
| 872 | .array => { | ||
| 873 | const slice: []const u8 = &value; | ||
| 874 | return printHex(w, slice, .upper); | ||
| 875 | }, | ||
| 876 | .vector => return printVector(w, fmt, options, value, max_depth), | ||
| 877 | else => invalidFmtError(fmt, value), | ||
| 878 | }, | ||
| 879 | 's' => switch (@typeInfo(T)) { | ||
| 880 | .pointer => |info| switch (info.size) { | ||
| 881 | .one, .slice => { | ||
| 882 | const slice: []const u8 = value; | ||
| 883 | return w.writeAll(slice); | ||
| 884 | }, | ||
| 885 | .many, .c => { | ||
| 886 | const slice: [:0]const u8 = std.mem.span(value); | ||
| 887 | return w.writeAll(slice); | ||
| 888 | }, | ||
| 889 | }, | ||
| 890 | .array => { | ||
| 891 | const slice: []const u8 = &value; | ||
| 892 | return w.writeAll(slice); | ||
| 893 | }, | ||
| 894 | else => invalidFmtError(fmt, value), | ||
| 895 | }, | ||
| 896 | 'B' => switch (@typeInfo(T)) { | ||
| 897 | .int, .comptime_int => return w.printByteSize(value, .decimal, options), | ||
| 898 | .@"struct" => return value.formatByteSize(w, .decimal), | ||
| 899 | else => invalidFmtError(fmt, value), | ||
| 900 | }, | ||
| 901 | 'D' => switch (@typeInfo(T)) { | ||
| 902 | .int, .comptime_int => return w.printDuration(value, options), | ||
| 903 | .@"struct" => return value.formatDuration(w), | ||
| 904 | else => invalidFmtError(fmt, value), | ||
| 905 | }, | ||
| 906 | 'e' => switch (@typeInfo(T)) { | ||
| 907 | .float, .comptime_float => return printFloat(w, value, .scientific, options), | ||
| 908 | .@"struct" => return value.formatFloat(w, .scientific), | ||
| 909 | else => invalidFmtError(fmt, value), | ||
| 910 | }, | ||
| 911 | 't' => switch (@typeInfo(T)) { | ||
| 912 | .error_set => return w.writeAll(@errorName(value)), | ||
| 913 | .@"enum", .@"union" => return w.writeAll(@tagName(value)), | ||
| 914 | else => invalidFmtError(fmt, value), | ||
| 915 | }, | ||
| 916 | else => {}, | ||
| 917 | }, | ||
| 918 | 2 => switch (fmt[0]) { | ||
| 919 | 'B' => switch (fmt[1]) { | ||
| 920 | 'i' => switch (@typeInfo(T)) { | ||
| 921 | .int, .comptime_int => return w.printByteSize(value, .binary, options), | ||
| 922 | .@"struct" => return value.formatByteSize(w, .binary), | ||
| 923 | else => invalidFmtError(fmt, value), | ||
| 924 | }, | ||
| 925 | else => {}, | ||
| 926 | }, | ||
| 927 | else => {}, | ||
| 928 | }, | ||
| 929 | 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') switch (@typeInfo(T)) { | ||
| 930 | .pointer => |info| switch (info.size) { | ||
| 931 | .one, .slice => { | ||
| 932 | const slice: []const u8 = value; | ||
| 933 | return w.printBase64(slice); | ||
| 934 | }, | ||
| 935 | .many, .c => { | ||
| 936 | const slice: [:0]const u8 = std.mem.span(value); | ||
| 937 | return w.printBase64(slice); | ||
| 938 | }, | ||
| 939 | }, | ||
| 940 | .array => { | ||
| 941 | const slice: []const u8 = &value; | ||
| 942 | return w.printBase64(slice); | ||
| 943 | }, | ||
| 944 | else => invalidFmtError(fmt, value), | ||
| 945 | }, | ||
| 810 | else => {}, | 946 | else => {}, |
| 811 | }; | 947 | } |
| 812 | 948 | ||
| 813 | const is_any = comptime std.mem.eql(u8, fmt, ANY); | 949 | const is_any = comptime std.mem.eql(u8, fmt, ANY); |
| 814 | if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) { | 950 | if (!is_any and std.meta.hasMethod(T, "format") and fmt.len == 0) { |
| ... | @@ -817,15 +953,21 @@ pub fn printValue( | ... | @@ -817,15 +953,21 @@ pub fn printValue( |
| 817 | } | 953 | } |
| 818 | 954 | ||
| 819 | switch (@typeInfo(T)) { | 955 | switch (@typeInfo(T)) { |
| 820 | .float, .comptime_float => return w.printFloat(if (is_any) "d" else fmt, options, value), | 956 | .float, .comptime_float => { |
| 821 | .int, .comptime_int => return w.printInt(if (is_any) "d" else fmt, options, value), | 957 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 958 | return printFloat(w, value, .decimal, options); | ||
| 959 | }, | ||
| 960 | .int, .comptime_int => { | ||
| 961 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | ||
| 962 | return printInt(w, value, 10, .lower, options); | ||
| 963 | }, | ||
| 822 | .bool => { | 964 | .bool => { |
| 823 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 965 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 824 | return w.alignBufferOptions(if (value) "true" else "false", options); | 966 | return w.writeAll(if (value) "true" else "false"); |
| 825 | }, | 967 | }, |
| 826 | .void => { | 968 | .void => { |
| 827 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 969 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 828 | return w.alignBufferOptions("void", options); | 970 | return w.writeAll("void"); |
| 829 | }, | 971 | }, |
| 830 | .optional => { | 972 | .optional => { |
| 831 | const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '?') | 973 | const remaining_fmt = comptime if (fmt.len > 0 and fmt[0] == '?') |
| ... | @@ -854,40 +996,18 @@ pub fn printValue( | ... | @@ -854,40 +996,18 @@ pub fn printValue( |
| 854 | } | 996 | } |
| 855 | }, | 997 | }, |
| 856 | .error_set => { | 998 | .error_set => { |
| 857 | if (fmt.len == 1 and fmt[0] == 't') return w.writeAll(@errorName(value)); | ||
| 858 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 999 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 859 | try printErrorSet(w, value); | 1000 | return printErrorSet(w, value); |
| 860 | }, | 1001 | }, |
| 861 | .@"enum" => { | 1002 | .@"enum" => |info| { |
| 862 | if (fmt.len == 1 and fmt[0] == 't') { | 1003 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 863 | try w.writeAll(@tagName(value)); | 1004 | if (info.is_exhaustive) { |
| 864 | return; | 1005 | return printEnumExhaustive(w, value); |
| 865 | } | 1006 | } else { |
| 866 | if (!is_any) { | 1007 | return printEnumNonexhaustive(w, value); |
| 867 | if (fmt.len != 0) return printValue(w, fmt, options, @intFromEnum(value), max_depth); | ||
| 868 | return printValue(w, ANY, options, value, max_depth); | ||
| 869 | } | ||
| 870 | const enum_info = @typeInfo(T).@"enum"; | ||
| 871 | if (enum_info.is_exhaustive) { | ||
| 872 | var vecs: [2][]const u8 = .{ ".", @tagName(value) }; | ||
| 873 | try w.writeVecAll(&vecs); | ||
| 874 | return; | ||
| 875 | } | ||
| 876 | if (std.enums.tagName(T, value)) |tag_name| { | ||
| 877 | var vecs: [2][]const u8 = .{ ".", tag_name }; | ||
| 878 | try w.writeVecAll(&vecs); | ||
| 879 | return; | ||
| 880 | } | 1008 | } |
| 881 | try w.writeAll("@enumFromInt("); | ||
| 882 | try w.printValue(ANY, options, @intFromEnum(value), max_depth); | ||
| 883 | try w.writeByte(')'); | ||
| 884 | return; | ||
| 885 | }, | 1009 | }, |
| 886 | .@"union" => |info| { | 1010 | .@"union" => |info| { |
| 887 | if (fmt.len == 1 and fmt[0] == 't') { | ||
| 888 | try w.writeAll(@tagName(value)); | ||
| 889 | return; | ||
| 890 | } | ||
| 891 | if (!is_any) { | 1011 | if (!is_any) { |
| 892 | if (fmt.len != 0) invalidFmtError(fmt, value); | 1012 | if (fmt.len != 0) invalidFmtError(fmt, value); |
| 893 | return printValue(w, ANY, options, value, max_depth); | 1013 | return printValue(w, ANY, options, value, max_depth); |
| ... | @@ -971,38 +1091,18 @@ pub fn printValue( | ... | @@ -971,38 +1091,18 @@ pub fn printValue( |
| 971 | else => { | 1091 | else => { |
| 972 | var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" }; | 1092 | var buffers: [2][]const u8 = .{ @typeName(ptr_info.child), "@" }; |
| 973 | try w.writeVecAll(&buffers); | 1093 | try w.writeVecAll(&buffers); |
| 974 | try w.printIntOptions(@intFromPtr(value), 16, .lower, options); | 1094 | try w.printInt(@intFromPtr(value), 16, .lower, options); |
| 975 | return; | 1095 | return; |
| 976 | }, | 1096 | }, |
| 977 | }, | 1097 | }, |
| 978 | .many, .c => { | 1098 | .many, .c => { |
| 979 | if (ptr_info.sentinel() != null) | 1099 | if (!is_any) @compileError("cannot format pointer without a specifier (i.e. {s} or {*})"); |
| 980 | return w.printValue(fmt, options, std.mem.span(value), max_depth); | ||
| 981 | if (fmt.len == 1 and fmt[0] == 's' and ptr_info.child == u8) | ||
| 982 | return w.alignBufferOptions(std.mem.span(value), options); | ||
| 983 | if (!is_any and fmt.len == 0) | ||
| 984 | @compileError("cannot format pointer without a specifier (i.e. {s} or {*})"); | ||
| 985 | if (!is_any and fmt.len != 0) | ||
| 986 | invalidFmtError(fmt, value); | ||
| 987 | try w.printAddress(value); | 1100 | try w.printAddress(value); |
| 988 | }, | 1101 | }, |
| 989 | .slice => { | 1102 | .slice => { |
| 990 | if (!is_any and fmt.len == 0) | 1103 | if (!is_any) |
| 991 | @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})"); | 1104 | @compileError("cannot format slice without a specifier (i.e. {s}, {x}, {b64}, or {any})"); |
| 992 | if (max_depth == 0) | 1105 | if (max_depth == 0) return w.writeAll("{ ... }"); |
| 993 | return w.writeAll("{ ... }"); | ||
| 994 | if (ptr_info.child == u8) switch (fmt.len) { | ||
| 995 | 1 => switch (fmt[0]) { | ||
| 996 | 's' => return w.alignBufferOptions(value, options), | ||
| 997 | 'x' => return w.printHex(value, .lower), | ||
| 998 | 'X' => return w.printHex(value, .upper), | ||
| 999 | else => {}, | ||
| 1000 | }, | ||
| 1001 | 3 => if (fmt[0] == 'b' and fmt[1] == '6' and fmt[2] == '4') { | ||
| 1002 | return w.printBase64(value); | ||
| 1003 | }, | ||
| 1004 | else => {}, | ||
| 1005 | }; | ||
| 1006 | try w.writeAll("{ "); | 1106 | try w.writeAll("{ "); |
| 1007 | for (value, 0..) |elem, i| { | 1107 | for (value, 0..) |elem, i| { |
| 1008 | try w.printValue(fmt, options, elem, max_depth - 1); | 1108 | try w.printValue(fmt, options, elem, max_depth - 1); |
| ... | @@ -1013,21 +1113,9 @@ pub fn printValue( | ... | @@ -1013,21 +1113,9 @@ pub fn printValue( |
| 1013 | try w.writeAll(" }"); | 1113 | try w.writeAll(" }"); |
| 1014 | }, | 1114 | }, |
| 1015 | }, | 1115 | }, |
| 1016 | .array => |info| { | 1116 | .array => { |
| 1017 | if (fmt.len == 0) | 1117 | if (!is_any) @compileError("cannot format array without a specifier (i.e. {s} or {any})"); |
| 1018 | @compileError("cannot format array without a specifier (i.e. {s} or {any})"); | 1118 | if (max_depth == 0) return w.writeAll("{ ... }"); |
| 1019 | if (max_depth == 0) { | ||
| 1020 | return w.writeAll("{ ... }"); | ||
| 1021 | } | ||
| 1022 | if (info.child == u8) { | ||
| 1023 | if (fmt[0] == 's') { | ||
| 1024 | return w.alignBufferOptions(&value, options); | ||
| 1025 | } else if (fmt[0] == 'x') { | ||
| 1026 | return w.printHex(&value, .lower); | ||
| 1027 | } else if (fmt[0] == 'X') { | ||
| 1028 | return w.printHex(&value, .upper); | ||
| 1029 | } | ||
| 1030 | } | ||
| 1031 | try w.writeAll("{ "); | 1119 | try w.writeAll("{ "); |
| 1032 | for (value, 0..) |elem, i| { | 1120 | for (value, 0..) |elem, i| { |
| 1033 | try w.printValue(fmt, options, elem, max_depth - 1); | 1121 | try w.printValue(fmt, options, elem, max_depth - 1); |
| ... | @@ -1037,33 +1125,23 @@ pub fn printValue( | ... | @@ -1037,33 +1125,23 @@ pub fn printValue( |
| 1037 | } | 1125 | } |
| 1038 | try w.writeAll(" }"); | 1126 | try w.writeAll(" }"); |
| 1039 | }, | 1127 | }, |
| 1040 | .vector => |info| { | 1128 | .vector => { |
| 1041 | if (max_depth == 0) { | 1129 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 1042 | return w.writeAll("{ ... }"); | 1130 | return printVector(w, fmt, options, value, max_depth); |
| 1043 | } | ||
| 1044 | try w.writeAll("{ "); | ||
| 1045 | var i: usize = 0; | ||
| 1046 | while (i < info.len) : (i += 1) { | ||
| 1047 | try w.printValue(fmt, options, value[i], max_depth - 1); | ||
| 1048 | if (i < info.len - 1) { | ||
| 1049 | try w.writeAll(", "); | ||
| 1050 | } | ||
| 1051 | } | ||
| 1052 | try w.writeAll(" }"); | ||
| 1053 | }, | 1131 | }, |
| 1054 | .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"), | 1132 | .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"), |
| 1055 | .type => { | 1133 | .type => { |
| 1056 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 1134 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 1057 | return w.alignBufferOptions(@typeName(value), options); | 1135 | return w.writeAll(@typeName(value)); |
| 1058 | }, | 1136 | }, |
| 1059 | .enum_literal => { | 1137 | .enum_literal => { |
| 1060 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 1138 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 1061 | const buffer = [_]u8{'.'} ++ @tagName(value); | 1139 | var vecs: [2][]const u8 = .{ ".", @tagName(value) }; |
| 1062 | return w.alignBufferOptions(buffer, options); | 1140 | return w.writeVecAll(&vecs); |
| 1063 | }, | 1141 | }, |
| 1064 | .null => { | 1142 | .null => { |
| 1065 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 1143 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 1066 | return w.alignBufferOptions("null", options); | 1144 | return w.writeAll("null"); |
| 1067 | }, | 1145 | }, |
| 1068 | else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"), | 1146 | else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"), |
| 1069 | } | 1147 | } |
| ... | @@ -1074,75 +1152,68 @@ fn printErrorSet(w: *Writer, error_set: anyerror) Error!void { | ... | @@ -1074,75 +1152,68 @@ fn printErrorSet(w: *Writer, error_set: anyerror) Error!void { |
| 1074 | try w.writeVecAll(&vecs); | 1152 | try w.writeVecAll(&vecs); |
| 1075 | } | 1153 | } |
| 1076 | 1154 | ||
| 1077 | pub fn printInt( | 1155 | fn printEnumExhaustive(w: *Writer, value: anytype) Error!void { |
| 1156 | var vecs: [2][]const u8 = .{ ".", @tagName(value) }; | ||
| 1157 | try w.writeVecAll(&vecs); | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | fn printEnumNonexhaustive(w: *Writer, value: anytype) Error!void { | ||
| 1161 | if (std.enums.tagName(@TypeOf(value), value)) |tag_name| { | ||
| 1162 | var vecs: [2][]const u8 = .{ ".", tag_name }; | ||
| 1163 | try w.writeVecAll(&vecs); | ||
| 1164 | return; | ||
| 1165 | } | ||
| 1166 | try w.writeAll("@enumFromInt("); | ||
| 1167 | try w.printInt(@intFromEnum(value), 10, .lower, .{}); | ||
| 1168 | try w.writeByte(')'); | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | pub fn printVector( | ||
| 1078 | w: *Writer, | 1172 | w: *Writer, |
| 1079 | comptime fmt: []const u8, | 1173 | comptime fmt: []const u8, |
| 1080 | options: std.fmt.Options, | 1174 | options: std.fmt.Options, |
| 1081 | value: anytype, | 1175 | value: anytype, |
| 1176 | max_depth: usize, | ||
| 1082 | ) Error!void { | 1177 | ) Error!void { |
| 1083 | const int_value = if (@TypeOf(value) == comptime_int) blk: { | 1178 | const len = @typeInfo(@TypeOf(value)).vector.len; |
| 1084 | const Int = std.math.IntFittingRange(value, value); | 1179 | if (max_depth == 0) return w.writeAll("{ ... }"); |
| 1085 | break :blk @as(Int, value); | 1180 | try w.writeAll("{ "); |
| 1086 | } else value; | 1181 | inline for (0..len) |i| { |
| 1087 | 1182 | try w.printValue(fmt, options, value[i], max_depth - 1); | |
| 1088 | switch (fmt.len) { | 1183 | if (i < len - 1) try w.writeAll(", "); |
| 1089 | 0 => return w.printIntOptions(int_value, 10, .lower, options), | ||
| 1090 | 1 => switch (fmt[0]) { | ||
| 1091 | 'd' => return w.printIntOptions(int_value, 10, .lower, options), | ||
| 1092 | 'c' => { | ||
| 1093 | if (@typeInfo(@TypeOf(int_value)).int.bits <= 8) { | ||
| 1094 | return w.printAsciiChar(@as(u8, int_value), options); | ||
| 1095 | } else { | ||
| 1096 | @compileError("cannot print integer that is larger than 8 bits as an ASCII character"); | ||
| 1097 | } | ||
| 1098 | }, | ||
| 1099 | 'u' => { | ||
| 1100 | if (@typeInfo(@TypeOf(int_value)).int.bits <= 21) { | ||
| 1101 | return w.printUnicodeCodepoint(@as(u21, int_value), options); | ||
| 1102 | } else { | ||
| 1103 | @compileError("cannot print integer that is larger than 21 bits as an UTF-8 sequence"); | ||
| 1104 | } | ||
| 1105 | }, | ||
| 1106 | 'b' => return w.printIntOptions(int_value, 2, .lower, options), | ||
| 1107 | 'x' => return w.printIntOptions(int_value, 16, .lower, options), | ||
| 1108 | 'X' => return w.printIntOptions(int_value, 16, .upper, options), | ||
| 1109 | 'o' => return w.printIntOptions(int_value, 8, .lower, options), | ||
| 1110 | 'B' => return w.printByteSize(int_value, .decimal, options), | ||
| 1111 | 'D' => return w.printDuration(int_value, options), | ||
| 1112 | else => invalidFmtError(fmt, value), | ||
| 1113 | }, | ||
| 1114 | 2 => { | ||
| 1115 | if (fmt[0] == 'B' and fmt[1] == 'i') { | ||
| 1116 | return w.printByteSize(int_value, .binary, options); | ||
| 1117 | } else { | ||
| 1118 | invalidFmtError(fmt, value); | ||
| 1119 | } | ||
| 1120 | }, | ||
| 1121 | else => invalidFmtError(fmt, value), | ||
| 1122 | } | 1184 | } |
| 1123 | comptime unreachable; | 1185 | try w.writeAll(" }"); |
| 1124 | } | ||
| 1125 | |||
| 1126 | pub fn printAsciiChar(w: *Writer, c: u8, options: std.fmt.Options) Error!void { | ||
| 1127 | return w.alignBufferOptions(@as(*const [1]u8, &c), options); | ||
| 1128 | } | 1186 | } |
| 1129 | 1187 | ||
| 1130 | pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error!void { | 1188 | // A wrapper around `printIntAny` to avoid the generic explosion of this |
| 1131 | return w.alignBufferOptions(bytes, options); | 1189 | // function by funneling smaller integer types through `isize` and `usize`. |
| 1132 | } | 1190 | pub inline fn printInt( |
| 1133 | 1191 | w: *Writer, | |
| 1134 | pub fn printUnicodeCodepoint(w: *Writer, c: u21, options: std.fmt.Options) Error!void { | 1192 | value: anytype, |
| 1135 | var buf: [4]u8 = undefined; | 1193 | base: u8, |
| 1136 | const len = std.unicode.utf8Encode(c, &buf) catch |err| switch (err) { | 1194 | case: std.fmt.Case, |
| 1137 | error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => l: { | 1195 | options: std.fmt.Options, |
| 1138 | buf[0..3].* = std.unicode.replacement_character_utf8; | 1196 | ) Error!void { |
| 1139 | break :l 3; | 1197 | switch (@TypeOf(value)) { |
| 1198 | isize, usize => {}, | ||
| 1199 | comptime_int => { | ||
| 1200 | if (comptime std.math.cast(usize, value)) |x| return printIntAny(w, x, base, case, options); | ||
| 1201 | if (comptime std.math.cast(isize, value)) |x| return printIntAny(w, x, base, case, options); | ||
| 1202 | const Int = std.math.IntFittingRange(value, value); | ||
| 1203 | return printIntAny(w, @as(Int, value), base, case, options); | ||
| 1140 | }, | 1204 | }, |
| 1141 | }; | 1205 | else => switch (@typeInfo(@TypeOf(value)).int.signedness) { |
| 1142 | return w.alignBufferOptions(buf[0..len], options); | 1206 | .signed => if (std.math.cast(isize, value)) |x| return printIntAny(w, x, base, case, options), |
| 1207 | .unsigned => if (std.math.cast(usize, value)) |x| return printIntAny(w, x, base, case, options), | ||
| 1208 | }, | ||
| 1209 | } | ||
| 1210 | return printIntAny(w, value, base, case, options); | ||
| 1143 | } | 1211 | } |
| 1144 | 1212 | ||
| 1145 | pub fn printIntOptions( | 1213 | /// In general, prefer `printInt` to avoid generic explosion. However this |
| 1214 | /// function may be used when optimal codegen for a particular integer type is | ||
| 1215 | /// desired. | ||
| 1216 | pub fn printIntAny( | ||
| 1146 | w: *Writer, | 1217 | w: *Writer, |
| 1147 | value: anytype, | 1218 | value: anytype, |
| 1148 | base: u8, | 1219 | base: u8, |
| ... | @@ -1150,20 +1221,14 @@ pub fn printIntOptions( | ... | @@ -1150,20 +1221,14 @@ pub fn printIntOptions( |
| 1150 | options: std.fmt.Options, | 1221 | options: std.fmt.Options, |
| 1151 | ) Error!void { | 1222 | ) Error!void { |
| 1152 | assert(base >= 2); | 1223 | assert(base >= 2); |
| 1153 | 1224 | const value_info = @typeInfo(@TypeOf(value)).int; | |
| 1154 | const int_value = if (@TypeOf(value) == comptime_int) blk: { | ||
| 1155 | const Int = std.math.IntFittingRange(value, value); | ||
| 1156 | break :blk @as(Int, value); | ||
| 1157 | } else value; | ||
| 1158 | |||
| 1159 | const value_info = @typeInfo(@TypeOf(int_value)).int; | ||
| 1160 | 1225 | ||
| 1161 | // The type must have the same size as `base` or be wider in order for the | 1226 | // The type must have the same size as `base` or be wider in order for the |
| 1162 | // division to work | 1227 | // division to work |
| 1163 | const min_int_bits = comptime @max(value_info.bits, 8); | 1228 | const min_int_bits = comptime @max(value_info.bits, 8); |
| 1164 | const MinInt = std.meta.Int(.unsigned, min_int_bits); | 1229 | const MinInt = std.meta.Int(.unsigned, min_int_bits); |
| 1165 | 1230 | ||
| 1166 | const abs_value = @abs(int_value); | 1231 | const abs_value = @abs(value); |
| 1167 | // The worst case in terms of space needed is base 2, plus 1 for the sign | 1232 | // The worst case in terms of space needed is base 2, plus 1 for the sign |
| 1168 | var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined; | 1233 | var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined; |
| 1169 | 1234 | ||
| ... | @@ -1210,38 +1275,49 @@ pub fn printIntOptions( | ... | @@ -1210,38 +1275,49 @@ pub fn printIntOptions( |
| 1210 | return w.alignBufferOptions(buf[index..], options); | 1275 | return w.alignBufferOptions(buf[index..], options); |
| 1211 | } | 1276 | } |
| 1212 | 1277 | ||
| 1278 | pub fn printAsciiChar(w: *Writer, c: u8, options: std.fmt.Options) Error!void { | ||
| 1279 | return w.alignBufferOptions(@as(*const [1]u8, &c), options); | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | pub fn printAscii(w: *Writer, bytes: []const u8, options: std.fmt.Options) Error!void { | ||
| 1283 | return w.alignBufferOptions(bytes, options); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | pub fn printUnicodeCodepoint(w: *Writer, c: u21) Error!void { | ||
| 1287 | var buf: [4]u8 = undefined; | ||
| 1288 | const len = std.unicode.utf8Encode(c, &buf) catch |err| switch (err) { | ||
| 1289 | error.Utf8CannotEncodeSurrogateHalf, error.CodepointTooLarge => l: { | ||
| 1290 | buf[0..3].* = std.unicode.replacement_character_utf8; | ||
| 1291 | break :l 3; | ||
| 1292 | }, | ||
| 1293 | }; | ||
| 1294 | return w.writeAll(buf[0..len]); | ||
| 1295 | } | ||
| 1296 | |||
| 1213 | pub fn printFloat( | 1297 | pub fn printFloat( |
| 1214 | w: *Writer, | 1298 | w: *Writer, |
| 1215 | comptime fmt: []const u8, | ||
| 1216 | options: std.fmt.Options, | ||
| 1217 | value: anytype, | 1299 | value: anytype, |
| 1300 | mode: std.fmt.float.Mode, | ||
| 1301 | options: std.fmt.Options, | ||
| 1218 | ) Error!void { | 1302 | ) Error!void { |
| 1219 | var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined; | 1303 | var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined; |
| 1304 | const s = std.fmt.float.render(&buf, value, .{ | ||
| 1305 | .mode = mode, | ||
| 1306 | .precision = options.precision, | ||
| 1307 | }) catch |err| switch (err) { | ||
| 1308 | error.BufferTooSmall => "(float)", | ||
| 1309 | }; | ||
| 1310 | return w.alignBufferOptions(s, options); | ||
| 1311 | } | ||
| 1220 | 1312 | ||
| 1221 | if (fmt.len > 1) invalidFmtError(fmt, value); | 1313 | pub fn printFloatHexOptions(w: *Writer, value: anytype, case: std.fmt.Case, options: std.fmt.Options) Error!void { |
| 1222 | switch (if (fmt.len == 0) 'e' else fmt[0]) { | 1314 | var buf: [50]u8 = undefined; // for aligning |
| 1223 | 'e' => { | 1315 | var sub_writer: Writer = .fixed(&buf); |
| 1224 | const s = std.fmt.float.render(&buf, value, .{ .mode = .scientific, .precision = options.precision }) catch |err| switch (err) { | 1316 | printFloatHex(&sub_writer, value, case, options.precision) catch unreachable; // buf is large enough |
| 1225 | error.BufferTooSmall => "(float)", | 1317 | return w.alignBufferOptions(sub_writer.buffered(), options); |
| 1226 | }; | ||
| 1227 | return w.alignBufferOptions(s, options); | ||
| 1228 | }, | ||
| 1229 | 'd' => { | ||
| 1230 | const s = std.fmt.float.render(&buf, value, .{ .mode = .decimal, .precision = options.precision }) catch |err| switch (err) { | ||
| 1231 | error.BufferTooSmall => "(float)", | ||
| 1232 | }; | ||
| 1233 | return w.alignBufferOptions(s, options); | ||
| 1234 | }, | ||
| 1235 | 'x' => { | ||
| 1236 | var sub_bw: Writer = .fixed(&buf); | ||
| 1237 | sub_bw.printFloatHexadecimal(value, options.precision) catch unreachable; | ||
| 1238 | return w.alignBufferOptions(sub_bw.buffered(), options); | ||
| 1239 | }, | ||
| 1240 | else => invalidFmtError(fmt, value), | ||
| 1241 | } | ||
| 1242 | } | 1318 | } |
| 1243 | 1319 | ||
| 1244 | pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize) Error!void { | 1320 | pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void { |
| 1245 | if (std.math.signbit(value)) try w.writeByte('-'); | 1321 | if (std.math.signbit(value)) try w.writeByte('-'); |
| 1246 | if (std.math.isNan(value)) return w.writeAll("nan"); | 1322 | if (std.math.isNan(value)) return w.writeAll("nan"); |
| 1247 | if (std.math.isInf(value)) return w.writeAll("inf"); | 1323 | if (std.math.isInf(value)) return w.writeAll("inf"); |
| ... | @@ -1320,7 +1396,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize) | ... | @@ -1320,7 +1396,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize) |
| 1320 | 1396 | ||
| 1321 | // +1 for the decimal part. | 1397 | // +1 for the decimal part. |
| 1322 | var buf: [1 + mantissa_digits]u8 = undefined; | 1398 | var buf: [1 + mantissa_digits]u8 = undefined; |
| 1323 | assert(std.fmt.printInt(&buf, mantissa, 16, .lower, .{ .fill = '0', .width = 1 + mantissa_digits }) == buf.len); | 1399 | assert(std.fmt.printInt(&buf, mantissa, 16, case, .{ .fill = '0', .width = 1 + mantissa_digits }) == buf.len); |
| 1324 | 1400 | ||
| 1325 | try w.writeAll("0x"); | 1401 | try w.writeAll("0x"); |
| 1326 | try w.writeByte(buf[0]); | 1402 | try w.writeByte(buf[0]); |
| ... | @@ -1337,7 +1413,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize) | ... | @@ -1337,7 +1413,7 @@ pub fn printFloatHexadecimal(w: *Writer, value: anytype, opt_precision: ?usize) |
| 1337 | try w.splatByteAll('0', precision - trimmed.len); | 1413 | try w.splatByteAll('0', precision - trimmed.len); |
| 1338 | }; | 1414 | }; |
| 1339 | try w.writeAll("p"); | 1415 | try w.writeAll("p"); |
| 1340 | try w.printIntOptions(exponent - exponent_bias, 10, .lower, .{}); | 1416 | try w.printInt(exponent - exponent_bias, 10, case, .{}); |
| 1341 | } | 1417 | } |
| 1342 | 1418 | ||
| 1343 | pub const ByteSizeUnits = enum { | 1419 | pub const ByteSizeUnits = enum { |
| ... | @@ -1433,7 +1509,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { | ... | @@ -1433,7 +1509,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { |
| 1433 | }) |unit| { | 1509 | }) |unit| { |
| 1434 | if (ns_remaining >= unit.ns) { | 1510 | if (ns_remaining >= unit.ns) { |
| 1435 | const units = ns_remaining / unit.ns; | 1511 | const units = ns_remaining / unit.ns; |
| 1436 | try w.printIntOptions(units, 10, .lower, .{}); | 1512 | try w.printInt(units, 10, .lower, .{}); |
| 1437 | try w.writeByte(unit.sep); | 1513 | try w.writeByte(unit.sep); |
| 1438 | ns_remaining -= units * unit.ns; | 1514 | ns_remaining -= units * unit.ns; |
| 1439 | if (ns_remaining == 0) return; | 1515 | if (ns_remaining == 0) return; |
| ... | @@ -1447,13 +1523,13 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { | ... | @@ -1447,13 +1523,13 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { |
| 1447 | }) |unit| { | 1523 | }) |unit| { |
| 1448 | const kunits = ns_remaining * 1000 / unit.ns; | 1524 | const kunits = ns_remaining * 1000 / unit.ns; |
| 1449 | if (kunits >= 1000) { | 1525 | if (kunits >= 1000) { |
| 1450 | try w.printIntOptions(kunits / 1000, 10, .lower, .{}); | 1526 | try w.printInt(kunits / 1000, 10, .lower, .{}); |
| 1451 | const frac = kunits % 1000; | 1527 | const frac = kunits % 1000; |
| 1452 | if (frac > 0) { | 1528 | if (frac > 0) { |
| 1453 | // Write up to 3 decimal places | 1529 | // Write up to 3 decimal places |
| 1454 | var decimal_buf = [_]u8{ '.', 0, 0, 0 }; | 1530 | var decimal_buf = [_]u8{ '.', 0, 0, 0 }; |
| 1455 | var inner: Writer = .fixed(decimal_buf[1..]); | 1531 | var inner: Writer = .fixed(decimal_buf[1..]); |
| 1456 | inner.printIntOptions(frac, 10, .lower, .{ .fill = '0', .width = 3 }) catch unreachable; | 1532 | inner.printInt(frac, 10, .lower, .{ .fill = '0', .width = 3 }) catch unreachable; |
| 1457 | var end: usize = 4; | 1533 | var end: usize = 4; |
| 1458 | while (end > 1) : (end -= 1) { | 1534 | while (end > 1) : (end -= 1) { |
| 1459 | if (decimal_buf[end - 1] != '0') break; | 1535 | if (decimal_buf[end - 1] != '0') break; |
| ... | @@ -1464,7 +1540,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { | ... | @@ -1464,7 +1540,7 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { |
| 1464 | } | 1540 | } |
| 1465 | } | 1541 | } |
| 1466 | 1542 | ||
| 1467 | try w.printIntOptions(ns_remaining, 10, .lower, .{}); | 1543 | try w.printInt(ns_remaining, 10, .lower, .{}); |
| 1468 | try w.writeAll("ns"); | 1544 | try w.writeAll("ns"); |
| 1469 | } | 1545 | } |
| 1470 | 1546 | ||
| ... | @@ -1474,12 +1550,18 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { | ... | @@ -1474,12 +1550,18 @@ pub fn printDurationUnsigned(w: *Writer, ns: u64) Error!void { |
| 1474 | pub fn printDuration(w: *Writer, nanoseconds: anytype, options: std.fmt.Options) Error!void { | 1550 | pub fn printDuration(w: *Writer, nanoseconds: anytype, options: std.fmt.Options) Error!void { |
| 1475 | // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 24 | 1551 | // worst case: "-XXXyXXwXXdXXhXXmXX.XXXs".len = 24 |
| 1476 | var buf: [24]u8 = undefined; | 1552 | var buf: [24]u8 = undefined; |
| 1477 | var sub_bw: Writer = .fixed(&buf); | 1553 | var sub_writer: Writer = .fixed(&buf); |
| 1478 | switch (@typeInfo(@TypeOf(nanoseconds)).int.signedness) { | 1554 | if (@TypeOf(nanoseconds) == comptime_int) { |
| 1479 | .signed => sub_bw.printDurationSigned(nanoseconds) catch unreachable, | 1555 | if (nanoseconds >= 0) { |
| 1480 | .unsigned => sub_bw.printDurationUnsigned(nanoseconds) catch unreachable, | 1556 | sub_writer.printDurationUnsigned(nanoseconds) catch unreachable; |
| 1557 | } else { | ||
| 1558 | sub_writer.printDurationSigned(nanoseconds) catch unreachable; | ||
| 1559 | } | ||
| 1560 | } else switch (@typeInfo(@TypeOf(nanoseconds)).int.signedness) { | ||
| 1561 | .signed => sub_writer.printDurationSigned(nanoseconds) catch unreachable, | ||
| 1562 | .unsigned => sub_writer.printDurationUnsigned(nanoseconds) catch unreachable, | ||
| 1481 | } | 1563 | } |
| 1482 | return w.alignBufferOptions(sub_bw.buffered(), options); | 1564 | return w.alignBufferOptions(sub_writer.buffered(), options); |
| 1483 | } | 1565 | } |
| 1484 | 1566 | ||
| 1485 | pub fn printHex(w: *Writer, bytes: []const u8, case: std.fmt.Case) Error!void { | 1567 | pub fn printHex(w: *Writer, bytes: []const u8, case: std.fmt.Case) Error!void { |
| ... | @@ -1749,7 +1831,7 @@ fn testDurationCaseSigned(expected: []const u8, input: i64) !void { | ... | @@ -1749,7 +1831,7 @@ fn testDurationCaseSigned(expected: []const u8, input: i64) !void { |
| 1749 | try testing.expectEqualStrings(expected, w.buffered()); | 1831 | try testing.expectEqualStrings(expected, w.buffered()); |
| 1750 | } | 1832 | } |
| 1751 | 1833 | ||
| 1752 | test printIntOptions { | 1834 | test printInt { |
| 1753 | try testPrintIntCase("-1", @as(i1, -1), 10, .lower, .{}); | 1835 | try testPrintIntCase("-1", @as(i1, -1), 10, .lower, .{}); |
| 1754 | 1836 | ||
| 1755 | try testPrintIntCase("-101111000110000101001110", @as(i32, -12345678), 2, .lower, .{}); | 1837 | try testPrintIntCase("-101111000110000101001110", @as(i32, -12345678), 2, .lower, .{}); |
| ... | @@ -1765,27 +1847,22 @@ test printIntOptions { | ... | @@ -1765,27 +1847,22 @@ test printIntOptions { |
| 1765 | 1847 | ||
| 1766 | try testPrintIntCase("+42", @as(i32, 42), 10, .lower, .{ .width = 3 }); | 1848 | try testPrintIntCase("+42", @as(i32, 42), 10, .lower, .{ .width = 3 }); |
| 1767 | try testPrintIntCase("-42", @as(i32, -42), 10, .lower, .{ .width = 3 }); | 1849 | try testPrintIntCase("-42", @as(i32, -42), 10, .lower, .{ .width = 3 }); |
| 1768 | } | ||
| 1769 | 1850 | ||
| 1770 | test "printInt with comptime_int" { | 1851 | try testPrintIntCase("123456789123456789", @as(comptime_int, 123456789123456789), 10, .lower, .{}); |
| 1771 | var buf: [20]u8 = undefined; | ||
| 1772 | var w: Writer = .fixed(&buf); | ||
| 1773 | try w.printInt("", .{}, @as(comptime_int, 123456789123456789)); | ||
| 1774 | try std.testing.expectEqualStrings("123456789123456789", w.buffered()); | ||
| 1775 | } | 1852 | } |
| 1776 | 1853 | ||
| 1777 | test "printFloat with comptime_float" { | 1854 | test "printFloat with comptime_float" { |
| 1778 | var buf: [20]u8 = undefined; | 1855 | var buf: [20]u8 = undefined; |
| 1779 | var w: Writer = .fixed(&buf); | 1856 | var w: Writer = .fixed(&buf); |
| 1780 | try w.printFloat("", .{}, @as(comptime_float, 1.0)); | 1857 | try w.printFloat(@as(comptime_float, 1.0), .scientific, .{}); |
| 1781 | try std.testing.expectEqualStrings(w.buffered(), "1e0"); | 1858 | try std.testing.expectEqualStrings(w.buffered(), "1e0"); |
| 1782 | try std.testing.expectFmt("1e0", "{}", .{1.0}); | 1859 | try std.testing.expectFmt("1", "{}", .{1.0}); |
| 1783 | } | 1860 | } |
| 1784 | 1861 | ||
| 1785 | fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void { | 1862 | fn testPrintIntCase(expected: []const u8, value: anytype, base: u8, case: std.fmt.Case, options: std.fmt.Options) !void { |
| 1786 | var buffer: [100]u8 = undefined; | 1863 | var buffer: [100]u8 = undefined; |
| 1787 | var w: Writer = .fixed(&buffer); | 1864 | var w: Writer = .fixed(&buffer); |
| 1788 | try w.printIntOptions(value, base, case, options); | 1865 | try w.printInt(value, base, case, options); |
| 1789 | try testing.expectEqualStrings(expected, w.buffered()); | 1866 | try testing.expectEqualStrings(expected, w.buffered()); |
| 1790 | } | 1867 | } |
| 1791 | 1868 |
lib/std/json/dynamic_test.zig+2-2| ... | @@ -254,7 +254,7 @@ test "Value.jsonStringify" { | ... | @@ -254,7 +254,7 @@ test "Value.jsonStringify" { |
| 254 | \\ true, | 254 | \\ true, |
| 255 | \\ 42, | 255 | \\ 42, |
| 256 | \\ 43, | 256 | \\ 43, |
| 257 | \\ 4.2e1, | 257 | \\ 42, |
| 258 | \\ "weeee", | 258 | \\ "weeee", |
| 259 | \\ [ | 259 | \\ [ |
| 260 | \\ 1, | 260 | \\ 1, |
| ... | @@ -266,7 +266,7 @@ test "Value.jsonStringify" { | ... | @@ -266,7 +266,7 @@ test "Value.jsonStringify" { |
| 266 | \\ } | 266 | \\ } |
| 267 | \\] | 267 | \\] |
| 268 | ; | 268 | ; |
| 269 | try testing.expectEqualSlices(u8, expected, fbs.getWritten()); | 269 | try testing.expectEqualStrings(expected, fbs.getWritten()); |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | test "parseFromValue(std.json.Value,...)" { | 272 | test "parseFromValue(std.json.Value,...)" { |
lib/std/json/stringify.zig-1| ... | @@ -469,7 +469,6 @@ pub fn WriteStream( | ... | @@ -469,7 +469,6 @@ pub fn WriteStream( |
| 469 | /// * When option `emit_nonportable_numbers_as_strings` is true, if the value is outside the range `+-1<<53` (the precise integer range of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number. | 469 | /// * When option `emit_nonportable_numbers_as_strings` is true, if the value is outside the range `+-1<<53` (the precise integer range of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number. |
| 470 | /// * Zig floats -> JSON number or string. | 470 | /// * Zig floats -> JSON number or string. |
| 471 | /// * If the value cannot be precisely represented by an f64, it is rendered as a JSON string. Otherwise, it is rendered as JSON number. | 471 | /// * If the value cannot be precisely represented by an f64, it is rendered as a JSON string. Otherwise, it is rendered as JSON number. |
| 472 | /// * TODO: Float rendering will likely change in the future, e.g. to remove the unnecessary "e+00". | ||
| 473 | /// * Zig `[]const u8`, `[]u8`, `*[N]u8`, `@Vector(N, u8)`, and similar -> JSON string. | 472 | /// * Zig `[]const u8`, `[]u8`, `*[N]u8`, `@Vector(N, u8)`, and similar -> JSON string. |
| 474 | /// * See `StringifyOptions.emit_strings_as_arrays`. | 473 | /// * See `StringifyOptions.emit_strings_as_arrays`. |
| 475 | /// * If the content is not valid UTF-8, rendered as an array of numbers instead. | 474 | /// * If the content is not valid UTF-8, rendered as an array of numbers instead. |
lib/std/json/stringify_test.zig+6-6| ... | @@ -74,16 +74,16 @@ fn testBasicWriteStream(w: anytype, slice_stream: anytype) !void { | ... | @@ -74,16 +74,16 @@ fn testBasicWriteStream(w: anytype, slice_stream: anytype) !void { |
| 74 | \\{ | 74 | \\{ |
| 75 | \\ "object": { | 75 | \\ "object": { |
| 76 | \\ "one": 1, | 76 | \\ "one": 1, |
| 77 | \\ "two": 2e0 | 77 | \\ "two": 2 |
| 78 | \\ }, | 78 | \\ }, |
| 79 | \\ "string": "This is a string", | 79 | \\ "string": "This is a string", |
| 80 | \\ "array": [ | 80 | \\ "array": [ |
| 81 | \\ "Another string", | 81 | \\ "Another string", |
| 82 | \\ 1, | 82 | \\ 1, |
| 83 | \\ 3.5e0 | 83 | \\ 3.5 |
| 84 | \\ ], | 84 | \\ ], |
| 85 | \\ "int": 10, | 85 | \\ "int": 10, |
| 86 | \\ "float": 3.5e0 | 86 | \\ "float": 3.5 |
| 87 | \\} | 87 | \\} |
| 88 | ; | 88 | ; |
| 89 | try std.testing.expectEqualStrings(expected, result); | 89 | try std.testing.expectEqualStrings(expected, result); |
| ... | @@ -123,12 +123,12 @@ test "stringify basic types" { | ... | @@ -123,12 +123,12 @@ test "stringify basic types" { |
| 123 | try testStringify("null", @as(?u8, null), .{}); | 123 | try testStringify("null", @as(?u8, null), .{}); |
| 124 | try testStringify("null", @as(?*u32, null), .{}); | 124 | try testStringify("null", @as(?*u32, null), .{}); |
| 125 | try testStringify("42", 42, .{}); | 125 | try testStringify("42", 42, .{}); |
| 126 | try testStringify("4.2e1", 42.0, .{}); | 126 | try testStringify("42", 42.0, .{}); |
| 127 | try testStringify("42", @as(u8, 42), .{}); | 127 | try testStringify("42", @as(u8, 42), .{}); |
| 128 | try testStringify("42", @as(u128, 42), .{}); | 128 | try testStringify("42", @as(u128, 42), .{}); |
| 129 | try testStringify("9999999999999999", 9999999999999999, .{}); | 129 | try testStringify("9999999999999999", 9999999999999999, .{}); |
| 130 | try testStringify("4.2e1", @as(f32, 42), .{}); | 130 | try testStringify("42", @as(f32, 42), .{}); |
| 131 | try testStringify("4.2e1", @as(f64, 42), .{}); | 131 | try testStringify("42", @as(f64, 42), .{}); |
| 132 | try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{}); | 132 | try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{}); |
| 133 | try testStringify("\"ItBroke\"", error.ItBroke, .{}); | 133 | try testStringify("\"ItBroke\"", error.ItBroke, .{}); |
| 134 | } | 134 | } |
lib/std/math/big/int.zig+13-19| ... | @@ -2028,6 +2028,14 @@ pub const Mutable = struct { | ... | @@ -2028,6 +2028,14 @@ pub const Mutable = struct { |
| 2028 | pub fn normalize(r: *Mutable, length: usize) void { | 2028 | pub fn normalize(r: *Mutable, length: usize) void { |
| 2029 | r.len = llnormalize(r.limbs[0..length]); | 2029 | r.len = llnormalize(r.limbs[0..length]); |
| 2030 | } | 2030 | } |
| 2031 | |||
| 2032 | pub fn format(self: Mutable, w: *std.io.Writer) std.io.Writer.Error!void { | ||
| 2033 | return formatInteger(self, w, 10, .lower); | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | pub fn formatInteger(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void { | ||
| 2037 | return self.toConst().formatInteger(w, base, case); | ||
| 2038 | } | ||
| 2031 | }; | 2039 | }; |
| 2032 | 2040 | ||
| 2033 | /// A arbitrary-precision big integer, with a fixed set of immutable limbs. | 2041 | /// A arbitrary-precision big integer, with a fixed set of immutable limbs. |
| ... | @@ -2321,7 +2329,7 @@ pub const Const = struct { | ... | @@ -2321,7 +2329,7 @@ pub const Const = struct { |
| 2321 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. | 2329 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. |
| 2322 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. | 2330 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. |
| 2323 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. | 2331 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. |
| 2324 | pub fn print(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void { | 2332 | pub fn formatInteger(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void { |
| 2325 | const available_len = 64; | 2333 | const available_len = 64; |
| 2326 | if (self.limbs.len > available_len) | 2334 | if (self.limbs.len > available_len) |
| 2327 | return w.writeAll("(BigInt)"); | 2335 | return w.writeAll("(BigInt)"); |
| ... | @@ -2337,20 +2345,6 @@ pub const Const = struct { | ... | @@ -2337,20 +2345,6 @@ pub const Const = struct { |
| 2337 | return w.writeAll(buf[0..len]); | 2345 | return w.writeAll(buf[0..len]); |
| 2338 | } | 2346 | } |
| 2339 | 2347 | ||
| 2340 | const Format = struct { | ||
| 2341 | int: Const, | ||
| 2342 | base: u8, | ||
| 2343 | case: std.fmt.Case, | ||
| 2344 | |||
| 2345 | pub fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void { | ||
| 2346 | return print(f.int, w, f.base, f.case); | ||
| 2347 | } | ||
| 2348 | }; | ||
| 2349 | |||
| 2350 | pub fn fmt(self: Const, base: u8, case: std.fmt.Case) std.fmt.Formatter(Format, Format.default) { | ||
| 2351 | return .{ .data = .{ .int = self, .base = base, .case = case } }; | ||
| 2352 | } | ||
| 2353 | |||
| 2354 | /// Converts self to a string in the requested base. | 2348 | /// Converts self to a string in the requested base. |
| 2355 | /// Caller owns returned memory. | 2349 | /// Caller owns returned memory. |
| 2356 | /// Asserts that `base` is in the range [2, 36]. | 2350 | /// Asserts that `base` is in the range [2, 36]. |
| ... | @@ -2918,16 +2912,16 @@ pub const Managed = struct { | ... | @@ -2918,16 +2912,16 @@ pub const Managed = struct { |
| 2918 | } | 2912 | } |
| 2919 | 2913 | ||
| 2920 | /// To allow `std.fmt.format` to work with `Managed`. | 2914 | /// To allow `std.fmt.format` to work with `Managed`. |
| 2921 | pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { | 2915 | pub fn format(self: Managed, w: *std.io.Writer) std.io.Writer.Error!void { |
| 2922 | return self.toConst().format(w, f); | 2916 | return formatInteger(self, w, 10, .lower); |
| 2923 | } | 2917 | } |
| 2924 | 2918 | ||
| 2925 | /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, | 2919 | /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, |
| 2926 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. | 2920 | /// this function will fail to print the string, printing "(BigInt)" instead of a number. |
| 2927 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. | 2921 | /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. |
| 2928 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. | 2922 | /// See `toString` and `toStringAlloc` for a way to print big integers without failure. |
| 2929 | pub fn fmt(self: Managed, base: u8, case: std.fmt.Case) std.fmt.Formatter(Const.Format, Const.Format.default) { | 2923 | pub fn formatInteger(self: Managed, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void { |
| 2930 | return .{ .data = .{ .int = self.toConst(), .base = base, .case = case } }; | 2924 | return self.toConst().formatInteger(w, base, case); |
| 2931 | } | 2925 | } |
| 2932 | 2926 | ||
| 2933 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| == | 2927 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| == |
lib/std/math/big/int_test.zig+4-4| ... | @@ -3813,8 +3813,8 @@ test "(BigInt) positive" { | ... | @@ -3813,8 +3813,8 @@ test "(BigInt) positive" { |
| 3813 | try a.pow(&a, 64 * @sizeOf(Limb) * 8); | 3813 | try a.pow(&a, 64 * @sizeOf(Limb) * 8); |
| 3814 | try b.sub(&a, &c); | 3814 | try b.sub(&a, &c); |
| 3815 | 3815 | ||
| 3816 | try testing.expectFmt("(BigInt)", "{f}", .{a.fmt(10, .lower)}); | 3816 | try testing.expectFmt("(BigInt)", "{d}", .{a}); |
| 3817 | try testing.expectFmt("1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190335", "{f}", .{b.fmt(10, .lower)}); | 3817 | try testing.expectFmt("1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190335", "{d}", .{b}); |
| 3818 | } | 3818 | } |
| 3819 | 3819 | ||
| 3820 | test "(BigInt) negative" { | 3820 | test "(BigInt) negative" { |
| ... | @@ -3832,10 +3832,10 @@ test "(BigInt) negative" { | ... | @@ -3832,10 +3832,10 @@ test "(BigInt) negative" { |
| 3832 | a.negate(); | 3832 | a.negate(); |
| 3833 | try b.add(&a, &c); | 3833 | try b.add(&a, &c); |
| 3834 | 3834 | ||
| 3835 | const a_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{a.fmt(10, .lower)}); | 3835 | const a_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{a}); |
| 3836 | defer testing.allocator.free(a_fmt); | 3836 | defer testing.allocator.free(a_fmt); |
| 3837 | 3837 | ||
| 3838 | const b_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{b.fmt(10, .lower)}); | 3838 | const b_fmt = try std.fmt.allocPrint(testing.allocator, "{d}", .{b}); |
| 3839 | defer testing.allocator.free(b_fmt); | 3839 | defer testing.allocator.free(b_fmt); |
| 3840 | 3840 | ||
| 3841 | try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); | 3841 | try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); |
lib/std/zig.zig+2-2| ... | @@ -475,7 +475,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo | ... | @@ -475,7 +475,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo |
| 475 | ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte), | 475 | ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte), |
| 476 | else => { | 476 | else => { |
| 477 | try w.writeAll("\\x"); | 477 | try w.writeAll("\\x"); |
| 478 | try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' }); | 478 | try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); |
| 479 | }, | 479 | }, |
| 480 | }; | 480 | }; |
| 481 | } | 481 | } |
| ... | @@ -492,7 +492,7 @@ pub fn charEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void | ... | @@ -492,7 +492,7 @@ pub fn charEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void |
| 492 | ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte), | 492 | ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte), |
| 493 | else => { | 493 | else => { |
| 494 | try w.writeAll("\\x"); | 494 | try w.writeAll("\\x"); |
| 495 | try w.printIntOptions(byte, 16, .lower, .{ .width = 2, .fill = '0' }); | 495 | try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); |
| 496 | }, | 496 | }, |
| 497 | }; | 497 | }; |
| 498 | } | 498 | } |
lib/std/zig/llvm/Builder.zig+166-64| ... | @@ -246,7 +246,7 @@ pub const Type = enum(u32) { | ... | @@ -246,7 +246,7 @@ pub const Type = enum(u32) { |
| 246 | _, | 246 | _, |
| 247 | 247 | ||
| 248 | pub const ptr_amdgpu_constant = | 248 | pub const ptr_amdgpu_constant = |
| 249 | @field(Type, std.fmt.comptimePrint("ptr{f }", .{AddrSpace.amdgpu.constant})); | 249 | @field(Type, std.fmt.comptimePrint("ptr{f}", .{AddrSpace.amdgpu.constant.fmt(" ")})); |
| 250 | 250 | ||
| 251 | pub const Tag = enum(u4) { | 251 | pub const Tag = enum(u4) { |
| 252 | simple, | 252 | simple, |
| ... | @@ -779,7 +779,7 @@ pub const Type = enum(u32) { | ... | @@ -779,7 +779,7 @@ pub const Type = enum(u32) { |
| 779 | } | 779 | } |
| 780 | }, | 780 | }, |
| 781 | .integer => try w.print("i{d}", .{item.data}), | 781 | .integer => try w.print("i{d}", .{item.data}), |
| 782 | .pointer => try w.print("ptr{f }", .{@as(AddrSpace, @enumFromInt(item.data))}), | 782 | .pointer => try w.print("ptr{f}", .{@as(AddrSpace, @enumFromInt(item.data)).fmt(" ")}), |
| 783 | .target => { | 783 | .target => { |
| 784 | var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); | 784 | var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); |
| 785 | const types = extra.trail.next(extra.data.types_len, Type, data.builder); | 785 | const types = extra.trail.next(extra.data.types_len, Type, data.builder); |
| ... | @@ -1242,7 +1242,7 @@ pub const Attribute = union(Kind) { | ... | @@ -1242,7 +1242,7 @@ pub const Attribute = union(Kind) { |
| 1242 | .sret, | 1242 | .sret, |
| 1243 | .elementtype, | 1243 | .elementtype, |
| 1244 | => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }), | 1244 | => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }), |
| 1245 | .@"align" => |alignment| try w.print("{f }", .{alignment}), | 1245 | .@"align" => |alignment| try w.print("{f}", .{alignment.fmt(" ")}), |
| 1246 | .dereferenceable, | 1246 | .dereferenceable, |
| 1247 | .dereferenceable_or_null, | 1247 | .dereferenceable_or_null, |
| 1248 | => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }), | 1248 | => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }), |
| ... | @@ -1853,10 +1853,31 @@ pub const ThreadLocal = enum(u3) { | ... | @@ -1853,10 +1853,31 @@ pub const ThreadLocal = enum(u3) { |
| 1853 | initialexec = 3, | 1853 | initialexec = 3, |
| 1854 | localexec = 4, | 1854 | localexec = 4, |
| 1855 | 1855 | ||
| 1856 | pub fn format(self: ThreadLocal, w: *Writer, comptime prefix: []const u8) Writer.Error!void { | 1856 | pub fn format(tl: ThreadLocal, w: *Writer) Writer.Error!void { |
| 1857 | if (self == .default) return; | 1857 | return Prefixed.format(.{ .thread_local = tl, .prefix = "" }, w); |
| 1858 | try w.print("{s}thread_local", .{prefix}); | 1858 | } |
| 1859 | if (self != .generaldynamic) try w.print("({s})", .{@tagName(self)}); | 1859 | |
| 1860 | pub const Prefixed = struct { | ||
| 1861 | thread_local: ThreadLocal, | ||
| 1862 | prefix: []const u8, | ||
| 1863 | |||
| 1864 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | ||
| 1865 | switch (p.thread_local) { | ||
| 1866 | .default => return, | ||
| 1867 | .generaldynamic => { | ||
| 1868 | var vecs: [2][]const u8 = .{ p.prefix, "thread_local" }; | ||
| 1869 | return w.writeVecAll(&vecs); | ||
| 1870 | }, | ||
| 1871 | else => { | ||
| 1872 | var vecs: [4][]const u8 = .{ p.prefix, "thread_local(", @tagName(p.thread_local), ")" }; | ||
| 1873 | return w.writeVecAll(&vecs); | ||
| 1874 | }, | ||
| 1875 | } | ||
| 1876 | } | ||
| 1877 | }; | ||
| 1878 | |||
| 1879 | pub fn fmt(tl: ThreadLocal, prefix: []const u8) Prefixed { | ||
| 1880 | return .{ .thread_local = tl, .prefix = prefix }; | ||
| 1860 | } | 1881 | } |
| 1861 | }; | 1882 | }; |
| 1862 | 1883 | ||
| ... | @@ -1961,8 +1982,24 @@ pub const AddrSpace = enum(u24) { | ... | @@ -1961,8 +1982,24 @@ pub const AddrSpace = enum(u24) { |
| 1961 | pub const funcref: AddrSpace = @enumFromInt(20); | 1982 | pub const funcref: AddrSpace = @enumFromInt(20); |
| 1962 | }; | 1983 | }; |
| 1963 | 1984 | ||
| 1964 | pub fn format(self: AddrSpace, w: *Writer, comptime prefix: []const u8) Writer.Error!void { | 1985 | pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void { |
| 1965 | if (self != .default) try w.print("{s}addrspace({d})", .{ prefix, @intFromEnum(self) }); | 1986 | return Prefixed.format(.{ .addr_space = addr_space, .prefix = "" }, w); |
| 1987 | } | ||
| 1988 | |||
| 1989 | pub const Prefixed = struct { | ||
| 1990 | addr_space: AddrSpace, | ||
| 1991 | prefix: []const u8, | ||
| 1992 | |||
| 1993 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | ||
| 1994 | switch (p.addr_space) { | ||
| 1995 | .default => return, | ||
| 1996 | else => return w.print("{s}addrspace({d})", .{ p.prefix, p.addr_space }), | ||
| 1997 | } | ||
| 1998 | } | ||
| 1999 | }; | ||
| 2000 | |||
| 2001 | pub fn fmt(addr_space: AddrSpace, prefix: []const u8) Prefixed { | ||
| 2002 | return .{ .addr_space = addr_space, .prefix = prefix }; | ||
| 1966 | } | 2003 | } |
| 1967 | }; | 2004 | }; |
| 1968 | 2005 | ||
| ... | @@ -1994,8 +2031,18 @@ pub const Alignment = enum(u6) { | ... | @@ -1994,8 +2031,18 @@ pub const Alignment = enum(u6) { |
| 1994 | return if (self == .default) 0 else (@intFromEnum(self) + 1); | 2031 | return if (self == .default) 0 else (@intFromEnum(self) + 1); |
| 1995 | } | 2032 | } |
| 1996 | 2033 | ||
| 1997 | pub fn format(self: Alignment, w: *Writer, comptime prefix: []const u8) Writer.Error!void { | 2034 | pub const Prefixed = struct { |
| 1998 | try w.print("{s}align {d}", .{ prefix, self.toByteUnits() orelse return }); | 2035 | alignment: Alignment, |
| 2036 | prefix: []const u8, | ||
| 2037 | |||
| 2038 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | ||
| 2039 | const byte_units = p.alignment.toByteUnits() orelse return; | ||
| 2040 | return w.print("{s}align ({d})", .{ p.prefix, byte_units }); | ||
| 2041 | } | ||
| 2042 | }; | ||
| 2043 | |||
| 2044 | pub fn fmt(alignment: Alignment, prefix: []const u8) Prefixed { | ||
| 2045 | return .{ .alignment = alignment, .prefix = prefix }; | ||
| 1999 | } | 2046 | } |
| 2000 | }; | 2047 | }; |
| 2001 | 2048 | ||
| ... | @@ -6978,8 +7025,27 @@ pub const MemoryAccessKind = enum(u1) { | ... | @@ -6978,8 +7025,27 @@ pub const MemoryAccessKind = enum(u1) { |
| 6978 | normal, | 7025 | normal, |
| 6979 | @"volatile", | 7026 | @"volatile", |
| 6980 | 7027 | ||
| 6981 | pub fn format(self: MemoryAccessKind, w: *Writer, comptime prefix: []const u8) Writer.Error!void { | 7028 | pub fn format(memory_access_kind: MemoryAccessKind, w: *Writer) Writer.Error!void { |
| 6982 | if (self != .normal) try w.print("{s}{s}", .{ prefix, @tagName(self) }); | 7029 | return Prefixed.format(.{ .memory_access_kind = memory_access_kind, .prefix = "" }, w); |
| 7030 | } | ||
| 7031 | |||
| 7032 | pub const Prefixed = struct { | ||
| 7033 | memory_access_kind: MemoryAccessKind, | ||
| 7034 | prefix: []const u8, | ||
| 7035 | |||
| 7036 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | ||
| 7037 | switch (p.memory_access_kind) { | ||
| 7038 | .normal => return, | ||
| 7039 | .@"volatile" => { | ||
| 7040 | var vecs: [2][]const u8 = .{ p.prefix, "volatile" }; | ||
| 7041 | return w.writeVecAll(&vecs); | ||
| 7042 | }, | ||
| 7043 | } | ||
| 7044 | } | ||
| 7045 | }; | ||
| 7046 | |||
| 7047 | pub fn fmt(memory_access_kind: MemoryAccessKind, prefix: []const u8) Prefixed { | ||
| 7048 | return .{ .memory_access_kind = memory_access_kind, .prefix = prefix }; | ||
| 6983 | } | 7049 | } |
| 6984 | }; | 7050 | }; |
| 6985 | 7051 | ||
| ... | @@ -6987,10 +7053,27 @@ pub const SyncScope = enum(u1) { | ... | @@ -6987,10 +7053,27 @@ pub const SyncScope = enum(u1) { |
| 6987 | singlethread, | 7053 | singlethread, |
| 6988 | system, | 7054 | system, |
| 6989 | 7055 | ||
| 6990 | pub fn format(self: SyncScope, w: *Writer, comptime prefix: []const u8) Writer.Error!void { | 7056 | pub fn format(sync_scope: SyncScope, w: *Writer) Writer.Error!void { |
| 6991 | if (self != .system) try w.print( | 7057 | return Prefixed.format(.{ .sync_scope = sync_scope, .prefix = "" }, w); |
| 6992 | \\{s}syncscope("{s}") | 7058 | } |
| 6993 | , .{ prefix, @tagName(self) }); | 7059 | |
| 7060 | pub const Prefixed = struct { | ||
| 7061 | sync_scope: SyncScope, | ||
| 7062 | prefix: []const u8, | ||
| 7063 | |||
| 7064 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | ||
| 7065 | switch (p.sync_scope) { | ||
| 7066 | .system => return, | ||
| 7067 | .singlethread => { | ||
| 7068 | var vecs: [2][]const u8 = .{ p.prefix, "syncscope(\"singlethread\")" }; | ||
| 7069 | return w.writeVecAll(&vecs); | ||
| 7070 | }, | ||
| 7071 | } | ||
| 7072 | } | ||
| 7073 | }; | ||
| 7074 | |||
| 7075 | pub fn fmt(sync_scope: SyncScope, prefix: []const u8) Prefixed { | ||
| 7076 | return .{ .sync_scope = sync_scope, .prefix = prefix }; | ||
| 6994 | } | 7077 | } |
| 6995 | }; | 7078 | }; |
| 6996 | 7079 | ||
| ... | @@ -7003,8 +7086,27 @@ pub const AtomicOrdering = enum(u3) { | ... | @@ -7003,8 +7086,27 @@ pub const AtomicOrdering = enum(u3) { |
| 7003 | acq_rel = 5, | 7086 | acq_rel = 5, |
| 7004 | seq_cst = 6, | 7087 | seq_cst = 6, |
| 7005 | 7088 | ||
| 7006 | pub fn format(self: AtomicOrdering, w: *Writer, comptime prefix: []const u8) Writer.Error!void { | 7089 | pub fn format(atomic_ordering: AtomicOrdering, w: *Writer) Writer.Error!void { |
| 7007 | if (self != .none) try w.print("{s}{s}", .{ prefix, @tagName(self) }); | 7090 | return Prefixed.format(.{ .atomic_ordering = atomic_ordering, .prefix = "" }, w); |
| 7091 | } | ||
| 7092 | |||
| 7093 | pub const Prefixed = struct { | ||
| 7094 | atomic_ordering: AtomicOrdering, | ||
| 7095 | prefix: []const u8, | ||
| 7096 | |||
| 7097 | pub fn format(p: Prefixed, w: *Writer) Writer.Error!void { | ||
| 7098 | switch (p.atomic_ordering) { | ||
| 7099 | .none => return, | ||
| 7100 | else => { | ||
| 7101 | var vecs: [2][]const u8 = .{ p.prefix, @tagName(p.atomic_ordering) }; | ||
| 7102 | return w.writeVecAll(&vecs); | ||
| 7103 | }, | ||
| 7104 | } | ||
| 7105 | } | ||
| 7106 | }; | ||
| 7107 | |||
| 7108 | pub fn fmt(atomic_ordering: AtomicOrdering, prefix: []const u8) Prefixed { | ||
| 7109 | return .{ .atomic_ordering = atomic_ordering, .prefix = prefix }; | ||
| 7008 | } | 7110 | } |
| 7009 | }; | 7111 | }; |
| 7010 | 7112 | ||
| ... | @@ -8550,7 +8652,7 @@ pub fn init(options: Options) Allocator.Error!Builder { | ... | @@ -8550,7 +8652,7 @@ pub fn init(options: Options) Allocator.Error!Builder { |
| 8550 | inline for (.{ 0, 4 }) |addr_space_index| { | 8652 | inline for (.{ 0, 4 }) |addr_space_index| { |
| 8551 | const addr_space: AddrSpace = @enumFromInt(addr_space_index); | 8653 | const addr_space: AddrSpace = @enumFromInt(addr_space_index); |
| 8552 | assert(self.ptrTypeAssumeCapacity(addr_space) == | 8654 | assert(self.ptrTypeAssumeCapacity(addr_space) == |
| 8553 | @field(Type, std.fmt.comptimePrint("ptr{f }", .{addr_space}))); | 8655 | @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")}))); |
| 8554 | } | 8656 | } |
| 8555 | } | 8657 | } |
| 8556 | 8658 | ||
| ... | @@ -9469,7 +9571,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9469,7 +9571,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9469 | metadata_formatter.need_comma = true; | 9571 | metadata_formatter.need_comma = true; |
| 9470 | defer metadata_formatter.need_comma = undefined; | 9572 | defer metadata_formatter.need_comma = undefined; |
| 9471 | try w.print( | 9573 | try w.print( |
| 9472 | \\{f} ={f}{f}{f}{f}{f }{f}{f }{f} {s} {f}{f}{f, }{f} | 9574 | \\{f} ={f}{f}{f}{f}{f}{f}{f}{f} {s} {f}{f}{f}{f} |
| 9473 | \\ | 9575 | \\ |
| 9474 | , .{ | 9576 | , .{ |
| 9475 | variable.global.fmt(self), | 9577 | variable.global.fmt(self), |
| ... | @@ -9479,14 +9581,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9479,14 +9581,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9479 | global.preemption, | 9581 | global.preemption, |
| 9480 | global.visibility, | 9582 | global.visibility, |
| 9481 | global.dll_storage_class, | 9583 | global.dll_storage_class, |
| 9482 | variable.thread_local, | 9584 | variable.thread_local.fmt(" "), |
| 9483 | global.unnamed_addr, | 9585 | global.unnamed_addr, |
| 9484 | global.addr_space, | 9586 | global.addr_space.fmt(" "), |
| 9485 | global.externally_initialized, | 9587 | global.externally_initialized, |
| 9486 | @tagName(variable.mutability), | 9588 | @tagName(variable.mutability), |
| 9487 | global.type.fmt(self, .percent), | 9589 | global.type.fmt(self, .percent), |
| 9488 | variable.init.fmt(self, .{ .space = true }), | 9590 | variable.init.fmt(self, .{ .space = true }), |
| 9489 | variable.alignment, | 9591 | variable.alignment.fmt(", "), |
| 9490 | try metadata_formatter.fmt("!dbg ", global.dbg, null), | 9592 | try metadata_formatter.fmt("!dbg ", global.dbg, null), |
| 9491 | }); | 9593 | }); |
| 9492 | } | 9594 | } |
| ... | @@ -9500,7 +9602,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9500,7 +9602,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9500 | metadata_formatter.need_comma = true; | 9602 | metadata_formatter.need_comma = true; |
| 9501 | defer metadata_formatter.need_comma = undefined; | 9603 | defer metadata_formatter.need_comma = undefined; |
| 9502 | try w.print( | 9604 | try w.print( |
| 9503 | \\{f} ={f}{f}{f}{f}{f }{f} alias {f}, {f}{f} | 9605 | \\{f} ={f}{f}{f}{f}{f}{f} alias {f}, {f}{f} |
| 9504 | \\ | 9606 | \\ |
| 9505 | , .{ | 9607 | , .{ |
| 9506 | alias.global.fmt(self), | 9608 | alias.global.fmt(self), |
| ... | @@ -9508,7 +9610,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9508,7 +9610,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9508 | global.preemption, | 9610 | global.preemption, |
| 9509 | global.visibility, | 9611 | global.visibility, |
| 9510 | global.dll_storage_class, | 9612 | global.dll_storage_class, |
| 9511 | alias.thread_local, | 9613 | alias.thread_local.fmt(" "), |
| 9512 | global.unnamed_addr, | 9614 | global.unnamed_addr, |
| 9513 | global.type.fmt(self, .percent), | 9615 | global.type.fmt(self, .percent), |
| 9514 | alias.aliasee.fmt(self, .{ .percent = true }), | 9616 | alias.aliasee.fmt(self, .{ .percent = true }), |
| ... | @@ -9564,15 +9666,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9564,15 +9666,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9564 | try w.writeAll("..."); | 9666 | try w.writeAll("..."); |
| 9565 | }, | 9667 | }, |
| 9566 | } | 9668 | } |
| 9567 | try w.print("){f}{f }", .{ global.unnamed_addr, global.addr_space }); | 9669 | try w.print("){f}{f}", .{ global.unnamed_addr, global.addr_space.fmt(" ") }); |
| 9568 | if (function_attributes != .none) try w.print(" #{d}", .{ | 9670 | if (function_attributes != .none) try w.print(" #{d}", .{ |
| 9569 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, | 9671 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, |
| 9570 | }); | 9672 | }); |
| 9571 | { | 9673 | { |
| 9572 | metadata_formatter.need_comma = false; | 9674 | metadata_formatter.need_comma = false; |
| 9573 | defer metadata_formatter.need_comma = undefined; | 9675 | defer metadata_formatter.need_comma = undefined; |
| 9574 | try w.print("{f }{f}", .{ | 9676 | try w.print("{f}{f}", .{ |
| 9575 | function.alignment, | 9677 | function.alignment.fmt(" "), |
| 9576 | try metadata_formatter.fmt(" !dbg ", global.dbg, null), | 9678 | try metadata_formatter.fmt(" !dbg ", global.dbg, null), |
| 9577 | }); | 9679 | }); |
| 9578 | } | 9680 | } |
| ... | @@ -9709,7 +9811,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9709,7 +9811,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9709 | .@"alloca inalloca", | 9811 | .@"alloca inalloca", |
| 9710 | => |tag| { | 9812 | => |tag| { |
| 9711 | const extra = function.extraData(Function.Instruction.Alloca, instruction.data); | 9813 | const extra = function.extraData(Function.Instruction.Alloca, instruction.data); |
| 9712 | try w.print(" %{f} = {s} {f}{f}{f, }{f, }", .{ | 9814 | try w.print(" %{f} = {s} {f}{f}{f}{f}", .{ |
| 9713 | instruction_index.name(&function).fmt(self), | 9815 | instruction_index.name(&function).fmt(self), |
| 9714 | @tagName(tag), | 9816 | @tagName(tag), |
| 9715 | extra.type.fmt(self, .percent), | 9817 | extra.type.fmt(self, .percent), |
| ... | @@ -9720,24 +9822,24 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9720,24 +9822,24 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9720 | .comma = true, | 9822 | .comma = true, |
| 9721 | .percent = true, | 9823 | .percent = true, |
| 9722 | }), | 9824 | }), |
| 9723 | extra.info.alignment, | 9825 | extra.info.alignment.fmt(", "), |
| 9724 | extra.info.addr_space, | 9826 | extra.info.addr_space.fmt(", "), |
| 9725 | }); | 9827 | }); |
| 9726 | }, | 9828 | }, |
| 9727 | .arg => unreachable, | 9829 | .arg => unreachable, |
| 9728 | .atomicrmw => |tag| { | 9830 | .atomicrmw => |tag| { |
| 9729 | const extra = | 9831 | const extra = |
| 9730 | function.extraData(Function.Instruction.AtomicRmw, instruction.data); | 9832 | function.extraData(Function.Instruction.AtomicRmw, instruction.data); |
| 9731 | try w.print(" %{f} = {s}{f } {s} {f}, {f}{f }{f }{f, }", .{ | 9833 | try w.print(" %{f} = {t}{f} {t} {f}, {f}{f}{f}{f}", .{ |
| 9732 | instruction_index.name(&function).fmt(self), | 9834 | instruction_index.name(&function).fmt(self), |
| 9733 | @tagName(tag), | 9835 | tag, |
| 9734 | extra.info.access_kind, | 9836 | extra.info.access_kind.fmt(" "), |
| 9735 | @tagName(extra.info.atomic_rmw_operation), | 9837 | extra.info.atomic_rmw_operation, |
| 9736 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 9838 | extra.ptr.fmt(function_index, self, .{ .percent = true }), |
| 9737 | extra.val.fmt(function_index, self, .{ .percent = true }), | 9839 | extra.val.fmt(function_index, self, .{ .percent = true }), |
| 9738 | extra.info.sync_scope, | 9840 | extra.info.sync_scope.fmt(" "), |
| 9739 | extra.info.success_ordering, | 9841 | extra.info.success_ordering.fmt(" "), |
| 9740 | extra.info.alignment, | 9842 | extra.info.alignment.fmt(", "), |
| 9741 | }); | 9843 | }); |
| 9742 | }, | 9844 | }, |
| 9743 | .block => { | 9845 | .block => { |
| ... | @@ -9792,8 +9894,8 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9792,8 +9894,8 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9792 | }), | 9894 | }), |
| 9793 | .none => unreachable, | 9895 | .none => unreachable, |
| 9794 | } | 9896 | } |
| 9795 | try w.print("{s}{f}{f}{f} {f} {f}(", .{ | 9897 | try w.print("{t}{f}{f}{f} {f} {f}(", .{ |
| 9796 | @tagName(tag), | 9898 | tag, |
| 9797 | extra.data.info.call_conv, | 9899 | extra.data.info.call_conv, |
| 9798 | extra.data.attributes.ret(self).fmt(self, .{}), | 9900 | extra.data.attributes.ret(self).fmt(self, .{}), |
| 9799 | extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), | 9901 | extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), |
| ... | @@ -9831,17 +9933,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9831,17 +9933,17 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9831 | => |tag| { | 9933 | => |tag| { |
| 9832 | const extra = | 9934 | const extra = |
| 9833 | function.extraData(Function.Instruction.CmpXchg, instruction.data); | 9935 | function.extraData(Function.Instruction.CmpXchg, instruction.data); |
| 9834 | try w.print(" %{f} = {s}{f } {f}, {f}, {f}{f }{f }{f }{f, }", .{ | 9936 | try w.print(" %{f} = {t}{f} {f}, {f}, {f}{f}{f}{f}{f}", .{ |
| 9835 | instruction_index.name(&function).fmt(self), | 9937 | instruction_index.name(&function).fmt(self), |
| 9836 | @tagName(tag), | 9938 | tag, |
| 9837 | extra.info.access_kind, | 9939 | extra.info.access_kind.fmt(" "), |
| 9838 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 9940 | extra.ptr.fmt(function_index, self, .{ .percent = true }), |
| 9839 | extra.cmp.fmt(function_index, self, .{ .percent = true }), | 9941 | extra.cmp.fmt(function_index, self, .{ .percent = true }), |
| 9840 | extra.new.fmt(function_index, self, .{ .percent = true }), | 9942 | extra.new.fmt(function_index, self, .{ .percent = true }), |
| 9841 | extra.info.sync_scope, | 9943 | extra.info.sync_scope.fmt(" "), |
| 9842 | extra.info.success_ordering, | 9944 | extra.info.success_ordering.fmt(" "), |
| 9843 | extra.info.failure_ordering, | 9945 | extra.info.failure_ordering.fmt(" "), |
| 9844 | extra.info.alignment, | 9946 | extra.info.alignment.fmt(", "), |
| 9845 | }); | 9947 | }); |
| 9846 | }, | 9948 | }, |
| 9847 | .extractelement => |tag| { | 9949 | .extractelement => |tag| { |
| ... | @@ -9869,10 +9971,10 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9869,10 +9971,10 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9869 | }, | 9971 | }, |
| 9870 | .fence => |tag| { | 9972 | .fence => |tag| { |
| 9871 | const info: MemoryAccessInfo = @bitCast(instruction.data); | 9973 | const info: MemoryAccessInfo = @bitCast(instruction.data); |
| 9872 | try w.print(" {s}{f }{f }", .{ | 9974 | try w.print(" {t}{f}{f}", .{ |
| 9873 | @tagName(tag), | 9975 | tag, |
| 9874 | info.sync_scope, | 9976 | info.sync_scope.fmt(" "), |
| 9875 | info.success_ordering, | 9977 | info.success_ordering.fmt(" "), |
| 9876 | }); | 9978 | }); |
| 9877 | }, | 9979 | }, |
| 9878 | .fneg, | 9980 | .fneg, |
| ... | @@ -9947,15 +10049,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -9947,15 +10049,15 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 9947 | .@"load atomic", | 10049 | .@"load atomic", |
| 9948 | => |tag| { | 10050 | => |tag| { |
| 9949 | const extra = function.extraData(Function.Instruction.Load, instruction.data); | 10051 | const extra = function.extraData(Function.Instruction.Load, instruction.data); |
| 9950 | try w.print(" %{f} = {s}{f } {f}, {f}{f }{f }{f, }", .{ | 10052 | try w.print(" %{f} = {t}{f} {f}, {f}{f}{f}{f}", .{ |
| 9951 | instruction_index.name(&function).fmt(self), | 10053 | instruction_index.name(&function).fmt(self), |
| 9952 | @tagName(tag), | 10054 | tag, |
| 9953 | extra.info.access_kind, | 10055 | extra.info.access_kind.fmt(" "), |
| 9954 | extra.type.fmt(self, .percent), | 10056 | extra.type.fmt(self, .percent), |
| 9955 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 10057 | extra.ptr.fmt(function_index, self, .{ .percent = true }), |
| 9956 | extra.info.sync_scope, | 10058 | extra.info.sync_scope.fmt(" "), |
| 9957 | extra.info.success_ordering, | 10059 | extra.info.success_ordering.fmt(" "), |
| 9958 | extra.info.alignment, | 10060 | extra.info.alignment.fmt(", "), |
| 9959 | }); | 10061 | }); |
| 9960 | }, | 10062 | }, |
| 9961 | .phi, | 10063 | .phi, |
| ... | @@ -10015,14 +10117,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void | ... | @@ -10015,14 +10117,14 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10015 | .@"store atomic", | 10117 | .@"store atomic", |
| 10016 | => |tag| { | 10118 | => |tag| { |
| 10017 | const extra = function.extraData(Function.Instruction.Store, instruction.data); | 10119 | const extra = function.extraData(Function.Instruction.Store, instruction.data); |
| 10018 | try w.print(" {s}{f } {f}, {f}{f }{f }{f, }", .{ | 10120 | try w.print(" {t}{f} {f}, {f}{f}{f}{f}", .{ |
| 10019 | @tagName(tag), | 10121 | tag, |
| 10020 | extra.info.access_kind, | 10122 | extra.info.access_kind.fmt(" "), |
| 10021 | extra.val.fmt(function_index, self, .{ .percent = true }), | 10123 | extra.val.fmt(function_index, self, .{ .percent = true }), |
| 10022 | extra.ptr.fmt(function_index, self, .{ .percent = true }), | 10124 | extra.ptr.fmt(function_index, self, .{ .percent = true }), |
| 10023 | extra.info.sync_scope, | 10125 | extra.info.sync_scope.fmt(" "), |
| 10024 | extra.info.success_ordering, | 10126 | extra.info.success_ordering.fmt(" "), |
| 10025 | extra.info.alignment, | 10127 | extra.info.alignment.fmt(", "), |
| 10026 | }); | 10128 | }); |
| 10027 | }, | 10129 | }, |
| 10028 | .@"switch" => |tag| { | 10130 | .@"switch" => |tag| { |
lib/std/zon/stringify.zig+1-1| ... | @@ -615,7 +615,7 @@ pub fn Serializer(Writer: type) type { | ... | @@ -615,7 +615,7 @@ pub fn Serializer(Writer: type) type { |
| 615 | 615 | ||
| 616 | /// Serialize an integer. | 616 | /// Serialize an integer. |
| 617 | pub fn int(self: *Self, val: anytype) Writer.Error!void { | 617 | pub fn int(self: *Self, val: anytype) Writer.Error!void { |
| 618 | //try self.writer.printIntOptions(val, 10, .lower, .{}); | 618 | //try self.writer.printInt(val, 10, .lower, .{}); |
| 619 | try std.fmt.deprecatedFormat(self.writer, "{d}", .{val}); | 619 | try std.fmt.deprecatedFormat(self.writer, "{d}", .{val}); |
| 620 | } | 620 | } |
| 621 | 621 |
src/Builtin.zig+2-2| ... | @@ -200,8 +200,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { | ... | @@ -200,8 +200,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 200 | }), | 200 | }), |
| 201 | .windows => |windows| try buffer.print( | 201 | .windows => |windows| try buffer.print( |
| 202 | \\ .windows = .{{ | 202 | \\ .windows = .{{ |
| 203 | \\ .min = {fc}, | 203 | \\ .min = {f}, |
| 204 | \\ .max = {fc}, | 204 | \\ .max = {f}, |
| 205 | \\ }}}}, | 205 | \\ }}}}, |
| 206 | \\ | 206 | \\ |
| 207 | , .{ windows.min, windows.max }), | 207 | , .{ windows.min, windows.max }), |
src/Package/Fetch.zig+6-3| ... | @@ -227,9 +227,9 @@ pub const JobQueue = struct { | ... | @@ -227,9 +227,9 @@ pub const JobQueue = struct { |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | try buf.writer().print( | 229 | try buf.writer().print( |
| 230 | \\ pub const build_root = "{fq}"; | 230 | \\ pub const build_root = "{f}"; |
| 231 | \\ | 231 | \\ |
| 232 | , .{fetch.package_root}); | 232 | , .{std.fmt.alt(fetch.package_root, .formatEscapeString)}); |
| 233 | 233 | ||
| 234 | if (fetch.has_build_zig) { | 234 | if (fetch.has_build_zig) { |
| 235 | try buf.writer().print( | 235 | try buf.writer().print( |
| ... | @@ -1079,7 +1079,10 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re | ... | @@ -1079,7 +1079,10 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re |
| 1079 | }); | 1079 | }); |
| 1080 | const notes_start = try eb.reserveNotes(notes_len); | 1080 | const notes_start = try eb.reserveNotes(notes_len); |
| 1081 | eb.extra.items[notes_start] = @intFromEnum(try eb.addErrorMessage(.{ | 1081 | eb.extra.items[notes_start] = @intFromEnum(try eb.addErrorMessage(.{ |
| 1082 | .msg = try eb.printString("try .url = \"{f;+/}#{f}\",", .{ uri, want_oid }), | 1082 | .msg = try eb.printString("try .url = \"{f}#{f}\",", .{ |
| 1083 | uri.fmt(.{ .scheme = true, .authority = true, .path = true }), | ||
| 1084 | want_oid, | ||
| 1085 | }), | ||
| 1083 | })); | 1086 | })); |
| 1084 | return error.FetchFailed; | 1087 | return error.FetchFailed; |
| 1085 | } | 1088 | } |
src/Package/Fetch/git.zig+24-8| ... | @@ -662,13 +662,21 @@ pub const Session = struct { | ... | @@ -662,13 +662,21 @@ pub const Session = struct { |
| 662 | fn init(allocator: Allocator, uri: std.Uri) !Location { | 662 | fn init(allocator: Allocator, uri: std.Uri) !Location { |
| 663 | const scheme = try allocator.dupe(u8, uri.scheme); | 663 | const scheme = try allocator.dupe(u8, uri.scheme); |
| 664 | errdefer allocator.free(scheme); | 664 | errdefer allocator.free(scheme); |
| 665 | const user = if (uri.user) |user| try std.fmt.allocPrint(allocator, "{fuser}", .{user}) else null; | 665 | const user = if (uri.user) |user| try std.fmt.allocPrint(allocator, "{f}", .{ |
| 666 | std.fmt.alt(user, .formatUser), | ||
| 667 | }) else null; | ||
| 666 | errdefer if (user) |s| allocator.free(s); | 668 | errdefer if (user) |s| allocator.free(s); |
| 667 | const password = if (uri.password) |password| try std.fmt.allocPrint(allocator, "{fpassword}", .{password}) else null; | 669 | const password = if (uri.password) |password| try std.fmt.allocPrint(allocator, "{f}", .{ |
| 670 | std.fmt.alt(password, .formatPassword), | ||
| 671 | }) else null; | ||
| 668 | errdefer if (password) |s| allocator.free(s); | 672 | errdefer if (password) |s| allocator.free(s); |
| 669 | const host = if (uri.host) |host| try std.fmt.allocPrint(allocator, "{fhost}", .{host}) else null; | 673 | const host = if (uri.host) |host| try std.fmt.allocPrint(allocator, "{f}", .{ |
| 674 | std.fmt.alt(host, .formatHost), | ||
| 675 | }) else null; | ||
| 670 | errdefer if (host) |s| allocator.free(s); | 676 | errdefer if (host) |s| allocator.free(s); |
| 671 | const path = try std.fmt.allocPrint(allocator, "{fpath}", .{uri.path}); | 677 | const path = try std.fmt.allocPrint(allocator, "{f}", .{ |
| 678 | std.fmt.alt(uri.path, .formatPath), | ||
| 679 | }); | ||
| 672 | errdefer allocator.free(path); | 680 | errdefer allocator.free(path); |
| 673 | // The query and fragment are not used as part of the base server URI. | 681 | // The query and fragment are not used as part of the base server URI. |
| 674 | return .{ | 682 | return .{ |
| ... | @@ -699,7 +707,9 @@ pub const Session = struct { | ... | @@ -699,7 +707,9 @@ pub const Session = struct { |
| 699 | fn getCapabilities(session: *Session, http_headers_buffer: []u8) !CapabilityIterator { | 707 | fn getCapabilities(session: *Session, http_headers_buffer: []u8) !CapabilityIterator { |
| 700 | var info_refs_uri = session.location.uri; | 708 | var info_refs_uri = session.location.uri; |
| 701 | { | 709 | { |
| 702 | const session_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{session.location.uri.path}); | 710 | const session_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{ |
| 711 | std.fmt.alt(session.location.uri.path, .formatPath), | ||
| 712 | }); | ||
| 703 | defer session.allocator.free(session_uri_path); | 713 | defer session.allocator.free(session_uri_path); |
| 704 | info_refs_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "info/refs" }) }; | 714 | info_refs_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "info/refs" }) }; |
| 705 | } | 715 | } |
| ... | @@ -723,7 +733,9 @@ pub const Session = struct { | ... | @@ -723,7 +733,9 @@ pub const Session = struct { |
| 723 | if (request.response.status != .ok) return error.ProtocolError; | 733 | if (request.response.status != .ok) return error.ProtocolError; |
| 724 | const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects; | 734 | const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects; |
| 725 | if (any_redirects_occurred) { | 735 | if (any_redirects_occurred) { |
| 726 | const request_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{request.uri.path}); | 736 | const request_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{ |
| 737 | std.fmt.alt(request.uri.path, .formatPath), | ||
| 738 | }); | ||
| 727 | defer session.allocator.free(request_uri_path); | 739 | defer session.allocator.free(request_uri_path); |
| 728 | if (!mem.endsWith(u8, request_uri_path, "/info/refs")) return error.UnparseableRedirect; | 740 | if (!mem.endsWith(u8, request_uri_path, "/info/refs")) return error.UnparseableRedirect; |
| 729 | var new_uri = request.uri; | 741 | var new_uri = request.uri; |
| ... | @@ -810,7 +822,9 @@ pub const Session = struct { | ... | @@ -810,7 +822,9 @@ pub const Session = struct { |
| 810 | pub fn listRefs(session: Session, options: ListRefsOptions) !RefIterator { | 822 | pub fn listRefs(session: Session, options: ListRefsOptions) !RefIterator { |
| 811 | var upload_pack_uri = session.location.uri; | 823 | var upload_pack_uri = session.location.uri; |
| 812 | { | 824 | { |
| 813 | const session_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{session.location.uri.path}); | 825 | const session_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{ |
| 826 | std.fmt.alt(session.location.uri.path, .formatPath), | ||
| 827 | }); | ||
| 814 | defer session.allocator.free(session_uri_path); | 828 | defer session.allocator.free(session_uri_path); |
| 815 | upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) }; | 829 | upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) }; |
| 816 | } | 830 | } |
| ... | @@ -925,7 +939,9 @@ pub const Session = struct { | ... | @@ -925,7 +939,9 @@ pub const Session = struct { |
| 925 | ) !FetchStream { | 939 | ) !FetchStream { |
| 926 | var upload_pack_uri = session.location.uri; | 940 | var upload_pack_uri = session.location.uri; |
| 927 | { | 941 | { |
| 928 | const session_uri_path = try std.fmt.allocPrint(session.allocator, "{fpath}", .{session.location.uri.path}); | 942 | const session_uri_path = try std.fmt.allocPrint(session.allocator, "{f}", .{ |
| 943 | std.fmt.alt(session.location.uri.path, .formatPath), | ||
| 944 | }); | ||
| 929 | defer session.allocator.free(session_uri_path); | 945 | defer session.allocator.free(session_uri_path); |
| 930 | upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) }; | 946 | upload_pack_uri.path = .{ .percent_encoded = try std.fs.path.resolvePosix(session.allocator, &.{ "/", session_uri_path, "git-upload-pack" }) }; |
| 931 | } | 947 | } |
src/Sema/LowerZon.zig+1-1| ... | @@ -492,7 +492,7 @@ fn lowerInt( | ... | @@ -492,7 +492,7 @@ fn lowerInt( |
| 492 | if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) { | 492 | if (!val.fitsInTwosComp(int_info.signedness, int_info.bits)) { |
| 493 | return self.fail( | 493 | return self.fail( |
| 494 | node, | 494 | node, |
| 495 | "type '{f}' cannot represent integer value '{f}'", | 495 | "type '{f}' cannot represent integer value '{d}'", |
| 496 | .{ res_ty.fmt(self.sema.pt), val }, | 496 | .{ res_ty.fmt(self.sema.pt), val }, |
| 497 | ); | 497 | ); |
| 498 | } | 498 | } |
src/arch/riscv64/CodeGen.zig+2-2| ... | @@ -1151,7 +1151,7 @@ fn gen(func: *Func) !void { | ... | @@ -1151,7 +1151,7 @@ fn gen(func: *Func) !void { |
| 1151 | func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off), | 1151 | func.ret_mcv.long.address().offset(-func.ret_mcv.short.indirect.off), |
| 1152 | ); | 1152 | ); |
| 1153 | func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; | 1153 | func.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; |
| 1154 | tracking_log.debug("spill {} to {f}", .{ func.ret_mcv.long, frame_index }); | 1154 | tracking_log.debug("spill {} to {}", .{ func.ret_mcv.long, frame_index }); |
| 1155 | }, | 1155 | }, |
| 1156 | else => unreachable, | 1156 | else => unreachable, |
| 1157 | } | 1157 | } |
| ... | @@ -1987,7 +1987,7 @@ fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex { | ... | @@ -1987,7 +1987,7 @@ fn allocFrameIndex(func: *Func, alloc: FrameAlloc) !FrameIndex { |
| 1987 | } | 1987 | } |
| 1988 | const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len); | 1988 | const frame_index: FrameIndex = @enumFromInt(func.frame_allocs.len); |
| 1989 | try func.frame_allocs.append(func.gpa, alloc); | 1989 | try func.frame_allocs.append(func.gpa, alloc); |
| 1990 | log.debug("allocated frame {f}", .{frame_index}); | 1990 | log.debug("allocated frame {}", .{frame_index}); |
| 1991 | return frame_index; | 1991 | return frame_index; |
| 1992 | } | 1992 | } |
| 1993 | 1993 |
src/arch/riscv64/bits.zig+6| ... | @@ -249,6 +249,12 @@ pub const FrameIndex = enum(u32) { | ... | @@ -249,6 +249,12 @@ pub const FrameIndex = enum(u32) { |
| 249 | spill_frame, | 249 | spill_frame, |
| 250 | /// Other indices are used for local variable stack slots | 250 | /// Other indices are used for local variable stack slots |
| 251 | _, | 251 | _, |
| 252 | |||
| 253 | pub const named_count = @typeInfo(FrameIndex).@"enum".fields.len; | ||
| 254 | |||
| 255 | pub fn isNamed(fi: FrameIndex) bool { | ||
| 256 | return @intFromEnum(fi) < named_count; | ||
| 257 | } | ||
| 252 | }; | 258 | }; |
| 253 | 259 | ||
| 254 | /// A linker symbol not yet allocated in VM. | 260 | /// A linker symbol not yet allocated in VM. |
src/arch/x86_64/CodeGen.zig+27-27| ... | @@ -525,47 +525,47 @@ pub const MCValue = union(enum) { | ... | @@ -525,47 +525,47 @@ pub const MCValue = union(enum) { |
| 525 | }; | 525 | }; |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | pub fn format(mcv: MCValue, bw: *Writer) Writer.Error!void { | 528 | pub fn format(mcv: MCValue, w: *Writer) Writer.Error!void { |
| 529 | switch (mcv) { | 529 | switch (mcv) { |
| 530 | .none, .unreach, .dead, .undef => try bw.print("({s})", .{@tagName(mcv)}), | 530 | .none, .unreach, .dead, .undef => try w.print("({s})", .{@tagName(mcv)}), |
| 531 | .immediate => |pl| try bw.print("0x{x}", .{pl}), | 531 | .immediate => |pl| try w.print("0x{x}", .{pl}), |
| 532 | .memory => |pl| try bw.print("[ds:0x{x}]", .{pl}), | 532 | .memory => |pl| try w.print("[ds:0x{x}]", .{pl}), |
| 533 | inline .eflags, .register => |pl| try bw.print("{s}", .{@tagName(pl)}), | 533 | inline .eflags, .register => |pl| try w.print("{s}", .{@tagName(pl)}), |
| 534 | .register_pair => |pl| try bw.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }), | 534 | .register_pair => |pl| try w.print("{s}:{s}", .{ @tagName(pl[1]), @tagName(pl[0]) }), |
| 535 | .register_triple => |pl| try bw.print("{s}:{s}:{s}", .{ | 535 | .register_triple => |pl| try w.print("{s}:{s}:{s}", .{ |
| 536 | @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]), | 536 | @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]), |
| 537 | }), | 537 | }), |
| 538 | .register_quadruple => |pl| try bw.print("{s}:{s}:{s}:{s}", .{ | 538 | .register_quadruple => |pl| try w.print("{s}:{s}:{s}:{s}", .{ |
| 539 | @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]), | 539 | @tagName(pl[3]), @tagName(pl[2]), @tagName(pl[1]), @tagName(pl[0]), |
| 540 | }), | 540 | }), |
| 541 | .register_offset => |pl| try bw.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }), | 541 | .register_offset => |pl| try w.print("{s} + 0x{x}", .{ @tagName(pl.reg), pl.off }), |
| 542 | .register_overflow => |pl| try bw.print("{s}:{s}", .{ | 542 | .register_overflow => |pl| try w.print("{s}:{s}", .{ |
| 543 | @tagName(pl.eflags), | 543 | @tagName(pl.eflags), |
| 544 | @tagName(pl.reg), | 544 | @tagName(pl.reg), |
| 545 | }), | 545 | }), |
| 546 | .register_mask => |pl| try bw.print("mask({s},{f}):{c}{s}", .{ | 546 | .register_mask => |pl| try w.print("mask({s},{f}):{c}{s}", .{ |
| 547 | @tagName(pl.info.kind), | 547 | @tagName(pl.info.kind), |
| 548 | pl.info.scalar, | 548 | pl.info.scalar, |
| 549 | @as(u8, if (pl.info.inverted) '!' else ' '), | 549 | @as(u8, if (pl.info.inverted) '!' else ' '), |
| 550 | @tagName(pl.reg), | 550 | @tagName(pl.reg), |
| 551 | }), | 551 | }), |
| 552 | .indirect => |pl| try bw.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), | 552 | .indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), |
| 553 | .indirect_load_frame => |pl| try bw.print("[[{f} + 0x{x}]]", .{ pl.index, pl.off }), | 553 | .indirect_load_frame => |pl| try w.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }), |
| 554 | .load_frame => |pl| try bw.print("[{f} + 0x{x}]", .{ pl.index, pl.off }), | 554 | .load_frame => |pl| try w.print("[{} + 0x{x}]", .{ pl.index, pl.off }), |
| 555 | .lea_frame => |pl| try bw.print("{f} + 0x{x}", .{ pl.index, pl.off }), | 555 | .lea_frame => |pl| try w.print("{} + 0x{x}", .{ pl.index, pl.off }), |
| 556 | .load_nav => |pl| try bw.print("[nav:{d}]", .{@intFromEnum(pl)}), | 556 | .load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}), |
| 557 | .lea_nav => |pl| try bw.print("nav:{d}", .{@intFromEnum(pl)}), | 557 | .lea_nav => |pl| try w.print("nav:{d}", .{@intFromEnum(pl)}), |
| 558 | .load_uav => |pl| try bw.print("[uav:{d}]", .{@intFromEnum(pl.val)}), | 558 | .load_uav => |pl| try w.print("[uav:{d}]", .{@intFromEnum(pl.val)}), |
| 559 | .lea_uav => |pl| try bw.print("uav:{d}", .{@intFromEnum(pl.val)}), | 559 | .lea_uav => |pl| try w.print("uav:{d}", .{@intFromEnum(pl.val)}), |
| 560 | .load_lazy_sym => |pl| try bw.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }), | 560 | .load_lazy_sym => |pl| try w.print("[lazy:{s}:{d}]", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }), |
| 561 | .lea_lazy_sym => |pl| try bw.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }), | 561 | .lea_lazy_sym => |pl| try w.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }), |
| 562 | .load_extern_func => |pl| try bw.print("[extern:{d}]", .{@intFromEnum(pl)}), | 562 | .load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}), |
| 563 | .lea_extern_func => |pl| try bw.print("extern:{d}", .{@intFromEnum(pl)}), | 563 | .lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}), |
| 564 | .elementwise_args => |pl| try bw.print("elementwise:{d}:[{f} + 0x{x}]", .{ | 564 | .elementwise_args => |pl| try w.print("elementwise:{d}:[{} + 0x{x}]", .{ |
| 565 | pl.regs, pl.frame_index, pl.frame_off, | 565 | pl.regs, pl.frame_index, pl.frame_off, |
| 566 | }), | 566 | }), |
| 567 | .reserved_frame => |pl| try bw.print("(dead:{f})", .{pl}), | 567 | .reserved_frame => |pl| try w.print("(dead:{})", .{pl}), |
| 568 | .air_ref => |pl| try bw.print("(air:0x{x})", .{@intFromEnum(pl)}), | 568 | .air_ref => |pl| try w.print("(air:0x{x})", .{@intFromEnum(pl)}), |
| 569 | } | 569 | } |
| 570 | } | 570 | } |
| 571 | }; | 571 | }; |
| ... | @@ -2026,7 +2026,7 @@ fn gen( | ... | @@ -2026,7 +2026,7 @@ fn gen( |
| 2026 | .{}, | 2026 | .{}, |
| 2027 | ); | 2027 | ); |
| 2028 | self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; | 2028 | self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; |
| 2029 | tracking_log.debug("spill {f} to {f}", .{ self.ret_mcv.long, frame_index }); | 2029 | tracking_log.debug("spill {f} to {}", .{ self.ret_mcv.long, frame_index }); |
| 2030 | }, | 2030 | }, |
| 2031 | else => unreachable, | 2031 | else => unreachable, |
| 2032 | } | 2032 | } |
src/arch/x86_64/bits.zig+6| ... | @@ -721,6 +721,12 @@ pub const FrameIndex = enum(u32) { | ... | @@ -721,6 +721,12 @@ pub const FrameIndex = enum(u32) { |
| 721 | call_frame, | 721 | call_frame, |
| 722 | // Other indices are used for local variable stack slots | 722 | // Other indices are used for local variable stack slots |
| 723 | _, | 723 | _, |
| 724 | |||
| 725 | pub const named_count = @typeInfo(FrameIndex).@"enum".fields.len; | ||
| 726 | |||
| 727 | pub fn isNamed(fi: FrameIndex) bool { | ||
| 728 | return @intFromEnum(fi) < named_count; | ||
| 729 | } | ||
| 724 | }; | 730 | }; |
| 725 | 731 | ||
| 726 | pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; | 732 | pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; |
src/arch/x86_64/encoder.zig+1-1| ... | @@ -259,7 +259,7 @@ pub const Instruction = struct { | ... | @@ -259,7 +259,7 @@ pub const Instruction = struct { |
| 259 | switch (sib.base) { | 259 | switch (sib.base) { |
| 260 | .none => any = false, | 260 | .none => any = false, |
| 261 | .reg => |reg| try w.print("{s}", .{@tagName(reg)}), | 261 | .reg => |reg| try w.print("{s}", .{@tagName(reg)}), |
| 262 | .frame => |frame_index| try w.print("{f}", .{frame_index}), | 262 | .frame => |frame_index| try w.print("{}", .{frame_index}), |
| 263 | .table => try w.print("Table", .{}), | 263 | .table => try w.print("Table", .{}), |
| 264 | .rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}), | 264 | .rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}), |
| 265 | .nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}), | 265 | .nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}), |
src/link.zig+8-6| ... | @@ -838,8 +838,10 @@ pub const File = struct { | ... | @@ -838,8 +838,10 @@ pub const File = struct { |
| 838 | const cached_pp_file_path = the_key.status.success.object_path; | 838 | const cached_pp_file_path = the_key.status.success.object_path; |
| 839 | cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| { | 839 | cached_pp_file_path.root_dir.handle.copyFile(cached_pp_file_path.sub_path, emit.root_dir.handle, emit.sub_path, .{}) catch |err| { |
| 840 | const diags = &base.comp.link_diags; | 840 | const diags = &base.comp.link_diags; |
| 841 | return diags.fail("failed to copy '{f'}' to '{f'}': {s}", .{ | 841 | return diags.fail("failed to copy '{f}' to '{f}': {s}", .{ |
| 842 | @as(Path, cached_pp_file_path), @as(Path, emit), @errorName(err), | 842 | std.fmt.alt(@as(Path, cached_pp_file_path), .formatEscapeChar), |
| 843 | std.fmt.alt(@as(Path, emit), .formatEscapeChar), | ||
| 844 | @errorName(err), | ||
| 843 | }); | 845 | }); |
| 844 | }; | 846 | }; |
| 845 | return; | 847 | return; |
| ... | @@ -2086,14 +2088,14 @@ fn resolvePathInputLib( | ... | @@ -2086,14 +2088,14 @@ fn resolvePathInputLib( |
| 2086 | }) { | 2088 | }) { |
| 2087 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { | 2089 | var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) { |
| 2088 | error.FileNotFound => return .no_match, | 2090 | error.FileNotFound => return .no_match, |
| 2089 | else => |e| fatal("unable to search for {s} library '{f'}': {s}", .{ | 2091 | else => |e| fatal("unable to search for {s} library '{f}': {s}", .{ |
| 2090 | @tagName(link_mode), test_path, @errorName(e), | 2092 | @tagName(link_mode), std.fmt.alt(test_path, .formatEscapeChar), @errorName(e), |
| 2091 | }), | 2093 | }), |
| 2092 | }; | 2094 | }; |
| 2093 | errdefer file.close(); | 2095 | errdefer file.close(); |
| 2094 | try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len)); | 2096 | try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len)); |
| 2095 | const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f'}': {s}", .{ | 2097 | const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{f}': {s}", .{ |
| 2096 | test_path, @errorName(err), | 2098 | std.fmt.alt(test_path, .formatEscapeChar), @errorName(err), |
| 2097 | }); | 2099 | }); |
| 2098 | const buf = ld_script_bytes.items[0..n]; | 2100 | const buf = ld_script_bytes.items[0..n]; |
| 2099 | if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) { | 2101 | if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) { |
src/link/C.zig+2-2| ... | @@ -503,8 +503,8 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P | ... | @@ -503,8 +503,8 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P |
| 503 | var fw = file.writer(&.{}); | 503 | var fw = file.writer(&.{}); |
| 504 | var w = &fw.interface; | 504 | var w = &fw.interface; |
| 505 | w.writeVecAll(f.all_buffers.items) catch |err| switch (err) { | 505 | w.writeVecAll(f.all_buffers.items) catch |err| switch (err) { |
| 506 | error.WriteFailed => return diags.fail("failed to write to '{f'}': {s}", .{ | 506 | error.WriteFailed => return diags.fail("failed to write to '{f}': {s}", .{ |
| 507 | self.base.emit, @errorName(fw.err.?), | 507 | std.fmt.alt(self.base.emit, .formatEscapeChar), @errorName(fw.err.?), |
| 508 | }), | 508 | }), |
| 509 | }; | 509 | }; |
| 510 | } | 510 | } |
src/main.zig+3-1| ... | @@ -6964,7 +6964,9 @@ fn cmdFetch( | ... | @@ -6964,7 +6964,9 @@ fn cmdFetch( |
| 6964 | std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex }); | 6964 | std.log.info("resolved ref '{s}' to commit {s}", .{ target_ref, latest_commit_hex }); |
| 6965 | 6965 | ||
| 6966 | // include the original refspec in a query parameter, could be used to check for updates | 6966 | // include the original refspec in a query parameter, could be used to check for updates |
| 6967 | uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={f%}", .{fragment}) }; | 6967 | uri.query = .{ .percent_encoded = try std.fmt.allocPrint(arena, "ref={f}", .{ |
| 6968 | std.fmt.alt(fragment, .formatEscaped), | ||
| 6969 | }) }; | ||
| 6968 | } else { | 6970 | } else { |
| 6969 | std.log.info("resolved to commit {s}", .{latest_commit_hex}); | 6971 | std.log.info("resolved to commit {s}", .{latest_commit_hex}); |
| 6970 | } | 6972 | } |
src/print_value.zig+1-1| ... | @@ -77,7 +77,7 @@ pub fn print( | ... | @@ -77,7 +77,7 @@ pub fn print( |
| 77 | .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}), | 77 | .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}), |
| 78 | .int => |int| switch (int.storage) { | 78 | .int => |int| switch (int.storage) { |
| 79 | inline .u64, .i64 => |x| try writer.print("{d}", .{x}), | 79 | inline .u64, .i64 => |x| try writer.print("{d}", .{x}), |
| 80 | .big_int => |x| try writer.print("{fd}", .{x}), | 80 | .big_int => |x| try writer.print("{d}", .{x}), |
| 81 | .lazy_align => |ty| if (opt_sema != null) { | 81 | .lazy_align => |ty| if (opt_sema != null) { |
| 82 | const a = try Type.fromInterned(ty).abiAlignmentSema(pt); | 82 | const a = try Type.fromInterned(ty).abiAlignmentSema(pt); |
| 83 | try writer.print("{d}", .{a.toByteUnits() orelse 0}); | 83 | try writer.print("{d}", .{a.toByteUnits() orelse 0}); |