From 2d3eece3f4c6ab67165aab2c6c0bc890ad2338ea Mon Sep 17 00:00:00 2001 From: CMDRZero Date: Tue, 14 Jul 2026 13:42:31 -0500 Subject: [PATCH] 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