From 16894c484c316c110a843ee15514790cc589dbfa Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Tue, 7 Jul 2026 17:43:04 -0700 Subject: [PATCH 01/20] doctest: Fix logic error when detecting target and host mismatch --- tools/doctest.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/doctest.zig b/tools/doctest.zig index f39c56d4d12c65cca732f4c9dd9aea620b5f6ba9..4c986bd7d002973357334c3cd23077dab8ec1925 100644 --- a/tools/doctest.zig +++ b/tools/doctest.zig @@ -225,7 +225,7 @@ fn printOutput( if (mem.startsWith(u8, triple, "wasm32") or mem.startsWith(u8, triple, "riscv64-linux") or (mem.startsWith(u8, triple, "x86_64-linux") and - builtin.os.tag != .linux or builtin.cpu.arch != .x86_64)) + (builtin.os.tag != .linux or builtin.cpu.arch != .x86_64))) { // skip execution break :code_block; -- 2.54.0 From 64e4f9db8fa6fc47b0a2ef3143edacf472fb8c48 Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Wed, 17 Sep 2025 19:49:34 -0700 Subject: [PATCH 02/20] Implement partially ordered operator precedence --- lib/c/math.zig | 4 +- lib/c/stdlib/drand48.zig | 12 +- lib/compiler/Maker/Step/Compile.zig | 2 +- lib/compiler/aro/aro/Compilation.zig | 6 +- lib/compiler/aro/aro/Driver.zig | 2 +- lib/compiler/aro/aro/Parser.zig | 2 +- lib/compiler/aro/aro/Preprocessor.zig | 6 +- lib/compiler/aro/aro/Preprocessor/Parser.zig | 2 +- lib/compiler/aro/aro/char_info.zig | 4 +- lib/compiler/aro/aro/record_layout.zig | 2 +- lib/compiler_rt/absv.zig | 2 +- lib/compiler_rt/addf3.zig | 2 +- lib/compiler_rt/atomics.zig | 2 +- lib/compiler_rt/comparef.zig | 8 +- lib/compiler_rt/divdf3.zig | 16 +- lib/compiler_rt/divsf3.zig | 14 +- lib/compiler_rt/divtf3.zig | 20 +- lib/compiler_rt/divxf3.zig | 20 +- lib/compiler_rt/elf/tls.zig | 2 +- lib/compiler_rt/extendf.zig | 4 +- lib/compiler_rt/floor_ceil.zig | 8 +- lib/compiler_rt/fmod.zig | 4 +- lib/compiler_rt/mulf3.zig | 2 +- lib/compiler_rt/rem_pio2l.zig | 2 +- lib/compiler_rt/sqrt.zig | 10 +- lib/compiler_rt/truncf.zig | 6 +- lib/std/Io/Dispatch.zig | 4 +- lib/std/Io/Kqueue.zig | 2 +- lib/std/Io/Threaded/test.zig | 2 +- lib/std/Io/Writer.zig | 2 +- lib/std/Io/net/HostName.zig | 2 +- lib/std/base64.zig | 6 +- lib/std/bit_set.zig | 8 +- lib/std/coff.zig | 2 +- lib/std/compress/flate/Compress.zig | 4 +- lib/std/crypto/aes/soft.zig | 2 +- lib/std/crypto/codecs/base64_hex_ct.zig | 2 +- lib/std/crypto/ml_kem.zig | 2 +- lib/std/crypto/scrypt.zig | 2 +- lib/std/crypto/sha2.zig | 2 +- lib/std/debug.zig | 2 +- lib/std/debug/SelfInfo/Elf.zig | 8 +- lib/std/debug/SelfInfo/MachO.zig | 4 +- lib/std/debug/SelfInfo/Windows.zig | 8 +- lib/std/dynamic_library.zig | 14 +- lib/std/fmt/parse_float/common.zig | 2 +- lib/std/hash/cityhash.zig | 2 +- lib/std/hash/xxhash.zig | 2 +- lib/std/hash_map.zig | 2 +- lib/std/heap/SafeAllocator.zig | 2 +- lib/std/math.zig | 28 +- lib/std/math/acos.zig | 2 +- lib/std/math/asin.zig | 2 +- lib/std/math/big/int.zig | 6 +- lib/std/math/big/int_test.zig | 32 +- lib/std/math/float.zig | 4 +- lib/std/mem.zig | 2 +- lib/std/os/linux/vdso.zig | 8 +- lib/std/os/uefi/status.zig | 2 +- lib/std/unicode.zig | 2 +- lib/std/zig/Ast.zig | 32 ++ lib/std/zig/Ast/Render.zig | 6 +- lib/std/zig/Parse.zig | 355 ++++++++++++++++--- lib/std/zig/TokenSmith.zig | 2 +- lib/std/zig/llvm/BitcodeReader.zig | 2 +- lib/std/zig/llvm/Builder.zig | 52 +-- lib/std/zig/llvm/bitcode_writer.zig | 2 +- lib/std/zig/parser_test.zig | 48 ++- lib/std/zig/system.zig | 10 +- lib/std/zig/system/windows.zig | 4 +- src/Air.zig | 2 +- src/Compilation.zig | 4 +- src/IncrementalDebugServer.zig | 4 +- src/InternPool.zig | 36 +- src/Sema.zig | 4 +- src/codegen/aarch64/Assemble.zig | 4 +- src/codegen/aarch64/Disassemble.zig | 8 +- src/codegen/aarch64/Mir.zig | 6 +- src/codegen/aarch64/Select.zig | 8 +- src/codegen/aarch64/encoding.zig | 38 +- src/codegen/loongarch/Mir.zig | 2 +- src/codegen/riscv64/CodeGen.zig | 4 +- src/codegen/riscv64/encoding.zig | 4 +- src/codegen/sparc64/CodeGen.zig | 4 +- src/codegen/spirv/CodeGen.zig | 2 +- src/codegen/x86_64/CodeGen.zig | 34 +- src/codegen/x86_64/Disassembler.zig | 2 +- src/codegen/x86_64/Emit.zig | 12 +- src/codegen/x86_64/Mir.zig | 2 +- src/codegen/x86_64/bits.zig | 2 +- src/codegen/x86_64/encoder.zig | 28 +- src/fmt.zig | 3 +- src/link/Dwarf.zig | 6 +- src/link/Dwarf2.zig | 4 +- src/link/Elf2.zig | 8 +- src/link/MachO/UnwindInfo.zig | 2 +- src/link/MachO/load_commands.zig | 4 +- src/link/Wasm/Flush.zig | 2 +- src/link/riscv.zig | 4 +- src/main.zig | 2 +- test/Runner.zig | 8 +- test/behavior/bitcast.zig | 2 +- test/behavior/error.zig | 2 +- test/behavior/math.zig | 6 +- test/behavior/try.zig | 6 +- test/behavior/x86_64/binary.zig | 4 +- test/behavior/x86_64/cast.zig | 8 +- tools/loongarch/OpcodeDesc.zig | 4 +- 108 files changed, 727 insertions(+), 411 deletions(-) diff --git a/lib/c/math.zig b/lib/c/math.zig index f9073add14799636be748725d54cf786e84c45aa..f5fdd126cda9ac2cd9d2be8f82235fa972c907fd 100644 --- a/lib/c/math.zig +++ b/lib/c/math.zig @@ -355,7 +355,7 @@ fn pow10f(x: f32) callconv(.c) f32 { fn rint(x: f64) callconv(.c) f64 { const toint: f64 = 1.0 / math.floatEps(f64); const a: u64 = @bitCast(x); - const e = a >> 52 & 0x7ff; + const e = (a >> 52) & 0x7ff; const s = a >> 63; var y: f64 = undefined; @@ -376,7 +376,7 @@ fn rint(x: f64) callconv(.c) f64 { fn rintf(x: f32) callconv(.c) f32 { const toint: f32 = 1.0 / math.floatEps(f32); const a: u32 = @bitCast(x); - const e = a >> 23 & 0xff; + const e = (a >> 23) & 0xff; const s = a >> 31; var y: f32 = undefined; diff --git a/lib/c/stdlib/drand48.zig b/lib/c/stdlib/drand48.zig index 46e72de0b901d45fab48ad0f8d3eafc5e56281d5..ce148a9a1524bb9d3399739755b68397eda3baea 100644 --- a/lib/c/stdlib/drand48.zig +++ b/lib/c/stdlib/drand48.zig @@ -30,7 +30,7 @@ var lcg: Lcg = .init(0, default_multiplier, default_addend); var seed48_xi: [3]c_ushort = undefined; fn erand48(xsubi: *[3]c_ushort) callconv(.c) f64 { - const xi = @as(u48, @as(u16, @truncate(xsubi[0])) | (@as(u48, @as(u16, @truncate(xsubi[1])))) << 16) | (@as(u48, @as(u16, @truncate(xsubi[2]))) << 32); + const xi = @as(u48, @as(u16, @truncate(xsubi[0])) | ((@as(u48, @as(u16, @truncate(xsubi[1])))) << 16)) | (@as(u48, @as(u16, @truncate(xsubi[2]))) << 32); var separate_lcg: Lcg = .init(xi, lcg.a, lcg.c); const next_xi = separate_lcg.next(); @@ -40,7 +40,7 @@ fn erand48(xsubi: *[3]c_ushort) callconv(.c) f64 { } fn jrand48(xsubi: *[3]c_ushort) callconv(.c) c_long { - const xi = @as(u48, @as(u16, @truncate(xsubi[0])) | (@as(u48, @as(u16, @truncate(xsubi[1])))) << 16) | (@as(u48, @as(u16, @truncate(xsubi[2]))) << 32); + const xi = @as(u48, @as(u16, @truncate(xsubi[0])) | ((@as(u48, @as(u16, @truncate(xsubi[1])))) << 16)) | (@as(u48, @as(u16, @truncate(xsubi[2]))) << 32); var separate_lcg: Lcg = .init(xi, lcg.a, lcg.c); const next_xi = separate_lcg.next(); @@ -50,7 +50,7 @@ fn jrand48(xsubi: *[3]c_ushort) callconv(.c) c_long { } fn nrand48(xsubi: *[3]c_ushort) callconv(.c) c_long { - const xi = @as(u48, @as(u16, @truncate(xsubi[0])) | (@as(u48, @as(u16, @truncate(xsubi[1])))) << 16) | (@as(u48, @as(u16, @truncate(xsubi[2]))) << 32); + const xi = @as(u48, @as(u16, @truncate(xsubi[0])) | ((@as(u48, @as(u16, @truncate(xsubi[1])))) << 16)) | (@as(u48, @as(u16, @truncate(xsubi[2]))) << 32); var separate_lcg: Lcg = .init(xi, lcg.a, lcg.c); const next_xi = separate_lcg.next(); @@ -74,14 +74,14 @@ fn mrand48() callconv(.c) c_long { // 0..3 is `Xi`, 3..6 is `a`, 6 is `c` // first low 16-bits, then mid, then high. fn lcong48(param: *[7]c_ushort) callconv(.c) void { - lcg.xi = (@as(u48, @as(u16, @truncate(param[0]))) | (@as(u48, @as(u16, @truncate(param[1])))) << 16) | (@as(u48, @as(u16, @truncate(param[2]))) << 32); - lcg.a = (@as(u48, @as(u16, @truncate(param[3]))) | (@as(u48, @as(u16, @truncate(param[4])))) << 16) | (@as(u48, @as(u16, @truncate(param[5]))) << 32); + lcg.xi = (@as(u48, @as(u16, @truncate(param[0]))) | ((@as(u48, @as(u16, @truncate(param[1])))) << 16)) | (@as(u48, @as(u16, @truncate(param[2]))) << 32); + lcg.a = (@as(u48, @as(u16, @truncate(param[3]))) | ((@as(u48, @as(u16, @truncate(param[4])))) << 16)) | (@as(u48, @as(u16, @truncate(param[5]))) << 32); lcg.c = @as(u16, @truncate(param[6])); } fn seed48(seed16v: *[3]c_ushort) callconv(.c) *[3]c_ushort { seed48_xi = .{ @truncate(lcg.xi & 0xFFFF), @truncate((lcg.xi >> 16) & 0xFFFF), @truncate((lcg.xi >> 32) & 0xFFFF) }; - const xi = (@as(u48, @as(u16, @truncate(seed16v[0]))) | (@as(u48, @as(u16, @truncate(seed16v[1])))) << 16) | (@as(u48, @as(u16, @truncate(seed16v[2]))) << 32); + const xi = (@as(u48, @as(u16, @truncate(seed16v[0]))) | ((@as(u48, @as(u16, @truncate(seed16v[1])))) << 16)) | (@as(u48, @as(u16, @truncate(seed16v[2]))) << 32); lcg = .init(xi, default_multiplier, default_addend); return &seed48_xi; } diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig index 7e25860277b72a91cf62d23877325cd41ef85a09..8c6ab5fe30c55becc28af17276c89b3f4baca121 100644 --- a/lib/compiler/Maker/Step/Compile.zig +++ b/lib/compiler/Maker/Step/Compile.zig @@ -45,7 +45,7 @@ pub fn make( try lowerZigArgs(arena, compile_index, maker, progress_node, &argv, false); - const incremental = conf_comp.flags4.incremental.toBool() orelse graph.incremental == true; + const incremental = conf_comp.flags4.incremental.toBool() orelse graph.incremental orelse false; const opt_cache_digest = Step.evalZigProcess( compile_index, diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig index 39cbb1c0b955e61c3b11779f9a1a42ca4a6da2ba..8d893abfc38bdb4200447838ceee77f7693fb75e 100644 --- a/lib/compiler/aro/aro/Compilation.zig +++ b/lib/compiler/aro/aro/Compilation.zig @@ -287,7 +287,7 @@ fn generateSystemDefines(comp: *Compilation, w: *Io.Writer) !void { const gnuc_version = comp.langopts.gnuc_version orelse comp.langopts.emulate.defaultGccVersion(); if (gnuc_version > 0) { try w.print("#define __GNUC__ {d}\n", .{gnuc_version / 10_000}); - try w.print("#define __GNUC_MINOR__ {d}\n", .{gnuc_version / 100 % 100}); + try w.print("#define __GNUC_MINOR__ {d}\n", .{(gnuc_version / 100) % 100}); try w.print("#define __GNUC_PATCHLEVEL__ {d}\n", .{gnuc_version % 100}); } @@ -962,7 +962,7 @@ fn generateSystemDefines(comp: *Compilation, w: *Io.Writer) !void { try define(w, "__ARM_ARCH_EXT_IDIV__"); } var sat = false; - if (arm_version == 6 and !target.cpu.has(.arm, .mclass) or arm_version > 6) { + if ((arm_version == 6 and !target.cpu.has(.arm, .mclass)) or arm_version > 6) { try define(w, "__ARM_FEATURE_SAT"); sat = true; } @@ -2856,7 +2856,7 @@ test "addSourceFromBuffer - exhaustive check for carriage return elimination" { if (buf[j] == alphabet[0]) buf[j - 1] = alphabet[(idx + 1) % alen] else break; } } - try std.testing.expect(source_count == std.math.powi(usize, alen, alen) catch unreachable); + try std.testing.expect(source_count == (std.math.powi(usize, alen, alen) catch unreachable)); } test "ignore BOM at beginning of file" { diff --git a/lib/compiler/aro/aro/Driver.zig b/lib/compiler/aro/aro/Driver.zig index b41a7a191135c0ee0402b90ac2e54e631f641c3a..0313cb62cb2db62735977ed5fed8b5d4b5c4b15f 100644 --- a/lib/compiler/aro/aro/Driver.zig +++ b/lib/compiler/aro/aro/Driver.zig @@ -1373,7 +1373,7 @@ fn getOutFileName(d: *Driver, source: Source, buf: *[std.fs.max_name_bytes]u8) ! if (d.only_preprocess_and_compile) ".s" else d.comp.target.ofmt.fileExt(d.comp.target.cpu.arch), }; return d.output_name orelse - mem.print(buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args); + (mem.print(buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args)); } return d.getRandomFilename(buf, d.comp.target.ofmt.fileExt(d.comp.target.cpu.arch)); diff --git a/lib/compiler/aro/aro/Parser.zig b/lib/compiler/aro/aro/Parser.zig index d6a48966f28db2edf53b019a084b3704ca0528e8..0405c0536e8795eb02d9a4427cf91fd24cbc66fc 100644 --- a/lib/compiler/aro/aro/Parser.zig +++ b/lib/compiler/aro/aro/Parser.zig @@ -7084,7 +7084,7 @@ pub const Result = struct { const b_child_qt = b.qt.get(p.comp, .pointer).?.child; if (!a_child_qt.eql(b_child_qt, p.comp)) try p.err(tok, .incompatible_pointers, .{ a.qt, b.qt }); - if (a.qt.childType(p.comp).sizeofOrNull(p.comp) orelse 1 == 0) try p.err(tok, .subtract_pointers_zero_elem_size, .{a.qt.childType(p.comp)}); + if ((a.qt.childType(p.comp).sizeofOrNull(p.comp) orelse 1) == 0) try p.err(tok, .subtract_pointers_zero_elem_size, .{a.qt.childType(p.comp)}); a.qt = p.comp.type_store.ptrdiff; } diff --git a/lib/compiler/aro/aro/Preprocessor.zig b/lib/compiler/aro/aro/Preprocessor.zig index 5df5c1c8f9969ff25b83cf11e5b1610f8e14a725..98f0b7a004c2950383278beb89a45e6204daa806 100644 --- a/lib/compiler/aro/aro/Preprocessor.zig +++ b/lib/compiler/aro/aro/Preprocessor.zig @@ -310,13 +310,13 @@ pub const InitOptions = struct { }; pub fn init(comp: *Compilation, options: InitOptions) !Preprocessor { - const source_epoch: SourceEpoch = options.source_epoch orelse comp.environment.sourceEpoch(comp.io) catch |er| switch (er) { + const source_epoch: SourceEpoch = options.source_epoch orelse (comp.environment.sourceEpoch(comp.io) catch |er| switch (er) { error.InvalidEpoch => blk: { const diagnostic: Diagnostic = .invalid_source_epoch; try comp.diagnostics.add(.{ .text = diagnostic.fmt, .kind = diagnostic.kind, .opt = diagnostic.opt, .location = null }); break :blk .default; }, - }; + }); var pp: Preprocessor = .{ .comp = comp, @@ -3882,7 +3882,7 @@ pub fn prettyPrintTokens(pp: *Preprocessor, w: *std.Io.Writer, macro_dump_mode: }, .keyword_pragma => { const pragma_name = pp.expandedSlice(pp.tokens.get(i + 1)); - const end_idx = mem.findScalarPos(Token.Id, tok_ids, i, .nl) orelse i + 1; + const end_idx = mem.findScalarPos(Token.Id, tok_ids, i, .nl) orelse (i + 1); const pragma_len = @as(u32, @intCast(end_idx)) - i; if (pp.comp.getPragma(pragma_name)) |prag| { diff --git a/lib/compiler/aro/aro/Preprocessor/Parser.zig b/lib/compiler/aro/aro/Preprocessor/Parser.zig index c4b3f60c5908bb220e876b63105156421ce6cdd4..c9a964b44ce5ac3e48cf3ca711218d478d8ff46c 100644 --- a/lib/compiler/aro/aro/Preprocessor/Parser.zig +++ b/lib/compiler/aro/aro/Preprocessor/Parser.zig @@ -323,7 +323,7 @@ fn binaryExpr(p: *Parser, min_prec: Token.Precedence, eval: bool) Error!?Value { const else_res = try p.binaryExpr(op_prec, eval_else) orelse return null; lhs = if (lhs.toBool()) rhs else else_res; - if (eval and rhs == .unsigned or else_res == .unsigned) { + if ((eval and rhs == .unsigned) or else_res == .unsigned) { try lhs.toUnsigned(p, operator, "right"); } }, diff --git a/lib/compiler/aro/aro/char_info.zig b/lib/compiler/aro/aro/char_info.zig index a4d5857c80e3d69cc72dd318a52f6f5de0da95db..b8a41a53ba05baf0c5bfe96cf02751bfe8fbdfbf 100644 --- a/lib/compiler/aro/aro/char_info.zig +++ b/lib/compiler/aro/aro/char_info.zig @@ -492,7 +492,7 @@ pub fn isXidStart(c: u21) bool { assert(c > 0x7F); const idx = c / 8 / tables.chunk; const chunk: usize = if (idx < tables.trie_start.len) tables.trie_start[idx] else 0; - const offset = chunk * tables.chunk / 2 + c / 8 % tables.chunk; + const offset = chunk * tables.chunk / 2 + (c / 8) % tables.chunk; return (tables.leaf[offset] >> (@as(u3, @intCast(c % 8)))) & 1 != 0; } @@ -500,7 +500,7 @@ pub fn isXidContinue(c: u21) bool { assert(c > 0x7F); const idx = c / 8 / tables.chunk; const chunk: usize = if (idx < tables.trie_continue.len) tables.trie_continue[idx] else 0; - const offset = chunk * tables.chunk / 2 + c / 8 % tables.chunk; + const offset = chunk * tables.chunk / 2 + (c / 8) % tables.chunk; return (tables.leaf[offset] >> (@as(u3, @intCast(c % 8)))) & 1 != 0; } diff --git a/lib/compiler/aro/aro/record_layout.zig b/lib/compiler/aro/aro/record_layout.zig index be725952ee63f3a5eb34826954b02d91d0f983df..ce37449c7b7e30fe6cfd863b27eeb96fa6877c45 100644 --- a/lib/compiler/aro/aro/record_layout.zig +++ b/lib/compiler/aro/aro/record_layout.zig @@ -324,7 +324,7 @@ const SysVContext = struct { // On Clang, the alignment requested by annotations is not respected if it is // larger than the value of #pragma pack. See test case 0083. - if (annotation_alignment <= self.max_field_align_bits orelse std.math.maxInt(u29)) { + if (annotation_alignment <= (self.max_field_align_bits orelse std.math.maxInt(u29))) { field_align_bits = @max(field_align_bits, annotation_alignment); } // On Clang, if there are no packing annotations and the field would cross a diff --git a/lib/compiler_rt/absv.zig b/lib/compiler_rt/absv.zig index 4621835dd6f6abd9cdb37a53231e88139556eb9a..b430b7c710b00305ea0ab9f98df83be49c84437d 100644 --- a/lib/compiler_rt/absv.zig +++ b/lib/compiler_rt/absv.zig @@ -11,7 +11,7 @@ pub inline fn absv(comptime ST: type, a: ST) ST { // compute the integer absolute value (abs) without branching var x: ST = a; const N: UT = @bitSizeOf(ST); - const sign: ST = a >> N - 1; + const sign: ST = a >> (N - 1); x +%= sign; x ^= sign; if (x < 0) @panic("integer overflow"); diff --git a/lib/compiler_rt/addf3.zig b/lib/compiler_rt/addf3.zig index 189f7afd6d02c78bdb63de8e38ca7731c96684d4..37c4f639fffe9c27e47c51359ae898c71d21cc73 100644 --- a/lib/compiler_rt/addf3.zig +++ b/lib/compiler_rt/addf3.zig @@ -259,7 +259,7 @@ inline fn addf3(comptime T: type, a: T, b: T) T { // adjust the exponent: if (aSignificand & (integerBit << 4) != 0) { const sticky = aSignificand & 1; - aSignificand = aSignificand >> 1 | sticky; + aSignificand = (aSignificand >> 1) | sticky; aExponent += 1; } } diff --git a/lib/compiler_rt/atomics.zig b/lib/compiler_rt/atomics.zig index 8b7861537a06cc8c9c9075f3faba1bba9488a709..f04eb95090dffb3428cd377ec5cedc7dee4dfc24 100644 --- a/lib/compiler_rt/atomics.zig +++ b/lib/compiler_rt/atomics.zig @@ -241,7 +241,7 @@ fn wideUpdate(comptime T: type, ptr: *T, val: T, update: anytype) T { while (true) { const old = @as(T, @truncate((wide_old & mask) >> inner_shift)); const new = update(val, old); - const wide_new = wide_old & ~mask | (@as(WideAtomic, new) << inner_shift); + const wide_new = (wide_old & ~mask) | (@as(WideAtomic, new) << inner_shift); if (@cmpxchgWeak(WideAtomic, wide_ptr, wide_old, wide_new, .seq_cst, .seq_cst)) |new_wide_old| { wide_old = new_wide_old; } else { diff --git a/lib/compiler_rt/comparef.zig b/lib/compiler_rt/comparef.zig index d230e9a6b42f8ef88114e4d72b838f3f47c01cec..af9d298ce15f38e1ab5f54335516c6d447a22e6f 100644 --- a/lib/compiler_rt/comparef.zig +++ b/lib/compiler_rt/comparef.zig @@ -130,13 +130,13 @@ fn __aeabi_fcmplt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { return @intFromBool(cmp_f32(a, b) == .lt); } fn __aeabi_fcmple(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmp_f32(a, b) orelse .gt != .gt); + return @intFromBool((cmp_f32(a, b) orelse .gt) != .gt); } fn __gesf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order { return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .lt; } fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmp_f32(a, b) orelse .lt != .lt); + return @intFromBool((cmp_f32(a, b) orelse .lt) != .lt); } fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { return @intFromBool(cmp_f32(a, b) == .gt); @@ -164,13 +164,13 @@ fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { return @intFromBool(cmp_f64(a, b) == .lt); } fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmp_f64(a, b) orelse .gt != .gt); + return @intFromBool((cmp_f64(a, b) orelse .gt) != .gt); } fn __gedf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order { return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .lt; } fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { - return @intFromBool(cmp_f64(a, b) orelse .lt != .lt); + return @intFromBool((cmp_f64(a, b) orelse .lt) != .lt); } fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { return @intFromBool(cmp_f64(a, b) == .gt); diff --git a/lib/compiler_rt/divdf3.zig b/lib/compiler_rt/divdf3.zig index 90953e0d0616d6a211872eef0b0c18ba1ff0cdb4..cb390ef03e96971878fd7ffa49d3c9e2f748f757 100644 --- a/lib/compiler_rt/divdf3.zig +++ b/lib/compiler_rt/divdf3.zig @@ -119,12 +119,12 @@ pub fn div_f64(a: f64, b: f64) f64 { // with each iteration, so after three iterations, we have about 28 binary // digits of accuracy. var correction32: u32 = undefined; - correction32 = @truncate(~(@as(u64, recip32) *% q31b >> 32) +% 1); - recip32 = @truncate(@as(u64, recip32) *% correction32 >> 31); - correction32 = @truncate(~(@as(u64, recip32) *% q31b >> 32) +% 1); - recip32 = @truncate(@as(u64, recip32) *% correction32 >> 31); - correction32 = @truncate(~(@as(u64, recip32) *% q31b >> 32) +% 1); - recip32 = @truncate(@as(u64, recip32) *% correction32 >> 31); + correction32 = @truncate(~((@as(u64, recip32) *% q31b) >> 32) +% 1); + recip32 = @truncate((@as(u64, recip32) *% correction32) >> 31); + correction32 = @truncate(~((@as(u64, recip32) *% q31b) >> 32) +% 1); + recip32 = @truncate((@as(u64, recip32) *% correction32) >> 31); + correction32 = @truncate(~((@as(u64, recip32) *% q31b) >> 32) +% 1); + recip32 = @truncate((@as(u64, recip32) *% correction32) >> 31); // recip32 might have overflowed to exactly zero in the preceding // computation if the high word of b is exactly 1.0. This would sabotage @@ -137,10 +137,10 @@ pub fn div_f64(a: f64, b: f64) f64 { const q63blo: u32 = @truncate(bSignificand << 11); var correction: u64 = undefined; var reciprocal: u64 = undefined; - correction = ~(@as(u64, recip32) *% q31b +% (@as(u64, recip32) *% q63blo >> 32)) +% 1; + correction = ~(@as(u64, recip32) *% q31b +% ((@as(u64, recip32) *% q63blo) >> 32)) +% 1; const cHi: u32 = @truncate(correction >> 32); const cLo: u32 = @truncate(correction); - reciprocal = @as(u64, recip32) *% cHi +% (@as(u64, recip32) *% cLo >> 32); + reciprocal = @as(u64, recip32) *% cHi +% ((@as(u64, recip32) *% cLo) >> 32); // We already adjusted the 32-bit estimate, now we need to adjust the final // 64-bit reciprocal estimate downward to ensure that it is strictly smaller diff --git a/lib/compiler_rt/divsf3.zig b/lib/compiler_rt/divsf3.zig index c86c860948d315b260498c959e4678f5f64b9e94..bee27aef4b93258021e6160b172b6f7decdb5a56 100644 --- a/lib/compiler_rt/divsf3.zig +++ b/lib/compiler_rt/divsf3.zig @@ -126,12 +126,12 @@ pub fn div_f32(a: f32, b: f32) f32 { // with each iteration, so after three iterations, we have about 28 binary // digits of accuracy. var correction: u32 = undefined; - correction = @truncate(~(@as(u64, reciprocal) *% q31b >> 32) +% 1); - reciprocal = @truncate(@as(u64, reciprocal) *% correction >> 31); - correction = @truncate(~(@as(u64, reciprocal) *% q31b >> 32) +% 1); - reciprocal = @truncate(@as(u64, reciprocal) *% correction >> 31); - correction = @truncate(~(@as(u64, reciprocal) *% q31b >> 32) +% 1); - reciprocal = @truncate(@as(u64, reciprocal) *% correction >> 31); + correction = @truncate(~((@as(u64, reciprocal) *% q31b) >> 32) +% 1); + reciprocal = @truncate((@as(u64, reciprocal) *% correction) >> 31); + correction = @truncate(~((@as(u64, reciprocal) *% q31b) >> 32) +% 1); + reciprocal = @truncate((@as(u64, reciprocal) *% correction) >> 31); + correction = @truncate(~((@as(u64, reciprocal) *% q31b) >> 32) +% 1); + reciprocal = @truncate((@as(u64, reciprocal) *% correction) >> 31); // Exhaustive testing shows that the error in reciprocal after three steps // is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our @@ -153,7 +153,7 @@ pub fn div_f32(a: f32, b: f32) f32 { // is the error in the reciprocal of b scaled by the maximum // possible value of a. As a consequence of this error bound, // either q or nextafter(q) is the correctly rounded - var quotient: Z = @truncate(@as(u64, reciprocal) *% (aSignificand << 1) >> 32); + var quotient: Z = @truncate((@as(u64, reciprocal) *% (aSignificand << 1)) >> 32); // Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0). // In either case, we are going to compute a residual of the form diff --git a/lib/compiler_rt/divtf3.zig b/lib/compiler_rt/divtf3.zig index 9995a9bfd796070d9573ac050bf233c9646a5d98..e7b0164451f51b60bed8edd51cec07000588e073 100644 --- a/lib/compiler_rt/divtf3.zig +++ b/lib/compiler_rt/divtf3.zig @@ -119,16 +119,16 @@ pub fn div_f128(a: f128, b: f128) f128 { // This doubles the number of correct binary digits in the approximation // with each iteration. var correction64: u64 = undefined; - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); // The reciprocal may have overflowed to zero if the upper half of b is // exactly 1.0. This would sabatoge the full-width final stage of the diff --git a/lib/compiler_rt/divxf3.zig b/lib/compiler_rt/divxf3.zig index eb3fde6862ab3937e8828d729287a35ea9d3ead9..6921d63da57d547a08e122d55691a3b2328389b6 100644 --- a/lib/compiler_rt/divxf3.zig +++ b/lib/compiler_rt/divxf3.zig @@ -102,16 +102,16 @@ pub fn div_f80(a: f80, b: f80) f80 { // This doubles the number of correct binary digits in the approximation // with each iteration. var correction64: u64 = undefined; - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); - correction64 = @truncate(~(@as(u128, recip64) *% q63b >> 64) +% 1); - recip64 = @truncate(@as(u128, recip64) *% correction64 >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); + correction64 = @truncate(~((@as(u128, recip64) *% q63b) >> 64) +% 1); + recip64 = @truncate((@as(u128, recip64) *% correction64) >> 63); // The reciprocal may have overflowed to zero if the upper half of b is // exactly 1.0. This would sabatoge the full-width final stage of the diff --git a/lib/compiler_rt/elf/tls.zig b/lib/compiler_rt/elf/tls.zig index 944cf394b65e1d629787fd09114dfee02bb080c5..c93dc3d258b0a2dfc639c98ab71195c9a53f6ab1 100644 --- a/lib/compiler_rt/elf/tls.zig +++ b/lib/compiler_rt/elf/tls.zig @@ -251,7 +251,7 @@ fn setThreadPointer(addr: usize) void { // Update the %gs selector asm volatile ("movl %[gs_val], %%gs" : - : [gs_val] "r" (gdt_entry_number << 3 | 3), + : [gs_val] "r" ((gdt_entry_number << 3) | 3), ); }, .x86_64 => { diff --git a/lib/compiler_rt/extendf.zig b/lib/compiler_rt/extendf.zig index a0c637b352680a3b1bf1728c662bce3bdb6db91c..b8c3178b42e53c181162302af93b2023e8b3e579 100644 --- a/lib/compiler_rt/extendf.zig +++ b/lib/compiler_rt/extendf.zig @@ -165,7 +165,7 @@ pub fn f128_floatCast_f80(a: f80) f128 { } // Apply the signbit to (dst_t)abs(a). - const result: u128 = abs_result | @as(u128, sign) << (dst_bits - 16); + const result: u128 = abs_result | (@as(u128, sign) << (dst_bits - 16)); return @bitCast(result); } @@ -232,7 +232,7 @@ inline fn extendf(comptime dst_t: type, comptime src_t: type, f: src_t) dst_t { } // Apply the signbit to (dst_t)abs(a). - const result: dst_rep_t = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); + const result: dst_rep_t = absResult | (@as(dst_rep_t, sign) << (dstBits - srcBits)); return @bitCast(result); } diff --git a/lib/compiler_rt/floor_ceil.zig b/lib/compiler_rt/floor_ceil.zig index a11076bb0bcfa1da7a55e3608544c8c8b2f5d211..7691e408d5dae5cdbff6b71c56ce2062d14ae6d9 100644 --- a/lib/compiler_rt/floor_ceil.zig +++ b/lib/compiler_rt/floor_ceil.zig @@ -141,13 +141,13 @@ inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T { const m = (@as(U, 1) << @intCast(mantissa - e)) - 1; if (u & m == 0) return x; if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); - if (u >> bits - 1 == @intFromBool(op == .floor)) u += m; + if (u >> (bits - 1) == @intFromBool(op == .floor)) u += m; return @bitCast(u & ~m); } else { if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); return switch (op) { - .floor => if (u >> bits - 1 == 0) 0.0 else if (u << 1 != 0) -1.0 else x, - .ceil => if (u >> bits - 1 != 0) -0.0 else if (u << 1 != 0) 1.0 else x, + .floor => if (u >> (bits - 1) == 0) 0.0 else if (u << 1 != 0) -1.0 else x, + .ceil => if (u >> (bits - 1) != 0) -0.0 else if (u << 1 != 0) 1.0 else x, }; } }, @@ -155,7 +155,7 @@ inline fn impl(comptime T: type, comptime op: enum { floor, ceil }, x: T) T { const e = (u >> mantissa) & mask; if (e >= bias + math.floatFractionalBits(T) or x == 0) return x; - const positive = u >> @bitSizeOf(T) - 1 == 0; + const positive = u >> (@bitSizeOf(T) - 1) == 0; const y: T = if (positive) x + C - C - x else diff --git a/lib/compiler_rt/fmod.zig b/lib/compiler_rt/fmod.zig index c079049f15d08ba6b59301db1523a3644dd1e940..bd4bc5c1b1037a688c15eaa5958e36877b4f0bbb 100644 --- a/lib/compiler_rt/fmod.zig +++ b/lib/compiler_rt/fmod.zig @@ -204,8 +204,8 @@ pub fn fmod_f128(a: f128, b: f128) f128 { } // OR in extra non-stored mantissa digit - var highA: u64 = (aPtr_u64[high_index] & (std.math.maxInt(u64) >> 16)) | 1 << 48; - const highB: u64 = (bPtr_u64[high_index] & (std.math.maxInt(u64) >> 16)) | 1 << 48; + var highA: u64 = (aPtr_u64[high_index] & (std.math.maxInt(u64) >> 16)) | (1 << 48); + const highB: u64 = (bPtr_u64[high_index] & (std.math.maxInt(u64) >> 16)) | (1 << 48); var lowA: u64 = aPtr_u64[low_index]; const lowB: u64 = bPtr_u64[low_index]; diff --git a/lib/compiler_rt/mulf3.zig b/lib/compiler_rt/mulf3.zig index 7367339dbc82f74dc99a9f6de7f842e8cbb71968..f4dff4ed37218e8224c81aa854240429ca6903e8 100644 --- a/lib/compiler_rt/mulf3.zig +++ b/lib/compiler_rt/mulf3.zig @@ -237,7 +237,7 @@ fn wideShrWithTruncation(comptime Z: type, hi: *Z, lo: *Z, count: u32) bool { lo.* = (hi.* << @intCast(typeWidth -% count)) | (lo.* >> @intCast(count)); hi.* = hi.* >> @intCast(count); } else if (count < 2 * typeWidth) { - inexact = (hi.* << @intCast(2 * typeWidth -% count) | lo.*) != 0; + inexact = ((hi.* << @intCast(2 * typeWidth -% count)) | lo.*) != 0; lo.* = hi.* >> @intCast(count -% typeWidth); hi.* = 0; } else { diff --git a/lib/compiler_rt/rem_pio2l.zig b/lib/compiler_rt/rem_pio2l.zig index a6ff502500ae6a1365a7ea794a6d0bc6cd4421aa..fbb5011b350284c950814f6b1ca0112c1caa5da3 100644 --- a/lib/compiler_rt/rem_pio2l.zig +++ b/lib/compiler_rt/rem_pio2l.zig @@ -37,7 +37,7 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { const se = ld.signExponent(x_val); const top = ld.mantissaTop(x_val); const lhs = (@as(u32, se & 0x7fff) << 16) | top; - const rhs: u32 = ((0x3fff + 25) << 16) | 0x921f >> 1 | 0x8000; + const rhs: u32 = ((0x3fff + 25) << 16) | (0x921f >> 1) | 0x8000; return lhs < rhs; } diff --git a/lib/compiler_rt/sqrt.zig b/lib/compiler_rt/sqrt.zig index 6ba6d62b8e92d8d07e9ca99f2dd65559bd2ecfdb..d5282a6c9a7b92cf8d7f881c8d945033cb19248a 100644 --- a/lib/compiler_rt/sqrt.zig +++ b/lib/compiler_rt/sqrt.zig @@ -523,15 +523,15 @@ const rsqrt_tab: [128]u16 = .{ }; inline fn mul16(a: u16, b: u16) u16 { - return @intCast(@as(u32, a) * b >> 16); + return @intCast((@as(u32, a) * b) >> 16); } inline fn mul32(a: u32, b: u32) u32 { - return @intCast(@as(u64, a) * b >> 32); + return @intCast((@as(u64, a) * b) >> 32); } inline fn mul64(a: u64, b: u64) u64 { - return @intCast(@as(u128, a) * b >> 64); + return @intCast((@as(u128, a) * b) >> 64); } inline fn mul80(a: u80, b: u80) u80 { @@ -539,7 +539,7 @@ inline fn mul80(a: u80, b: u80) u80 { const alo = a & 0xFF_FFFF_FFFF; const bhi = b >> 40; const blo = b & 0xFF_FFFF_FFFF; - return ahi * bhi + (ahi * blo >> 40) + (alo * bhi >> 40); + return ahi * bhi + ((ahi * blo) >> 40) + ((alo * bhi) >> 40); } inline fn mul128(a: u128, b: u128) u128 { @@ -547,7 +547,7 @@ inline fn mul128(a: u128, b: u128) u128 { const alo = a & 0xFFFF_FFFF_FFFF_FFFF; const bhi = b >> 64; const blo = b & 0xFFFF_FFFF_FFFF_FFFF; - return ahi * bhi + (ahi * blo >> 64) + (alo * bhi >> 64); + return ahi * bhi + ((ahi * blo) >> 64) + ((alo * bhi) >> 64); } inline fn mul80_tail(a: u80, b: u80) u80 { diff --git a/lib/compiler_rt/truncf.zig b/lib/compiler_rt/truncf.zig index 9a1cb491e27bc214a2c5c7a4a91f8f236efae1ef..cd8e8cc2bd5088d71b9471d8112bf4266ec6d02a 100644 --- a/lib/compiler_rt/truncf.zig +++ b/lib/compiler_rt/truncf.zig @@ -279,7 +279,7 @@ inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { absResult = 0; } else { const sticky: src_rep_t = @intFromBool(significand << @intCast(srcBits - shift) != 0); - const denormalizedSignificand: src_rep_t = significand >> @intCast(shift) | sticky; + const denormalizedSignificand: src_rep_t = (significand >> @intCast(shift)) | sticky; absResult = @intCast(denormalizedSignificand >> (srcSigBits - dstSigBits)); const roundBits: src_rep_t = denormalizedSignificand & roundMask; if (roundBits > halfway) { @@ -362,7 +362,7 @@ inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { abs_result = 0; } else { const sticky = @intFromBool(a_rep.fraction << @intCast(shift) != 0); - const denormalized_significand = a_rep.fraction >> @intCast(shift) | sticky; + const denormalized_significand = (a_rep.fraction >> @intCast(shift)) | sticky; abs_result = @intCast(denormalized_significand >> (src_sig_bits - dst_sig_bits)); const round_bits = denormalized_significand & round_mask; if (round_bits > halfway) { @@ -375,7 +375,7 @@ inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { } } - const result align(@alignOf(dst_t)) = abs_result | @as(dst_rep_t, sign) << dst_bits - 16; + const result align(@alignOf(dst_t)) = abs_result | (@as(dst_rep_t, sign) << (dst_bits - 16)); return @bitCast(result); } diff --git a/lib/std/Io/Dispatch.zig b/lib/std/Io/Dispatch.zig index 41236b214ec68db199e0693c142adb7c3a822303..9ae2985c948dbd5e149b21654b88d1faf2b22fa9 100644 --- a/lib/std/Io/Dispatch.zig +++ b/lib/std/Io/Dispatch.zig @@ -1931,10 +1931,10 @@ const BatchWaiter = struct { fn batchAwaitAsync(userdata: ?*anyopaque, batch: *Io.Batch) Io.Cancelable!void { const ev: *Evented = @ptrCast(@alignCast(userdata)); - const queue = ev.batchDrainSubmitted(batch, false) catch |err| switch (err) { + const queue = (ev.batchDrainSubmitted(batch, false) catch |err| switch (err) { error.ConcurrencyUnavailable => unreachable, // passed concurrency=false error.Canceled => |e| return e, - } orelse return; + }) orelse return; if (batch.pending.head == .none) return; var waiter: BatchWaiter = .{ .sleeper = .init(ev.queue, Thread.current().currentFiber()), diff --git a/lib/std/Io/Kqueue.zig b/lib/std/Io/Kqueue.zig index 20e7820d0611c944701b599f703ddcd8424e541d..b4d2417848a06b42d2f5b3fe341f6816a48995cf 100644 --- a/lib/std/Io/Kqueue.zig +++ b/lib/std/Io/Kqueue.zig @@ -164,7 +164,7 @@ pub const InitError = Allocator.Error || CreateFileDescriptorError; pub fn init(k: *Kqueue, gpa: Allocator, options: InitOptions) !void { assert(options.n_threads != 0); - const n_threads = @max(1, options.n_threads orelse std.Thread.getCpuCount() catch 1); + const n_threads = @max(1, options.n_threads orelse (std.Thread.getCpuCount() catch 1)); const threads_size = n_threads * @sizeOf(Thread); const idle_stack_end_offset = std.mem.alignForward(usize, threads_size + idle_stack_size, std.heap.page_size_max); const allocated_slice = try gpa.alignedAlloc(u8, .of(Thread), idle_stack_end_offset); diff --git a/lib/std/Io/Threaded/test.zig b/lib/std/Io/Threaded/test.zig index 2f2da58252b540df458c26262218a2e4fbf11329..8580f792089a4a8e5b981a49d1296b5fc66cd8da 100644 --- a/lib/std/Io/Threaded/test.zig +++ b/lib/std/Io/Threaded/test.zig @@ -36,7 +36,7 @@ fn put(io: Io, queue: *Io.Queue(u8)) void { } fn get(io: Io, queue: *Io.Queue(u8)) void { - assert(queue.getOneUncancelable(io) catch unreachable == 42); + assert((queue.getOneUncancelable(io) catch unreachable) == 42); } test "concurrent vs concurrent prevents deadlock via oversubscription" { diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index fc9f6e6052aa49aff5a5fdf7e22cee25073cc681..aa38dbc8430198e3cc7510c64c30996cd9cde12a 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -1827,7 +1827,7 @@ pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precisi // Restore the alignment. mantissa <<= @as(std.math.Log2Int(TU), @intCast((mantissa_digits - precision) * 4)); - const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0; + const overflow = mantissa & (1 << (1 + mantissa_digits * 4)) != 0; // Prefer a normalized result in case of overflow. if (overflow) { mantissa >>= 1; diff --git a/lib/std/Io/net/HostName.zig b/lib/std/Io/net/HostName.zig index 81f239948a6426404be3329660e68647bd75060c..0ebe427f75cb5a5b3aede4aa5e3be78128321451 100644 --- a/lib/std/Io/net/HostName.zig +++ b/lib/std/Io/net/HostName.zig @@ -230,7 +230,7 @@ pub fn expand(noalias packet: []const u8, start_i: usize, noalias dest_buffer: [ i += 1 + label_len; } else { return .{ - len orelse i - start_i + 1, + len orelse (i - start_i + 1), try .init(dest[0..dest_i]), }; } diff --git a/lib/std/base64.zig b/lib/std/base64.zig index 9771436f45b4943669910077e2938a34eae1cd08..3c3ca62ea20025167e4be1402df9205028a729d9 100644 --- a/lib/std/base64.zig +++ b/lib/std/base64.zig @@ -148,7 +148,7 @@ pub const Base64Encoder = struct { if (idx + 2 < source.len) { dest[out_idx] = encoder.alphabet_chars[source[idx] >> 2]; dest[out_idx + 1] = encoder.alphabet_chars[((source[idx] & 0x3) << 4) | (source[idx + 1] >> 4)]; - dest[out_idx + 2] = encoder.alphabet_chars[(source[idx + 1] & 0xf) << 2 | (source[idx + 2] >> 6)]; + dest[out_idx + 2] = encoder.alphabet_chars[((source[idx + 1] & 0xf) << 2) | (source[idx + 2] >> 6)]; dest[out_idx + 3] = encoder.alphabet_chars[source[idx + 2] & 0x3f]; out_idx += 4; } else if (idx + 1 < source.len) { @@ -282,7 +282,7 @@ pub const Base64Decoder = struct { dest_idx += 1; } } - if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) { + if (acc_len > 4 or (acc & ((@as(u12, 1) << acc_len) - 1)) != 0) { return error.InvalidPadding; } if (leftover_idx == null) return; @@ -357,7 +357,7 @@ pub const Base64DecoderWithIgnore = struct { dest_idx += 1; } } - if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) { + if (acc_len > 4 or (acc & ((@as(u12, 1) << acc_len) - 1)) != 0) { return error.InvalidPadding; } const padding_len = acc_len / 2; diff --git a/lib/std/bit_set.zig b/lib/std/bit_set.zig index b74cb49f0659b0693ee9f1b1cd3ba8298a22f319..1326570c1c6583e2c0cad45e3668f929195bacdf 100644 --- a/lib/std/bit_set.zig +++ b/lib/std/bit_set.zig @@ -468,11 +468,11 @@ pub fn Array(comptime MaskIntType: type, comptime size: usize) type { if (start_mask_index == end_mask_index) { var mask1 = std.math.boolMask(MaskInt, true) << start_bit; - var mask2 = std.math.boolMask(MaskInt, true) >> (mask_len - 1) - (end_bit - 1); + var mask2 = std.math.boolMask(MaskInt, true) >> ((mask_len - 1) - (end_bit - 1)); self.masks[start_mask_index] &= ~(mask1 & mask2); mask1 = std.math.boolMask(MaskInt, value) << start_bit; - mask2 = std.math.boolMask(MaskInt, value) >> (mask_len - 1) - (end_bit - 1); + mask2 = std.math.boolMask(MaskInt, value) >> ((mask_len - 1) - (end_bit - 1)); self.masks[start_mask_index] |= mask1 & mask2; } else { var bulk_mask_index: usize = undefined; @@ -875,11 +875,11 @@ pub const Dynamic = struct { if (start_mask_index == end_mask_index) { var mask1 = std.math.boolMask(MaskInt, true) << start_bit; - var mask2 = std.math.boolMask(MaskInt, true) >> (@bitSizeOf(MaskInt) - 1) - (end_bit - 1); + var mask2 = std.math.boolMask(MaskInt, true) >> ((@bitSizeOf(MaskInt) - 1) - (end_bit - 1)); self.masks[start_mask_index] &= ~(mask1 & mask2); mask1 = std.math.boolMask(MaskInt, value) << start_bit; - mask2 = std.math.boolMask(MaskInt, value) >> (@bitSizeOf(MaskInt) - 1) - (end_bit - 1); + mask2 = std.math.boolMask(MaskInt, value) >> ((@bitSizeOf(MaskInt) - 1) - (end_bit - 1)); self.masks[start_mask_index] |= mask1 & mask2; } else { var bulk_mask_index: usize = undefined; diff --git a/lib/std/coff.zig b/lib/std/coff.zig index a9a125f3e43e67a82dd509198bb396ee4e856f12..8bd58e906cac370b7885c97792636f3b38325802 100644 --- a/lib/std/coff.zig +++ b/lib/std/coff.zig @@ -2035,7 +2035,7 @@ pub const ArchiveMemberHeader = extern struct { if (trim.len == 0) return error.BadName; return if (trim[0] == '/') name: { if (trim.len == 1 or - trim.len == 2 and trim[1] == '/') + (trim.len == 2 and trim[1] == '/')) break :name trim; const offset = std.fmt.parseUnsigned(u50, trim[1..], 10) catch diff --git a/lib/std/compress/flate/Compress.zig b/lib/std/compress/flate/Compress.zig index 167bddd1b6923b2dd22fa2267c38c6e5118f8c39..3aade0c7c53b591f47e08812980e7223dbc764a3 100644 --- a/lib/std/compress/flate/Compress.zig +++ b/lib/std/compress/flate/Compress.zig @@ -1333,8 +1333,8 @@ const huffman = struct { const incomplete_allowed = smith.value(bool); while (nfreqs < @as(u8, @intFromBool(!incomplete_allowed)) + 1 or - nfreqs != freqs_buf.len and freqs_limit != 0 and - smith.eosWeightedSimple(15, 1)) + (nfreqs != freqs_buf.len and freqs_limit != 0 and + smith.eosWeightedSimple(15, 1))) { const f = smith.valueWeighted(u16, &.{ .rangeAtMost(u16, 0, @min(31, freqs_limit), @max(freqs_limit, 1)), diff --git a/lib/std/crypto/aes/soft.zig b/lib/std/crypto/aes/soft.zig index 35b9ed2cb5218b980037e4c146eebc74adb9dd26..c901ba548b79a14f932c8cf8af28949c60194dcf 100644 --- a/lib/std/crypto/aes/soft.zig +++ b/lib/std/crypto/aes/soft.zig @@ -728,7 +728,7 @@ pub const Aes256 = struct { // constants // Rijndael's irreducible polynomial. -const poly: u9 = 1 << 8 | 1 << 4 | 1 << 3 | 1 << 1 | 1 << 0; // x⁸ + x⁴ + x³ + x + 1 +const poly: u9 = (1 << 8) | (1 << 4) | (1 << 3) | (1 << 1) | (1 << 0); // x⁸ + x⁴ + x³ + x + 1 // Powers of x mod poly in GF(2). const powx = init: { diff --git a/lib/std/crypto/codecs/base64_hex_ct.zig b/lib/std/crypto/codecs/base64_hex_ct.zig index 3da08ceb25989747d6984d2f4017b8009543a865..8080eda2142d3fbc9286ce22b849ee46e54a7437 100644 --- a/lib/std/crypto/codecs/base64_hex_ct.zig +++ b/lib/std/crypto/codecs/base64_hex_ct.zig @@ -29,7 +29,7 @@ pub const hex = struct { const c: u16 = v & 0xf; const off = if (case == .upper) 32 else 0; const x = - ((87 - off + c + (((c -% 10) >> 8) & ~@as(u16, 38 - off))) & 0xff) << 8 | + (((87 - off + c + (((c -% 10) >> 8) & ~@as(u16, 38 - off))) & 0xff) << 8) | ((87 - off + b + (((b -% 10) >> 8) & ~@as(u16, 38 - off))) & 0xff); encoded[i * 2] = @truncate(x); encoded[i * 2 + 1] = @truncate(x >> 8); diff --git a/lib/std/crypto/ml_kem.zig b/lib/std/crypto/ml_kem.zig index 261b8f037f9b87131097e82e25db4ce31cc6af4d..70a306aa0f2c51a218f797119e85d112e727f144 100644 --- a/lib/std/crypto/ml_kem.zig +++ b/lib/std/crypto/ml_kem.zig @@ -1264,7 +1264,7 @@ const Poly = struct { const b1 = @as(i16, buf[3 * i + 1]); const b2 = @as(i16, buf[3 * i + 2]); ret.cs[2 * i] = b0 | ((b1 & 0xf) << 8); - ret.cs[2 * i + 1] = (b1 >> 4) | b2 << 4; + ret.cs[2 * i + 1] = (b1 >> 4) | (b2 << 4); } return ret; } diff --git a/lib/std/crypto/scrypt.zig b/lib/std/crypto/scrypt.zig index 9939188ebff47ad0a631255d7a2bf4be49c30e57..d99678d28002ff227fe9b6a37f46fb6f8dd156b7 100644 --- a/lib/std/crypto/scrypt.zig +++ b/lib/std/crypto/scrypt.zig @@ -82,7 +82,7 @@ fn blockMix(tmp: *align(16) [16]u32, in: []align(16) const u32, out: []align(16) fn integerify(b: []align(16) const u32, r: u30) u64 { const j = (2 * r - 1) * 16; - return @as(u64, b[j]) | @as(u64, b[j + 1]) << 32; + return @as(u64, b[j]) | (@as(u64, b[j + 1]) << 32); } fn smix(b: []align(16) u8, r: u30, n: usize, v: []align(16) u32, xy: []align(16) u32) void { diff --git a/lib/std/crypto/sha2.zig b/lib/std/crypto/sha2.zig index 3c5773af50fc827bc34cd10af4d90185d86f27d7..c390c0abbbfdc619ebd06323b3e44de7d2864f0d 100644 --- a/lib/std/crypto/sha2.zig +++ b/lib/std/crypto/sha2.zig @@ -557,7 +557,7 @@ fn Sha2x64(comptime iv: Iv64, digest_bits: comptime_int) type { } if (digest_bits % 8 != 0) @compileError("impl doesn't support non-byte digest_len"); - const bytes_left = digest_bits / 8 % 8; + const bytes_left = (digest_bits / 8) % 8; if (bytes_left > 0) { const rest = d.s[(digest_bits / 64)]; var buf: [8]u8 = undefined; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 0822957bc98e790b17f8b00835661bf0ba7f6ba1..5d709fdaa5435cf558b88a06229d09d64b036fce 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1306,7 +1306,7 @@ fn printLineInfo( try writer.print("0x{x} in {s} ({s})", .{ address, symbol.name orelse "???", - symbol.compile_unit_name orelse debug_info.getModuleName(io, address) catch "???", + symbol.compile_unit_name orelse (debug_info.getModuleName(io, address) catch "???"), }); t.setColor(.reset) catch {}; try writer.writeAll("\n"); diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index af6bf48aaa718c75eacb22abb4445ce1b1483a6a..68080d1f25380dec9cc49b69635bfd07b233b850 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -16,11 +16,11 @@ pub fn deinit(si: *SelfInfo, io: Io) void { const gpa = std.debug.getDebugInfoAllocator(); for (si.modules.items) |*mod| { unwind: { - const u = &(mod.unwind orelse break :unwind catch break :unwind); + const u = &((mod.unwind orelse break :unwind) catch break :unwind); for (u.buf[0..u.len]) |*unwind| unwind.deinit(gpa); } loaded: { - const l = &(mod.loaded_elf orelse break :loaded catch break :loaded); + const l = &((mod.loaded_elf orelse break :loaded) catch break :loaded); l.file.deinit(gpa); } } @@ -431,11 +431,11 @@ fn findModule(si: *SelfInfo, gpa: Allocator, io: Io, address: usize, lock: enum } for (si.modules.items) |*mod| { unwind: { - const u = &(mod.unwind orelse break :unwind catch break :unwind); + const u = &((mod.unwind orelse break :unwind) catch break :unwind); for (u.buf[0..u.len]) |*unwind| unwind.deinit(gpa); } loaded: { - const l = &(mod.loaded_elf orelse break :loaded catch break :loaded); + const l = &((mod.loaded_elf orelse break :loaded) catch break :loaded); l.file.deinit(gpa); } } diff --git a/lib/std/debug/SelfInfo/MachO.zig b/lib/std/debug/SelfInfo/MachO.zig index f68572d1ca07fab3f0a9249f1bdf42c85ba9ee2e..6f2e983a3e273cc8ec370e86a8af8190d6cb5f41 100644 --- a/lib/std/debug/SelfInfo/MachO.zig +++ b/lib/std/debug/SelfInfo/MachO.zig @@ -11,11 +11,11 @@ pub fn deinit(si: *SelfInfo, io: Io) void { const gpa = std.debug.getDebugInfoAllocator(); for (si.modules.keys()) |*module| { unwind: { - const u = &(module.unwind orelse break :unwind catch break :unwind); + const u = &((module.unwind orelse break :unwind) catch break :unwind); if (u.dwarf) |*dwarf| dwarf.deinit(gpa); } file: { - const f = &(module.file orelse break :file catch break :file); + const f = &((module.file orelse break :file) catch break :file); f.deinit(gpa); } } diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig index ae81cccae4304e3222e6a24208112c4da9b91aaa..6cf7b03341326e93200c11798648fd7dd7820548 100644 --- a/lib/std/debug/SelfInfo/Windows.zig +++ b/lib/std/debug/SelfInfo/Windows.zig @@ -280,7 +280,7 @@ const Module = struct { // we have no information to add to the address break :pdb; }; - const module = pdb.getModule(mod_index) catch |err| switch (err) { + const module = (pdb.getModule(mod_index) catch |err| switch (err) { error.InvalidDebugInfo, error.MissingDebugInfo, error.OutOfMemory, @@ -289,7 +289,7 @@ const Module = struct { error.ReadFailed, error.EndOfStream, => return error.InvalidDebugInfo, - } orelse { + }) orelse { return error.InvalidDebugInfo; // bad module index }; @@ -539,9 +539,9 @@ const Module = struct { } var opt_pdb: ?Pdb = pdb: { - const path = coff_obj.getPdbPath() catch { + const path = (coff_obj.getPdbPath() catch { return error.InvalidDebugInfo; - } orelse { + }) orelse { break :pdb null; }; const pdb_file_open_result = if (fs.path.isAbsolute(path)) res: { diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 37001e165729cd87af1fcdf9a93ae6d5d5ae0819..995a3d644905764993ec3574e2fb7d4708cf8a90 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -13,7 +13,7 @@ const posix = std.posix; /// Platform-specific functionality is available through the `inner` field. pub const DynLib = struct { const InnerType = switch (native_os) { - .linux => if (!builtin.link_libc or builtin.abi == .musl and builtin.link_mode == .static) + .linux => if (!builtin.link_libc or (builtin.abi == .musl and builtin.link_mode == .static)) ElfDynLib else DlDynLib, @@ -434,15 +434,15 @@ pub const ElfDynLib = struct { pub fn lookupAddress(self: *const ElfDynLib, vername: []const u8, name: []const u8) ?usize { const maybe_versym = if (self.verdef == null) null else self.versym; - const OK_TYPES = (1 << elf.STT_NOTYPE | 1 << elf.STT_OBJECT | 1 << elf.STT_FUNC | 1 << elf.STT_COMMON); - const OK_BINDS = (1 << elf.STB_GLOBAL | 1 << elf.STB_WEAK | 1 << elf.STB_GNU_UNIQUE); + const OK_TYPES = (1 << elf.STT_NOTYPE) | (1 << elf.STT_OBJECT) | (1 << elf.STT_FUNC) | (1 << elf.STT_COMMON); + const OK_BINDS = (1 << elf.STB_GLOBAL) | (1 << elf.STB_WEAK) | (1 << elf.STB_GNU_UNIQUE); switch (self.hash_table) { .dt_hash => |hashtab| { var i: usize = 0; while (i < hashtab[1]) : (i += 1) { - if (0 == (@as(u32, 1) << @as(u5, @intCast(self.syms[i].st_info & 0xf)) & OK_TYPES)) continue; - if (0 == (@as(u32, 1) << @as(u5, @intCast(self.syms[i].st_info >> 4)) & OK_BINDS)) continue; + if (0 == (@as(u32, 1) << @as(u5, @intCast(self.syms[i].st_info & 0xf))) & OK_TYPES) continue; + if (0 == (@as(u32, 1) << @as(u5, @intCast(self.syms[i].st_info >> 4))) & OK_BINDS) continue; if (0 == self.syms[i].st_shndx) continue; if (!mem.eql(u8, name, mem.sliceTo(self.strings + self.syms[i].st_name, 0))) continue; if (maybe_versym) |versym| { @@ -494,8 +494,8 @@ pub const ElfDynLib = struct { const symbol_index = current_index + gnu_hash_header.symoffset; const symbol = self.syms[symbol_index]; - if (0 == (@as(u32, 1) << @as(u5, @intCast(symbol.st_info & 0xf)) & OK_TYPES)) continue; - if (0 == (@as(u32, 1) << @as(u5, @intCast(symbol.st_info >> 4)) & OK_BINDS)) continue; + if (0 == (@as(u32, 1) << @as(u5, @intCast(symbol.st_info & 0xf))) & OK_TYPES) continue; + if (0 == (@as(u32, 1) << @as(u5, @intCast(symbol.st_info >> 4))) & OK_BINDS) continue; if (0 == symbol.st_shndx) continue; const symbol_name = mem.sliceTo(self.strings + symbol.st_name, 0); diff --git a/lib/std/fmt/parse_float/common.zig b/lib/std/fmt/parse_float/common.zig index 4c33a9081d040ed912b553c8287f8838090a306b..2f6813ed99af3a53dd7721a6aed83e21a0ac896c 100644 --- a/lib/std/fmt/parse_float/common.zig +++ b/lib/std/fmt/parse_float/common.zig @@ -82,7 +82,7 @@ pub fn isDigit(c: u8, comptime base: u8) bool { return if (base == 10) '0' <= c and c <= '9' else - '0' <= c and c <= '9' or 'a' <= c and c <= 'f' or 'A' <= c and c <= 'F'; + ('0' <= c and c <= '9') or ('a' <= c and c <= 'f') or ('A' <= c and c <= 'F'); } /// Returns the underlying storage type used for the mantissa of floating-point type. diff --git a/lib/std/hash/cityhash.zig b/lib/std/hash/cityhash.zig index 1acb039dab5551e4e0ef0b691c4d5ae8770bebb7..784db7d6551cfd3b52b02af931059989847d891f 100644 --- a/lib/std/hash/cityhash.zig +++ b/lib/std/hash/cityhash.zig @@ -222,7 +222,7 @@ pub const CityHash64 = struct { const c: u8 = str[str.len - 1]; const y: u32 = @as(u32, @intCast(a)) +% (@as(u32, @intCast(b)) << 8); const z: u32 = @as(u32, @truncate(str.len)) +% (@as(u32, @intCast(c)) << 2); - return shiftmix(@as(u64, @intCast(y)) *% k2 ^ @as(u64, @intCast(z)) *% k0) *% k2; + return shiftmix((@as(u64, @intCast(y)) *% k2) ^ (@as(u64, @intCast(z)) *% k0)) *% k2; } return k2; } diff --git a/lib/std/hash/xxhash.zig b/lib/std/hash/xxhash.zig index b33ac61b5bd233a0c6ccea59033d7ee6c2b62045..655b1f7ed2f6fb93e5efc166dbf41d580fc4498b 100644 --- a/lib/std/hash/xxhash.zig +++ b/lib/std/hash/xxhash.zig @@ -398,7 +398,7 @@ pub const XxHash32 = struct { } fn avalanche(value: u32) u32 { - var acc = value ^ value >> 15; + var acc = value ^ (value >> 15); acc *%= prime_2; acc ^= acc >> 13; acc *%= prime_3; diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index 58dc8524e8ac07e960a47186eb6d8dd3a49d3efd..aa67d22466d73754401603bb9a2b6c6cedde1d5d 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -2019,7 +2019,7 @@ test "getOrPutAdapted" { const AdaptedContext = struct { fn eql(self: @This(), adapted_key: []const u8, test_key: u64) bool { _ = self; - return std.fmt.parseInt(u64, adapted_key, 10) catch unreachable == test_key; + return (std.fmt.parseInt(u64, adapted_key, 10) catch unreachable) == test_key; } fn hash(self: @This(), adapted_key: []const u8) u64 { _ = self; diff --git a/lib/std/heap/SafeAllocator.zig b/lib/std/heap/SafeAllocator.zig index 91f65184241713f66a39953092d889cd2bed4b84..77457e8685046d0115e076ee44041c062d83662f 100644 --- a/lib/std/heap/SafeAllocator.zig +++ b/lib/std/heap/SafeAllocator.zig @@ -211,7 +211,7 @@ const Bucket = struct { fn of(s: *SafeAllocator, ptr: [*]u8) *Bucket { const size_log2 = s.bucket_size_log2; - return @ptrFromInt(@intFromPtr(ptr) >> @intCast(size_log2) << @intCast(size_log2)); + return @ptrFromInt((@intFromPtr(ptr) >> @intCast(size_log2)) << @intCast(size_log2)); } fn fillAt(s: *SafeAllocator, ptr: [*]const u8) u32 { diff --git a/lib/std/math.zig b/lib/std/math.zig index 27d5e0d584dca43e838d31eabec11ca2134045d9..627cc50ecb3deac16ec4bd542e8f847fded75e46 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -710,7 +710,7 @@ pub fn rotr(comptime T: type, x: T, r: anytype) T { if (comptime isPowerOfTwo(@typeInfo(T).int.bits)) { const ar: Log2Int(T) = @intCast(@mod(r, @typeInfo(T).int.bits)); - return x >> ar | x << (1 +% ~ar); + return (x >> ar) | (x << (1 +% ~ar)); } else { const ar = @mod(r, @typeInfo(T).int.bits); return shr(T, x, ar) | shl(T, x, @typeInfo(T).int.bits - ar); @@ -753,7 +753,7 @@ pub fn rotl(comptime T: type, x: T, r: anytype) T { if (comptime isPowerOfTwo(@typeInfo(T).int.bits)) { const ar: Log2Int(T) = @intCast(@mod(r, @typeInfo(T).int.bits)); - return x << ar | x >> 1 +% ~ar; + return (x << ar) | (x >> (1 +% ~ar)); } else { const ar = @mod(r, @typeInfo(T).int.bits); return shl(T, x, ar) | shr(T, x, @typeInfo(T).int.bits - ar); @@ -1542,21 +1542,21 @@ pub const Order = enum { const neg: i32 = -1; const zero: i32 = 0; const pos: i32 = 1; - try testing.expect(order(zero, neg).differ() orelse - order(pos, zero) == .gt); - try testing.expect(order(zero, zero).differ() orelse - order(zero, zero) == .eq); - try testing.expect(order(pos, pos).differ() orelse - order(neg, zero) == .lt); - try testing.expect(order(zero, zero).differ() orelse + try testing.expect((order(zero, neg).differ() orelse + order(pos, zero)) == .gt); + try testing.expect((order(zero, zero).differ() orelse + order(zero, zero)) == .eq); + try testing.expect((order(pos, pos).differ() orelse + order(neg, zero)) == .lt); + try testing.expect((order(zero, zero).differ() orelse order(pos, neg).differ() orelse - order(neg, zero) == .gt); - try testing.expect(order(pos, pos).differ() orelse + order(neg, zero)) == .gt); + try testing.expect((order(pos, pos).differ() orelse order(pos, pos).differ() orelse - order(neg, neg) == .eq); - try testing.expect(order(zero, pos).differ() orelse + order(neg, neg)) == .eq); + try testing.expect((order(zero, pos).differ() orelse order(neg, pos).differ() orelse - order(pos, neg) == .lt); + order(pos, neg)) == .lt); } pub fn compare(self: Order, op: CompareOperator) bool { diff --git a/lib/std/math/acos.zig b/lib/std/math/acos.zig index d79c36182e0aa6ebd784c45f56c0232905a9c1a2..40fdef0b3d5b697a41dd60a1399e53340bfab620 100644 --- a/lib/std/math/acos.zig +++ b/lib/std/math/acos.zig @@ -176,7 +176,7 @@ fn acosBinary64(x: f64) f64 { // |x| >= 1 or nan if (ix >= 0x3ff0_0000) { const lx: u32 = @truncate(@as(u64, @bitCast(x))); - if ((ix - 0x3ff0_0000 | lx) == 0) { + if (((ix - 0x3ff0_0000) | lx) == 0) { if (hx >> 31 != 0) { return 2.0 * pio2_hi + 0x1.0p-120; } diff --git a/lib/std/math/asin.zig b/lib/std/math/asin.zig index dfd3f063954c68d25230993b0875873273eb9ff8..917c04216b49715e29b15b797e5aa02a07d8dead 100644 --- a/lib/std/math/asin.zig +++ b/lib/std/math/asin.zig @@ -156,7 +156,7 @@ fn asinBinary64(x: f64) f64 { if (ix >= 0x3ff0_0000) { const lx: u32 = @truncate(@as(u64, @bitCast(x))); // asin(1) = +-pi/2 with inexact - if ((ix - 0x3ff0_0000 | lx) == 0) { + if (((ix - 0x3ff0_0000) | lx) == 0) { return x * pio2_hi + 0x1.0p-120; } return 0.0 / (x - x); diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index ba0ea5807b95a6f4fe287373763b7260f08caac8..2c2e57d150d07c566b49b6f8712cf3a20d583cfd 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -2401,7 +2401,7 @@ pub const Const = struct { const shift: usize = @intCast(exponent - @bitSizeOf(Repr.Normalized.Fraction)); mantissa.shiftRight(normalized_abs, shift); const final_limb_index = (shift - 1) / limb_bits; - const round_bits = normalized_abs.limbs[final_limb_index] << @truncate(-%shift) | + const round_bits = (normalized_abs.limbs[final_limb_index] << @truncate(-%shift)) | @intFromBool(!std.mem.allEqual(Limb, normalized_abs.limbs[0..final_limb_index], 0)); if (round_bits == 0) break :exactness .exact; round: switch (round) { @@ -4902,10 +4902,10 @@ test "format" { try a.set(20000000000000000000); // > maxInt(u64) try testFormat(a, "20000000000000000000"); - try a.set(1 << 64 * @sizeOf(usize) * 8); + try a.set(1 << (64 * @sizeOf(usize) * 8)); try testFormat(a, "(BigInt)"); - try a.set(-(1 << 64 * @sizeOf(usize) * 8)); + try a.set(-(1 << (64 * @sizeOf(usize) * 8))); try testFormat(a, "(BigInt)"); } diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 271041e761a1d6f089c7733aa2964913c771dc0d..1660b3bdfc98479e1dd0169b9c7b712273b5837f 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -2489,14 +2489,14 @@ test "truncate to minimum signed integer" { .len = undefined, .positive = undefined, }; - res.truncate(.{ .positive = true, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .signed, @bitSizeOf(Limb)); - try testing.expect(res.toConst().orderAgainstScalar(-1 << @bitSizeOf(Limb) - 1).compare(.eq)); - res.truncate(.{ .positive = false, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .signed, @bitSizeOf(Limb)); - try testing.expect(res.toConst().orderAgainstScalar(-1 << @bitSizeOf(Limb) - 1).compare(.eq)); - res.truncate(.{ .positive = true, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .unsigned, @bitSizeOf(Limb)); - try testing.expect(res.toConst().orderAgainstScalar(1 << @bitSizeOf(Limb) - 1).compare(.eq)); - res.truncate(.{ .positive = false, .limbs = &.{1 << @bitSizeOf(Limb) - 1} }, .unsigned, @bitSizeOf(Limb)); - try testing.expect(res.toConst().orderAgainstScalar(1 << @bitSizeOf(Limb) - 1).compare(.eq)); + res.truncate(.{ .positive = true, .limbs = &.{1 << (@bitSizeOf(Limb) - 1)} }, .signed, @bitSizeOf(Limb)); + try testing.expect(res.toConst().orderAgainstScalar(-1 << (@bitSizeOf(Limb) - 1)).compare(.eq)); + res.truncate(.{ .positive = false, .limbs = &.{1 << (@bitSizeOf(Limb) - 1)} }, .signed, @bitSizeOf(Limb)); + try testing.expect(res.toConst().orderAgainstScalar(-1 << (@bitSizeOf(Limb) - 1)).compare(.eq)); + res.truncate(.{ .positive = true, .limbs = &.{1 << (@bitSizeOf(Limb) - 1)} }, .unsigned, @bitSizeOf(Limb)); + try testing.expect(res.toConst().orderAgainstScalar(1 << (@bitSizeOf(Limb) - 1)).compare(.eq)); + res.truncate(.{ .positive = false, .limbs = &.{1 << (@bitSizeOf(Limb) - 1)} }, .unsigned, @bitSizeOf(Limb)); + try testing.expect(res.toConst().orderAgainstScalar(1 << (@bitSizeOf(Limb) - 1)).compare(.eq)); } test "saturate single signed positive" { @@ -3880,7 +3880,7 @@ test "clz" { try testing.expectEqual(0, neg_limb_max_squared_plus_one.clz(@bitSizeOf(Limb) * 2 + 1)); const neg_limb_msb_squared: std.math.big.int.Const = .{ - .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 }, + .limbs = &.{ 0, 1 << (@bitSizeOf(Limb) - 2) }, .positive = false, }; try testing.expectEqual(0, neg_limb_msb_squared.clz(@bitSizeOf(Limb) * 2)); @@ -3896,7 +3896,7 @@ test "clz" { try testing.expectEqual(0, neg_limb_max.clz(@bitSizeOf(Limb) * 2 + 1)); const neg_limb_msb: std.math.big.int.Const = .{ - .limbs = &.{1 << @bitSizeOf(Limb) - 1}, + .limbs = &.{1 << (@bitSizeOf(Limb) - 1)}, .positive = false, }; try testing.expectEqual(0, neg_limb_msb.clz(@bitSizeOf(Limb))); @@ -3936,7 +3936,7 @@ test "clz" { try testing.expectEqual(@bitSizeOf(Limb) * 2, one.clz(@bitSizeOf(Limb) * 2 + 1)); const limb_msb: std.math.big.int.Const = .{ - .limbs = &.{1 << @bitSizeOf(Limb) - 1}, + .limbs = &.{1 << (@bitSizeOf(Limb) - 1)}, .positive = true, }; try testing.expectEqual(0, limb_msb.clz(@bitSizeOf(Limb))); @@ -3956,7 +3956,7 @@ test "clz" { try testing.expectEqual(@bitSizeOf(Limb) + 1, limb_max.clz(@bitSizeOf(Limb) * 2 + 1)); const limb_msb_squared: std.math.big.int.Const = .{ - .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 }, + .limbs = &.{ 0, 1 << (@bitSizeOf(Limb) - 2) }, .positive = true, }; try testing.expectEqual(0, limb_msb_squared.clz(@bitSizeOf(Limb) * 2 - 1)); @@ -3992,7 +3992,7 @@ test "ctz" { try testing.expectEqual(@bitSizeOf(Limb) + 1, neg_limb_max_squared_plus_one.ctz(@bitSizeOf(Limb) * 2 + 1)); const neg_limb_msb_squared: std.math.big.int.Const = .{ - .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 }, + .limbs = &.{ 0, 1 << (@bitSizeOf(Limb) - 2) }, .positive = false, }; try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, neg_limb_msb_squared.ctz(@bitSizeOf(Limb) * 2)); @@ -4008,7 +4008,7 @@ test "ctz" { try testing.expectEqual(0, neg_limb_max.ctz(@bitSizeOf(Limb) * 2 + 1)); const neg_limb_msb: std.math.big.int.Const = .{ - .limbs = &.{1 << @bitSizeOf(Limb) - 1}, + .limbs = &.{1 << (@bitSizeOf(Limb) - 1)}, .positive = false, }; try testing.expectEqual(@bitSizeOf(Limb) - 1, neg_limb_msb.ctz(@bitSizeOf(Limb))); @@ -4048,7 +4048,7 @@ test "ctz" { try testing.expectEqual(0, one.ctz(@bitSizeOf(Limb) * 2 + 1)); const limb_msb: std.math.big.int.Const = .{ - .limbs = &.{1 << @bitSizeOf(Limb) - 1}, + .limbs = &.{1 << (@bitSizeOf(Limb) - 1)}, .positive = true, }; try testing.expectEqual(@bitSizeOf(Limb) - 1, limb_msb.ctz(@bitSizeOf(Limb))); @@ -4068,7 +4068,7 @@ test "ctz" { try testing.expectEqual(0, limb_max.ctz(@bitSizeOf(Limb) * 2 + 1)); const limb_msb_squared: std.math.big.int.Const = .{ - .limbs = &.{ 0, 1 << @bitSizeOf(Limb) - 2 }, + .limbs = &.{ 0, 1 << (@bitSizeOf(Limb) - 2) }, .positive = true, }; try testing.expectEqual(@bitSizeOf(Limb) * 2 - 2, limb_msb_squared.ctz(@bitSizeOf(Limb) * 2 - 1)); diff --git a/lib/std/math/float.zig b/lib/std/math/float.zig index 0b16875cc3559756a91ac10f96afee9d9a9fb5f1..afbf9ccf2a10b2d79e988f89365483478e4933cc 100644 --- a/lib/std/math/float.zig +++ b/lib/std/math/float.zig @@ -281,7 +281,7 @@ pub inline fn nan(comptime Type: type) Type { return reconstructFloat( RuntimeType, floatExponentMax(RuntimeType) + 1, - mantissaOne(RuntimeType) | 1 << (floatFractionalBits(RuntimeType) - 1), + mantissaOne(RuntimeType) | (1 << (floatFractionalBits(RuntimeType) - 1)), ); } @@ -297,7 +297,7 @@ pub inline fn snan(comptime Type: type) Type { return reconstructFloat( RuntimeType, floatExponentMax(RuntimeType) + 1, - mantissaOne(RuntimeType) | 1 << (floatFractionalBits(RuntimeType) - 2), + mantissaOne(RuntimeType) | (1 << (floatFractionalBits(RuntimeType) - 2)), ); } diff --git a/lib/std/mem.zig b/lib/std/mem.zig index a679291dba1bcae6e79286ad3b7b199562f68695..ce4523c71cc6d24ad79f8e48bce3b2117522aa01 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -4354,7 +4354,7 @@ pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize { @compileError("expected many item pointer, got " ++ @typeName(T)); // Do nothing if the pointer is already well-aligned. - if (align_to <= info.pointer.attrs.@"align" orelse @alignOf(info.pointer.child)) + if (align_to <= (info.pointer.attrs.@"align" orelse @alignOf(info.pointer.child))) return 0; // Calculate the aligned base address with an eye out for overflow. diff --git a/lib/std/os/linux/vdso.zig b/lib/std/os/linux/vdso.zig index 5add23f5c42bd6f93cfdc39825b42cc969d8e321..21546043d5d2614852127dd9dca0beca5aaff29f 100644 --- a/lib/std/os/linux/vdso.zig +++ b/lib/std/os/linux/vdso.zig @@ -62,13 +62,13 @@ pub fn lookup(vername: []const u8, name: []const u8) usize { const hashtab = maybe_hashtab orelse return 0; if (maybe_verdef == null) maybe_versym = null; - const OK_TYPES = (1 << elf.STT_NOTYPE | 1 << elf.STT_OBJECT | 1 << elf.STT_FUNC | 1 << elf.STT_COMMON); - const OK_BINDS = (1 << elf.STB_GLOBAL | 1 << elf.STB_WEAK | 1 << elf.STB_GNU_UNIQUE); + const OK_TYPES = (1 << elf.STT_NOTYPE) | (1 << elf.STT_OBJECT) | (1 << elf.STT_FUNC) | (1 << elf.STT_COMMON); + const OK_BINDS = (1 << elf.STB_GLOBAL) | (1 << elf.STB_WEAK) | (1 << elf.STB_GNU_UNIQUE); var i: usize = 0; while (i < hashtab[1]) : (i += 1) { - if (0 == (@as(u32, 1) << @as(u5, @intCast(syms[i].st_info & 0xf)) & OK_TYPES)) continue; - if (0 == (@as(u32, 1) << @as(u5, @intCast(syms[i].st_info >> 4)) & OK_BINDS)) continue; + if (0 == (@as(u32, 1) << @as(u5, @intCast(syms[i].st_info & 0xf))) & OK_TYPES) continue; + if (0 == (@as(u32, 1) << @as(u5, @intCast(syms[i].st_info >> 4))) & OK_BINDS) continue; if (0 == syms[i].st_shndx) continue; const sym_name = @as([*:0]u8, @ptrCast(strings + syms[i].st_name)); if (!mem.eql(u8, name, mem.sliceTo(sym_name, 0))) continue; diff --git a/lib/std/os/uefi/status.zig b/lib/std/os/uefi/status.zig index 2e17ef64c98a6af1a43e44a88deb8f0d0eb72ea7..b48694c22eb854613cd1cea3b20d0c9103c784f4 100644 --- a/lib/std/os/uefi/status.zig +++ b/lib/std/os/uefi/status.zig @@ -1,6 +1,6 @@ const testing = @import("std").testing; -const high_bit = 1 << @typeInfo(usize).int.bits - 1; +const high_bit = 1 << (@typeInfo(usize).int.bits - 1); pub const Status = enum(usize) { /// The operation completed successfully. diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig index a6cd094800cc0a77fcd84394bc08736df7352b0f..9929be13e9ac09c0904c378cfe4248717a27973c 100644 --- a/lib/std/unicode.zig +++ b/lib/std/unicode.zig @@ -485,7 +485,7 @@ pub fn utf16DecodeSurrogatePair(surrogate_pair: []const u16) !u21 { const high_half: u21 = surrogate_pair[0]; const low_half = surrogate_pair[1]; if (!utf16IsLowSurrogate(low_half)) return error.ExpectedSecondSurrogateHalf; - return 0x10000 + ((high_half & 0x03ff) << 10) | (low_half & 0x03ff); + return (0x10000 + ((high_half & 0x03ff) << 10)) | (low_half & 0x03ff); } pub const Utf16LeIterator = struct { diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index a0a2dda60d90503e92394892a82677b0d44a045a..14a16e1730564aa7add9e659dc81a76175b5a95c 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -555,6 +555,33 @@ pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void .var_const_decl => { return w.writeAll("use 'var' or 'const' to declare variable"); }, + .ambiguous_operator_precedence => { + return w.print("ambiguous operator precedence with operators … {s} … {s} …; use parentheses to disambiguate", .{ + tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, + tree.tokenTag(parse_error.token).lexeme().?, + }); + }, + .previous_ambiguous_operator => { + return w.writeAll("previous ambiguous operator here"); + }, + .illegal_chained_operators => { + return w.print("repetition of non-chainable operators … {s} … {s} …; use parentheses to disambiguate", .{ + tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, + tree.tokenTag(parse_error.token).lexeme().?, + }); + }, + .hint_operator_precedence_left => { + return w.print("did you mean `(… {s} …) {s} …` ?", .{ + tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, + tree.tokenTag(parse_error.token).lexeme().?, + }); + }, + .hint_operator_precedence_right => { + return w.print("did you mean `… {s} (… {s} …)` ?", .{ + tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, + tree.tokenTag(parse_error.token).lexeme().?, + }); + }, .invalid_byte => { const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..]; @@ -2893,6 +2920,11 @@ pub const Error = struct { expected_var_const, wrong_equal_var_decl, var_const_decl, + ambiguous_operator_precedence, + previous_ambiguous_operator, + hint_operator_precedence_left, + hint_operator_precedence_right, + illegal_chained_operators, zig_style_container, previous_field, diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig index 79916610ecfb2112fb077e07e5d6a230761fea3a..f4cfed386044725ea7074d584d1879ac42b33777 100644 --- a/lib/std/zig/Ast/Render.zig +++ b/lib/std/zig/Ast/Render.zig @@ -1483,9 +1483,9 @@ fn renderThenElse( last_else_token = error_token + 1; // | } - const indent_else_expr = indent_then_expr and + const indent_else_expr = (indent_then_expr and !nodeIsBlock(tree.nodeTag(else_expr)) and - !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr)) or + !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr))) or tree.tokenTag(tree.firstToken(else_expr)) == .multiline_string_literal_line; if (indent_else_expr) { @@ -3195,7 +3195,7 @@ fn renderComments(r: *Render, start: usize, end: usize) Error!bool { } } - index = 1 + (newline orelse end - 1); + index = 1 + (newline orelse (end - 1)); const comment_content = mem.trimStart(u8, trimmed_comment["//".len..], &std.ascii.whitespace); if (ais.disabled_offset != null and mem.eql(u8, comment_content, "zig fmt: on")) { diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index facb74a006b5389a61bcc6a089234028fa0b1128..79e90e487284339b5a438e15bbdb8fc40b9a27ef 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -1512,7 +1512,7 @@ fn expectAssignExpr(p: *Parse) !Node.Index { } fn parseExpr(p: *Parse) Error!?Node.Index { - return p.parseExprPrecedence(0); + return p.parseExprPrecedence(.start, p.tok_i); } fn expectExpr(p: *Parse) Error!Node.Index { @@ -1524,67 +1524,317 @@ const Assoc = enum { none, }; +const PrecClass = struct { + group: Group, + assoc: Assoc = Assoc.left, + + const Group = enum { + const num_distinct = std.meta.fieldNames(Group).len; + + arithmetic_product_chainable, + arithmetic_mod_nonchainable, + arithmetic_sum, + + bitwise_shift, + bitwise_and, + bitwise_xor, + bitwise_or, + + comparison, + + bool_and, + bool_or, + + recovery_orelse, + recovery_catch, + + root, + + /// For this to work correctly we require that all subgroups are strictly adjacent + /// Major groups are defined by the first text before an underscore + const Major: type = b: { + var major_names: []const []const u8 = &.{}; + for (std.meta.fieldNames(Group)) |fieldname| { + var major_name: []const u8 = fieldname[0..]; + for (fieldname, 0..) |c, i| { + if (c == '_') { + major_name = fieldname[0..i]; + break; + } + } + if (major_names.len == 0 or !std.mem.eql(u8, major_name, major_names[major_names.len - 1])) { + major_names = major_names ++ &[1][]const u8{major_name}; + } + } + + const IntType = std.math.IntFittingRange(0, major_names.len - 1); + var values: [major_names.len]IntType = undefined; + for (0..major_names.len) |i| values[i] = i; + + break :b @Enum( + IntType, + .exhaustive, + major_names, + &values, + ); + }; + }; + + pub const start: PrecClass = .{ .group = .root }; + + pub const Rel = enum(i2) { + lt = -1, + eq = 0, + gt = 1, + + fn inverted(self: Rel) Rel { + return @enumFromInt(-@intFromEnum(self)); + } + }; + + const PrecedenceArray = [Group.num_distinct][Group.num_distinct]?Rel; + + fn setMajorRelation(prec_array: *PrecedenceArray, major_a: Group.Major, rel: Rel, major_b: Group.Major) void { + for (std.meta.fieldNames(Group), 0..) |fieldname_i, i| { + if (!std.mem.startsWith(u8, fieldname_i, @tagName(major_a))) continue; + + for (std.meta.fieldNames(Group), 0..) |fieldname_j, j| { + if (!std.mem.startsWith(u8, fieldname_j, @tagName(major_b))) continue; + + prec_array.*[i][j] = rel; + } + } + } + + fn setMinorRelation(prec_array: *PrecedenceArray, minor_a: Group, rel: Rel, minor_b: Group) void { + prec_array.*[@intFromEnum(minor_a)][@intFromEnum(minor_b)] = rel; + } + + /// Arithmetic_* > Comparison + /// Bitwise_* > Comparison + /// Comparison > Bool_* > Root + /// Recovery > Root + /// + /// *_Product > *_Sum + /// + /// order[y][x] --> y cmp x + const precedence_ordering = b: { + @setEvalBranchQuota(20_000); + const major_greater_than_relations = [_][2]Group.Major{ + // zig fmt: off + .{ .arithmetic, .comparison }, + .{ .bitwise, .comparison }, + .{ .comparison, .bool }, + .{ .bool, .root }, + .{ .recovery, .root }, + // zig fmt: on + }; + + var order: PrecedenceArray = @splat(@splat(null)); + + for (major_greater_than_relations) |relation| { + setMajorRelation(&order, relation[0], .gt, relation[1]); + } + + setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum); + setMinorRelation(&order, .arithmetic_product_chainable, .gt, .arithmetic_sum); + + computeTransativeOrdering(&order); + break :b order; + }; + + /// Uses the table from Zig-0.16.0 + /// * / % *% *| || + /// + - ++ +% -% +| -| + /// << >> <<| + /// & ^ | orelse catch + /// == != < > <= >= + /// and + /// or + const v16_precedence_ordering = b: { + @setEvalBranchQuota(20_000); + + var order: PrecedenceArray = @splat(@splat(null)); + + setMinorRelation(&order, .arithmetic_product_chainable, .eq, .arithmetic_mod_nonchainable); + setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum); + setMinorRelation(&order, .arithmetic_product_chainable, .gt, .arithmetic_sum); + + setMinorRelation(&order, .arithmetic_sum, .gt, .bitwise_shift); + + // Here since the transative ordering computer cant leverage equals to derive a = b < c --> a < c, we have to manually list these + setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_and); + setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_xor); + setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_or); + setMinorRelation(&order, .bitwise_shift, .gt, .recovery_catch); + setMinorRelation(&order, .bitwise_shift, .gt, .recovery_orelse); + + setMinorRelation(&order, .bitwise_and, .eq, .bitwise_xor); + setMinorRelation(&order, .bitwise_xor, .eq, .bitwise_or); + setMinorRelation(&order, .bitwise_or, .eq, .recovery_catch); + setMinorRelation(&order, .recovery_catch, .eq, .recovery_orelse); + setMinorRelation(&order, .recovery_orelse, .eq, .bitwise_and); + + setMinorRelation(&order, .bitwise_and, .gt, .comparison); + setMinorRelation(&order, .bitwise_xor, .gt, .comparison); + setMinorRelation(&order, .bitwise_or, .gt, .comparison); + setMinorRelation(&order, .recovery_catch, .gt, .comparison); + setMinorRelation(&order, .recovery_orelse, .gt, .comparison); + + setMinorRelation(&order, .comparison, .gt, .bool_and); + + setMinorRelation(&order, .bool_and, .gt, .bool_or); + + setMinorRelation(&order, .bool_or, .gt, .root); + + computeTransativeOrdering(&order); + for (order) |row| { + for (row) |item| { + if (item == null) @compileError("Null entry in old precedence ordering which had none."); + } + } + break :b order; + }; + + pub fn cmp(lhs: PrecClass, rhs: PrecClass) ?Rel { + return PrecClass.precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)]; + } + + pub fn v16_cmp(lhs: PrecClass, rhs: PrecClass) Rel { + return PrecClass.v16_precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)].?; + } + + fn computeTransativeOrdering(order: *PrecedenceArray) void { + for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| for (0..Group.num_distinct) |k| { + if (order[i][k] == order[k][j] and order[i][k] != null) order[i][j] = order[i][k]; + }; + for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| { + if (i == j) order[i][j] = .eq; + if (order[i][j] == null and order[j][i] != null) order[i][j] = order[j][i].?.inverted(); + }; + } +}; + const OperInfo = struct { - prec: i8, + prec: PrecClass, tag: Node.Tag, - assoc: Assoc = Assoc.left, }; -// A table of binary operator information. Higher precedence numbers are -// stickier. All operators at the same precedence level should have the same -// associativity. -const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec = -1, .tag = Node.Tag.root }, 0, .{ - .keyword_or = .{ .prec = 10, .tag = .bool_or }, - - .keyword_and = .{ .prec = 20, .tag = .bool_and }, - - .equal_equal = .{ .prec = 30, .tag = .equal_equal, .assoc = Assoc.none }, - .bang_equal = .{ .prec = 30, .tag = .bang_equal, .assoc = Assoc.none }, - .angle_bracket_left = .{ .prec = 30, .tag = .less_than, .assoc = Assoc.none }, - .angle_bracket_right = .{ .prec = 30, .tag = .greater_than, .assoc = Assoc.none }, - .angle_bracket_left_equal = .{ .prec = 30, .tag = .less_or_equal, .assoc = Assoc.none }, - .angle_bracket_right_equal = .{ .prec = 30, .tag = .greater_or_equal, .assoc = Assoc.none }, - - .ampersand = .{ .prec = 40, .tag = .bit_and }, - .caret = .{ .prec = 40, .tag = .bit_xor }, - .pipe = .{ .prec = 40, .tag = .bit_or }, - .keyword_orelse = .{ .prec = 40, .tag = .@"orelse" }, - .keyword_catch = .{ .prec = 40, .tag = .@"catch" }, - - .angle_bracket_angle_bracket_left = .{ .prec = 50, .tag = .shl }, - .angle_bracket_angle_bracket_left_pipe = .{ .prec = 50, .tag = .shl_sat }, - .angle_bracket_angle_bracket_right = .{ .prec = 50, .tag = .shr }, - - .plus = .{ .prec = 60, .tag = .add }, - .minus = .{ .prec = 60, .tag = .sub }, - .plus_plus = .{ .prec = 60, .tag = .array_cat }, - .plus_percent = .{ .prec = 60, .tag = .add_wrap }, - .minus_percent = .{ .prec = 60, .tag = .sub_wrap }, - .plus_pipe = .{ .prec = 60, .tag = .add_sat }, - .minus_pipe = .{ .prec = 60, .tag = .sub_sat }, - - .pipe_pipe = .{ .prec = 70, .tag = .merge_error_sets }, - .asterisk = .{ .prec = 70, .tag = .mul }, - .slash = .{ .prec = 70, .tag = .div }, - .percent = .{ .prec = 70, .tag = .mod }, - .asterisk_percent = .{ .prec = 70, .tag = .mul_wrap }, - .asterisk_pipe = .{ .prec = 70, .tag = .mul_sat }, +const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec = .start, .tag = Node.Tag.root }, 0, .{ + // zig fmt: off + .keyword_or = .{ .prec = .{ .group = .bool_or }, .tag = .bool_or }, + + .keyword_and = .{ .prec = .{ .group = .bool_and }, .tag = .bool_and }, + + .equal_equal = .{ .prec = .{ .group = .comparison, .assoc = Assoc.none }, .tag = .equal_equal }, + .bang_equal = .{ .prec = .{ .group = .comparison, .assoc = Assoc.none }, .tag = .bang_equal }, + .angle_bracket_left = .{ .prec = .{ .group = .comparison, .assoc = Assoc.none }, .tag = .less_than }, + .angle_bracket_right = .{ .prec = .{ .group = .comparison, .assoc = Assoc.none }, .tag = .greater_than }, + .angle_bracket_left_equal = .{ .prec = .{ .group = .comparison, .assoc = Assoc.none }, .tag = .less_or_equal }, + .angle_bracket_right_equal = .{ .prec = .{ .group = .comparison, .assoc = Assoc.none }, .tag = .greater_or_equal }, + + .ampersand = .{ .prec = .{ .group = .bitwise_and }, .tag = .bit_and }, + .caret = .{ .prec = .{ .group = .bitwise_xor }, .tag = .bit_xor }, + .pipe = .{ .prec = .{ .group = .bitwise_or }, .tag = .bit_or }, + + .keyword_orelse = .{ .prec = .{ .group = .recovery_orelse }, .tag = .@"orelse" }, + .keyword_catch = .{ .prec = .{ .group = .recovery_catch }, .tag = .@"catch" }, + + .angle_bracket_angle_bracket_left = .{ .prec = .{ .group = .bitwise_shift, .assoc = Assoc.none }, .tag = .shl }, + .angle_bracket_angle_bracket_left_pipe = .{ .prec = .{ .group = .bitwise_shift, .assoc = Assoc.none }, .tag = .shl_sat }, + .angle_bracket_angle_bracket_right = .{ .prec = .{ .group = .bitwise_shift, .assoc = Assoc.none }, .tag = .shr }, + + .plus = .{ .prec = .{ .group = .arithmetic_sum }, .tag = .add }, + .minus = .{ .prec = .{ .group = .arithmetic_sum }, .tag = .sub }, + .plus_plus = .{ .prec = .{ .group = .arithmetic_sum }, .tag = .array_cat }, + .plus_percent = .{ .prec = .{ .group = .arithmetic_sum }, .tag = .add_wrap }, + .minus_percent = .{ .prec = .{ .group = .arithmetic_sum }, .tag = .sub_wrap }, + .plus_pipe = .{ .prec = .{ .group = .arithmetic_sum }, .tag = .add_sat }, + .minus_pipe = .{ .prec = .{ .group = .arithmetic_sum }, .tag = .sub_sat }, + + .pipe_pipe = .{ .prec = .{ .group = .arithmetic_product_chainable }, .tag = .merge_error_sets }, + .asterisk = .{ .prec = .{ .group = .arithmetic_product_chainable }, .tag = .mul }, + .slash = .{ .prec = .{ .group = .arithmetic_product_chainable }, .tag = .div }, + .asterisk_percent = .{ .prec = .{ .group = .arithmetic_product_chainable }, .tag = .mul_wrap }, + .asterisk_pipe = .{ .prec = .{ .group = .arithmetic_product_chainable }, .tag = .mul_sat }, + + .percent = .{ .prec = .{ .group = .arithmetic_mod_nonchainable, .assoc = Assoc.none }, .tag = .mod }, + // zig fmt: on }); -fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index { - assert(min_prec >= 0); +fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index { var node = try p.parsePrefixExpr() orelse return null; - var banned_prec: i8 = -1; + var prev_operator_token = prev_token_const; while (true) { const tok_tag = p.tokenTag(p.tok_i); - const info = operTable[@as(usize, @intCast(@backingInt(tok_tag)))]; - if (info.prec < min_prec) { + const info = operTable[@intFromEnum(tok_tag)]; + + const rel = info.prec.cmp(min_exc_prec) orelse b: { + const prev_op_tok_tag = p.tokenTag(prev_operator_token); + const prev_op_info = operTable[@intFromEnum(prev_op_tok_tag)]; + const v16_rel = prev_op_info.prec.v16_cmp(info.prec); + try p.warnMsg(.{ + .tag = .ambiguous_operator_precedence, + .is_note = false, + .token = p.tok_i, + .extra = .{ .offset = p.tok_i - prev_operator_token }, + }); + try p.warnMsg(.{ + .tag = .previous_ambiguous_operator, + .is_note = true, + .token = prev_operator_token, + }); + if (v16_rel == .gt or v16_rel == .eq) { + try p.warnMsg(.{ + .tag = .hint_operator_precedence_left, + .is_note = true, + .token = p.tok_i, + .extra = .{ .offset = p.tok_i - prev_operator_token }, + }); + } else { + try p.warnMsg(.{ + .tag = .hint_operator_precedence_right, + .is_note = true, + .token = p.tok_i, + .extra = .{ .offset = p.tok_i - prev_operator_token }, + }); + } + break :b .gt; + }; + + if (rel == .lt) { break; } - if (info.prec == banned_prec) { - return p.fail(.chained_comparison_operators); + + if (min_exc_prec.group == info.prec.group and min_exc_prec.assoc == .none and info.prec.assoc == .none) { + //Special cased check to maintain the old more helpful error for chained comparisons. + if (info.prec.group == .comparison) { + try p.warn(.chained_comparison_operators); + } else { + try p.warnMsg(.{ + .tag = .illegal_chained_operators, + .is_note = false, + .token = p.tok_i, + .extra = .{ .offset = p.tok_i - prev_operator_token }, + }); + try p.warnMsg(.{ + .tag = .previous_ambiguous_operator, + .is_note = true, + .token = prev_operator_token, + }); + try p.warnMsg(.{ + .tag = .hint_operator_precedence_left, + .is_note = true, + .token = p.tok_i, + .extra = .{ .offset = p.tok_i - prev_operator_token }, + }); + } + } + + if (rel == .eq) { + break; } const oper_token = p.nextToken(); @@ -1614,7 +1864,8 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index { } } - const rhs = try p.parseExprPrecedence(info.prec + 1) orelse { + prev_operator_token = oper_token; + const rhs = try p.parseExprPrecedence(info.prec, prev_operator_token) orelse { try p.warn(.expected_expr); return node; }; @@ -1624,10 +1875,6 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index { .main_token = oper_token, .data = .{ .node_and_node = .{ node, rhs } }, }); - - if (info.assoc == Assoc.none) { - banned_prec = info.prec; - } } return node; diff --git a/lib/std/zig/TokenSmith.zig b/lib/std/zig/TokenSmith.zig index cdc30da0f2f9cba86bf0b508d1f5b627f25feb9a..43829781aee29063c1493072ebd129ef0b671299 100644 --- a/lib/std/zig/TokenSmith.zig +++ b/lib/std/zig/TokenSmith.zig @@ -160,7 +160,7 @@ pub fn gen(smith: *Smith) TokenSmith { var no_period = false; var not_exponent = true; for (t.source_buf[t.source_len..][0..len], 0..) |*c, i| { - const invalid_period = no_period and c.* == '.' or i + 1 == len; + const invalid_period = (no_period and c.* == '.') or i + 1 == len; const is_exponent = c.* == '-' or c.* == '+'; const invalid_exponent = not_exponent and is_exponent; const valid_exponent = !not_exponent and is_exponent; diff --git a/lib/std/zig/llvm/BitcodeReader.zig b/lib/std/zig/llvm/BitcodeReader.zig index f32a85e01e36dd7176871fdac0fef32ee2d5a8e7..0e96d0ac5963d405384674d49bd94eeb88e017dc 100644 --- a/lib/std/zig/llvm/BitcodeReader.zig +++ b/lib/std/zig/llvm/BitcodeReader.zig @@ -404,7 +404,7 @@ fn readFixed(bc: *BitcodeReader, comptime T: type, bits: u7) !T { if (bc.bit_offset == 0) bc.bit_buffer = try bc.read32Bits(); const chunk_len = @min(@as(u6, 32) - bc.bit_offset, remaining); const chunk_mask = @as(u32, std.math.maxInt(u32)) >> @intCast(32 - chunk_len); - result |= @as(T, @intCast(bc.bit_buffer >> bc.bit_offset & chunk_mask)) << @intCast(shift); + result |= @as(T, @intCast((bc.bit_buffer >> bc.bit_offset) & chunk_mask)) << @intCast(shift); shift += @intCast(chunk_len); remaining -= chunk_len; bc.bit_offset = @truncate(bc.bit_offset + chunk_len); diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 16a4f283ce6ccf976af56428e5ac996c94138bdf..5cf1765116b517eafe92790d5cb2542ede043b83 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -1076,7 +1076,7 @@ pub const Type = enum(u32) { child: Type, fn length(self: Array) u64 { - return @as(u64, self.len_hi) << 32 | self.len_lo; + return (@as(u64, self.len_hi) << 32) | self.len_lo; } }; @@ -9520,7 +9520,7 @@ pub const Metadata = packed struct(u32) { size_in_bits_hi: u32, pub fn bitSize(self: BasicType) u64 { - return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo; + return (@as(u64, self.size_in_bits_hi) << 32) | self.size_in_bits_lo; } }; @@ -9537,10 +9537,10 @@ pub const Metadata = packed struct(u32) { fields_tuple: Metadata.Optional, pub fn bitSize(self: CompositeType) u64 { - return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo; + return (@as(u64, self.size_in_bits_hi) << 32) | self.size_in_bits_lo; } pub fn bitAlign(self: CompositeType) u64 { - return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo; + return (@as(u64, self.align_in_bits_hi) << 32) | self.align_in_bits_lo; } }; @@ -9558,13 +9558,13 @@ pub const Metadata = packed struct(u32) { offset_in_bits_hi: u32, pub fn bitSize(self: DerivedType) u64 { - return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo; + return (@as(u64, self.size_in_bits_hi) << 32) | self.size_in_bits_lo; } pub fn bitAlign(self: DerivedType) u64 { - return @as(u64, self.align_in_bits_hi) << 32 | self.align_in_bits_lo; + return (@as(u64, self.align_in_bits_hi) << 32) | self.align_in_bits_lo; } pub fn bitOffset(self: DerivedType) u64 { - return @as(u64, self.offset_in_bits_hi) << 32 | self.offset_in_bits_lo; + return (@as(u64, self.offset_in_bits_hi) << 32) | self.offset_in_bits_lo; } }; @@ -12457,7 +12457,7 @@ fn doubleConstAssumeCapacity(self: *Builder, val: f64) Constant { if (ctx.builder.constant_items.items(.tag)[rhs_index] != .double) return false; const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; const rhs_extra = ctx.builder.constantExtraData(Constant.Double, rhs_data); - return @as(u64, @bitCast(lhs_key)) == @as(u64, rhs_extra.hi) << 32 | rhs_extra.lo; + return @as(u64, @bitCast(lhs_key)) == (@as(u64, rhs_extra.hi) << 32) | rhs_extra.lo; } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(val, Adapter{ .builder = self }); @@ -12488,8 +12488,8 @@ fn fp128ConstAssumeCapacity(self: *Builder, val: f128) Constant { if (ctx.builder.constant_items.items(.tag)[rhs_index] != .fp128) return false; const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; const rhs_extra = ctx.builder.constantExtraData(Constant.Fp128, rhs_data); - return @as(u128, @bitCast(lhs_key)) == @as(u128, rhs_extra.hi_hi) << 96 | - @as(u128, rhs_extra.hi_lo) << 64 | @as(u128, rhs_extra.lo_hi) << 32 | rhs_extra.lo_lo; + return @as(u128, @bitCast(lhs_key)) == (@as(u128, rhs_extra.hi_hi) << 96) | + (@as(u128, rhs_extra.hi_lo) << 64) | (@as(u128, rhs_extra.lo_hi) << 32) | rhs_extra.lo_lo; } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(val, Adapter{ .builder = self }); @@ -12522,8 +12522,8 @@ fn x86_fp80ConstAssumeCapacity(self: *Builder, val: f80) Constant { if (ctx.builder.constant_items.items(.tag)[rhs_index] != .x86_fp80) return false; const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; const rhs_extra = ctx.builder.constantExtraData(Constant.Fp80, rhs_data); - return @as(u80, @bitCast(lhs_key)) == @as(u80, rhs_extra.hi) << 64 | - @as(u80, rhs_extra.lo_hi) << 32 | rhs_extra.lo_lo; + return @as(u80, @bitCast(lhs_key)) == (@as(u80, rhs_extra.hi) << 64) | + (@as(u80, rhs_extra.lo_hi) << 32) | rhs_extra.lo_lo; } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(val, Adapter{ .builder = self }); @@ -12555,8 +12555,8 @@ fn ppc_fp128ConstAssumeCapacity(self: *Builder, val: [2]f64) Constant { if (ctx.builder.constant_items.items(.tag)[rhs_index] != .ppc_fp128) return false; const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; const rhs_extra = ctx.builder.constantExtraData(Constant.Fp128, rhs_data); - return @as(u64, @bitCast(lhs_key[0])) == @as(u64, rhs_extra.lo_hi) << 32 | rhs_extra.lo_lo and - @as(u64, @bitCast(lhs_key[1])) == @as(u64, rhs_extra.hi_hi) << 32 | rhs_extra.hi_lo; + return @as(u64, @bitCast(lhs_key[0])) == (@as(u64, rhs_extra.lo_hi) << 32) | rhs_extra.lo_lo and + @as(u64, @bitCast(lhs_key[1])) == (@as(u64, rhs_extra.hi_hi) << 32) | rhs_extra.hi_lo; } }; const gop = self.constant_map.getOrPutAssumeCapacityAdapted(val, Adapter{ .builder = self }); @@ -15225,18 +15225,18 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco for (limbs) |*limb| { const val = std.mem.littleToNative(i64, @bitCast(limb.*)); limb.* = @bitCast(if (val >= 0) - val << 1 | 0 + (val << 1) | 0 else - -%val << 1 | 1); + (-%val << 1) | 1); } try constants_block.writeUnabbrev(5, record.items); continue; }; try constants_block.writeAbbrev(ConstantsBlock.Integer{ .value = @bitCast(if (val >= 0) - val << 1 | 0 + (val << 1) | 0 else - -%val << 1 | 1), + (-%val << 1) | 1), }); }, .half, @@ -15252,8 +15252,8 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .x86_fp80 => { const extra = self.constantExtraData(Constant.Fp80, data); try constants_block.writeAbbrev(ConstantsBlock.Fp80{ - .hi = @as(u64, extra.hi) << 48 | @as(u64, extra.lo_hi) << 16 | - extra.lo_lo >> 16, + .hi = (@as(u64, extra.hi) << 48) | (@as(u64, extra.lo_hi) << 16) | + (extra.lo_lo >> 16), .lo = @truncate(extra.lo_lo), }); }, @@ -15262,8 +15262,8 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco => { const extra = self.constantExtraData(Constant.Fp128, data); try constants_block.writeAbbrev(ConstantsBlock.Fp128{ - .lo = @as(u64, extra.lo_hi) << 32 | @as(u64, extra.lo_lo), - .hi = @as(u64, extra.hi_hi) << 32 | @as(u64, extra.hi_lo), + .lo = (@as(u64, extra.lo_hi) << 32) | @as(u64, extra.lo_lo), + .hi = (@as(u64, extra.hi_hi) << 32) | @as(u64, extra.hi_lo), }); }, .array, @@ -15724,9 +15724,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco for (limbs) |*limb| { const val = std.mem.littleToNative(i64, @bitCast(limb.*)); limb.* = @bitCast(if (val >= 0) - val << 1 | 0 + (val << 1) | 0 else - -%val << 1 | 1); + (-%val << 1) | 1); } try metadata_block.writeUnabbrev(@backingInt(MetadataBlock.Code.ENUMERATOR), record.items); continue; @@ -15736,9 +15736,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco .bit_width = extra.bit_width, .name = extra.name, .value = @bitCast(if (val >= 0) - val << 1 | 0 + (val << 1) | 0 else - -%val << 1 | 1), + (-%val << 1) | 1), }, metadata_adapter); }, .subrange => { diff --git a/lib/std/zig/llvm/bitcode_writer.zig b/lib/std/zig/llvm/bitcode_writer.zig index 0ee722165be0a39a2695d4f23f249c6e2a8299f0..9c9e9d4473c26e2c1b9fa0e63befb5bbc420fc02 100644 --- a/lib/std/zig/llvm/bitcode_writer.zig +++ b/lib/std/zig/llvm/bitcode_writer.zig @@ -102,7 +102,7 @@ pub fn BitcodeWriter(comptime types: []const type) type { // If input is larger than one VBR block can store // then store vbr_bits - 1 bits and a continue bit while (in_buffer > mask) { - try self.writeBits(in_buffer & mask | continue_bit, vbr_bits); + try self.writeBits((in_buffer & mask) | continue_bit, vbr_bits); in_buffer >>= @intCast(vbr_bits - 1); } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index f8b93bd4c960502651073a3097cfc80195f05022..696515cdf62614c4a477256b5dcc5b641ba4d6d7 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -3046,19 +3046,14 @@ test "zig fmt: precedence" { \\ !(a{}); \\ a + b{}; \\ (a + b){}; - \\ a << b + c; \\ (a << b) + c; - \\ a & b << c; \\ (a & b) << c; - \\ a ^ b & c; \\ (a ^ b) & c; - \\ a | b ^ c; \\ (a | b) ^ c; \\ a == b | c; \\ (a == b) | c; \\ a and b == c; \\ (a and b) == c; - \\ a or b and c; \\ (a or b) and c; \\ (a or b) and c; \\ a == b and c == d; @@ -3067,6 +3062,47 @@ test "zig fmt: precedence" { ); } +test "zig fmt: ambiguous precedence" { + try testError( + \\test "ambiguous precedence" { + \\ a & b << c; + \\ a << b + c; + \\ a << b | c; + \\ a ^ b & c; + \\ a | b ^ c; + \\ a or b and c; + \\ a orelse b catch c; + \\ a % b % c; + \\} + \\ + , &[_]Error{ + .ambiguous_operator_precedence, + .previous_ambiguous_operator, + .hint_operator_precedence_right, + .ambiguous_operator_precedence, + .previous_ambiguous_operator, + .hint_operator_precedence_right, + .ambiguous_operator_precedence, + .previous_ambiguous_operator, + .hint_operator_precedence_left, + .ambiguous_operator_precedence, + .previous_ambiguous_operator, + .hint_operator_precedence_left, + .ambiguous_operator_precedence, + .previous_ambiguous_operator, + .hint_operator_precedence_left, + .ambiguous_operator_precedence, + .previous_ambiguous_operator, + .hint_operator_precedence_right, + .ambiguous_operator_precedence, + .previous_ambiguous_operator, + .hint_operator_precedence_left, + .illegal_chained_operators, + .previous_ambiguous_operator, + .hint_operator_precedence_left, + }); +} + test "zig fmt: prefix operators" { try testCanonical( \\test "prefix operators" { @@ -7205,7 +7241,7 @@ test "recovery: missing comma" { \\ 2 => {} \\ 3 => {} \\ else => { - \\ foo & bar +; + \\ foo & bar &; \\ } \\ } \\} diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 41de483284a972e2f6e87668b739fba5592415ae..70e2d4b6dd25d25f20b995e5d262f7a631a81151 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -266,8 +266,8 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { // Minor * 1(0),000 summed has been convention since FreeBSD 2.2 (1997) // e.g. 492101 = 4.11-STABLE = 4.(9+2) const major = value / 100_000; - const minor1 = value % 100_000 / 10_000; // usually 0 since 5.1 - const minor2 = value % 10_000 / 1_000; // 0 before 5.1, minor version since + const minor1 = (value % 100_000) / 10_000; // usually 0 since 5.1 + const minor2 = (value % 10_000) / 1_000; // 0 before 5.1, minor version since const patch = value % 1_000; os.version_range.semver.min = .{ .major = major, .minor = minor1 + minor2, .patch = patch }; os.version_range.semver.max = os.version_range.semver.min; @@ -280,8 +280,8 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { // r = 0 (*) // p = patchlevel const major = value / 100_000_000; - const minor = value % 100_000_000 / 1_000_000; - const patch = value % 10_000 / 100; + const minor = (value % 100_000_000) / 1_000_000; + const patch = (value % 10_000) / 100; os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch }; os.version_range.semver.max = os.version_range.semver.min; }, @@ -292,7 +292,7 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { // m = minor; odd-numbers indicate current dev branch // p = patch const major = value / 100_000; - const minor = value % 100_000 / 100; + const minor = (value % 100_000) / 100; const patch = value % 100; os.version_range.semver.min = .{ .major = major, .minor = minor, .patch = patch }; os.version_range.semver.max = os.version_range.semver.min; diff --git a/lib/std/zig/system/windows.zig b/lib/std/zig/system/windows.zig index 0df7d598572cc91192a7a2b5b11684cfd77dec7c..65ecc9f3ff8b84d1981765f29343a723cbe1ba54 100644 --- a/lib/std/zig/system/windows.zig +++ b/lib/std/zig/system/windows.zig @@ -25,7 +25,7 @@ pub fn detectRuntimeVersion() WindowsVersion { // `---` `` ``--> Sub-version (Starting from Windows 10 onwards) // \ `--> Service pack (Always zero in the constants defined) // `--> OS version (Major & minor) - const os_ver: u16 = @as(u16, @intCast(version_info.dwMajorVersion & 0xff)) << 8 | + const os_ver: u16 = (@as(u16, @intCast(version_info.dwMajorVersion & 0xff)) << 8) | @as(u16, @intCast(version_info.dwMinorVersion & 0xff)); const sp_ver: u8 = 0; const sub_ver: u8 = if (os_ver >= 0x0A00) subver: { @@ -40,7 +40,7 @@ pub fn detectRuntimeVersion() WindowsVersion { break :subver @as(u8, @truncate(last_idx)); } else 0; - const version: u32 = @as(u32, os_ver) << 16 | @as(u16, sp_ver) << 8 | sub_ver; + const version: u32 = (@as(u32, os_ver) << 16) | (@as(u16, sp_ver) << 8) | sub_ver; return @as(WindowsVersion, @fromBackingInt(@intCast(version))); } diff --git a/src/Air.zig b/src/Air.zig index 56d2e22b8c8f994cec690ce9d2661001dea16223..c786837dbf773b88868217f130b433b82a53d655 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -1505,7 +1505,7 @@ pub const ShuffleTwoMask = enum(u32) { return @fromBackingInt(@intCast(idx << 1)); } pub fn bElem(idx: u32) ShuffleTwoMask { - return @fromBackingInt(@intCast(idx << 1 | 1)); + return @fromBackingInt(@intCast((idx << 1) | 1)); } pub const Unwrapped = union(enum) { /// The resulting element is this index into the first runtime vector. diff --git a/src/Compilation.zig b/src/Compilation.zig index 94dad2b74fa251bafaa9dd8246d52d8e45fdf0e1..886b46179a789159d76b2b782f249d9a079ef370 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1990,7 +1990,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .path = try options.dirs.global_cache.join(arena, &.{zir_sub_dir}), }; - const std_mod = options.std_mod orelse Module.create(arena, .{ + const std_mod = options.std_mod orelse (Module.create(arena, .{ .paths = .{ .root = try .fromRoot(arena, options.dirs, .zig_lib, "std"), .root_src_path = "std.zig", @@ -2015,7 +2015,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, error.StackProtectorUnsupportedByTarget => unreachable, error.StackProtectorUnavailableWithoutLibC => unreachable, error.PatchableFunctionEntryUnsupportedByBackend => unreachable, - }; + }); const zcu = try arena.create(Zcu); zcu.* = .{ diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig index c8cb5a26907835fa808d8f05eb6ba1d567131dc5..3e696d49ab3758b54e682de46ceba04d82337a71 100644 --- a/src/IncrementalDebugServer.zig +++ b/src/IncrementalDebugServer.zig @@ -243,7 +243,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const for (zcu.incremental_debug_state.types.keys()) |type_ip_index| { const ty: Type = .fromInterned(type_ip_index); const ty_name = ty.containerTypeName(ip).fqn.toSlice(ip); - const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) { + const success = switch ((@as(u2, @intFromBool(anchor_start)) << 1) | @intFromBool(anchor_end)) { 0b00 => std.mem.find(u8, ty_name, query) != null, 0b01 => std.mem.endsWith(u8, ty_name, query), 0b10 => std.mem.startsWith(u8, ty_name, query), @@ -264,7 +264,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const for (zcu.incremental_debug_state.navs.keys()) |nav_index| { const nav = ip.getNav(nav_index); const nav_fqn = nav.fqn.toSlice(ip); - const success = switch (@as(u2, @intFromBool(anchor_start)) << 1 | @intFromBool(anchor_end)) { + const success = switch ((@as(u2, @intFromBool(anchor_start)) << 1) | @intFromBool(anchor_end)) { 0b00 => std.mem.find(u8, nav_fqn, query) != null, 0b01 => std.mem.endsWith(u8, nav_fqn, query), 0b10 => std.mem.startsWith(u8, nav_fqn, query), diff --git a/src/InternPool.zig b/src/InternPool.zig index 77bf96a5f0a46a67a56e1d445d3a9d9e3ff4e5d7..8c076a75dfc977feea4b1dc0d75adb2e582bd00d 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -215,7 +215,7 @@ pub const TrackedInst = extern struct { }; pub fn unwrap(tracked_inst_index: TrackedInst.Index, ip: *const InternPool) Unwrapped { return .{ - .tid = @fromBackingInt(@intCast(@backingInt(tracked_inst_index) >> ip.tid_shift_32 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(tracked_inst_index) >> ip.tid_shift_32) & ip.getTidMask())), .index = @backingInt(tracked_inst_index) & ip.getIndexMask(u32), }; } @@ -517,7 +517,7 @@ pub const ComptimeUnit = extern struct { }; fn unwrap(id: Id, ip: *const InternPool) Unwrapped { return .{ - .tid = @fromBackingInt(@intCast(@backingInt(id) >> ip.tid_shift_32 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(id) >> ip.tid_shift_32) & ip.getTidMask())), .index = @backingInt(id) & ip.getIndexMask(u31), }; } @@ -655,7 +655,7 @@ pub const Nav = struct { }; fn unwrap(nav_index: Nav.Index, ip: *const InternPool) Unwrapped { return .{ - .tid = @fromBackingInt(@intCast(@backingInt(nav_index) >> ip.tid_shift_30 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(nav_index) >> ip.tid_shift_30) & ip.getTidMask())), .index = @backingInt(nav_index) & ip.getIndexMask(u30), }; } @@ -1627,7 +1627,7 @@ pub const MapIndex = enum(u32) { }; fn unwrap(map_index: MapIndex, ip: *const InternPool) Unwrapped { return .{ - .tid = @fromBackingInt(@intCast(@backingInt(map_index) >> ip.tid_shift_32 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(map_index) >> ip.tid_shift_32) & ip.getTidMask())), .index = @backingInt(map_index) & ip.getIndexMask(u32), }; } @@ -1648,14 +1648,14 @@ pub const NamespaceIndex = enum(u32) { assert(unwrapped.bucket_index <= ip.getIndexMask(u32) >> Local.namespaces_bucket_width); assert(unwrapped.index <= Local.namespaces_bucket_mask); return @fromBackingInt(@intCast(@shlExact(@as(u32, @backingInt(unwrapped.tid)), ip.tid_shift_32) | - unwrapped.bucket_index << Local.namespaces_bucket_width | + (unwrapped.bucket_index << Local.namespaces_bucket_width) | unwrapped.index)); } }; fn unwrap(namespace_index: NamespaceIndex, ip: *const InternPool) Unwrapped { const index = @backingInt(namespace_index) & ip.getIndexMask(u32); return .{ - .tid = @fromBackingInt(@intCast(@backingInt(namespace_index) >> ip.tid_shift_32 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(namespace_index) >> ip.tid_shift_32) & ip.getTidMask())), .bucket_index = index >> Local.namespaces_bucket_width, .index = index & Local.namespaces_bucket_mask, }; @@ -1696,7 +1696,7 @@ pub const FileIndex = enum(u32) { }; pub fn unwrap(file_index: FileIndex, ip: *const InternPool) Unwrapped { return .{ - .tid = @fromBackingInt(@intCast(@backingInt(file_index) >> ip.tid_shift_32 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(file_index) >> ip.tid_shift_32) & ip.getTidMask())), .index = @backingInt(file_index) & ip.getIndexMask(u32), }; } @@ -1755,7 +1755,7 @@ pub const String = enum(u32) { }; fn unwrap(string: String, ip: *const InternPool) Unwrapped { return .{ - .tid = @fromBackingInt(@intCast(@backingInt(string) >> ip.tid_shift_32 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(string) >> ip.tid_shift_32) & ip.getTidMask())), .index = @backingInt(string) & ip.getIndexMask(u32), }; } @@ -4199,7 +4199,7 @@ pub const Index = enum(u32) { }; pub fn unwrap(index: Index, ip: *const InternPool) Unwrapped { return .{ - .tid = @fromBackingInt(@intCast(@backingInt(index) >> ip.tid_shift_30 & ip.getTidMask())), + .tid = @fromBackingInt(@intCast((@backingInt(index) >> ip.tid_shift_30) & ip.getTidMask())), .index = @backingInt(index) & ip.getIndexMask(u30), }; } @@ -6062,7 +6062,7 @@ pub const PtrNav = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -6080,7 +6080,7 @@ pub const PtrUav = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -6101,7 +6101,7 @@ pub const PtrUavAligned = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -6119,7 +6119,7 @@ pub const PtrComptimeAlloc = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -6137,7 +6137,7 @@ pub const PtrComptimeField = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -6155,7 +6155,7 @@ pub const PtrBase = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -6175,7 +6175,7 @@ pub const PtrBaseIndex = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -6191,7 +6191,7 @@ pub const PtrInt = struct { }; } fn byteOffset(data: @This()) u64 { - return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + return (@as(u64, data.byte_offset_a) << 32) | data.byte_offset_b; } }; @@ -12634,7 +12634,7 @@ const PackedCallingConvention = packed struct(u18) { std.lang.CallingConvention.SpirvFragmentOptions => .{ .tag = tag, .incoming_stack_alignment = .none, - .extra = @as(u4, @backingInt(pl.depth_assumption)) << 1 | @intFromBool(pl.pixel_centered_integer), + .extra = (@as(u4, @backingInt(pl.depth_assumption)) << 1) | @intFromBool(pl.pixel_centered_integer), }, std.lang.CallingConvention.SpirvMeshOptions => .{ .tag = tag, diff --git a/src/Sema.zig b/src/Sema.zig index e5ee288187f627f9438a64f3d91eac833268ed9c..971b0f6835b590ed3274fa2606408544797838ee 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -29942,10 +29942,10 @@ fn coerceVarArgParam( if (!uncasted_ty.validateExtern(.param_ty, zcu)) break :int inst; const target = zcu.getTarget(); const uncasted_info = uncasted_ty.intInfo(zcu); - if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { + if (uncasted_info.bits <= (target.cTypeBitSize(switch (uncasted_info.signedness) { .signed => .int, .unsigned => .uint, - }) orelse break :int inst) break :int try sema.coerce(block, switch (uncasted_info.signedness) { + }) orelse break :int inst)) break :int try sema.coerce(block, switch (uncasted_info.signedness) { .signed => .c_int, .unsigned => .c_uint, }, inst, inst_src); diff --git a/src/codegen/aarch64/Assemble.zig b/src/codegen/aarch64/Assemble.zig index ec80072277625ee3f749d806534ec969587231fa..6e72682cf92e386b3d3630859a920cfd397671d6 100644 --- a/src/codegen/aarch64/Assemble.zig +++ b/src/codegen/aarch64/Assemble.zig @@ -164,7 +164,7 @@ const matchers = matchers: { return @call(.auto, encode, args); } else if (pattern_token[0] == '<') { const symbol_name = comptime pattern_token[1 .. std.mem.findScalarPos(u8, pattern_token, 1, '|') orelse - pattern_token.len - 1]; + (pattern_token.len - 1)]; const symbol = @field(Symbol, symbol_name); const symbol_ptr = &@field(symbols, symbol_name); const symbol_value = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse { @@ -453,7 +453,7 @@ const SymbolSpec = union(enum) { } else { const Repr = std.math.FloatRepr(f16); const repr: Repr = @bitCast(fimm); - if (repr.mantissa & std.math.maxInt(Repr.Mantissa) >> 5 != 0 or switch (repr.exponent) { + if ((repr.mantissa & (std.math.maxInt(Repr.Mantissa) >> 5)) != 0 or switch (repr.exponent) { .denormal, .infinite => true, else => std.math.cast(i3, repr.exponent.unbias() - 1) == null, }) { diff --git a/src/codegen/aarch64/Disassemble.zig b/src/codegen/aarch64/Disassemble.zig index 76e2b89f4f962cbed82cdb8a2695f15f066b5cb2..2f0450aacea53118c1675125ec44d237f222e244 100644 --- a/src/codegen/aarch64/Disassemble.zig +++ b/src/codegen/aarch64/Disassemble.zig @@ -31,7 +31,7 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr .unallocated => break :unallocated, .pc_relative_addressing => |pc_relative_addressing| { const group = pc_relative_addressing.group; - const imm = (@as(i33, group.immhi) << 2 | @as(i33, group.immlo) << 0) + @as(i33, switch (group.op) { + const imm = ((@as(i33, group.immhi) << 2) | (@as(i33, group.immlo) << 0)) + @as(i33, switch (group.op) { .adr => aarch64.encoding.Instruction.size, .adrp => 0, }); @@ -311,7 +311,7 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr .hint => |hint| return writer.print("{f}{s}#0x{x}", .{ fmtCase(.hint, dis.case), dis.mnemonic_operands_separator, - @as(u7, hint.CRm) << 3 | @as(u7, hint.op2) << 0, + (@as(u7, hint.CRm) << 3) | (@as(u7, hint.op2) << 0), }), else => |decoded| return writer.print("{f}", .{fmtCase(decoded, dis.case)}), }, @@ -365,8 +365,8 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr dis.mnemonic_operands_separator, group.Rt.decode(.{}).general(@fromBackingInt(@intCast(group.b5))).fmtCase(dis.case), dis.operands_separator, - @as(u6, group.b5) << 5 | - @as(u6, group.b40) << 0, + (@as(u6, group.b5) << 5) | + (@as(u6, group.b40) << 0), dis.operands_separator, @as(u8, if (imm < 0) '-' else '+'), @abs(imm) << 2, diff --git a/src/codegen/aarch64/Mir.zig b/src/codegen/aarch64/Mir.zig index 1233a8180db0e726d2d2904eb2246734ad18ab56..d339069b3aba6ee3cd4157c764f3d0dceef21340 100644 --- a/src/codegen/aarch64/Mir.zig +++ b/src/codegen/aarch64/Mir.zig @@ -208,7 +208,7 @@ fn emitReloc( }; try atom.addReloc(gpa, .{ .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(r_type), + .r_info = (@as(u64, @backingInt(sym_index)) << 32) | @backingInt(r_type), .r_addend = @bitCast(addend), }, zo); } else if (lf.cast(.macho)) |mf| { @@ -265,7 +265,7 @@ fn emitReloc( }; try atom.addReloc(gpa, .{ .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(r_type), + .r_info = (@as(u64, @backingInt(sym_index)) << 32) | @backingInt(r_type), .r_addend = @bitCast(addend), }, zo); } else if (lf.cast(.macho)) |mf| { @@ -328,7 +328,7 @@ fn emitReloc( }; try atom.addReloc(gpa, .{ .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(r_type), + .r_info = (@as(u64, @backingInt(sym_index)) << 32) | @backingInt(r_type), .r_addend = @bitCast(addend), }, zo); } else if (lf.cast(.macho)) |mf| { diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 202793ebdc1a3284eed294988deccc9dfa8da12e..147432c3d8e1e19ffcd58cf231b16457bb019652 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -8099,7 +8099,7 @@ fn movImmediate(isel: *Select, dst_reg: Register, src_imm: u64) !void { .{ .immediate = .{ .N = @fromBackingInt(@intCast(elem_width >> 6)), .immr = hi + mid_masked, - .imms = ((((lo + hi) & smask) | mid_masked) - 1) | -%@as(u6, @truncate(elem_width)) << 1, + .imms = ((((lo + hi) & smask) | mid_masked) - 1) | (-%@as(u6, @truncate(elem_width)) << 1), } }, )); } @@ -10831,7 +10831,7 @@ pub const Value = struct { if (feat_fp16) { const Repr = std.math.FloatRepr(f16); const repr: Repr = @bitCast(imm); - if (repr.mantissa & std.math.maxInt(Repr.Mantissa) >> 5 == 0 and switch (repr.exponent) { + if (repr.mantissa & (std.math.maxInt(Repr.Mantissa) >> 5) == 0 and switch (repr.exponent) { .denormal, .infinite => false, else => std.math.cast(i3, repr.exponent.unbias() - 1) != null, }) break :free try isel.emit(.fmov(mat.ra.h(), .{ .immediate = imm })); @@ -10855,7 +10855,7 @@ pub const Value = struct { } }; const Repr = std.math.FloatRepr(f32); const repr: Repr = @bitCast(imm); - if (repr.mantissa & std.math.maxInt(Repr.Mantissa) >> 5 == 0 and switch (repr.exponent) { + if (repr.mantissa & (std.math.maxInt(Repr.Mantissa) >> 5) == 0 and switch (repr.exponent) { .denormal, .infinite => false, else => std.math.cast(i3, repr.exponent.unbias() - 1) != null, }) break :free try isel.emit(.fmov(mat.ra.s(), .{ .immediate = @floatCast(imm) })); @@ -10878,7 +10878,7 @@ pub const Value = struct { } }; const Repr = std.math.FloatRepr(f64); const repr: Repr = @bitCast(imm); - if (repr.mantissa & std.math.maxInt(Repr.Mantissa) >> 5 == 0 and switch (repr.exponent) { + if (repr.mantissa & (std.math.maxInt(Repr.Mantissa) >> 5) == 0 and switch (repr.exponent) { .denormal, .infinite => false, else => std.math.cast(i3, repr.exponent.unbias() - 1) != null, }) break :free try isel.emit(.fmov(mat.ra.d(), .{ .immediate = @floatCast(imm) })); diff --git a/src/codegen/aarch64/encoding.zig b/src/codegen/aarch64/encoding.zig index c25d2fe507fcfe67a53e35a7e912fd8300d5aaa8..d26167109f10997c8fa795d94775d7f7ef00c83b 100644 --- a/src/codegen/aarch64/encoding.zig +++ b/src/codegen/aarch64/encoding.zig @@ -11886,9 +11886,9 @@ pub const Instruction = packed union { .cmode = switch (arrangement) { else => unreachable, .@"4h", .@"8h" => @as(u3, 0b100) | - @as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0, + (@as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0), .@"2s", .@"4s" => @as(u3, 0b000) | - @as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0, + (@as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0), }, .imm3 = @intCast(shifted_immediate.immediate >> 5), .Q = arrangement.size(), @@ -12384,7 +12384,7 @@ pub const Instruction = packed union { .dup = .{ .Rd = d.alias.encode(.{ .V = true }), .Rn = n.alias.encode(.{ .V = true }), - .imm5 = @shlExact(@as(u5, n.format.element.index) << 1 | @as(u5, 0b1), @backingInt(elem_size)), + .imm5 = @shlExact((@as(u5, n.format.element.index) << 1) | @as(u5, 0b1), @backingInt(elem_size)), }, } } }; }, @@ -12400,7 +12400,7 @@ pub const Instruction = packed union { .Rd = d.alias.encode(.{ .V = true }), .Rn = n.alias.encode(.{ .V = true }), .imm4 = .element, - .imm5 = @shlExact(@as(u5, element.index) << 1 | @as(u5, 0b1), @backingInt(elem_size)), + .imm5 = @shlExact((@as(u5, element.index) << 1) | @as(u5, 0b1), @backingInt(elem_size)), .Q = arrangement.size(), }, } } }; @@ -14195,7 +14195,7 @@ pub const Instruction = packed union { .Rd = d.alias.encode(.{ .V = true }), .Rn = n.alias.encode(.{ .V = true }), .imm4 = .{ .element = element.index << @intCast(@backingInt(elem_size)) }, - .imm5 = (@as(u5, d.format.element.index) << 1 | @as(u5, 0b1) << 0) << @backingInt(elem_size), + .imm5 = ((@as(u5, d.format.element.index) << 1) | (@as(u5, 0b1) << 0)) << @backingInt(elem_size), .op = .element, }, } } }; @@ -14211,7 +14211,7 @@ pub const Instruction = packed union { .Rd = d.alias.encode(.{ .V = true }), .Rn = n.alias.encode(.{}), .imm4 = .{ .general = .general }, - .imm5 = (@as(u5, d.format.element.index) << 1 | @as(u5, 0b1) << 0) << @backingInt(elem_size), + .imm5 = ((@as(u5, d.format.element.index) << 1) | (@as(u5, 0b1) << 0)) << @backingInt(elem_size), .op = .general, }, } } }; @@ -15072,16 +15072,16 @@ pub const Instruction = packed union { .lsl => |amount| switch (arrangement) { else => unreachable, .@"8b", .@"16b" => @as(u4, 0b1110) | - @as(u4, @as(u0, @intCast(@shrExact(amount, 3)))) << 1, + (@as(u4, @as(u0, @intCast(@shrExact(amount, 3)))) << 1), .@"4h", .@"8h" => @as(u4, 0b1000) | - @as(u4, @as(u1, @intCast(@shrExact(amount, 3)))) << 1, + (@as(u4, @as(u1, @intCast(@shrExact(amount, 3)))) << 1), .@"2s", .@"4s" => @as(u4, 0b0000) | - @as(u4, @as(u2, @intCast(@shrExact(amount, 3)))) << 1, + (@as(u4, @as(u2, @intCast(@shrExact(amount, 3)))) << 1), }, .msl => |amount| switch (arrangement) { else => unreachable, .@"2s", .@"4s" => @as(u4, 0b1100) | - @as(u4, @as(u1, @intCast(@shrExact(amount, 3) - 1))) << 0, + (@as(u4, @as(u1, @intCast(@shrExact(amount, 3) - 1))) << 0), }, .replicate => switch (arrangement) { else => unreachable, @@ -15345,9 +15345,9 @@ pub const Instruction = packed union { .cmode = switch (arrangement) { else => unreachable, .@"4h", .@"8h" => @as(u3, 0b100) | - @as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0, + (@as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0), .@"2s", .@"4s" => @as(u3, 0b000) | - @as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0, + (@as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0), }, .imm3 = @intCast(shifted_immediate.immediate >> 5), .Q = arrangement.size(), @@ -15660,9 +15660,9 @@ pub const Instruction = packed union { .Rn = n.alias.encode(.{ .V = true }), .imm5 = switch (vs) { else => unreachable, - .byte => @as(u5, @as(u4, @intCast(n.format.element.index))) << 1 | @as(u5, 0b1) << 0, - .half => @as(u5, @as(u3, @intCast(n.format.element.index))) << 2 | @as(u5, 0b10) << 0, - .single => @as(u5, @as(u2, @intCast(n.format.element.index))) << 3 | @as(u5, 0b100) << 0, + .byte => (@as(u5, @as(u4, @intCast(n.format.element.index))) << 1) | (@as(u5, 0b1) << 0), + .half => (@as(u5, @as(u3, @intCast(n.format.element.index))) << 2) | (@as(u5, 0b10) << 0), + .single => (@as(u5, @as(u2, @intCast(n.format.element.index))) << 3) | (@as(u5, 0b100) << 0), }, .Q = sf, }, @@ -16492,10 +16492,10 @@ pub const Instruction = packed union { .Rn = n.alias.encode(.{ .V = true }), .imm5 = switch (vs) { else => unreachable, - .byte => @as(u5, @as(u4, @intCast(n.format.element.index))) << 1 | @as(u5, 0b1) << 0, - .half => @as(u5, @as(u3, @intCast(n.format.element.index))) << 2 | @as(u5, 0b10) << 0, - .single => @as(u5, @as(u2, @intCast(n.format.element.index))) << 3 | @as(u5, 0b100) << 0, - .double => @as(u5, @as(u1, @intCast(n.format.element.index))) << 4 | @as(u5, 0b1000) << 0, + .byte => (@as(u5, @as(u4, @intCast(n.format.element.index))) << 1) | (@as(u5, 0b1) << 0), + .half => (@as(u5, @as(u3, @intCast(n.format.element.index))) << 2) | (@as(u5, 0b10) << 0), + .single => (@as(u5, @as(u2, @intCast(n.format.element.index))) << 3) | (@as(u5, 0b100) << 0), + .double => (@as(u5, @as(u1, @intCast(n.format.element.index))) << 4) | (@as(u5, 0b1000) << 0), }, .Q = sf, }, diff --git a/src/codegen/loongarch/Mir.zig b/src/codegen/loongarch/Mir.zig index e107984767b547ccb82c9ac1ab869c4ee4d02e24..6c7f2fb01099fc5eb841718c63ea25f65975176e 100644 --- a/src/codegen/loongarch/Mir.zig +++ b/src/codegen/loongarch/Mir.zig @@ -181,7 +181,7 @@ fn emitReloc( const atom = zo.symbol(@backingInt(atom_index)).atom(ef).?; try atom.addReloc(zcu.gpa, .{ .r_offset = offset, - .r_info = @as(u64, @backingInt(sym_index)) << 32 | @backingInt(reloc_type), + .r_info = (@as(u64, @backingInt(sym_index)) << 32) | @backingInt(reloc_type), .r_addend = @bitCast(addend), }, zo); } else unreachable; diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index c01390c2d9ec26d2da3f227eafc7ed7b98b30ba2..1dc9b9ced4c94d00d71223672229bffac7d78c6d 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -1764,7 +1764,7 @@ fn finishAir( ) !void { const tomb_bits = func.liveness.getTombBits(inst); for (0.., operands) |op_index, op| { - if (tomb_bits & @as(Air.Liveness.Bpi, 1) << @intCast(op_index) == 0) continue; + if (tomb_bits & (@as(Air.Liveness.Bpi, 1) << @intCast(op_index)) == 0) continue; if (func.reused_operands.isSet(op_index)) continue; try func.processDeath(op.toIndexAllowNone() orelse continue); } @@ -6272,7 +6272,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { ""; op.* = switch (args.items[ - arg_map.get(op_str["%[".len .. mod_index orelse op_str.len - "]".len]) orelse + arg_map.get(op_str["%[".len .. mod_index orelse (op_str.len - "]".len)]) orelse return func.fail("no matching constraint: '{s}'", .{op_str}) ]) { .lea_symbol => |sym_off| if (mem.eql(u8, modifier, "plt")) blk: { diff --git a/src/codegen/riscv64/encoding.zig b/src/codegen/riscv64/encoding.zig index 5ca6a094d774fbaeb6a96c6c75ecd26a903da705..d04c77d7b806b9d7fc726fb382810b144ebc168d 100644 --- a/src/codegen/riscv64/encoding.zig +++ b/src/codegen/riscv64/encoding.zig @@ -582,8 +582,8 @@ pub const Instruction = union(Lir.Format) { .opcode = opcode, .funct3 = @backingInt(amo.width), - .funct7 = @as(u7, amo.funct5) << 2 | - @as(u7, @intFromBool(ops[3].barrier == .rl)) << 1 | + .funct7 = (@as(u7, amo.funct5) << 2) | + (@as(u7, @intFromBool(ops[3].barrier == .rl)) << 1) | @as(u7, @intFromBool(ops[4].barrier == .aq)), }, else => unreachable, diff --git a/src/codegen/sparc64/CodeGen.zig b/src/codegen/sparc64/CodeGen.zig index 6b1e44b16ebd803e448e68799ce8d8e769ac0573..63627e3d7d31f24f3092cb456a8e98d3a48ba63c 100644 --- a/src/codegen/sparc64/CodeGen.zig +++ b/src/codegen/sparc64/CodeGen.zig @@ -3475,11 +3475,11 @@ fn finishAirBookkeeping(self: *Self) void { fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Air.Liveness.bpi - 1]Air.Inst.Ref) void { const tomb_bits = self.liveness.getTombBits(inst); for (0.., operands) |op_index, op| { - if (tomb_bits & @as(Air.Liveness.Bpi, 1) << @intCast(op_index) == 0) continue; + if (tomb_bits & (@as(Air.Liveness.Bpi, 1) << @intCast(op_index)) == 0) continue; if (self.reused_operands.isSet(op_index)) continue; self.processDeath(op.toIndexAllowNone() orelse continue); } - if (tomb_bits & 1 << (Air.Liveness.bpi - 1) == 0) { + if (tomb_bits & (1 << (Air.Liveness.bpi - 1)) == 0) { log.debug("%{d} => {}", .{ inst, result }); const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; branch.inst_table.putAssumeCapacityNoClobber(inst, result); diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index f2931cc1212c90a3fbced96f3870b191eb92704d..f8caf7cfd993184d1646303834ca8378497f8e49 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -1191,7 +1191,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { const truncated_value = if (backing_bits == 64) value64 else - value64 & (@as(u64, 1) << @intCast(backing_bits)) - 1; + value64 & ((@as(u64, 1) << @intCast(backing_bits)) - 1); break :blk switch (backing_bits) { 1...32 => .{ .uint32 = @truncate(truncated_value) }, diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index e3cfed33b33300e71e703147362bf501873df1d6..dd36e7c304247f92c27cc96a3b15a6d879df2529 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -173255,7 +173255,7 @@ fn finishAir( ) !void { const tomb_bits = self.liveness.getTombBits(inst); for (0.., operands) |op_index, op| { - if (tomb_bits & @as(Air.Liveness.Bpi, 1) << @intCast(op_index) == 0) continue; + if (tomb_bits & (@as(Air.Liveness.Bpi, 1) << @intCast(op_index)) == 0) continue; if (self.reused_operands.isSet(op_index)) continue; try self.processDeath(op.toIndexAllowNone() orelse continue, .{}); } @@ -176321,7 +176321,7 @@ fn lowerSwitchBr( const unsigned_condition_ty = try cg.pt.intType(.unsigned, cg.intInfo(condition_ty).?.bits); const ExpectedContents = extern struct { - liveness_deaths: [1 << 8 | 1]Air.Inst.Index, + liveness_deaths: [(1 << 8) | 1]Air.Inst.Index, bigint_limbs: [std.math.big.int.calcTwosCompLimbCount(1 << 10)]std.math.big.Limb, relocs: [1 << 6]Mir.Inst.Index, }; @@ -177310,7 +177310,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { else ""; op.* = switch (args[ - arg_map.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse + arg_map.get(op_str["%[".len .. colon orelse (op_str.len - "]".len)]) orelse return self.fail("no matching constraint: '{s}'", .{op_str}) ]) { .immediate => |imm| if (std.mem.eql(u8, modifier, "") or @@ -177454,7 +177454,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { else ""; break :disp switch (args[ - arg_map.get(op_str["%[".len .. colon orelse open - "]".len]) orelse + arg_map.get(op_str["%[".len .. colon orelse (open - "]".len)]) orelse return self.fail("no matching constraint: '{s}'", .{op_str}) ]) { .immediate => |imm| if (std.mem.eql(u8, modifier, "") or @@ -179566,7 +179566,7 @@ fn atomicOp( }; defer if (mem_lock) |lock| self.register_manager.unlockReg(lock); - const use_sse = rmw_op orelse .Xchg != .Xchg and val_ty.isRuntimeFloat(); + const use_sse = (rmw_op orelse .Xchg) != .Xchg and val_ty.isRuntimeFloat(); const strat: enum { lock, loop, libcall } = if (use_sse) .loop else switch (rmw_op orelse .Xchg) { .Xchg, .Add, @@ -179626,7 +179626,7 @@ fn atomicOp( try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(.rax, val_abi_size), ptr_mem); const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len); - if (!use_sse and rmw_op orelse .Xchg != .Xchg) { + if (!use_sse and (rmw_op orelse .Xchg) != .Xchg) { try self.genSetReg(tmp_reg, val_ty, .{ .register = .rax }, .{}); } if (rmw_op) |op| if (use_sse) { @@ -188854,7 +188854,7 @@ const Temp = struct { for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| { if (op_temp.index == temp.index) continue; if (op_temp.tracking(cg).short != .dead) try op_temp.die(cg); - if (tomb_bits & @as(Air.Liveness.Bpi, 1) << @intCast(op_index) == 0) continue; + if (tomb_bits & (@as(Air.Liveness.Bpi, 1) << @intCast(op_index)) == 0) continue; if (cg.reused_operands.isSet(op_index)) continue; try cg.processDeath(op_ref.toIndexAllowNone() orelse continue, .{}); } @@ -188916,7 +188916,7 @@ const Temp = struct { } for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| { if (op_temp.index != temp.index) continue; - if (tomb_bits & @as(Air.Liveness.Bpi, 1) << @intCast(op_index) == 0) continue; + if (tomb_bits & (@as(Air.Liveness.Bpi, 1) << @intCast(op_index)) == 0) continue; if (cg.reused_operands.isSet(op_index)) continue; try cg.processDeath(op_ref.toIndexAllowNone() orelse continue, .{}); } @@ -190117,9 +190117,9 @@ const Select = struct { (@as(u64, std.math.maxInt(u64)) >> @intCast(res_scalar_info.bits - scalar_info.bits))), .@"0x1p63_mem" => switch (res_scalar_info.bits) { else => unreachable, - 16 => @as(i64, @as(i16, @bitCast(@as(f16, 0x1p63)))) << 64 - 16, - 32 => @as(i64, @as(i32, @bitCast(@as(f32, 0x1p63)))) << 64 - 32, - 64 => @as(i64, @as(i64, @bitCast(@as(f64, 0x1p63)))) << 64 - 64, + 16 => @as(i64, @as(i16, @bitCast(@as(f16, 0x1p63)))) << (64 - 16), + 32 => @as(i64, @as(i32, @bitCast(@as(f32, 0x1p63)))) << (64 - 32), + 64 => @as(i64, @as(i64, @bitCast(@as(f64, 0x1p63)))) << (64 - 64), }, }; const shift: u6 = @intCast(64 - res_scalar_info.bits); @@ -191518,8 +191518,8 @@ const Select = struct { @as(SignedImm, @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s)))), .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))), .elem_mask => @as(u8, std.math.maxInt(u8)) >> @intCast( - 8 - ((s.cg.unalignedSize(op.flags.base.ref.typeOf(s)) - 1) % - @divExact(op.flags.base.size.bitSize(s.cg.target), 8) + 1 >> + 8 - (((s.cg.unalignedSize(op.flags.base.ref.typeOf(s)) - 1) % + @divExact(op.flags.base.size.bitSize(s.cg.target), 8) + 1) >> op.flags.index.scale.toLog2()), ), inline .smin, .smax, .umax, .smin_shr_src1, .smax_shr_src1, .umax_shr_src1 => |adjust| switch (op.flags.base.size) { @@ -191548,7 +191548,7 @@ const Select = struct { }, .repeat => switch (SignedImm) { else => unreachable, - i64 => return @as(i64, op.imm) << 32 | @as(u32, @bitCast(op.imm)), + i64 => return (@as(i64, op.imm) << 32) | @as(u32, @bitCast(op.imm)), }, }; const rhs = op.flags.adjust.rhs.toLog2(); @@ -191559,10 +191559,10 @@ const Select = struct { break :op_res op_res[0]; }, .div => @shrExact(lhs, rhs), - .div_8_down => lhs >> 3 & @as(SignedImm, -1) << rhs, + .div_8_down => (lhs >> 3) & (@as(SignedImm, -1) << rhs), .rem_8_mul => lhs & ((@as(SignedImm, 8) << rhs) - 1), - .up_2_mul => ((lhs - 1) & @as(SignedImm, -2) << rhs) + (@as(SignedImm, 2) << rhs), - .up_32_mul => ((lhs - 1) & @as(SignedImm, -32) << rhs) + (@as(SignedImm, 32) << rhs), + .up_2_mul => ((lhs - 1) & (@as(SignedImm, -2) << rhs)) + (@as(SignedImm, 2) << rhs), + .up_32_mul => ((lhs - 1) & (@as(SignedImm, -32) << rhs)) + (@as(SignedImm, 32) << rhs), }; const disp: SignedImm = @bitCast(@as(UnsignedImm, @as(u32, @bitCast(op.imm)))); return switch (op.flags.adjust.sign) { diff --git a/src/codegen/x86_64/Disassembler.zig b/src/codegen/x86_64/Disassembler.zig index 4cbd66e9c834dd4efae40c438679e505c8632112..680781140bab39ebe4410066a42773bfa4a0d1a7 100644 --- a/src/codegen/x86_64/Disassembler.zig +++ b/src/codegen/x86_64/Disassembler.zig @@ -378,7 +378,7 @@ fn parseEncoding(dis: *Disassembler, prefixes: Prefixes) !?Encoding { } fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Register { - const reg_id: u4 = @as(u4, @intCast(@intFromBool(is_extended))) << 3 | low_enc; + const reg_id: u4 = (@as(u4, @intCast(@intFromBool(is_extended))) << 3) | low_enc; const reg = @as(Register, @fromBackingInt(@intCast(reg_id))).toBitSize(bit_size); return switch (reg) { .spl => if (rex.present or rex.isSet()) .spl else .ah, diff --git a/src/codegen/x86_64/Emit.zig b/src/codegen/x86_64/Emit.zig index a82ae415ac502309854af8e9ca44636ee3c8ab43..ea5cfee2e91069205bda5442f23c7272785f01f5 100644 --- a/src/codegen/x86_64/Emit.zig +++ b/src/codegen/x86_64/Emit.zig @@ -694,13 +694,13 @@ pub fn emitMir(emit: *Emit) Error!void { for (emit.table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{ .r_offset = table_reloc.source_offset, - .r_info = @as(u64, @backingInt(emit.atom_id)) << 32 | @backingInt(std.elf.R_X86_64.@"32S"), + .r_info = (@as(u64, @backingInt(emit.atom_id)) << 32) | @backingInt(std.elf.R_X86_64.@"32S"), .r_addend = @as(i64, table_offset) + table_reloc.target_offset, }, zo); for (emit.lower.mir.table) |entry| { try atom.addReloc(gpa, .{ .r_offset = table_offset, - .r_info = @as(u64, @backingInt(emit.atom_id)) << 32 | @backingInt(std.elf.R_X86_64.@"64"), + .r_info = (@as(u64, @backingInt(emit.atom_id)) << 32) | @backingInt(std.elf.R_X86_64.@"64"), .r_addend = emit.code_offset_mapping.items[entry], }, zo); table_offset += ptr_size; @@ -812,7 +812,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI .PC32; try atom.addReloc(gpa, .{ .r_offset = end_offset - 4, - .r_info = @as(u64, @backingInt(target.symbol)) << 32 | @backingInt(r_type), + .r_info = (@as(u64, @backingInt(target.symbol)) << 32) | @backingInt(r_type), .r_addend = if (emit.pic) reloc.off - 4 else reloc.off, }, zo); } else if (emit.bin_file.cast(.macho)) |macho_file| { @@ -854,7 +854,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI const r_type: std.elf.R_X86_64 = .PLT32; try atom.addReloc(gpa, .{ .r_offset = end_offset - 4, - .r_info = @as(u64, @backingInt(target.symbol)) << 32 | @backingInt(r_type), + .r_info = (@as(u64, @backingInt(target.symbol)) << 32) | @backingInt(r_type), .r_addend = reloc.off - 4, }, zo); } else if (emit.bin_file.cast(.elf2)) |elf| try elf.addReloc( @@ -894,7 +894,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI const r_type: std.elf.R_X86_64 = if (emit.pic) .TLSLD else unreachable; try atom.addReloc(gpa, .{ .r_offset = end_offset - 4, - .r_info = @as(u64, @backingInt(target_symbol)) << 32 | @backingInt(r_type), + .r_info = (@as(u64, @backingInt(target_symbol)) << 32) | @backingInt(r_type), .r_addend = reloc.off - 4, }, zo); } else if (emit.bin_file.cast(.elf2)) |elf| try elf.addReloc( @@ -912,7 +912,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI const r_type: std.elf.R_X86_64 = if (emit.pic) .DTPOFF32 else .TPOFF32; try atom.addReloc(gpa, .{ .r_offset = end_offset - 4, - .r_info = @as(u64, @backingInt(target.symbol)) << 32 | @backingInt(r_type), + .r_info = (@as(u64, @backingInt(target.symbol)) << 32) | @backingInt(r_type), .r_addend = reloc.off, }, zo); } else if (emit.bin_file.cast(.elf2)) |elf| try elf.addReloc( diff --git a/src/codegen/x86_64/Mir.zig b/src/codegen/x86_64/Mir.zig index 1b2d3cb63ebef6d025cb77cc109a4ddce7536e7b..07949a22b2a0c1fe407912278995518301e7c6e9 100644 --- a/src/codegen/x86_64/Mir.zig +++ b/src/codegen/x86_64/Mir.zig @@ -1949,7 +1949,7 @@ pub const Memory = struct { assert(mem.info.base == .reg); return encoder.Instruction.Memory.initMoffs( @fromBackingInt(@intCast(mem.base)), - @as(u64, mem.extra) << 32 | mem.off, + (@as(u64, mem.extra) << 32) | mem.off, ); }, } diff --git a/src/codegen/x86_64/bits.zig b/src/codegen/x86_64/bits.zig index cd4342b7f68b86a02834a36451b38a0cfa3e4444..ae7bb0d92c1ee36b5b6b2c28d23aa15a232a8d98 100644 --- a/src/codegen/x86_64/bits.zig +++ b/src/codegen/x86_64/bits.zig @@ -664,7 +664,7 @@ pub const Register = enum(u8) { .general_purpose, .gphi => if (reg.isExtended()) reg.enc() else - @as(u3, @truncate(@as(u24, 0o54673120) >> @as(u5, reg.enc()) * 3)), + @as(u3, @truncate(@as(u24, 0o54673120) >> (@as(u5, reg.enc()) * 3))), .sse => 17 + @as(u6, reg.enc()), .x87 => 33 + @as(u6, reg.enc()), .mmx => 41 + @as(u6, reg.enc()), diff --git a/src/codegen/x86_64/encoder.zig b/src/codegen/x86_64/encoder.zig index 56b76b42879bb05166d42162a7ac0b9801f244dd..ac7c2a2e8f0cc04f774290125a49198a3db4b075 100644 --- a/src/codegen/x86_64/encoder.zig +++ b/src/codegen/x86_64/encoder.zig @@ -844,25 +844,25 @@ fn Encoder(comptime opts: Options) type { try self.w.writeByte(0b1100_0100); try self.w.writeByte( - @as(u8, ~@intFromBool(fields.r)) << 7 | - @as(u8, ~@intFromBool(fields.x)) << 6 | - @as(u8, ~@intFromBool(fields.b)) << 5 | - @as(u8, @backingInt(fields.m)) << 0, + (@as(u8, ~@intFromBool(fields.r)) << 7) | + (@as(u8, ~@intFromBool(fields.x)) << 6) | + (@as(u8, ~@intFromBool(fields.b)) << 5) | + (@as(u8, @backingInt(fields.m)) << 0), ); try self.w.writeByte( - @as(u8, @intFromBool(fields.w)) << 7 | - @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 | - @as(u8, @intFromBool(fields.l)) << 2 | - @as(u8, @backingInt(fields.p)) << 0, + (@as(u8, @intFromBool(fields.w)) << 7) | + (@as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3) | + (@as(u8, @intFromBool(fields.l)) << 2) | + (@as(u8, @backingInt(fields.p)) << 0), ); } else { try self.w.writeByte(0b1100_0101); try self.w.writeByte( - @as(u8, ~@intFromBool(fields.r)) << 7 | - @as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3 | - @as(u8, @intFromBool(fields.l)) << 2 | - @as(u8, @backingInt(fields.p)) << 0, + (@as(u8, ~@intFromBool(fields.r)) << 7) | + (@as(u8, ~@as(u4, @intCast(fields.v.enc()))) << 3) | + (@as(u8, @intFromBool(fields.l)) << 2) | + (@as(u8, @backingInt(fields.p)) << 0), ); } } @@ -910,7 +910,7 @@ fn Encoder(comptime opts: Options) type { /// /// Remember to add a REX prefix byte if reg or rm are extended! pub fn modRm(self: Self, mod: u2, reg_or_opx: u3, rm: u3) !void { - try self.w.writeByte(@as(u8, mod) << 6 | @as(u8, reg_or_opx) << 3 | rm); + try self.w.writeByte((@as(u8, mod) << 6) | (@as(u8, reg_or_opx) << 3) | rm); } /// Construct a ModR/M byte using direct r/m addressing @@ -996,7 +996,7 @@ fn Encoder(comptime opts: Options) type { /// /// Remember to add a REX prefix byte if index or base are extended! pub fn sib(self: Self, scale: u2, index: u3, base: u3) !void { - try self.w.writeByte(@as(u8, scale) << 6 | @as(u8, index) << 3 | base); + try self.w.writeByte((@as(u8, scale) << 6) | (@as(u8, index) << 3) | base); } /// Construct a SIB byte with scale * index + base, no frills. diff --git a/src/fmt.zig b/src/fmt.zig index c12eadd95b5a3f25b57e0d497da887dcd7437616..42e7558ea9950968af8c026aa755951a052cd31e 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -323,7 +323,8 @@ fn fmtPathDir( if (mem.startsWith(u8, entry.name, ".")) continue; - if (is_dir or entry.kind == .file and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon"))) { + const is_zig_or_zon = entry.kind == .file and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon")); + if (is_dir or is_zig_or_zon) { const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name }); defer fmt.gpa.free(full_path); diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 7803ca1888a5748d2a2121b73c79df5527d2d019..10cb59aa9e12c117c95cd432d2e5b0ec512ce8cc 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -697,7 +697,7 @@ const Unit = struct { fw.writeByte(DW.LNS.extended_op) catch unreachable; const extended_op_bytes = fw.end; var op_len_bytes: u5 = 1; - while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) { + while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << (7 * op_len_bytes))) { .lt => break fw.writeUleb128(len - extended_op_bytes - op_len_bytes) catch unreachable, .eq => { // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte @@ -893,7 +893,7 @@ const Entry = struct { fw.writeUleb128(try dwarf.refAbbrevCode(.pad_n)) catch unreachable; const abbrev_code_bytes = fw.end; var block_len_bytes: u5 = 1; - while (true) switch (std.math.order(len - abbrev_code_bytes - block_len_bytes, @as(u32, 1) << 7 * block_len_bytes)) { + while (true) switch (std.math.order(len - abbrev_code_bytes - block_len_bytes, @as(u32, 1) << (7 * block_len_bytes))) { .lt => break fw.writeUleb128(len - abbrev_code_bytes - block_len_bytes) catch unreachable, .eq => { // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte @@ -915,7 +915,7 @@ const Entry = struct { fw.writeByte(DW.LNS.extended_op) catch unreachable; const extended_op_bytes = fw.end; var op_len_bytes: u5 = 1; - while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << 7 * op_len_bytes)) { + while (true) switch (std.math.order(len - extended_op_bytes - op_len_bytes, @as(u32, 1) << (7 * op_len_bytes))) { .lt => break fw.writeUleb128(len - extended_op_bytes - op_len_bytes) catch unreachable, .eq => { // no length will ever work, so undercount and futz with the leb encoding to make up the missing byte diff --git a/src/link/Dwarf2.zig b/src/link/Dwarf2.zig index 3c73609eb7bf663637ef432f198960a98f53ef68..ead00184c248ecd7c42b1f343d36f6ca1e60018e 100644 --- a/src/link/Dwarf2.zig +++ b/src/link/Dwarf2.zig @@ -1891,7 +1891,7 @@ pub fn genDebugInfoPadding(dwarf: *Dwarf, di_w: *std.Io.Writer, size: u64) std.I var block_len_size: u5 = 1; while (true) switch (std.math.order( size - abbrev_code_size - block_len_size, - @as(u64, 1) << 7 * block_len_size, + @as(u64, 1) << (7 * block_len_size), )) { .lt => break try di_w.writeUleb128(size - abbrev_code_size - block_len_size), .eq => { @@ -2023,7 +2023,7 @@ pub fn genDebugLinePadding(dl_w: *std.Io.Writer, size: u64) std.Io.Writer.Error! var op_len_size: u5 = 1; while (true) switch (std.math.order( size - extended_op_size - op_len_size, - @as(u64, 1) << 7 * op_len_size, + @as(u64, 1) << (7 * op_len_size), )) { .lt => break try dl_w.writeUleb128(size - extended_op_size - op_len_size), .eq => { diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index a585287261a2d73f365a4cb22ff89f041ddf7e2b..699174de84522cfe337fc4b662ac72e65250fc1f 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -7694,11 +7694,11 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load { break :load_object; } - const member = header.name() orelse member: { - const strtab_offset = header.nameOffset() catch |err| switch (err) { + const member = header.name() orelse (member: { + const strtab_offset = (header.nameOffset() catch |err| switch (err) { error.Overflow => break :member error.Overflow, error.InvalidCharacter => break :load_object, - } orelse break :load_object; + }) orelse break :load_object; const strtab_written = strtab.written(); if (strtab_offset > strtab_written.len) break :member error.Overflow; const member = std.mem.sliceTo(strtab_written[strtab_offset..], '\n'); @@ -7708,7 +7708,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load member; } catch |err| switch (err) { error.Overflow => return diags.failParse(path, "bad member name offset", .{}), - }; + }); try elf.loadObject(path, member, fr, .{ .offset = offset, .size = size }); } try fr.seekTo(std.mem.alignForward(u64, offset + size, 2)); diff --git a/src/link/MachO/UnwindInfo.zig b/src/link/MachO/UnwindInfo.zig index 7e54bd91e7888d230769ab962de967ebbf14ba47..e22099f396b7652f61baa27596e7f1861f0dd584 100644 --- a/src/link/MachO/UnwindInfo.zig +++ b/src/link/MachO/UnwindInfo.zig @@ -228,7 +228,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void { if (next.getAtomAddress(macho_file) >= range_start_max) { break; } else if (info.getCommonEncoding(next.enc) != null or - page.getPageEncoding(next.enc) != null and !is_dwarf) + (page.getPageEncoding(next.enc) != null and !is_dwarf)) { i += 1; space_left -= 1; diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index f6b97406849f031a235a51f31c64cb8e3b65b545..68053b67b0d6dbc7e58734fcb29edebfa9f132e9 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -266,8 +266,8 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { try writeDylibLC(.{ .cmd = .ID_DYLIB, .name = install_name, - .current_version = @as(u32, @intCast(curr.major << 16 | curr.minor << 8 | curr.patch)), - .compatibility_version = @as(u32, @intCast(compat.major << 16 | compat.minor << 8 | compat.patch)), + .current_version = @as(u32, @intCast((curr.major << 16) | (curr.minor << 8) | curr.patch)), + .compatibility_version = @as(u32, @intCast((compat.major << 16) | (compat.minor << 8) | compat.patch)), }, writer); } diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 745e3023dc0a9e61e68f7f6164c6ed220915447f..28da9ca08ec6eef24b5c125c949039a43fdc862e 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -1128,7 +1128,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { // indirect function table elements const table_index: u32 = @intCast( wasm.table_imports.getIndex(wasm.preloaded_strings.__indirect_function_table) orelse - wasm.table_imports.entries.len + wasm.tables.getIndex(.__indirect_function_table).?, + (wasm.table_imports.entries.len + wasm.tables.getIndex(.__indirect_function_table).?), ); // passive with implicit 0-index table or set table index manually const flags: u32 = if (table_index == 0) 0x0 else 0x02; diff --git a/src/link/riscv.zig b/src/link/riscv.zig index cfc42ac33969e1596982513fbad2216a4c52b62f..125668a7c11786487e110b52af4d7f6ce0439685 100644 --- a/src/link/riscv.zig +++ b/src/link/riscv.zig @@ -90,8 +90,8 @@ fn bitSlice( value: anytype, comptime high: comptime_int, comptime low: comptime_int, -) std.math.IntFittingRange(0, 1 << high - low) { - return @truncate((value >> low) & (1 << (high - low + 1)) - 1); +) std.math.IntFittingRange(0, 1 << (high - low)) { + return @truncate((value >> low) & ((1 << (high - low + 1)) - 1)); } pub const Eflags = packed struct(u32) { diff --git a/src/main.zig b/src/main.zig index 49838feb8beb6de697b763fc6852054050033a6e..5e55ccff87620a6c66b61e5a2fc4d1a7256a4f63 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3524,7 +3524,7 @@ fn buildOutputType( }; const thread_limit = @min( - @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), + @max(n_jobs orelse (std.Thread.getCpuCount() catch 1), 1), std.math.maxInt(Zcu.PerThread.IdBacking), ); try setThreadLimit(arena, thread_limit); diff --git a/test/Runner.zig b/test/Runner.zig index 1d838172a23bc9e182529cb6d37305def72f4c90..9f189e284818cb0b8e3a8bdf60af3b581a4fe66f 100644 --- a/test/Runner.zig +++ b/test/Runner.zig @@ -811,7 +811,7 @@ pub const DelimitedReader = struct { const d: *DelimitedReader = @fieldParentPtr("interface", r); const block = try d.unlimited.peekGreedy(d.delimiter.len); d.remaining = .limited(std.mem.findPos(u8, block, d.remaining.toInt().?, d.delimiter) orelse - block.len - d.delimiter.len + 1); + (block.len - d.delimiter.len + 1)); if (d.remaining == .nothing) return error.EndOfStream; const n = try d.unlimited.stream(w, limit.min(d.remaining)); d.remaining = d.remaining.subtract(n).?; @@ -821,7 +821,7 @@ pub const DelimitedReader = struct { const d: *DelimitedReader = @fieldParentPtr("interface", r); const block = try d.unlimited.peekGreedy(d.delimiter.len); d.remaining = .limited(std.mem.findPos(u8, block, d.remaining.toInt().?, d.delimiter) orelse - block.len - d.delimiter.len + 1); + (block.len - d.delimiter.len + 1)); if (d.remaining == .nothing) return error.EndOfStream; const n = try d.unlimited.discard(limit.min(d.remaining)); d.remaining = d.remaining.subtract(n).?; @@ -1397,9 +1397,9 @@ fn handleCommand( return update.fail("compiler failed to send terminating error_bundle", .{}); }, } - assert(contents_r.discardRemaining() catch |err| switch (err) { + assert((contents_r.discardRemaining() catch |err| switch (err) { error.ReadFailed => return error.ContentsReadFailed, - } == 0); + }) == 0); switch (cmd) { .todo, .skip => {}, else => update.allow_skip = false, diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 969e0a1af91cc39aa851be6cb6769aedd918113d..7f2b1e0984c717d2a77f5cfadd6f4ff015135dfc 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -470,7 +470,7 @@ test "@bitCast of packed struct with void field and multiple integers" { fn doTheTest(x: u8, y: u8) !void { const foo = @as(@This(), .{ .x = x, .v = {}, .y = y }); const as_int: u16 = @bitCast(foo); - try expect(as_int == @as(u16, y) << 8 | x); + try expect(as_int == (@as(u16, y) << 8) | x); } }; try S.doTheTest(123, 45); diff --git a/test/behavior/error.zig b/test/behavior/error.zig index 132193c85b777beabe63fad397d92d8d8e03918a..c6ad8ca25744096162d43d23b0000e40a94e16ac 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -209,7 +209,7 @@ fn testErrorSetType() !void { const a: MyErrSet!i32 = 5678; const b: MyErrSet!i32 = MyErrSet.OutOfMemory; - try expect(b catch error.OutOfMemory == error.OutOfMemory); + try expect((b catch error.OutOfMemory) == error.OutOfMemory); if (a) |value| try expect(value == 5678) else |err| switch (err) { error.OutOfMemory => unreachable, diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 9d35984b7c1cb2ebbd405727138cd13826c570aa..78b409af179da2308d225bb6f4d62389e8e8d1c2 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -49,10 +49,10 @@ fn testThreeExprInARow(f: bool, t: bool) !void { try assertFalse(1 | 2 | 4 != 7); try assertFalse(3 ^ 6 ^ 8 != 13); try assertFalse(7 & 14 & 28 != 4); - try assertFalse(9 << 1 << 2 != 9 << 3); - try assertFalse(90 >> 1 >> 2 != 90 >> 3); + try assertFalse((9 << 1) << 2 != 9 << 3); + try assertFalse((90 >> 1) >> 2 != 90 >> 3); try assertFalse(100 - 1 + 1000 != 1099); - try assertFalse(5 * 4 / 2 % 3 != 1); + try assertFalse((5 * 4 / 2) % 3 != 1); try assertFalse(@as(i32, @as(i32, 5)) != 5); try assertFalse(!!false); try assertFalse(@as(i32, 7) != --(@as(i32, 7))); diff --git a/test/behavior/try.zig b/test/behavior/try.zig index 649e22d5f94b1e30bd7892816b1ddbeb0da22db3..b9a368852d535dfbb7c644fe9208af4490edeebd 100644 --- a/test/behavior/try.zig +++ b/test/behavior/try.zig @@ -186,9 +186,9 @@ test "try ptr propagation mutate" { res1.* += 1; res2.* += 1; - try expect(f0 catch unreachable == 1); - try expect(f1 catch unreachable == 2); - try expect(f2 catch unreachable == 3); + try expect((f0 catch unreachable) == 1); + try expect((f1 catch unreachable) == 2); + try expect((f2 catch unreachable) == 3); try expect(res0.* == 1); try expect(res1.* == 2); diff --git a/test/behavior/x86_64/binary.zig b/test/behavior/x86_64/binary.zig index 899092f4058d5a1c1e75c155ec9280a4e11224dc..b9fad8d2a59c493e1fb758913144269d44080013 100644 --- a/test/behavior/x86_64/binary.zig +++ b/test/behavior/x86_64/binary.zig @@ -5503,7 +5503,7 @@ inline fn shrExact(comptime Type: type, lhs: Type, rhs: Type) Type { const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs); const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs); const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % @as(Log2Int(Type), @splat(bits)) else truncate_rhs; - return @shrExact(lhs >> final_rhs << final_rhs, final_rhs); + return @shrExact((lhs >> final_rhs) << final_rhs, final_rhs); } test shrExact { const test_shr_exact = binary(shrExact, .{}); @@ -5527,7 +5527,7 @@ inline fn shlExactUnsafe(comptime Type: type, lhs: Type, rhs: Type) Type { const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs); const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs); const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % @as(Log2Int(Type), @splat(bits)) else truncate_rhs; - return @shlExact(lhs << final_rhs >> final_rhs, final_rhs); + return @shlExact((lhs << final_rhs) >> final_rhs, final_rhs); } test shlExactUnsafe { const test_shl_exact_unsafe = binary(shlExactUnsafe, .{}); diff --git a/test/behavior/x86_64/cast.zig b/test/behavior/x86_64/cast.zig index 35f880fa174f18433529c24dec41ef9cddc2eaca..62e37fc74181e7fefdb23c44eb1a9af81af20e37 100644 --- a/test/behavior/x86_64/cast.zig +++ b/test/behavior/x86_64/cast.zig @@ -14502,15 +14502,15 @@ inline fn intCast(comptime Result: type, comptime Type: type, rhs: Type, comptim // TODO: if (bits == 0) rhs else rhs >> bits, .shift => |bits| if (bits == 0) rhs else switch (@typeInfo(Type)) { .int => if (ct_rhs < 0) - rhs | imin(Type) >> bits + rhs | (imin(Type) >> bits) else - rhs & imax(Type) >> bits, - .vector => rhs | @select( + rhs & (imax(Type) >> bits), + .vector => (rhs | @select( Scalar(Type), ct_rhs < @as(Type, @splat(0)), @as(Type, @splat(imin(Scalar(Type)) >> bits)), @as(Type, @splat(0)), - ) & ~@select( + )) & ~@select( Scalar(Type), ct_rhs >= @as(Type, @splat(0)), @as(Type, @splat(imin(Scalar(Type)) >> bits)), diff --git a/tools/loongarch/OpcodeDesc.zig b/tools/loongarch/OpcodeDesc.zig index e88a65c2718e8cc9d24219d8a7dc4c19b91d8f3d..10ddc86d8f679f6c53dc2717f9b0e6b7929e219e 100644 --- a/tools/loongarch/OpcodeDesc.zig +++ b/tools/loongarch/OpcodeDesc.zig @@ -95,10 +95,10 @@ pub const Format = struct { const index: Slot.Index = try .parse(&reader); const length = try takeInteger(u5, &reader); const post_proc = post_proc: { - if ('p' == reader.peekByte() catch |err| switch (err) { + if ('p' == (reader.peekByte() catch |err| switch (err) { error.EndOfStream => ' ', else => return err, - }) { + })) { reader.toss(1); break :post_proc try Slot.PostProcess.parse(&reader); } else break :post_proc Slot.PostProcess.none; -- 2.54.0 From 12ead9415ca1dfb15803c46d4598141daee314ba Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Mon, 13 Jul 2026 15:47:13 -0500 Subject: [PATCH 03/20] Update `grammar.peg` to conform to new Partial Operator Ordering --- doc/langref/grammar.peg | 62 ++- lib/std/zig/parser_generated_oracle.zig | 548 +++++++++++++++++++++--- 2 files changed, 523 insertions(+), 87 deletions(-) diff --git a/doc/langref/grammar.peg b/doc/langref/grammar.peg index d56beb04243f42b2c0b9204207a1e0f7aa6c9672..4aef3f4cbb8b696b2b222831ac01b3bd1f6b7dcb 100644 --- a/doc/langref/grammar.peg +++ b/doc/langref/grammar.peg @@ -127,21 +127,34 @@ AssignExpr <- Expr (AssignOp Expr / (COMMA Expr)+ EQUAL Expr / !AssignOp !COMMA) SingleAssignExpr <- Expr (AssignOp Expr / !AssignOp) -Expr <- BoolOrExpr +Expr <- PrefixExpr (OrElseExpr / CatchExpr / BoolExpr) -BoolOrExpr <- BoolAndExpr (OrOp BoolAndExpr)* !OrOp +OrElseExpr <- (OrElseOp PrefixExpr)+ !RecoveryNonmixingOp +CatchExpr <- (CatchOp PrefixExpr)+ !RecoveryNonmixingOp +RecoveryNonmixingOp <- ControlOp / CompareOp / BitwiseNonmixingOp +ControlOp <- OrElseOp / CatchOp / AndOp / OrOp -BoolAndExpr <- CompareExpr (AndOp CompareExpr)* !AndOp +BoolExpr <- CompareExpr (BoolAndExpr / BoolOrExpr / !ControlOp) +BoolAndExpr <- (AndOp PrefixExpr CompareExpr)+ !ControlOp +BoolOrExpr <- (OrOp PrefixExpr CompareExpr)+ !ControlOp -CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? !CompareOp +CompareExpr <- CompareOperand (CompareOp PrefixExpr CompareOperand)? !(CompareOp / OrElseOp / CatchOp) +CompareOperand + <- (BitwiseOrOp PrefixExpr)+ !BitwiseNonmixingOp + / (BitwiseAndOp PrefixExpr)+ !BitwiseNonmixingOp + / (BitwiseXorOp PrefixExpr)+ !BitwiseNonmixingOp + / BitShiftOp PrefixExpr !BitwiseNonmixingOp + / !BitOp AdditionExpr -BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* !BitwiseOp +BitOp <- BitwiseOrOp / BitwiseAndOp / BitwiseXorOp / BitShiftOp +BitwiseNonmixingOp <- MultiplyNonmixingOp / AdditionOp -BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)* !BitShiftOp +AdditionExpr <- MulOrModExpr (AdditionOp PrefixExpr MulOrModExpr)* !(AdditionOp / BitOp / OrElseOp / CatchOp) -AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)* !AdditionOp - -MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)* !MultiplyOp +MulOrModExpr <- ModExpr / !ModOp MultiplyExpr +ModExpr <- ModOp PrefixExpr !MultiplyNonmixingOp +MultiplyExpr <- (MultiplyOp PrefixExpr)* !MultiplyNonmixingOp +MultiplyNonmixingOp <- MultiplyOp / ModOp / BitOp / OrElseOp / CatchOp PrefixExpr <- PrefixOp* !PrefixOp PrimaryExpr @@ -323,15 +336,26 @@ CompareOpTok / LARROWEQUAL / RARROWEQUAL -BitwiseOp <- pre_op_white BitwiseOpTok post_op_white - / !pre_op_white BitwiseOpTok !post_op_white - / pre_op_white KEYWORD_catch post_op_white Payload? - / !pre_op_white KEYWORD_catch !post_op_white Payload? -BitwiseOpTok +BitwiseAndOp <- pre_op_white BitwiseAndOpTok post_op_white + / !pre_op_white BitwiseAndOpTok !post_op_white +BitwiseAndOpTok <- AMPERSAND ![&] - / CARET - / PIPE - / KEYWORD_orelse + +BitwiseOrOp <- pre_op_white BitwiseOrOpTok post_op_white + / !pre_op_white BitwiseOrOpTok !post_op_white +BitwiseOrOpTok + <- PIPE + +BitwiseXorOp <- pre_op_white BitwiseXorOpTok post_op_white + / !pre_op_white BitwiseXorOpTok !post_op_white +BitwiseXorOpTok + <- CARET + +CatchOp <- pre_op_white KEYWORD_catch post_op_white Payload? + / !pre_op_white KEYWORD_catch !post_op_white Payload? + +OrElseOp <- pre_op_white KEYWORD_orelse post_op_white + / !pre_op_white KEYWORD_orelse !post_op_white BitShiftOp <- pre_op_white BitShiftOpTok post_op_white / !pre_op_white BitShiftOpTok !post_op_white @@ -357,10 +381,12 @@ MultiplyOpTok <- PIPE2 / ASTERISK / SLASH - / PERCENT / ASTERISKPERCENT / ASTERISKPIPE +ModOp <- pre_op_white PERCENT post_op_white + / !pre_op_white PERCENT !post_op_white + PrefixOp <- EXCLAMATIONMARK / MINUS diff --git a/lib/std/zig/parser_generated_oracle.zig b/lib/std/zig/parser_generated_oracle.zig index 1cd16d6ce1495e8587fd16feb019f23501c90f3d..d5feeb4c5301524ad570d0f110087e96f1b269ac 100644 --- a/lib/std/zig/parser_generated_oracle.zig +++ b/lib/std/zig/parser_generated_oracle.zig @@ -42,13 +42,22 @@ const Def = enum { defAssignExpr, defSingleAssignExpr, defExpr, - defBoolOrExpr, + defOrElseExpr, + defCatchExpr, + defRecoveryNonmixingOp, + defControlOp, + defBoolExpr, defBoolAndExpr, + defBoolOrExpr, defCompareExpr, - defBitwiseExpr, - defBitShiftExpr, + defCompareOperand, + defBitOp, + defBitwiseNonmixingOp, defAdditionExpr, + defMulOrModExpr, + defModExpr, defMultiplyExpr, + defMultiplyNonmixingOp, defPrefixExpr, defPrimaryExpr, defIfExpr, @@ -103,14 +112,21 @@ const Def = enum { defAndOp, defCompareOp, defCompareOpTok, - defBitwiseOp, - defBitwiseOpTok, + defBitwiseAndOp, + defBitwiseAndOpTok, + defBitwiseOrOp, + defBitwiseOrOpTok, + defBitwiseXorOp, + defBitwiseXorOpTok, + defCatchOp, + defOrElseOp, defBitShiftOp, defBitShiftOpTok, defAdditionOp, defAdditionOpTok, defMultiplyOp, defMultiplyOpTok, + defModOp, defPrefixOp, defPrefixTypeOp, defPtrMods, @@ -290,7 +306,7 @@ const Def = enum { const Parser = struct { source: []const u8, i: usize, - depths: [272]u8, + depths: [288]u8, pub fn parseRoot(p: *Parser) Error!bool { const def_index = @backingInt(Def.defRoot); if (p.depths[def_index] > max_depth) return error.MaxDepth; @@ -964,33 +980,44 @@ const Parser = struct { defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parseBoolOrExpr()) break :blk_0 true; + if (try p.parsePrefixExpr() and blk_2: { + const pos_2 = p.i; + if (try p.parseOrElseExpr()) break :blk_2 true; + p.i = pos_2; + if (try p.parseCatchExpr()) break :blk_2 true; + p.i = pos_2; + if (try p.parseBoolExpr()) break :blk_2 true; + p.i = pos_2; + break :blk_2 false; + }) break :blk_0 true; p.i = pos_0; break :blk_0 false; }; } - pub fn parseBoolOrExpr(p: *Parser) Error!bool { - const def_index = @backingInt(Def.defBoolOrExpr); + pub fn parseOrElseExpr(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defOrElseExpr); if (p.depths[def_index] > max_depth) return error.MaxDepth; p.depths[def_index] += 1; defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parseBoolAndExpr() and blk_1: { + if (blk_1: { + var match_1 = false; var i_1: usize = 0; while (blk_3: { const pos_3 = p.i; - if (try p.parseOrOp() and try p.parseBoolAndExpr()) break :blk_3 true; + if (try p.parseOrElseOp() and try p.parsePrefixExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; }) { + match_1 = true; if (i_1 > max_depth) return error.MaxDepth; i_1 += 1; } - break :blk_1 true; + break :blk_1 match_1; } and blk_1: { const pos_1 = p.i; - const match_1 = try p.parseOrOp(); + const match_1 = try p.parseRecoveryNonmixingOp(); p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; @@ -998,6 +1025,97 @@ const Parser = struct { break :blk_0 false; }; } + pub fn parseCatchExpr(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defCatchExpr); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (blk_1: { + var match_1 = false; + var i_1: usize = 0; + while (blk_3: { + const pos_3 = p.i; + if (try p.parseCatchOp() and try p.parsePrefixExpr()) break :blk_3 true; + p.i = pos_3; + break :blk_3 false; + }) { + match_1 = true; + if (i_1 > max_depth) return error.MaxDepth; + i_1 += 1; + } + break :blk_1 match_1; + } and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseRecoveryNonmixingOp(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseRecoveryNonmixingOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defRecoveryNonmixingOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseControlOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseCompareOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseBitwiseNonmixingOp()) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseControlOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defControlOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseOrElseOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseCatchOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseAndOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseOrOp()) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseBoolExpr(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBoolExpr); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseCompareExpr() and blk_2: { + const pos_2 = p.i; + if (try p.parseBoolAndExpr()) break :blk_2 true; + p.i = pos_2; + if (try p.parseBoolOrExpr()) break :blk_2 true; + p.i = pos_2; + if (blk_3: { + const pos_3 = p.i; + const match_3 = try p.parseControlOp(); + p.i = pos_3; + break :blk_3 !match_3; + }) break :blk_2 true; + p.i = pos_2; + break :blk_2 false; + }) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } pub fn parseBoolAndExpr(p: *Parser) Error!bool { const def_index = @backingInt(Def.defBoolAndExpr); if (p.depths[def_index] > max_depth) return error.MaxDepth; @@ -1005,21 +1123,54 @@ const Parser = struct { defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parseCompareExpr() and blk_1: { + if (blk_1: { + var match_1 = false; var i_1: usize = 0; while (blk_3: { const pos_3 = p.i; - if (try p.parseAndOp() and try p.parseCompareExpr()) break :blk_3 true; + if (try p.parseAndOp() and try p.parsePrefixExpr() and try p.parseCompareExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; }) { + match_1 = true; if (i_1 > max_depth) return error.MaxDepth; i_1 += 1; } - break :blk_1 true; + break :blk_1 match_1; } and blk_1: { const pos_1 = p.i; - const match_1 = try p.parseAndOp(); + const match_1 = try p.parseControlOp(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseBoolOrExpr(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBoolOrExpr); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (blk_1: { + var match_1 = false; + var i_1: usize = 0; + while (blk_3: { + const pos_3 = p.i; + if (try p.parseOrOp() and try p.parsePrefixExpr() and try p.parseCompareExpr()) break :blk_3 true; + p.i = pos_3; + break :blk_3 false; + }) { + match_1 = true; + if (i_1 > max_depth) return error.MaxDepth; + i_1 += 1; + } + break :blk_1 match_1; + } and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseControlOp(); p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; @@ -1034,14 +1185,23 @@ const Parser = struct { defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parseBitwiseExpr() and (blk_3: { + if (try p.parseCompareOperand() and (blk_3: { const pos_3 = p.i; - if (try p.parseCompareOp() and try p.parseBitwiseExpr()) break :blk_3 true; + if (try p.parseCompareOp() and try p.parsePrefixExpr() and try p.parseCompareOperand()) break :blk_3 true; p.i = pos_3; break :blk_3 false; } or true) and blk_1: { const pos_1 = p.i; - const match_1 = try p.parseCompareOp(); + const match_1 = blk_3: { + const pos_3 = p.i; + if (try p.parseCompareOp()) break :blk_3 true; + p.i = pos_3; + if (try p.parseOrElseOp()) break :blk_3 true; + p.i = pos_3; + if (try p.parseCatchOp()) break :blk_3 true; + p.i = pos_3; + break :blk_3 false; + }; p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; @@ -1049,61 +1209,122 @@ const Parser = struct { break :blk_0 false; }; } - pub fn parseBitwiseExpr(p: *Parser) Error!bool { - const def_index = @backingInt(Def.defBitwiseExpr); + pub fn parseCompareOperand(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defCompareOperand); if (p.depths[def_index] > max_depth) return error.MaxDepth; p.depths[def_index] += 1; defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parseBitShiftExpr() and blk_1: { + if (blk_1: { + var match_1 = false; var i_1: usize = 0; while (blk_3: { const pos_3 = p.i; - if (try p.parseBitwiseOp() and try p.parseBitShiftExpr()) break :blk_3 true; + if (try p.parseBitwiseOrOp() and try p.parsePrefixExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; }) { + match_1 = true; if (i_1 > max_depth) return error.MaxDepth; i_1 += 1; } - break :blk_1 true; + break :blk_1 match_1; } and blk_1: { const pos_1 = p.i; - const match_1 = try p.parseBitwiseOp(); + const match_1 = try p.parseBitwiseNonmixingOp(); p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; - break :blk_0 false; - }; - } - pub fn parseBitShiftExpr(p: *Parser) Error!bool { - const def_index = @backingInt(Def.defBitShiftExpr); - if (p.depths[def_index] > max_depth) return error.MaxDepth; - p.depths[def_index] += 1; - defer p.depths[def_index] -= 1; - return blk_0: { - const pos_0 = p.i; - if (try p.parseAdditionExpr() and blk_1: { + if (blk_1: { + var match_1 = false; + var i_1: usize = 0; + while (blk_3: { + const pos_3 = p.i; + if (try p.parseBitwiseAndOp() and try p.parsePrefixExpr()) break :blk_3 true; + p.i = pos_3; + break :blk_3 false; + }) { + match_1 = true; + if (i_1 > max_depth) return error.MaxDepth; + i_1 += 1; + } + break :blk_1 match_1; + } and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseBitwiseNonmixingOp(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + var match_1 = false; var i_1: usize = 0; while (blk_3: { const pos_3 = p.i; - if (try p.parseBitShiftOp() and try p.parseAdditionExpr()) break :blk_3 true; + if (try p.parseBitwiseXorOp() and try p.parsePrefixExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; }) { + match_1 = true; if (i_1 > max_depth) return error.MaxDepth; i_1 += 1; } - break :blk_1 true; + break :blk_1 match_1; } and blk_1: { const pos_1 = p.i; - const match_1 = try p.parseBitShiftOp(); + const match_1 = try p.parseBitwiseNonmixingOp(); p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; + if (try p.parseBitShiftOp() and try p.parsePrefixExpr() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseBitwiseNonmixingOp(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseBitOp(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parseAdditionExpr()) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseBitOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseBitwiseOrOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseBitwiseAndOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseBitwiseXorOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseBitShiftOp()) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseBitwiseNonmixingOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitwiseNonmixingOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseMultiplyNonmixingOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseAdditionOp()) break :blk_0 true; + p.i = pos_0; break :blk_0 false; }; } @@ -1114,11 +1335,11 @@ const Parser = struct { defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parseMultiplyExpr() and blk_1: { + if (try p.parseMulOrModExpr() and blk_1: { var i_1: usize = 0; while (blk_3: { const pos_3 = p.i; - if (try p.parseAdditionOp() and try p.parseMultiplyExpr()) break :blk_3 true; + if (try p.parseAdditionOp() and try p.parsePrefixExpr() and try p.parseMulOrModExpr()) break :blk_3 true; p.i = pos_3; break :blk_3 false; }) { @@ -1128,7 +1349,54 @@ const Parser = struct { break :blk_1 true; } and blk_1: { const pos_1 = p.i; - const match_1 = try p.parseAdditionOp(); + const match_1 = blk_3: { + const pos_3 = p.i; + if (try p.parseAdditionOp()) break :blk_3 true; + p.i = pos_3; + if (try p.parseBitOp()) break :blk_3 true; + p.i = pos_3; + if (try p.parseOrElseOp()) break :blk_3 true; + p.i = pos_3; + if (try p.parseCatchOp()) break :blk_3 true; + p.i = pos_3; + break :blk_3 false; + }; + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseMulOrModExpr(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defMulOrModExpr); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseModExpr()) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseModOp(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parseMultiplyExpr()) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseModExpr(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defModExpr); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseModOp() and try p.parsePrefixExpr() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parseMultiplyNonmixingOp(); p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; @@ -1143,7 +1411,7 @@ const Parser = struct { defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parsePrefixExpr() and blk_1: { + if (blk_1: { var i_1: usize = 0; while (blk_3: { const pos_3 = p.i; @@ -1157,7 +1425,7 @@ const Parser = struct { break :blk_1 true; } and blk_1: { const pos_1 = p.i; - const match_1 = try p.parseMultiplyOp(); + const match_1 = try p.parseMultiplyNonmixingOp(); p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; @@ -1165,6 +1433,26 @@ const Parser = struct { break :blk_0 false; }; } + pub fn parseMultiplyNonmixingOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defMultiplyNonmixingOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseMultiplyOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseModOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseBitOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseOrElseOp()) break :blk_0 true; + p.i = pos_0; + if (try p.parseCatchOp()) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } pub fn parsePrefixExpr(p: *Parser) Error!bool { const def_index = @backingInt(Def.defPrefixExpr); if (p.depths[def_index] > max_depth) return error.MaxDepth; @@ -2259,46 +2547,32 @@ const Parser = struct { break :blk_0 false; }; } - pub fn parseBitwiseOp(p: *Parser) Error!bool { - const def_index = @backingInt(Def.defBitwiseOp); + pub fn parseBitwiseAndOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitwiseAndOp); if (p.depths[def_index] > max_depth) return error.MaxDepth; p.depths[def_index] += 1; defer p.depths[def_index] -= 1; return blk_0: { const pos_0 = p.i; - if (try p.parsepre_op_white() and try p.parseBitwiseOpTok() and try p.parsepost_op_white()) break :blk_0 true; + if (try p.parsepre_op_white() and try p.parseBitwiseAndOpTok() and try p.parsepost_op_white()) break :blk_0 true; p.i = pos_0; if (blk_1: { const pos_1 = p.i; const match_1 = try p.parsepre_op_white(); p.i = pos_1; break :blk_1 !match_1; - } and try p.parseBitwiseOpTok() and blk_1: { + } and try p.parseBitwiseAndOpTok() and blk_1: { const pos_1 = p.i; const match_1 = try p.parsepost_op_white(); p.i = pos_1; break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; - if (try p.parsepre_op_white() and try p.parseKEYWORD_catch() and try p.parsepost_op_white() and (try p.parsePayload() or true)) break :blk_0 true; - p.i = pos_0; - if (blk_1: { - const pos_1 = p.i; - const match_1 = try p.parsepre_op_white(); - p.i = pos_1; - break :blk_1 !match_1; - } and try p.parseKEYWORD_catch() and blk_1: { - const pos_1 = p.i; - const match_1 = try p.parsepost_op_white(); - p.i = pos_1; - break :blk_1 !match_1; - } and (try p.parsePayload() or true)) break :blk_0 true; - p.i = pos_0; break :blk_0 false; }; } - pub fn parseBitwiseOpTok(p: *Parser) Error!bool { - const def_index = @backingInt(Def.defBitwiseOpTok); + pub fn parseBitwiseAndOpTok(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitwiseAndOpTok); if (p.depths[def_index] > max_depth) return error.MaxDepth; p.depths[def_index] += 1; defer p.depths[def_index] -= 1; @@ -2318,11 +2592,125 @@ const Parser = struct { break :blk_1 !match_1; }) break :blk_0 true; p.i = pos_0; - if (try p.parseCARET()) break :blk_0 true; + break :blk_0 false; + }; + } + pub fn parseBitwiseOrOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitwiseOrOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parsepre_op_white() and try p.parseBitwiseOrOpTok() and try p.parsepost_op_white()) break :blk_0 true; p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepre_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parseBitwiseOrOpTok() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepost_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseBitwiseOrOpTok(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitwiseOrOpTok); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; if (try p.parsePIPE()) break :blk_0 true; p.i = pos_0; - if (try p.parseKEYWORD_orelse()) break :blk_0 true; + break :blk_0 false; + }; + } + pub fn parseBitwiseXorOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitwiseXorOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parsepre_op_white() and try p.parseBitwiseXorOpTok() and try p.parsepost_op_white()) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepre_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parseBitwiseXorOpTok() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepost_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseBitwiseXorOpTok(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defBitwiseXorOpTok); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parseCARET()) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseCatchOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defCatchOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parsepre_op_white() and try p.parseKEYWORD_catch() and try p.parsepost_op_white() and (try p.parsePayload() or true)) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepre_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parseKEYWORD_catch() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepost_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and (try p.parsePayload() or true)) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } + pub fn parseOrElseOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defOrElseOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parsepre_op_white() and try p.parseKEYWORD_orelse() and try p.parsepost_op_white()) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepre_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parseKEYWORD_orelse() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepost_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; p.i = pos_0; break :blk_0 false; }; @@ -2452,8 +2840,6 @@ const Parser = struct { p.i = pos_0; if (try p.parseSLASH()) break :blk_0 true; p.i = pos_0; - if (try p.parsePERCENT()) break :blk_0 true; - p.i = pos_0; if (try p.parseASTERISKPERCENT()) break :blk_0 true; p.i = pos_0; if (try p.parseASTERISKPIPE()) break :blk_0 true; @@ -2461,6 +2847,30 @@ const Parser = struct { break :blk_0 false; }; } + pub fn parseModOp(p: *Parser) Error!bool { + const def_index = @backingInt(Def.defModOp); + if (p.depths[def_index] > max_depth) return error.MaxDepth; + p.depths[def_index] += 1; + defer p.depths[def_index] -= 1; + return blk_0: { + const pos_0 = p.i; + if (try p.parsepre_op_white() and try p.parsePERCENT() and try p.parsepost_op_white()) break :blk_0 true; + p.i = pos_0; + if (blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepre_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + } and try p.parsePERCENT() and blk_1: { + const pos_1 = p.i; + const match_1 = try p.parsepost_op_white(); + p.i = pos_1; + break :blk_1 !match_1; + }) break :blk_0 true; + p.i = pos_0; + break :blk_0 false; + }; + } pub fn parsePrefixOp(p: *Parser) Error!bool { const def_index = @backingInt(Def.defPrefixOp); if (p.depths[def_index] > max_depth) return error.MaxDepth; -- 2.54.0 From 2d3eece3f4c6ab67165aab2c6c0bc890ad2338ea Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Tue, 14 Jul 2026 13:42:31 -0500 Subject: [PATCH 04/20] Add WIP langref for new operators --- doc/langref.html.in | 2 ++ .../ambiguous_precedence_mul_bitand.zig | 13 ++++++++++ .../ambiguous_precedence_orelse_ne.zig | 21 ++++++++++++++++ .../ambiguous_precedence_shift_sub.zig | 10 ++++++++ doc/langref/chained_sibling_operators.zig | 5 ++++ doc/langref/nonchaining_sibling_operators.zig | 5 ++++ doc/langref/operator_precedence.zig | 24 +++++++++++++++++++ 7 files changed, 80 insertions(+) create mode 100644 doc/langref/ambiguous_precedence_mul_bitand.zig create mode 100644 doc/langref/ambiguous_precedence_orelse_ne.zig create mode 100644 doc/langref/ambiguous_precedence_shift_sub.zig create mode 100644 doc/langref/chained_sibling_operators.zig create mode 100644 doc/langref/nonchaining_sibling_operators.zig create mode 100644 doc/langref/operator_precedence.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index 936254958cb67e9260a5578c8e2e920deb412ef0..e8c1c675ed7b40bacc7f72e2ad2d68892ac81ca4 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1908,6 +1908,8 @@ or = *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |={#endsyntax#} {#header_close#} {#header_close#} + {#header_close#} + {#header_open|Arrays#} {#code|test_arrays.zig#} diff --git a/doc/langref/ambiguous_precedence_mul_bitand.zig b/doc/langref/ambiguous_precedence_mul_bitand.zig new file mode 100644 index 0000000000000000000000000000000000000000..e44997a93ca1496a8144b19d5045a10fdc8ea64b --- /dev/null +++ b/doc/langref/ambiguous_precedence_mul_bitand.zig @@ -0,0 +1,13 @@ +test "ambiguous precedence" { + const x: u8 = 1; + const y: u8 = 2; + const z: u8 = 3; + + // Its not obvious below if this is multiplication by a masked value + // `(x&y) *% z` + // or a masking of wrapped multiplication + // `x & (y*%z)` + _ = x & y *% z; +} + +// obj=ambiguous operator precedence with operators … & … *% …; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/ambiguous_precedence_orelse_ne.zig b/doc/langref/ambiguous_precedence_orelse_ne.zig new file mode 100644 index 0000000000000000000000000000000000000000..1bbd662837e71f9941b144bcbb7c353cb945a046 --- /dev/null +++ b/doc/langref/ambiguous_precedence_orelse_ne.zig @@ -0,0 +1,21 @@ +fn makeBool(x: u32) ?bool { + if (x == 0) return false; + if (x == 1) return true; + return null; +} + +test "ambiguous precedence" { + const x: ?u32 = 0; + const y: u8 = 0; + const z: u8 = 0; + + // We might expect the line below to parse something like: + // `makeBool(x) orelse (y != z)` + // but we might elsewhere want something like + // `(nullable(x) orelse y) != w` + // to perform a fallback and then a check, either way its + // not obvious the behavior so we get an error + _ = makeBool(x) orelse y != z; +} + +// obj=ambiguous operator precedence with operators … orelse … != …; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/ambiguous_precedence_shift_sub.zig b/doc/langref/ambiguous_precedence_shift_sub.zig new file mode 100644 index 0000000000000000000000000000000000000000..4791e81cd53fde58048bfb783eadf62fee0e4371 --- /dev/null +++ b/doc/langref/ambiguous_precedence_shift_sub.zig @@ -0,0 +1,10 @@ +test "ambiguous precedence" { + const x: u64 = 1; + const y: u6 = 63; + + // We probably meant `(x << y) - 1` + // But thats not how it would have compiled + _ = x << y - 1; +} + +// obj=ambiguous operator precedence with operators … << … - …; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/chained_sibling_operators.zig b/doc/langref/chained_sibling_operators.zig new file mode 100644 index 0000000000000000000000000000000000000000..f88b363d9f8bad0d26ee7daa2b80675d9f7991d2 --- /dev/null +++ b/doc/langref/chained_sibling_operators.zig @@ -0,0 +1,5 @@ +fn foo(x: anytype, y: anytype, z: anytype) void { + _ = x + y - z; +} + +// syntax \ No newline at end of file diff --git a/doc/langref/nonchaining_sibling_operators.zig b/doc/langref/nonchaining_sibling_operators.zig new file mode 100644 index 0000000000000000000000000000000000000000..9716a956b1580dd214df68aa6619f55996e52ac8 --- /dev/null +++ b/doc/langref/nonchaining_sibling_operators.zig @@ -0,0 +1,5 @@ +fn foo(x: anytype, y: anytype, z: anytype) void { + _ = x << y << z; +} + +// obj=repetition of non-chainable operators … << … << …; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/operator_precedence.zig b/doc/langref/operator_precedence.zig new file mode 100644 index 0000000000000000000000000000000000000000..3a5aae99bc2f8be1362a7fed71eb3df0ba2b42ad --- /dev/null +++ b/doc/langref/operator_precedence.zig @@ -0,0 +1,24 @@ +const assert = @import("std").debug.assert; + +test "operator precedence" { + const x = 1; + const y = 2; + const z = 3; + + // Because comparisons have a lower precedence than any arithmetic + // We can safely avoid parenthesizing the expressions + assert(x + y * z == x + (y*z)); + assert(x * y + z == (x*y) + z); + + // We can also use ambiguous operators as long as they are seperated + // by a well ordered one such as below + assert(x*y + x%y == (x*y) + (x%y)); + //That includes comparisons + assert(x & y != x + y); + + // We can freely chain or's and and's, but not with each other + assert(false or x == y or x + y == z); + assert(true and x != y and y != z); +} + +// test \ No newline at end of file -- 2.54.0 From 1bae04f02026427d1754f704bd24fce3317f3e89 Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Tue, 14 Jul 2026 23:48:51 -0500 Subject: [PATCH 05/20] Many tweaks to the langref to improve style, clarity, and make me sound less wierd. --- doc/langref/ambiguous_precedence_mul_bitand.zig | 6 ++---- doc/langref/ambiguous_precedence_orelse_ne.zig | 9 +++------ doc/langref/ambiguous_precedence_shift_sub.zig | 4 ++-- doc/langref/operator_precedence.zig | 11 +++++------ 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/doc/langref/ambiguous_precedence_mul_bitand.zig b/doc/langref/ambiguous_precedence_mul_bitand.zig index e44997a93ca1496a8144b19d5045a10fdc8ea64b..66f1f5a1a4535148a5377dc3e335dc9e1d498147 100644 --- a/doc/langref/ambiguous_precedence_mul_bitand.zig +++ b/doc/langref/ambiguous_precedence_mul_bitand.zig @@ -3,10 +3,8 @@ test "ambiguous precedence" { const y: u8 = 2; const z: u8 = 3; - // Its not obvious below if this is multiplication by a masked value - // `(x&y) *% z` - // or a masking of wrapped multiplication - // `x & (y*%z)` + // 1. Could be multiplication by a masked value: (x&y) *% z + // 2. Or masking the result of multiplication: x & (y*%z) _ = x & y *% z; } diff --git a/doc/langref/ambiguous_precedence_orelse_ne.zig b/doc/langref/ambiguous_precedence_orelse_ne.zig index 1bbd662837e71f9941b144bcbb7c353cb945a046..922886e24ba36b0f5e522269cf6eca593137122c 100644 --- a/doc/langref/ambiguous_precedence_orelse_ne.zig +++ b/doc/langref/ambiguous_precedence_orelse_ne.zig @@ -9,12 +9,9 @@ test "ambiguous precedence" { const y: u8 = 0; const z: u8 = 0; - // We might expect the line below to parse something like: - // `makeBool(x) orelse (y != z)` - // but we might elsewhere want something like - // `(nullable(x) orelse y) != w` - // to perform a fallback and then a check, either way its - // not obvious the behavior so we get an error + // Without parentheses the compiler cannot distinguish between two conflicting interpretations: + // 1. Compare on the value which may be recovered: (makeBool(x) orelse y) != z + // 2. Recover to the result of the comparison: makeBool(x) orelse (y != z) _ = makeBool(x) orelse y != z; } diff --git a/doc/langref/ambiguous_precedence_shift_sub.zig b/doc/langref/ambiguous_precedence_shift_sub.zig index 4791e81cd53fde58048bfb783eadf62fee0e4371..b5f7d8a679154bc66af1451224f62fac2f489c91 100644 --- a/doc/langref/ambiguous_precedence_shift_sub.zig +++ b/doc/langref/ambiguous_precedence_shift_sub.zig @@ -2,8 +2,8 @@ test "ambiguous precedence" { const x: u64 = 1; const y: u6 = 63; - // We probably meant `(x << y) - 1` - // But thats not how it would have compiled + // 1. Could mean shift then subtract: (x< Date: Sat, 18 Jul 2026 23:57:30 -0500 Subject: [PATCH 06/20] Add --upgrade for migrating precedence. Known bug: deletes comments from assignment lines. No clue why. --- lib/std/zig/Ast.zig | 6 +-- lib/std/zig/Ast/Render.zig | 37 ++++++++++++++-- lib/std/zig/Parse.zig | 91 ++++++++++++++++++++++++++------------ src/fmt.zig | 7 ++- 4 files changed, 105 insertions(+), 36 deletions(-) diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index 14a16e1730564aa7add9e659dc81a76175b5a95c..7a23a1653f9d68803c9b6689d293aecae0c55993 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -139,10 +139,7 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void { } pub const Mode = enum { zig, zon }; -pub const ParseOptions = struct { - recover: bool = true, - mode: Mode = .zig, -}; +pub const ParseOptions = struct { recover: bool = true, mode: Mode = .zig, use_old_precedence: bool = false }; /// Result should be freed with tree.deinit() when there are /// no more references to any of the tokens or nodes. @@ -185,6 +182,7 @@ pub fn parseTokens( .scratch = .empty, .tok_i = 0, .recover = options.recover, + .use_old_precedence = options.use_old_precedence, }; defer parser.errors.deinit(gpa); defer parser.nodes.deinit(gpa); diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig index f4cfed386044725ea7074d584d1879ac42b33777..5a111162cd63ee50209e713dcab954f103b0b009 100644 --- a/lib/std/zig/Ast/Render.zig +++ b/lib/std/zig/Ast/Render.zig @@ -4,6 +4,7 @@ const mem = std.mem; const Allocator = std.mem.Allocator; const meta = std.meta; const Ast = std.zig.Ast; +const Parse = @import("../../zig/Parse.zig"); const Token = std.zig.Token; const primitives = std.zig.primitives; const Writer = std.Io.Writer; @@ -539,13 +540,43 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { .@"orelse", => { const lhs, const rhs = tree.nodeData(node).node_and_node; - try renderExpression(r, lhs, .space); - const op_token = tree.nodeMainToken(node); + + const lhs_tag = tree.nodeTag(lhs); + const center_tag = tree.nodeTag(node); + const rhs_tag = tree.nodeTag(rhs); + + const lhs_prec = Parse.precedenceFromNodeTag(lhs_tag); + const center_prec = Parse.precedenceFromNodeTag(center_tag); + const rhs_prec = Parse.precedenceFromNodeTag(rhs_tag); + + const left_rel = lhs_prec.cmp(center_prec); + const right_rel = rhs_prec.cmp(center_prec); + + const paren_left = left_rel == null or left_rel == .lt or (left_rel == .eq and lhs_prec.group == center_prec.group and lhs_prec.assoc == .none); + const paren_right = right_rel == null or right_rel == .lt; + + + if (paren_left) try ais.writeByte('('); + try renderExpression(r, lhs, .none); + if (paren_left) try ais.writeByte(')'); + // Multiline string literals will eat the space so we need to skip if we thats next. + if (tree.tokenTag(tree.lastToken(lhs)) != .multiline_string_literal_line) try renderOnlySpace(r, .space); + try ais.pushIndent(.binop); + const op_token = tree.nodeMainToken(node); const rhs_seperate_line = !tree.tokensOnSameLine(op_token, op_token + 1) or tree.tokenTag(op_token + 1) == .multiline_string_literal_line; try renderToken(r, op_token, if (rhs_seperate_line) .newline else .space); - try renderExpression(r, rhs, space); + + if (paren_right) try ais.writeByte('('); + try renderExpression(r, rhs, .none); + if (paren_right) try ais.writeByte(')'); + + const most_recent = tree.lastToken(rhs); + const lexeme = tokenSliceForRender(tree, most_recent); + // If our space is .none, then the above code functions as normal and putting this here will duplicate comments and such + if (space != .none) try renderSpace(r, most_recent, lexeme.len, space); + ais.popIndent(); }, diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index 79e90e487284339b5a438e15bbdb8fc40b9a27ef..ff6a74821ac46dfefb5a64e84cffcc23aa6f5dc3 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -24,6 +24,7 @@ nodes: Ast.NodeList, extra_data: std.ArrayList(u32), scratch: std.ArrayList(Node.Index), recover: bool, +use_old_precedence: bool = false, fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag { return p.tokens.items(.tag)[token_index]; @@ -1531,6 +1532,8 @@ const PrecClass = struct { const Group = enum { const num_distinct = std.meta.fieldNames(Group).len; + top, + arithmetic_product_chainable, arithmetic_mod_nonchainable, arithmetic_sum, @@ -1588,7 +1591,7 @@ const PrecClass = struct { gt = 1, fn inverted(self: Rel) Rel { - return @enumFromInt(-@intFromEnum(self)); + return @fromBackingInt(@intCast(-@backingInt(self))); } }; @@ -1602,12 +1605,14 @@ const PrecClass = struct { if (!std.mem.startsWith(u8, fieldname_j, @tagName(major_b))) continue; prec_array.*[i][j] = rel; + prec_array.*[j][i] = rel.inverted(); } } } fn setMinorRelation(prec_array: *PrecedenceArray, minor_a: Group, rel: Rel, minor_b: Group) void { - prec_array.*[@intFromEnum(minor_a)][@intFromEnum(minor_b)] = rel; + prec_array.*[@backingInt(minor_a)][@backingInt(minor_b)] = rel; + prec_array.*[@backingInt(minor_b)][@backingInt(minor_a)] = rel.inverted(); } /// Arithmetic_* > Comparison @@ -1622,6 +1627,9 @@ const PrecClass = struct { @setEvalBranchQuota(20_000); const major_greater_than_relations = [_][2]Group.Major{ // zig fmt: off + .{ .top, .arithmetic }, + .{ .top, .bitwise }, + .{ .top, .recovery }, .{ .arithmetic, .comparison }, .{ .bitwise, .comparison }, .{ .comparison, .bool }, @@ -1656,30 +1664,21 @@ const PrecClass = struct { var order: PrecedenceArray = @splat(@splat(null)); + setMinorRelation(&order, .top, .gt, .arithmetic_product_chainable); + setMinorRelation(&order, .arithmetic_product_chainable, .eq, .arithmetic_mod_nonchainable); setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum); - setMinorRelation(&order, .arithmetic_product_chainable, .gt, .arithmetic_sum); setMinorRelation(&order, .arithmetic_sum, .gt, .bitwise_shift); - // Here since the transative ordering computer cant leverage equals to derive a = b < c --> a < c, we have to manually list these setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_and); - setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_xor); - setMinorRelation(&order, .bitwise_shift, .gt, .bitwise_or); - setMinorRelation(&order, .bitwise_shift, .gt, .recovery_catch); - setMinorRelation(&order, .bitwise_shift, .gt, .recovery_orelse); setMinorRelation(&order, .bitwise_and, .eq, .bitwise_xor); - setMinorRelation(&order, .bitwise_xor, .eq, .bitwise_or); - setMinorRelation(&order, .bitwise_or, .eq, .recovery_catch); - setMinorRelation(&order, .recovery_catch, .eq, .recovery_orelse); - setMinorRelation(&order, .recovery_orelse, .eq, .bitwise_and); + setMinorRelation(&order, .bitwise_and, .eq, .bitwise_or); + setMinorRelation(&order, .bitwise_and, .eq, .recovery_catch); + setMinorRelation(&order, .bitwise_and, .eq, .recovery_orelse); setMinorRelation(&order, .bitwise_and, .gt, .comparison); - setMinorRelation(&order, .bitwise_xor, .gt, .comparison); - setMinorRelation(&order, .bitwise_or, .gt, .comparison); - setMinorRelation(&order, .recovery_catch, .gt, .comparison); - setMinorRelation(&order, .recovery_orelse, .gt, .comparison); setMinorRelation(&order, .comparison, .gt, .bool_and); @@ -1697,16 +1696,22 @@ const PrecClass = struct { }; pub fn cmp(lhs: PrecClass, rhs: PrecClass) ?Rel { - return PrecClass.precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)]; + return PrecClass.precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)]; } pub fn v16_cmp(lhs: PrecClass, rhs: PrecClass) Rel { - return PrecClass.v16_precedence_ordering[@intFromEnum(lhs.group)][@intFromEnum(rhs.group)].?; + return PrecClass.v16_precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)].?; } fn computeTransativeOrdering(order: *PrecedenceArray) void { for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| for (0..Group.num_distinct) |k| { - if (order[i][k] == order[k][j] and order[i][k] != null) order[i][j] = order[i][k]; + if (order[i][j] == null or order[j][k] == null) continue; + // X < Y < Z ==> X < Z X > Y > Z ==> X > Z + if (order[i][j] == order[j][k]) order[i][k] = order[i][j]; + // X = Y < Z ==> X < Z X = Y > Z ==> X > Z + if (order[i][j] == .eq) order[i][k] = order[j][k]; + // X < Y = Z ==> X < Z X > Y = Z ==> X > Z + if (order[j][k] == .eq) order[i][k] = order[i][j]; }; for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| { if (i == j) order[i][j] = .eq; @@ -1762,6 +1767,23 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec // zig fmt: on }); +fn comptimePrecedenceFromNodeTag(comptime tag: Node.Tag) PrecClass { + for (operTable) |data| { + if (data.tag == tag) return data.prec; + } + return .{ .group = .top, .assoc = .left }; +} + +pub fn precedenceFromNodeTag(tag: Node.Tag) PrecClass { + return switch (tag) { + inline else => |ct_tag| comptimePrecedenceFromNodeTag(ct_tag), + }; +} + +pub fn newPrecedenceBetween(left_tok: Node.Tag, right_tok: Node.Tag) ?PrecClass.Rel { + return precedenceFromNodeTag(left_tok).cmp(precedenceFromNodeTag(right_tok)); +} + fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index { var node = try p.parsePrefixExpr() orelse return null; @@ -1769,17 +1791,21 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 while (true) { const tok_tag = p.tokenTag(p.tok_i); - const info = operTable[@intFromEnum(tok_tag)]; + const info = operTable[@backingInt(tok_tag)]; - const rel = info.prec.cmp(min_exc_prec) orelse b: { + const prec_relation = if (!p.use_old_precedence) info.prec.cmp(min_exc_prec) else info.prec.v16_cmp(min_exc_prec); + const rel = prec_relation orelse b: { + // This issues warnings if the relation is null, which it never is in 0.16.0 const prev_op_tok_tag = p.tokenTag(prev_operator_token); - const prev_op_info = operTable[@intFromEnum(prev_op_tok_tag)]; + const prev_op_info = operTable[@backingInt(prev_op_tok_tag)]; const v16_rel = prev_op_info.prec.v16_cmp(info.prec); try p.warnMsg(.{ .tag = .ambiguous_operator_precedence, .is_note = false, .token = p.tok_i, - .extra = .{ .offset = p.tok_i - prev_operator_token }, + .extra = .{ + .offset = p.tok_i - prev_operator_token, + }, }); try p.warnMsg(.{ .tag = .previous_ambiguous_operator, @@ -1791,14 +1817,18 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 .tag = .hint_operator_precedence_left, .is_note = true, .token = p.tok_i, - .extra = .{ .offset = p.tok_i - prev_operator_token }, + .extra = .{ + .offset = p.tok_i - prev_operator_token, + }, }); } else { try p.warnMsg(.{ .tag = .hint_operator_precedence_right, .is_note = true, .token = p.tok_i, - .extra = .{ .offset = p.tok_i - prev_operator_token }, + .extra = .{ + .offset = p.tok_i - prev_operator_token, + }, }); } break :b .gt; @@ -1812,12 +1842,15 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 //Special cased check to maintain the old more helpful error for chained comparisons. if (info.prec.group == .comparison) { try p.warn(.chained_comparison_operators); - } else { + // In 0.16.0 the only reptition prohibited was comparisons which we checked above + } else if (!p.use_old_precedence) { try p.warnMsg(.{ .tag = .illegal_chained_operators, .is_note = false, .token = p.tok_i, - .extra = .{ .offset = p.tok_i - prev_operator_token }, + .extra = .{ + .offset = p.tok_i - prev_operator_token, + }, }); try p.warnMsg(.{ .tag = .previous_ambiguous_operator, @@ -1828,7 +1861,9 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 .tag = .hint_operator_precedence_left, .is_note = true, .token = p.tok_i, - .extra = .{ .offset = p.tok_i - prev_operator_token }, + .extra = .{ + .offset = p.tok_i - prev_operator_token, + }, }); } } diff --git a/src/fmt.zig b/src/fmt.zig index 42e7558ea9950968af8c026aa755951a052cd31e..16dfb01d8f92a733ed2068d649dffc07ca6b587d 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -41,6 +41,7 @@ const Fmt = struct { out_buffer: std.Io.Writer.Allocating, stdout_writer: *Io.File.Writer, stats: ?*Stats, + fix_precedence: bool, const SeenMap = std.AutoHashMap(Io.File.INode, void); }; @@ -66,6 +67,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! var check_ast_flag = false; var force_zon = false; var enable_stats = false; + var fix_precedence = false; var input_files = std.array_list.Managed([]const u8).init(gpa); defer input_files.deinit(); @@ -107,6 +109,8 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! try excluded_files.append(next_arg); } else if (mem.eql(u8, arg, "--zon")) { force_zon = true; + } else if (mem.eql(u8, arg, "--upgrade")) { + fix_precedence = true; } else { fatal("unrecognized parameter: {q}", .{arg}); } @@ -198,6 +202,7 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! .out_buffer = .init(gpa), .stdout_writer = &stdout_writer, .stats = null, + .fix_precedence = fix_precedence, }; defer fmt.seen.deinit(); defer fmt.out_buffer.deinit(); @@ -382,7 +387,7 @@ fn fmtPathFile( break :mode .zig; }; - var tree = try std.zig.Ast.parse(gpa, source_code, .{ .mode = mode }); + var tree = try std.zig.Ast.parse(gpa, source_code, .{ .mode = mode, .use_old_precedence = fmt.fix_precedence }); defer tree.deinit(gpa); if (tree.errors.len != 0) { -- 2.54.0 From cb715212f7aa62ec33933138c3cd47efdf95c075 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 23 Jul 2026 23:44:43 -0700 Subject: [PATCH 07/20] Alternative zig fmt --upgrade implementation using Render.Fixups --- lib/std/zig/Ast.zig | 6 ++- lib/std/zig/Ast/Render.zig | 62 +++++++++++++--------------- lib/std/zig/Parse.zig | 10 ++--- src/fmt.zig | 83 +++++++++++++++++++++++++++++++++++++- 4 files changed, 116 insertions(+), 45 deletions(-) diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index 7a23a1653f9d68803c9b6689d293aecae0c55993..14a16e1730564aa7add9e659dc81a76175b5a95c 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -139,7 +139,10 @@ pub fn deinit(tree: *Ast, gpa: Allocator) void { } pub const Mode = enum { zig, zon }; -pub const ParseOptions = struct { recover: bool = true, mode: Mode = .zig, use_old_precedence: bool = false }; +pub const ParseOptions = struct { + recover: bool = true, + mode: Mode = .zig, +}; /// Result should be freed with tree.deinit() when there are /// no more references to any of the tokens or nodes. @@ -182,7 +185,6 @@ pub fn parseTokens( .scratch = .empty, .tok_i = 0, .recover = options.recover, - .use_old_precedence = options.use_old_precedence, }; defer parser.errors.deinit(gpa); defer parser.nodes.deinit(gpa); diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig index 5a111162cd63ee50209e713dcab954f103b0b009..060ce9af8d0b7673504ce0f7598c40c071d57dd8 100644 --- a/lib/std/zig/Ast/Render.zig +++ b/lib/std/zig/Ast/Render.zig @@ -4,7 +4,6 @@ const mem = std.mem; const Allocator = std.mem.Allocator; const meta = std.meta; const Ast = std.zig.Ast; -const Parse = @import("../../zig/Parse.zig"); const Token = std.zig.Token; const primitives = std.zig.primitives; const Writer = std.Io.Writer; @@ -46,6 +45,8 @@ pub const Fixups = struct { replace_nodes_with_node: std.AutoHashMapUnmanaged(Ast.Node.Index, Ast.Node.Index) = .empty, /// Change all identifier names matching the key to be value instead. rename_identifiers: std.array_hash_map.String([]const u8) = .empty, + /// Add parentheses surrounding the node. + insert_parentheses: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .empty, /// All `@import` builtin calls which refer to a file path will be prefixed /// with this path. @@ -59,6 +60,7 @@ pub const Fixups = struct { f.append_string_after_node.count() + f.replace_nodes_with_node.count() + f.rename_identifiers.count() + + f.insert_parentheses.count() + @intFromBool(f.rebase_imported_paths != null); } @@ -70,6 +72,7 @@ pub const Fixups = struct { f.append_string_after_node.clearRetainingCapacity(); f.replace_nodes_with_node.clearRetainingCapacity(); f.rename_identifiers.clearRetainingCapacity(); + f.insert_parentheses.clearRetainingCapacity(); f.rebase_imported_paths = null; } @@ -82,6 +85,7 @@ pub const Fixups = struct { f.append_string_after_node.deinit(gpa); f.replace_nodes_with_node.deinit(gpa); f.rename_identifiers.deinit(gpa); + f.insert_parentheses.deinit(gpa); f.* = undefined; } }; @@ -421,6 +425,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { tree.tokenTag(fallback_first) == .multiline_string_literal_line; const after_op_space: Space = if (seperate_line) .newline else .space; + if (r.fixups.insert_parentheses.contains(node)) { + try ais.writeByte('('); + } try renderExpression(r, lhs, .space); // target try ais.pushIndent(.normal); @@ -433,7 +440,13 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { assert(tree.tokenTag(fallback_first - 1) == .keyword_catch); try renderToken(r, main_token, after_op_space); // catch keyword } - try renderExpression(r, rhs, space); // fallback + if (r.fixups.insert_parentheses.contains(node)) { + try renderExpression(r, rhs, .none); + try ais.writeByte(')'); + try renderOnlySpace(r, space); + } else { + try renderExpression(r, rhs, space); // fallback + } ais.popIndent(); }, @@ -540,43 +553,22 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { .@"orelse", => { const lhs, const rhs = tree.nodeData(node).node_and_node; - - const lhs_tag = tree.nodeTag(lhs); - const center_tag = tree.nodeTag(node); - const rhs_tag = tree.nodeTag(rhs); - - const lhs_prec = Parse.precedenceFromNodeTag(lhs_tag); - const center_prec = Parse.precedenceFromNodeTag(center_tag); - const rhs_prec = Parse.precedenceFromNodeTag(rhs_tag); - - const left_rel = lhs_prec.cmp(center_prec); - const right_rel = rhs_prec.cmp(center_prec); - - const paren_left = left_rel == null or left_rel == .lt or (left_rel == .eq and lhs_prec.group == center_prec.group and lhs_prec.assoc == .none); - const paren_right = right_rel == null or right_rel == .lt; - - - if (paren_left) try ais.writeByte('('); - try renderExpression(r, lhs, .none); - if (paren_left) try ais.writeByte(')'); - // Multiline string literals will eat the space so we need to skip if we thats next. - if (tree.tokenTag(tree.lastToken(lhs)) != .multiline_string_literal_line) try renderOnlySpace(r, .space); - + if (r.fixups.insert_parentheses.contains(node)) { + try ais.writeByte('('); + } + try renderExpression(r, lhs, .space); + const op_token = tree.nodeMainToken(node); try ais.pushIndent(.binop); - const op_token = tree.nodeMainToken(node); const rhs_seperate_line = !tree.tokensOnSameLine(op_token, op_token + 1) or tree.tokenTag(op_token + 1) == .multiline_string_literal_line; try renderToken(r, op_token, if (rhs_seperate_line) .newline else .space); - - if (paren_right) try ais.writeByte('('); - try renderExpression(r, rhs, .none); - if (paren_right) try ais.writeByte(')'); - - const most_recent = tree.lastToken(rhs); - const lexeme = tokenSliceForRender(tree, most_recent); - // If our space is .none, then the above code functions as normal and putting this here will duplicate comments and such - if (space != .none) try renderSpace(r, most_recent, lexeme.len, space); - + if (r.fixups.insert_parentheses.contains(node)) { + try renderExpression(r, rhs, .none); + try ais.writeByte(')'); + try renderOnlySpace(r, space); + } else { + try renderExpression(r, rhs, space); + } ais.popIndent(); }, diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index ff6a74821ac46dfefb5a64e84cffcc23aa6f5dc3..64e5c398dded4cdeb52a29ba48ae78735e5b75b6 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -24,7 +24,6 @@ nodes: Ast.NodeList, extra_data: std.ArrayList(u32), scratch: std.ArrayList(Node.Index), recover: bool, -use_old_precedence: bool = false, fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag { return p.tokens.items(.tag)[token_index]; @@ -1793,8 +1792,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 const tok_tag = p.tokenTag(p.tok_i); const info = operTable[@backingInt(tok_tag)]; - const prec_relation = if (!p.use_old_precedence) info.prec.cmp(min_exc_prec) else info.prec.v16_cmp(min_exc_prec); - const rel = prec_relation orelse b: { + const rel = info.prec.cmp(min_exc_prec) orelse b: { // This issues warnings if the relation is null, which it never is in 0.16.0 const prev_op_tok_tag = p.tokenTag(prev_operator_token); const prev_op_info = operTable[@backingInt(prev_op_tok_tag)]; @@ -1831,7 +1829,8 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 }, }); } - break :b .gt; + // Use the old precedence rules to construct the tree to ease automatic fixups + break :b info.prec.v16_cmp(min_exc_prec); }; if (rel == .lt) { @@ -1842,8 +1841,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 //Special cased check to maintain the old more helpful error for chained comparisons. if (info.prec.group == .comparison) { try p.warn(.chained_comparison_operators); - // In 0.16.0 the only reptition prohibited was comparisons which we checked above - } else if (!p.use_old_precedence) { + } else { try p.warnMsg(.{ .tag = .illegal_chained_operators, .is_note = false, diff --git a/src/fmt.zig b/src/fmt.zig index 16dfb01d8f92a733ed2068d649dffc07ca6b587d..3e104386d51054041422e596131fdc7919087058 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -387,9 +387,88 @@ fn fmtPathFile( break :mode .zig; }; - var tree = try std.zig.Ast.parse(gpa, source_code, .{ .mode = mode, .use_old_precedence = fmt.fix_precedence }); + var tree = try std.zig.Ast.parse(gpa, source_code, .{ .mode = mode }); defer tree.deinit(gpa); + var fixups: std.zig.Ast.Render.Fixups = .{}; + defer fixups.deinit(gpa); + + fix: { + if (!fmt.fix_precedence) break :fix; + + var operators_to_fix: std.AutoHashMapUnmanaged(std.zig.Ast.TokenIndex, void) = .empty; + defer operators_to_fix.deinit(gpa); + + // Gather ambiguous operator precedence error tokens for quick lookup later + for (tree.errors) |err| { + switch (err.tag) { + .hint_operator_precedence_left => { + try operators_to_fix.putNoClobber(gpa, err.token - @as(u32, @intCast(err.extra.offset)), {}); + }, + .hint_operator_precedence_right => { + try operators_to_fix.putNoClobber(gpa, err.token, {}); + }, + else => continue, + } + } + + if (operators_to_fix.count() == 0) break :fix; + + // Build a new error list without the ambiguous operator precedence errors/notes + var fixed_errors: std.ArrayList(std.zig.Ast.Error) = try .initCapacity(gpa, tree.errors.len - (operators_to_fix.count() * 3)); + for (tree.errors) |err| { + switch (err.tag) { + .ambiguous_operator_precedence, + .illegal_chained_operators, + .previous_ambiguous_operator, + .hint_operator_precedence_left, + .hint_operator_precedence_right, + => continue, + else => { + fixed_errors.appendAssumeCapacity(err); + }, + } + } + gpa.free(tree.errors); + tree.errors = fixed_errors.toOwnedSliceAssert(); + + // Find the nodes we need to add parens to and add them to the list + for (tree.nodes.items(.tag), 0..) |tag, i| { + switch (tag) { + .merge_error_sets, + .mul, + .div, + .mod, + .mul_wrap, + .mul_sat, + .add, + .sub, + .array_cat, + .add_wrap, + .sub_wrap, + .add_sat, + .sub_sat, + .shl, + .shl_sat, + .shr, + .bit_and, + .bit_xor, + .bit_or, + .@"orelse", + .@"catch", + .bool_and, + .bool_or, + => { + const main_tok = tree.nodes.get(i).main_token; + if (operators_to_fix.contains(main_tok)) { + try fixups.insert_parentheses.put(gpa, @fromBackingInt(@intCast(i)), {}); + } + }, + else => {}, + } + } + } + if (tree.errors.len != 0) { try std.zig.printAstErrorsToStderr(gpa, io, tree, file_path, fmt.color); fmt.any_error = true; @@ -497,7 +576,7 @@ fn fmtPathFile( fmt.out_buffer.clearRetainingCapacity(); try fmt.out_buffer.ensureTotalCapacity(source_code.len); - tree.render(gpa, &fmt.out_buffer.writer, .{}) catch |err| switch (err) { + tree.render(gpa, &fmt.out_buffer.writer, fixups) catch |err| switch (err) { error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, }; if (!mem.eql(u8, fmt.out_buffer.written(), source_code)) { -- 2.54.0 From f4eee8a9f98670bda4c36a18a15e237c45a207b1 Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Fri, 24 Jul 2026 11:14:28 -0500 Subject: [PATCH 08/20] Fix tiny bug in Render.zig fixup ambiguous-precedence --- lib/std/zig/Ast/Render.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig index 060ce9af8d0b7673504ce0f7598c40c071d57dd8..bda190b245b3ae3a49a61a68af58511bcb698c21 100644 --- a/lib/std/zig/Ast/Render.zig +++ b/lib/std/zig/Ast/Render.zig @@ -565,7 +565,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { if (r.fixups.insert_parentheses.contains(node)) { try renderExpression(r, rhs, .none); try ais.writeByte(')'); - try renderOnlySpace(r, space); + const right_most_token = tree.lastToken(rhs); + const lexeme = tokenSliceForRender(tree, right_most_token); + // If our space was already .none, then the line below will be redundent as above handles it. + if (space != .none) try renderSpace(r, right_most_token, lexeme.len, space); } else { try renderExpression(r, rhs, space); } -- 2.54.0 From e5021bc3b7aca7ad179820e4584812b11162d81f Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Fri, 24 Jul 2026 13:39:14 -0500 Subject: [PATCH 09/20] Fix comment clobber in Render.zig for .catch in renderExpression, --- lib/std/zig/Ast/Render.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/std/zig/Ast/Render.zig b/lib/std/zig/Ast/Render.zig index bda190b245b3ae3a49a61a68af58511bcb698c21..198a7abc0d7327614a98800baff199f7bcf04d09 100644 --- a/lib/std/zig/Ast/Render.zig +++ b/lib/std/zig/Ast/Render.zig @@ -443,7 +443,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { if (r.fixups.insert_parentheses.contains(node)) { try renderExpression(r, rhs, .none); try ais.writeByte(')'); - try renderOnlySpace(r, space); + const right_most_token = tree.lastToken(rhs); + const lexeme = tokenSliceForRender(tree, right_most_token); + // If our space is .none, then the above code functions is normal and below shouldn't run + if (space != .none) try renderSpace(r, right_most_token, lexeme.len, space); } else { try renderExpression(r, rhs, space); // fallback } -- 2.54.0 From cc41245dc7c23e019a1bd307e074af4f2121e327 Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Fri, 24 Jul 2026 15:46:08 -0500 Subject: [PATCH 10/20] Langref builds with superhtml; Remove unicode note from Ast.zig; Improve clarity in Parse.zig --- .../ambiguous_precedence_mul_bitand.zig | 2 +- .../ambiguous_precedence_orelse_ne.zig | 2 +- .../ambiguous_precedence_shift_sub.zig | 2 +- doc/langref/nonchaining_sibling_operators.zig | 2 +- lib/std/zig/Ast.zig | 8 +- lib/std/zig/Parse.zig | 123 ++++++++---------- 6 files changed, 63 insertions(+), 76 deletions(-) diff --git a/doc/langref/ambiguous_precedence_mul_bitand.zig b/doc/langref/ambiguous_precedence_mul_bitand.zig index 66f1f5a1a4535148a5377dc3e335dc9e1d498147..af3c28cc6c04729e2fd1cec8084c2a1b9afb8ae3 100644 --- a/doc/langref/ambiguous_precedence_mul_bitand.zig +++ b/doc/langref/ambiguous_precedence_mul_bitand.zig @@ -8,4 +8,4 @@ test "ambiguous precedence" { _ = x & y *% z; } -// obj=ambiguous operator precedence with operators … & … *% …; use parentheses to disambiguate \ No newline at end of file +// obj=ambiguous operator precedence with operators ... & ... *% ...; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/ambiguous_precedence_orelse_ne.zig b/doc/langref/ambiguous_precedence_orelse_ne.zig index 922886e24ba36b0f5e522269cf6eca593137122c..b7be5d0c9bdff108e37183365fbcaa59705bb61a 100644 --- a/doc/langref/ambiguous_precedence_orelse_ne.zig +++ b/doc/langref/ambiguous_precedence_orelse_ne.zig @@ -15,4 +15,4 @@ test "ambiguous precedence" { _ = makeBool(x) orelse y != z; } -// obj=ambiguous operator precedence with operators … orelse … != …; use parentheses to disambiguate \ No newline at end of file +// obj=ambiguous operator precedence with operators ... orelse ... != ...; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/ambiguous_precedence_shift_sub.zig b/doc/langref/ambiguous_precedence_shift_sub.zig index b5f7d8a679154bc66af1451224f62fac2f489c91..2410aa950cfcc25060f6d8d341129983f8fd51e3 100644 --- a/doc/langref/ambiguous_precedence_shift_sub.zig +++ b/doc/langref/ambiguous_precedence_shift_sub.zig @@ -7,4 +7,4 @@ test "ambiguous precedence" { _ = x << y - 1; } -// obj=ambiguous operator precedence with operators … << … - …; use parentheses to disambiguate \ No newline at end of file +// obj=ambiguous operator precedence with operators ... << ... - ...; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/nonchaining_sibling_operators.zig b/doc/langref/nonchaining_sibling_operators.zig index 9716a956b1580dd214df68aa6619f55996e52ac8..9873620d783801578cdb5560a0541992be28ab4b 100644 --- a/doc/langref/nonchaining_sibling_operators.zig +++ b/doc/langref/nonchaining_sibling_operators.zig @@ -2,4 +2,4 @@ fn foo(x: anytype, y: anytype, z: anytype) void { _ = x << y << z; } -// obj=repetition of non-chainable operators … << … << …; use parentheses to disambiguate \ No newline at end of file +// obj=repetition of non-chainable operators ... << ... << ...; use parentheses to disambiguate \ No newline at end of file diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index 14a16e1730564aa7add9e659dc81a76175b5a95c..e5426856cd9aad238ae5dc0b43340a7f44c1a744 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -556,7 +556,7 @@ pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void return w.writeAll("use 'var' or 'const' to declare variable"); }, .ambiguous_operator_precedence => { - return w.print("ambiguous operator precedence with operators … {s} … {s} …; use parentheses to disambiguate", .{ + return w.print("ambiguous operator precedence with operators ... {s} ... {s} ...; use parentheses to disambiguate", .{ tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, tree.tokenTag(parse_error.token).lexeme().?, }); @@ -565,19 +565,19 @@ pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void return w.writeAll("previous ambiguous operator here"); }, .illegal_chained_operators => { - return w.print("repetition of non-chainable operators … {s} … {s} …; use parentheses to disambiguate", .{ + return w.print("repetition of non-chainable operators ... {s} ... {s} ...; use parentheses to disambiguate", .{ tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, tree.tokenTag(parse_error.token).lexeme().?, }); }, .hint_operator_precedence_left => { - return w.print("did you mean `(… {s} …) {s} …` ?", .{ + return w.print("previously evaluated as `(... {s} ...) {s} ...`", .{ tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, tree.tokenTag(parse_error.token).lexeme().?, }); }, .hint_operator_precedence_right => { - return w.print("did you mean `… {s} (… {s} …)` ?", .{ + return w.print("previously evaluated as `... {s} (... {s} ...)`", .{ tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, tree.tokenTag(parse_error.token).lexeme().?, }); diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index 64e5c398dded4cdeb52a29ba48ae78735e5b75b6..95f3c1603ddad89c898f9f90c9c819959812bac8 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -1552,34 +1552,47 @@ const PrecClass = struct { root, - /// For this to work correctly we require that all subgroups are strictly adjacent - /// Major groups are defined by the first text before an underscore - const Major: type = b: { - var major_names: []const []const u8 = &.{}; - for (std.meta.fieldNames(Group)) |fieldname| { - var major_name: []const u8 = fieldname[0..]; - for (fieldname, 0..) |c, i| { - if (c == '_') { - major_name = fieldname[0..i]; - break; - } - } - if (major_names.len == 0 or !std.mem.eql(u8, major_name, major_names[major_names.len - 1])) { - major_names = major_names ++ &[1][]const u8{major_name}; - } - } - - const IntType = std.math.IntFittingRange(0, major_names.len - 1); - var values: [major_names.len]IntType = undefined; - for (0..major_names.len) |i| values[i] = i; - - break :b @Enum( - IntType, - .exhaustive, - major_names, - &values, - ); + const Major = enum { + top, + arithmetic, + bitwise, + comparison, + bool, + recovery, + root, }; + + fn getMajor(group: Group) Major { + return switch (group) { + .top, + => .top, + + .arithmetic_product_chainable, + .arithmetic_mod_nonchainable, + .arithmetic_sum, + => .arithmetic, + + .bitwise_shift, + .bitwise_and, + .bitwise_xor, + .bitwise_or, + => .bitwise, + + .comparison, + => .comparison, + + .bool_and, + .bool_or, + => .bool, + + .recovery_orelse, + .recovery_catch, + => .recovery, + + .root, + => .root, + }; + } }; pub const start: PrecClass = .{ .group = .root }; @@ -1598,29 +1611,22 @@ const PrecClass = struct { fn setMajorRelation(prec_array: *PrecedenceArray, major_a: Group.Major, rel: Rel, major_b: Group.Major) void { for (std.meta.fieldNames(Group), 0..) |fieldname_i, i| { - if (!std.mem.startsWith(u8, fieldname_i, @tagName(major_a))) continue; + if (@field(Group, fieldname_i).getMajor() != major_a) continue; for (std.meta.fieldNames(Group), 0..) |fieldname_j, j| { - if (!std.mem.startsWith(u8, fieldname_j, @tagName(major_b))) continue; + if (@field(Group, fieldname_j).getMajor() != major_b) continue; - prec_array.*[i][j] = rel; - prec_array.*[j][i] = rel.inverted(); + prec_array[i][j] = rel; + prec_array[j][i] = rel.inverted(); } } } fn setMinorRelation(prec_array: *PrecedenceArray, minor_a: Group, rel: Rel, minor_b: Group) void { - prec_array.*[@backingInt(minor_a)][@backingInt(minor_b)] = rel; - prec_array.*[@backingInt(minor_b)][@backingInt(minor_a)] = rel.inverted(); + prec_array[@backingInt(minor_a)][@backingInt(minor_b)] = rel; + prec_array[@backingInt(minor_b)][@backingInt(minor_a)] = rel.inverted(); } - /// Arithmetic_* > Comparison - /// Bitwise_* > Comparison - /// Comparison > Bool_* > Root - /// Recovery > Root - /// - /// *_Product > *_Sum - /// /// order[y][x] --> y cmp x const precedence_ordering = b: { @setEvalBranchQuota(20_000); @@ -1646,7 +1652,7 @@ const PrecClass = struct { setMinorRelation(&order, .arithmetic_mod_nonchainable, .gt, .arithmetic_sum); setMinorRelation(&order, .arithmetic_product_chainable, .gt, .arithmetic_sum); - computeTransativeOrdering(&order); + computeTransitiveOrdering(&order); break :b order; }; @@ -1658,7 +1664,7 @@ const PrecClass = struct { /// == != < > <= >= /// and /// or - const v16_precedence_ordering = b: { + const v0_16_precedence_ordering = b: { @setEvalBranchQuota(20_000); var order: PrecedenceArray = @splat(@splat(null)); @@ -1685,7 +1691,7 @@ const PrecClass = struct { setMinorRelation(&order, .bool_or, .gt, .root); - computeTransativeOrdering(&order); + computeTransitiveOrdering(&order); for (order) |row| { for (row) |item| { if (item == null) @compileError("Null entry in old precedence ordering which had none."); @@ -1698,11 +1704,11 @@ const PrecClass = struct { return PrecClass.precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)]; } - pub fn v16_cmp(lhs: PrecClass, rhs: PrecClass) Rel { - return PrecClass.v16_precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)].?; + pub fn v0_16_cmp(lhs: PrecClass, rhs: PrecClass) Rel { + return PrecClass.v0_16_precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)].?; } - fn computeTransativeOrdering(order: *PrecedenceArray) void { + fn computeTransitiveOrdering(order: *PrecedenceArray) void { for (0..Group.num_distinct) |i| for (0..Group.num_distinct) |j| for (0..Group.num_distinct) |k| { if (order[i][j] == null or order[j][k] == null) continue; // X < Y < Z ==> X < Z X > Y > Z ==> X > Z @@ -1766,23 +1772,6 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec // zig fmt: on }); -fn comptimePrecedenceFromNodeTag(comptime tag: Node.Tag) PrecClass { - for (operTable) |data| { - if (data.tag == tag) return data.prec; - } - return .{ .group = .top, .assoc = .left }; -} - -pub fn precedenceFromNodeTag(tag: Node.Tag) PrecClass { - return switch (tag) { - inline else => |ct_tag| comptimePrecedenceFromNodeTag(ct_tag), - }; -} - -pub fn newPrecedenceBetween(left_tok: Node.Tag, right_tok: Node.Tag) ?PrecClass.Rel { - return precedenceFromNodeTag(left_tok).cmp(precedenceFromNodeTag(right_tok)); -} - fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index { var node = try p.parsePrefixExpr() orelse return null; @@ -1793,10 +1782,9 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 const info = operTable[@backingInt(tok_tag)]; const rel = info.prec.cmp(min_exc_prec) orelse b: { - // This issues warnings if the relation is null, which it never is in 0.16.0 const prev_op_tok_tag = p.tokenTag(prev_operator_token); const prev_op_info = operTable[@backingInt(prev_op_tok_tag)]; - const v16_rel = prev_op_info.prec.v16_cmp(info.prec); + const v0_16_rel = prev_op_info.prec.v0_16_cmp(info.prec); try p.warnMsg(.{ .tag = .ambiguous_operator_precedence, .is_note = false, @@ -1810,7 +1798,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 .is_note = true, .token = prev_operator_token, }); - if (v16_rel == .gt or v16_rel == .eq) { + if (v0_16_rel == .gt or v0_16_rel == .eq) { try p.warnMsg(.{ .tag = .hint_operator_precedence_left, .is_note = true, @@ -1830,7 +1818,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 }); } // Use the old precedence rules to construct the tree to ease automatic fixups - break :b info.prec.v16_cmp(min_exc_prec); + break :b info.prec.v0_16_cmp(min_exc_prec); }; if (rel == .lt) { @@ -1838,7 +1826,6 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 } if (min_exc_prec.group == info.prec.group and min_exc_prec.assoc == .none and info.prec.assoc == .none) { - //Special cased check to maintain the old more helpful error for chained comparisons. if (info.prec.group == .comparison) { try p.warn(.chained_comparison_operators); } else { -- 2.54.0 From 197f7ee6d248a004763d5bb640a14dc4117d5a70 Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Fri, 24 Jul 2026 16:14:42 -0500 Subject: [PATCH 11/20] Update langref to include simplified operator tables. --- doc/langref.html.in | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/langref.html.in b/doc/langref.html.in index e8c1c675ed7b40bacc7f72e2ad2d68892ac81ca4..9265b41fe3bff1fa02c032a5dd11cfc50a653bbf 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1907,6 +1907,34 @@ and or = *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |={#endsyntax#} {#header_close#} +

+ However, understanding the full ambiguity rules are not necessary for reading or writing code. Instead, having an understanding of the unambiguous cases for the operators, you're using is more practical. To that end, some simplified versions, of the precedence table are provided below, tailored to understanding particular groups of operator groups. The operators that have ambiguous precedence with the given operators in question have been omitted, as have operators with higher precedence. The operators colored orange have ambiguous precedence with other operators on the same line. + + For arithmetic and error set operators, the simplfied precedence table would look like this. +

+ +
* / *% *| || %
++ - ++ +% -% +| -|
+== != < > <= >=
+and or
+= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |=
+ +

+ For bitwise operators, it would look like this: +

+ +
<< <<| >> & ^ |
+== != < > <= >=
+and or
+= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |=
+ +

+ For null and error recovery, it would look like this: +

+ +
catch orelse
+= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |=
+ {#header_close#} {#header_close#} -- 2.54.0 From a25a20160258b9936ff402e5da404420004fecff Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Fri, 31 Jul 2026 12:21:38 -0500 Subject: [PATCH 12/20] Fix `Parse.zig` bug pointing to wrong ambiguous operator --- lib/std/zig/Parse.zig | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index 95f3c1603ddad89c898f9f90c9c819959812bac8..7467da142de32dff48d76bffa8af52074134f8fc 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -1772,11 +1772,9 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec // zig fmt: on }); -fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32) Error!?Node.Index { +fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_operator_token: u32) Error!?Node.Index { var node = try p.parsePrefixExpr() orelse return null; - var prev_operator_token = prev_token_const; - while (true) { const tok_tag = p.tokenTag(p.tok_i); const info = operTable[@backingInt(tok_tag)]; @@ -1884,8 +1882,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_token_const: u32 } } - prev_operator_token = oper_token; - const rhs = try p.parseExprPrecedence(info.prec, prev_operator_token) orelse { + const rhs = try p.parseExprPrecedence(info.prec, oper_token) orelse { try p.warn(.expected_expr); return node; }; -- 2.54.0 From 65924d31e4ed3234303d6c6ca72cf30cda0cbaa3 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 30 Jul 2026 18:45:58 -0700 Subject: [PATCH 13/20] Fix precedence upgrade when two lower prec operators surround a higher one For example, `a | b << c | d` gives two errors: one for `a | b << c` which would have been evaluated as `a | (b << c)` in 0.16.x and one for `b << c | d` which would have been evaluated as `(b << c) | d` in 0.16.x. This would have caused the `<<` to be the operator token for a hint_operator_precedence_right and a hint_operator_precedence_left note, which the fmt implementation could not handle. --- src/fmt.zig | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/fmt.zig b/src/fmt.zig index 3e104386d51054041422e596131fdc7919087058..4646fa1a28dc0467d65fd84d086797d01f468be1 100644 --- a/src/fmt.zig +++ b/src/fmt.zig @@ -400,14 +400,21 @@ fn fmtPathFile( defer operators_to_fix.deinit(gpa); // Gather ambiguous operator precedence error tokens for quick lookup later + var remaining_errors: usize = tree.errors.len; for (tree.errors) |err| { switch (err.tag) { .hint_operator_precedence_left => { - try operators_to_fix.putNoClobber(gpa, err.token - @as(u32, @intCast(err.extra.offset)), {}); + try operators_to_fix.put(gpa, err.token - @as(u32, @intCast(err.extra.offset)), {}); + remaining_errors -= 1; }, .hint_operator_precedence_right => { - try operators_to_fix.putNoClobber(gpa, err.token, {}); + try operators_to_fix.put(gpa, err.token, {}); + remaining_errors -= 1; }, + .ambiguous_operator_precedence, + .illegal_chained_operators, + .previous_ambiguous_operator, + => remaining_errors -= 1, else => continue, } } @@ -415,7 +422,7 @@ fn fmtPathFile( if (operators_to_fix.count() == 0) break :fix; // Build a new error list without the ambiguous operator precedence errors/notes - var fixed_errors: std.ArrayList(std.zig.Ast.Error) = try .initCapacity(gpa, tree.errors.len - (operators_to_fix.count() * 3)); + var fixed_errors: std.ArrayList(std.zig.Ast.Error) = try .initCapacity(gpa, remaining_errors); for (tree.errors) |err| { switch (err.tag) { .ambiguous_operator_precedence, -- 2.54.0 From 04e8a5e42b58f1fdeb749caf22a1c998344b3ba8 Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Sat, 8 Aug 2026 22:59:41 -0500 Subject: [PATCH 14/20] Update langref to perfer allowed operator mixing vs disallowed. --- doc/langref.html.in | 64 ++++++++------ .../incremental_operator_precedence.zig | 87 +++++++++++++++++++ 2 files changed, 123 insertions(+), 28 deletions(-) create mode 100644 doc/langref/incremental_operator_precedence.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index 9265b41fe3bff1fa02c032a5dd11cfc50a653bbf..959afdbf374e4eec44c150afa97616c564622dcc 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1907,35 +1907,7 @@ and or = *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |={#endsyntax#} {#header_close#} -

- However, understanding the full ambiguity rules are not necessary for reading or writing code. Instead, having an understanding of the unambiguous cases for the operators, you're using is more practical. To that end, some simplified versions, of the precedence table are provided below, tailored to understanding particular groups of operator groups. The operators that have ambiguous precedence with the given operators in question have been omitted, as have operators with higher precedence. The operators colored orange have ambiguous precedence with other operators on the same line. - For arithmetic and error set operators, the simplfied precedence table would look like this. -

- -
* / *% *| || %
-+ - ++ +% -% +| -|
-== != < > <= >=
-and or
-= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |=
- -

- For bitwise operators, it would look like this: -

- -
<< <<| >> & ^ |
-== != < > <= >=
-and or
-= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |=
- -

- For null and error recovery, it would look like this: -

- -
catch orelse
-= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |=
- - {#header_close#} {#header_close#} {#header_open|Arrays#} @@ -7909,6 +7881,42 @@ fn readU32Be() u32 {} {#header_open|Appendix#} {#header_open|Grammar#} {#grammar#} + {#header_open|Operator Precedence Flowchart#} +

+ To help understand the grammar, this flowchart is provided for the operator precedence. + The bottom represents any location where an expression may occur and the topmost row represents + a parenthesized expression. An operator will have a higher precedence (and therefore be the parent) to + another node if it is strictly lower on the tree (having a directed path from one to another). This is inverted from classical precedence, but + is closer to how a recursive descent parser views the grammar. +

+

+                     ┏━━━━━━━━━━━━━━━━━━━┓   
+                     ┃(expr)             ┃                  
+                     ┃x() x[] x.y x.* x.?┃                  
+                     ┃E!T                ┃                  
+                     ┃x{}                ┃                  
+                     ┃!x -x -%x ~x &x ?x ┃                  
+                     ┗━━━━━━━━━▲━━━━━━━━━┛                  
+          ┌─────────────┬──────┴───────┬───────┬──┬──┬─┐         
+          │             │              │       │  │  │ │         
+   ┏━━━━━━┷━━━━━┓╭Non╌Chaining╮ ╭Non╌Chaining╮┏┷┓┏┷┓┏┷┓│         
+   ┃* *% *| / ||┃╎      %     ╎ ╎ << <<|  >> ╎┃&┃┃^┃┃|┃│         
+   ┗━━━━━━▲━━━━━┛╰╌╌╌╌╌╌▲╌╌╌╌╌╯ ╰╌╌╌╌╌╌▲╌╌╌╌╌╯┗▲┛┗▲┛┗▲┛│         
+       ┏━━┷━━━━━━━━━━━━━┷━┓       ┌────┴───────┴──┴──┘ │         
+       ┃+ - +% -% +| -| ++┃       │                    │         
+       ┗━━━━━━━━━━━▲━━━━━━┛       │                    │         
+                  ╭┴╌Non-Chaining╌┴╮                   │         
+                  ╎== !=  < <= >= >╎                   │         
+                  ╰╌╌╌▲╌╌╌╌▲╌╌╌╌╌╌╌╯      ┌──────┬─────┘                
+                    ┏━┷━┓┏━┷━┓        ┏━━━┷━━┓┏━━┷━━┓                  
+                    ┃and┃┃or ┃        ┃orelse┃┃catch┃                  
+                    ┗━▲━┛┗━▲━┛        ┗━━━▲━━┛┗━━▲━━┛                  
+                   ╭╌╌┴╌╌╌╌┴╌╌╌╌╌╌╌╌╌╌╌╌╌╌┴╌╌╌╌╌╌┴╌╮ 
+                   ╎    Any expression location    ╎ 
+                   ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ 
+                                                              
+      
+ {#header_close#} {#header_close#} {#header_open|Zen#}
    diff --git a/doc/langref/incremental_operator_precedence.zig b/doc/langref/incremental_operator_precedence.zig new file mode 100644 index 0000000000000000000000000000000000000000..680f7ecc68c213773549aa2b9a80de0bdc53d180 --- /dev/null +++ b/doc/langref/incremental_operator_precedence.zig @@ -0,0 +1,87 @@ +const expectEqual = @import("std").testing.expectEqual; +const expect = @import("std").testing.expect; + +test "Operator Precedence" { + // Arithmetic + // + and - can be freely mixed and are left associative + try expectEqual((2 + 3) + 4, 2 + 3 + 4); + try expectEqual((1 - 2) - 3, 1 - 2 - 3); + + // Saturating and wrapping modifications to arithmetic operators act the same + const x: u8 = 255; + try expectEqual((x +% 2) -| 3, x +% 2 -| 3); + try expectEqual(0, x +% 2 -| 3); + + // Since all associative operators are left associative, non-left-to-right evaluation must be forced with parenthesis + try expectEqual(255, x +% (2 -| 3)); + + // * and / can be freely mixed and bind tigher than any addition + try expectEqual((8 / 2) * 4, 8 / 2 * 4); + try expectEqual(1 + (2 * 3), 1 + 2 * 3); + + // The Modulus is special in that it cannot be repeated without parenthesis + // The following line would be a compile error + // _ = x % 7 % 3; + // However it does bind tighter than addition + try expectEqual(1 + (x % 3), 1 + x % 3); + + // Bitwise Operators + // &, |, and ^ can all be freely repeated, but not mixed without parenthesis + try expectEqual((x & 0xF) & 1, x & 0xF & 1); + try expectEqual((x | 0xF) | 1, x | 0xF | 1); + try expectEqual((x ^ 0xF) ^ 1, x ^ 0xF ^ 1); + // The following line would be a compile error + // _ = x & 0xF | 0xF0; + + // Bitshifts <<, <<|, and >> cannot be repeated without parenthesis nor mixed with other bitwise operators + // The following lines would be compile errors + // _ = x >> 1 >> 2; + // _ = 1 << 16 | 1 << 8 | 1; + // Instead parentheses should be used + try expectEqual(63, (x >> 1) >> 2); + try expectEqual(0x10101, (1 << 16) | (1 << 8) | 1); + + // Comparisons + // < > <= >= == != cannot be chained + // Binds lower than either bitwise operators or arithmetic operators + // which allows one on one side and one on the other + try expect(1 | 4 <= 1 + 4); + // equivilent to this code + try expect((1 | 4) <= (1 + 4)); + + // Boolean Operators + // `and` and `or` can be freely chained with themselves, shortcircuiting left to right + // they may not be mixed with each other without parenthesis + // bind looser than comparisons + const false_expr: bool = 7 < 2; + const true_expr: bool = 1 + 1 == 2; + + try expect(false_expr or false_expr or true_expr); + try expect(7 < 2 or 7 < 2 or 1 + 1 == 2); + try expect(((7 < 2) or (7 < 2)) or (1 + 1 == 2)); + + try expect(true_expr and true_expr and true_expr); + try expect(1 + 1 == 2 and 1 + 1 == 2 and 1 + 1 == 2); + try expect(((1 + 1 == 2) and (1 + 1 == 2)) and (1 + 1 == 2)); + + // The following line would be a compile error + // _ = false_expr or true_expr and true_expr + // Instead parentheses should be used + try expect(false_expr or (true_expr and true_expr)); + + // Orelse and Catch + // Like Boolean Operators, may be chained with themselves, but not each other + // bind looser than prefix expressions + const some_null: ?u8 = null; + try expectEqual(2, some_null orelse some_null orelse 2); + + const some_error: error{invalid}!u8 = error.invalid; + try expectEqual(3, some_error catch some_error catch 3); + + // The following line would be a compile error + // _ = some_error catch some_null orelse 1; + // Instead parentheses should be used + try expectEqual(1, (some_error catch some_null) orelse 1); +} + +// obj \ No newline at end of file -- 2.54.0 From 723c70fd438a6e9221155ff632a9974e30a7fe14 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Wed, 9 Sep 2026 02:59:27 -0700 Subject: [PATCH 15/20] langref: Attempt to simplify precedence section/examples --- doc/langref.html.in | 77 +++++++++++-- .../ambiguous_precedence_mul_bitand.zig | 11 -- doc/langref/ambiguous_precedence_orelse.zig | 12 +++ .../ambiguous_precedence_orelse_ne.zig | 18 ---- .../ambiguous_precedence_shift_sub.zig | 10 -- doc/langref/chained_sibling_operators.zig | 5 - .../incremental_operator_precedence.zig | 87 --------------- doc/langref/nonchaining_sibling_operators.zig | 5 - doc/langref/operator_precedence.zig | 101 ++++++++++++++---- 9 files changed, 161 insertions(+), 165 deletions(-) delete mode 100644 doc/langref/ambiguous_precedence_mul_bitand.zig create mode 100644 doc/langref/ambiguous_precedence_orelse.zig delete mode 100644 doc/langref/ambiguous_precedence_orelse_ne.zig delete mode 100644 doc/langref/ambiguous_precedence_shift_sub.zig delete mode 100644 doc/langref/chained_sibling_operators.zig delete mode 100644 doc/langref/incremental_operator_precedence.zig delete mode 100644 doc/langref/nonchaining_sibling_operators.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index 959afdbf374e4eec44c150afa97616c564622dcc..df9af26b30173ad8dbf4aae164918fd14ee2781b 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1894,20 +1894,77 @@ const B = error{Two}; {#header_close#} {#header_open|Precedence#} +

    + Zig features partial operator precedence: not every operator has a defined precedence with + every other operator. Mixing operators with ambiguous precedence is prohibited and parentheses + are mandatory. Consequently, valid code is typically auto-descriptive; when reading and + writing Zig code, there are very few precedence rules you'll need to remember. +

    + + {#code|operator_precedence.zig#} + + {#code|ambiguous_precedence_orelse.zig#} + +

    + Simplified operator precedence tables are provided below, each tailored to a general group of + operators. For all of the groups shown below, the operators that have higher precedence are + the same, and themselves have the following precedence table: +

    +
    {#syntax#}x() x[] x.y x.* x.?
     a!b
     x{}
    -!x -x -%x ~x &x ?x try
    -* / % *% *| ||
    -+ - ++ +% -% +| -|
    -<< >> <<|
    -& ^ | orelse catch
    -== != < > <= >=
    -and
    -or
    -= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |={#endsyntax#}
    +!x -x -%x ~x &x ?x try{#endsyntax#} + +

    + For the tables below, the operators that have ambiguous precedence or semantic errors with the + given operators have been omitted, as have operators with higher precedence. + The operators colored red and + blue have ambiguous precedence with the other operators + on the same line. Those colored red also have ambiguous + precedence with themselves (they cannot be chained). +

    + +

    + For arithmetic operators: +

    + +
    * / *% *| %
    ++ - +% -% +| -|
    +== != < > <= >=
    +and or
    + +

    + For bitwise operators: +

    + +
    << <<| >> & ^ |
    +== != < > <= >=
    +and or
    + +

    + For null and error recovery operators: +

    + +
    catch orelse
    + +

    + For error set operators: +

    + +
    {#syntax#}||{#endsyntax#}
    + +

    + For array concatenation operators: +

    + +
    {#syntax#}++{#endsyntax#}
    + +

    + The full precedence rules can be found in the {#link|Grammar#}, which also includes an {#link|Operator Precedence Flowchart#}. +

    + {#header_close#} - {#header_close#} {#header_open|Arrays#} diff --git a/doc/langref/ambiguous_precedence_mul_bitand.zig b/doc/langref/ambiguous_precedence_mul_bitand.zig deleted file mode 100644 index af3c28cc6c04729e2fd1cec8084c2a1b9afb8ae3..0000000000000000000000000000000000000000 --- a/doc/langref/ambiguous_precedence_mul_bitand.zig +++ /dev/null @@ -1,11 +0,0 @@ -test "ambiguous precedence" { - const x: u8 = 1; - const y: u8 = 2; - const z: u8 = 3; - - // 1. Could be multiplication by a masked value: (x&y) *% z - // 2. Or masking the result of multiplication: x & (y*%z) - _ = x & y *% z; -} - -// obj=ambiguous operator precedence with operators ... & ... *% ...; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/ambiguous_precedence_orelse.zig b/doc/langref/ambiguous_precedence_orelse.zig new file mode 100644 index 0000000000000000000000000000000000000000..dcb9d4cab12f0992400e88c3eccf73711543947d --- /dev/null +++ b/doc/langref/ambiguous_precedence_orelse.zig @@ -0,0 +1,12 @@ +test "ambiguous precedence" { + const x: ?bool = true; + const y: bool = false; + const z: bool = false; + + // The following expression is always considered ambiguous, + // and, in this particular case, `(x orelse y) == z` would + // produce a different result than `x orelse (y == z)`. + _ = x orelse y == z; +} + +// obj=ambiguous operator precedence with operators ... orelse ... == ...; use parentheses to disambiguate diff --git a/doc/langref/ambiguous_precedence_orelse_ne.zig b/doc/langref/ambiguous_precedence_orelse_ne.zig deleted file mode 100644 index b7be5d0c9bdff108e37183365fbcaa59705bb61a..0000000000000000000000000000000000000000 --- a/doc/langref/ambiguous_precedence_orelse_ne.zig +++ /dev/null @@ -1,18 +0,0 @@ -fn makeBool(x: u32) ?bool { - if (x == 0) return false; - if (x == 1) return true; - return null; -} - -test "ambiguous precedence" { - const x: ?u32 = 0; - const y: u8 = 0; - const z: u8 = 0; - - // Without parentheses the compiler cannot distinguish between two conflicting interpretations: - // 1. Compare on the value which may be recovered: (makeBool(x) orelse y) != z - // 2. Recover to the result of the comparison: makeBool(x) orelse (y != z) - _ = makeBool(x) orelse y != z; -} - -// obj=ambiguous operator precedence with operators ... orelse ... != ...; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/ambiguous_precedence_shift_sub.zig b/doc/langref/ambiguous_precedence_shift_sub.zig deleted file mode 100644 index 2410aa950cfcc25060f6d8d341129983f8fd51e3..0000000000000000000000000000000000000000 --- a/doc/langref/ambiguous_precedence_shift_sub.zig +++ /dev/null @@ -1,10 +0,0 @@ -test "ambiguous precedence" { - const x: u64 = 1; - const y: u6 = 63; - - // 1. Could mean shift then subtract: (x<> cannot be repeated without parenthesis nor mixed with other bitwise operators - // The following lines would be compile errors - // _ = x >> 1 >> 2; - // _ = 1 << 16 | 1 << 8 | 1; - // Instead parentheses should be used - try expectEqual(63, (x >> 1) >> 2); - try expectEqual(0x10101, (1 << 16) | (1 << 8) | 1); - - // Comparisons - // < > <= >= == != cannot be chained - // Binds lower than either bitwise operators or arithmetic operators - // which allows one on one side and one on the other - try expect(1 | 4 <= 1 + 4); - // equivilent to this code - try expect((1 | 4) <= (1 + 4)); - - // Boolean Operators - // `and` and `or` can be freely chained with themselves, shortcircuiting left to right - // they may not be mixed with each other without parenthesis - // bind looser than comparisons - const false_expr: bool = 7 < 2; - const true_expr: bool = 1 + 1 == 2; - - try expect(false_expr or false_expr or true_expr); - try expect(7 < 2 or 7 < 2 or 1 + 1 == 2); - try expect(((7 < 2) or (7 < 2)) or (1 + 1 == 2)); - - try expect(true_expr and true_expr and true_expr); - try expect(1 + 1 == 2 and 1 + 1 == 2 and 1 + 1 == 2); - try expect(((1 + 1 == 2) and (1 + 1 == 2)) and (1 + 1 == 2)); - - // The following line would be a compile error - // _ = false_expr or true_expr and true_expr - // Instead parentheses should be used - try expect(false_expr or (true_expr and true_expr)); - - // Orelse and Catch - // Like Boolean Operators, may be chained with themselves, but not each other - // bind looser than prefix expressions - const some_null: ?u8 = null; - try expectEqual(2, some_null orelse some_null orelse 2); - - const some_error: error{invalid}!u8 = error.invalid; - try expectEqual(3, some_error catch some_error catch 3); - - // The following line would be a compile error - // _ = some_error catch some_null orelse 1; - // Instead parentheses should be used - try expectEqual(1, (some_error catch some_null) orelse 1); -} - -// obj \ No newline at end of file diff --git a/doc/langref/nonchaining_sibling_operators.zig b/doc/langref/nonchaining_sibling_operators.zig deleted file mode 100644 index 9873620d783801578cdb5560a0541992be28ab4b..0000000000000000000000000000000000000000 --- a/doc/langref/nonchaining_sibling_operators.zig +++ /dev/null @@ -1,5 +0,0 @@ -fn foo(x: anytype, y: anytype, z: anytype) void { - _ = x << y << z; -} - -// obj=repetition of non-chainable operators ... << ... << ...; use parentheses to disambiguate \ No newline at end of file diff --git a/doc/langref/operator_precedence.zig b/doc/langref/operator_precedence.zig index 9b5a2ed53323e20c44b01d5370de5c811b6ac10a..78d09e2441b8b78654893ff0d3dc2704d49d979b 100644 --- a/doc/langref/operator_precedence.zig +++ b/doc/langref/operator_precedence.zig @@ -1,23 +1,86 @@ -const assert = @import("std").debug.assert; +const std = @import("std"); test "operator precedence" { - const x = 1; - const y = 2; - const z = 3; - - assert(x + y * z == x + (y*z)); - assert(x * y + z == (x*y) + z); - - // Ambiguously related operators may exist in the same expression if they are not adjacent - assert(x*y + x%y == (x*y) + (x%y)); - // Thus includes comparisons - assert(x & y != x + y); - - // Or's and and's may be freely chained, but not with each other - assert(false or x == y or x + y == z); - assert(true and x != y and y != z); - // The following line would be a compile error - // assert(false or x != y and y != z); + // Arithmetic operators follow the conventional order of operations. + { + const a = 1 + 2 * 3 - 4 / 2; + const b = 1 + (2 * 3) - (4 / 2); + try std.testing.expectEqual(a, b); + } + + // Remainder division is a special case. It still has a higher precedence than + // addition and subtraction, but it has ambiguous precedence with itself and + // other multiplication/division operators. + { + const a = 1 + 2 % 3; + const b = 1 + (2 % 3); + try std.testing.expectEqual(a, b); + + // `1 % 2 % 3`, `1 % 2 / 3`, etc. would be a compile error, + // and parentheses would be required to disambiguate. + } + + // Bitwise operators have ambiguous precedence with other bitwise operators. + // However, non-shifting bitwise operators (&, |, ^) can be chained with themselves. + { + const a = 1 ^ 2 ^ 3; + const b = (1 ^ 2) ^ 3; + try std.testing.expectEqual(a, b); + + // `1 ^ 2 | 3`, `1 << 2 << 3`, etc. would be a compile error, + // and parentheses would be required to disambiguate. + + // To mix bitwise operators, parentheses must be used. + try std.testing.expectEqual(0x10101, (1 << 16) | (1 << 8) | 1); + } + + // Comparison operators have lower precedence than both arithmetic and bitwise + // operators. Comparisons cannot be chained. + { + const a = 1 | 4 <= 1 + 4; + const b = (1 | 4) <= (1 + 4); + try std.testing.expectEqual(a, b); + + // `1 == 2 >= 3`, etc. would be a compile error, + // and parentheses would be required to disambiguate. + } + + // Logical operators have lower precedence than comparison operators, + // and may only be chained homogeneously (`and` with `and`, but not + // with `or`, and vice versa). + { + const false_expr: bool = 7 < 2; + const true_expr: bool = 1 + 1 == 2; + + const a = false_expr or false_expr or true_expr; + const b = 7 < 2 or 7 < 2 or 1 + 1 == 2; + const c = ((7 < 2) or (7 < 2)) or (1 + 1 == 2); + try std.testing.expect(a and b and c); + + // `a or b and c`, etc. would be a compile error, + // and parentheses would be required to disambiguate. + } + + // `orelse` and `catch` may be chained with themselves, but not each other. + { + const some_null: ?u8 = null; + + const a = some_null orelse some_null orelse 2; + const b = (some_null orelse some_null) orelse 2; + try std.testing.expectEqual(a, b); + + // `a catch b orelse c`, etc. would be a compile error, + // and parentheses would be required to disambiguate. + + // Prefix operators like `try` have higher precedence than `orelse`/`catch`. + const c = try maybe() orelse 1; + const d = (try maybe()) orelse 1; + try std.testing.expectEqual(c, d); + } +} + +fn maybe() error{Fail}!?u8 { + return null; } -// test \ No newline at end of file +// test -- 2.54.0 From a2ce4c1bfbf28d1bd2f0b783ee6bef083327e98f Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Sat, 10 Oct 2026 01:20:24 -0700 Subject: [PATCH 16/20] aro: Always apply usual arithmetic conversion to ternary result See https://github.com/Vexu/arocc/pull/1117 for context --- lib/compiler/aro/aro/Preprocessor/Parser.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compiler/aro/aro/Preprocessor/Parser.zig b/lib/compiler/aro/aro/Preprocessor/Parser.zig index c9a964b44ce5ac3e48cf3ca711218d478d8ff46c..d005e02385b312daa7bb616ef6c77788fd94b351 100644 --- a/lib/compiler/aro/aro/Preprocessor/Parser.zig +++ b/lib/compiler/aro/aro/Preprocessor/Parser.zig @@ -323,7 +323,7 @@ fn binaryExpr(p: *Parser, min_prec: Token.Precedence, eval: bool) Error!?Value { const else_res = try p.binaryExpr(op_prec, eval_else) orelse return null; lhs = if (lhs.toBool()) rhs else else_res; - if ((eval and rhs == .unsigned) or else_res == .unsigned) { + if (rhs == .unsigned or else_res == .unsigned) { try lhs.toUnsigned(p, operator, "right"); } }, -- 2.54.0 From 29f793b3bf0316efba5085d9c3f4c9ca98e1b2cf Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Fri, 16 Oct 2026 00:03:55 -0700 Subject: [PATCH 17/20] langref: another pass at the precedence tables section --- doc/langref.html.in | 51 +++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index df9af26b30173ad8dbf4aae164918fd14ee2781b..0a57deea52f9ea3917336304810decddae6516ee 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1906,47 +1906,66 @@ const B = error{Two}; {#code|ambiguous_precedence_orelse.zig#}

    - Simplified operator precedence tables are provided below, each tailored to a general group of - operators. For all of the groups shown below, the operators that have higher precedence are - the same, and themselves have the following precedence table: + There is a set of operators (prefix operators, suffix operators, etc) that have unambiguously + higher precedence than all other operators. That set of operators has the following precedence table:

    {#syntax#}x() x[] x.y x.* x.?
     a!b
     x{}
    -!x -x -%x ~x &x ?x try{#endsyntax#}
    +!x -x -%x ~x &x ?x try +// lower precedence operators omitted{#endsyntax#}

    - For the tables below, the operators that have ambiguous precedence or semantic errors with the - given operators have been omitted, as have operators with higher precedence. - The operators colored red and - blue have ambiguous precedence with the other operators - on the same line. Those colored red also have ambiguous + For the other operators, simplified operator precedence tables are provided below, each containing only + the information that you'll need to know when reading/writing code that uses that particular category of operators. + The operators that have ambiguous precedence or semantic errors with the relevant operators have been omitted, + as have the operators with higher precedence (those shown above). +

    + + + +

    For arithmetic operators:

    -
    * / *% *| %
    +      
    * / *% *| %
     + - +% -% +| -|
    -== != < > <= >=
    -and or
    +== != < > <= >= +and or

    For bitwise operators:

    -
    << <<| >> & ^ |
    -== != < > <= >=
    -and or
    +
    << <<| >> & ^ |
    +== != < > <= >=
    +and or

    For null and error recovery operators:

    -
    catch orelse
    +
    catch orelse

    For error set operators: -- 2.54.0 From f98866c02c8e93eb5b3597b56a5dae475b21740d Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Fri, 16 Oct 2026 00:07:31 -0700 Subject: [PATCH 18/20] add more context to hint_operator_precedence 'previously evaluated as' notes --- lib/std/zig/Ast.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index e5426856cd9aad238ae5dc0b43340a7f44c1a744..e630103434d402d0b2dad132d537b8dd477fb7e7 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -571,13 +571,13 @@ pub fn renderError(tree: Ast, parse_error: Error, w: *Writer) Writer.Error!void }); }, .hint_operator_precedence_left => { - return w.print("previously evaluated as `(... {s} ...) {s} ...`", .{ + return w.print("in zig 0.17.x, this was evaluated as (... {s} ...) {s} ...", .{ tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, tree.tokenTag(parse_error.token).lexeme().?, }); }, .hint_operator_precedence_right => { - return w.print("previously evaluated as `... {s} (... {s} ...)`", .{ + return w.print("in zig 0.17.x, this was evaluated as ... {s} (... {s} ...)", .{ tree.tokenTag(parse_error.token - @as(u32, @intCast(parse_error.extra.offset))).lexeme().?, tree.tokenTag(parse_error.token).lexeme().?, }); -- 2.54.0 From a071b0e6d2b1f09d2292d719c33b0b1ee91f0918 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Tue, 20 Oct 2026 14:43:03 -0700 Subject: [PATCH 19/20] langref: simplify precedence tables The details about which operators are ambiguous with which other operators are superfluous and get in the way of what these tables are meant to convey. --- doc/langref.html.in | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 0a57deea52f9ea3917336304810decddae6516ee..83dee670a124ffb2e99621645722f4a5e3997dbf 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1923,49 +1923,28 @@ x{} as have the operators with higher precedence (those shown above).

    - - - -

    For arithmetic operators:

    -
    * / *% *| %
    +      
    {#syntax#}* / *% *| %
     + - +% -% +| -|
    -== != < > <= >=
    -and or
    +== != < > <= >= +and or{#endsyntax#}

    For bitwise operators:

    -
    << <<| >> & ^ |
    -== != < > <= >=
    -and or
    +
    {#syntax#}<< <<| >> & ^ |
    +== != < > <= >=
    +and or{#endsyntax#}

    For null and error recovery operators:

    -
    catch orelse
    +
    {#syntax#}catch orelse{#endsyntax#}

    For error set operators: -- 2.54.0 From 755333971b19907375410c131433668528bb1bc0 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Tue, 20 Oct 2026 14:44:06 -0700 Subject: [PATCH 20/20] 0.16 -> 0.17 --- lib/std/zig/Parse.zig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/std/zig/Parse.zig b/lib/std/zig/Parse.zig index 7467da142de32dff48d76bffa8af52074134f8fc..91dcbdc78ec5871936db438421eafbdbc896d535 100644 --- a/lib/std/zig/Parse.zig +++ b/lib/std/zig/Parse.zig @@ -1656,7 +1656,7 @@ const PrecClass = struct { break :b order; }; - /// Uses the table from Zig-0.16.0 + /// Uses the table from Zig-0.17.0 /// * / % *% *| || /// + - ++ +% -% +| -| /// << >> <<| @@ -1664,7 +1664,7 @@ const PrecClass = struct { /// == != < > <= >= /// and /// or - const v0_16_precedence_ordering = b: { + const v0_17_precedence_ordering = b: { @setEvalBranchQuota(20_000); var order: PrecedenceArray = @splat(@splat(null)); @@ -1704,8 +1704,8 @@ const PrecClass = struct { return PrecClass.precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)]; } - pub fn v0_16_cmp(lhs: PrecClass, rhs: PrecClass) Rel { - return PrecClass.v0_16_precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)].?; + pub fn v0_17_cmp(lhs: PrecClass, rhs: PrecClass) Rel { + return PrecClass.v0_17_precedence_ordering[@backingInt(lhs.group)][@backingInt(rhs.group)].?; } fn computeTransitiveOrdering(order: *PrecedenceArray) void { @@ -1782,7 +1782,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_operator_token: const rel = info.prec.cmp(min_exc_prec) orelse b: { const prev_op_tok_tag = p.tokenTag(prev_operator_token); const prev_op_info = operTable[@backingInt(prev_op_tok_tag)]; - const v0_16_rel = prev_op_info.prec.v0_16_cmp(info.prec); + const v0_17_rel = prev_op_info.prec.v0_17_cmp(info.prec); try p.warnMsg(.{ .tag = .ambiguous_operator_precedence, .is_note = false, @@ -1796,7 +1796,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_operator_token: .is_note = true, .token = prev_operator_token, }); - if (v0_16_rel == .gt or v0_16_rel == .eq) { + if (v0_17_rel == .gt or v0_17_rel == .eq) { try p.warnMsg(.{ .tag = .hint_operator_precedence_left, .is_note = true, @@ -1816,7 +1816,7 @@ fn parseExprPrecedence(p: *Parse, min_exc_prec: PrecClass, prev_operator_token: }); } // Use the old precedence rules to construct the tree to ease automatic fixups - break :b info.prec.v0_16_cmp(min_exc_prec); + break :b info.prec.v0_17_cmp(min_exc_prec); }; if (rel == .lt) { -- 2.54.0