1const std = @import("std");
2
3test "operator precedence" {
4 // Arithmetic operators follow the conventional order of operations.
5 {
6 const a = 1 + 2 * 3 - 4 / 2;
7 const b = 1 + (2 * 3) - (4 / 2);
8 try std.testing.expectEqual(a, b);
9 }
10
11 // Remainder division is a special case. It still has a higher precedence than
12 // addition and subtraction, but it has ambiguous precedence with itself and
13 // other multiplication/division operators.
14 {
15 const a = 1 + 2 % 3;
16 const b = 1 + (2 % 3);
17 try std.testing.expectEqual(a, b);
18
19 // `1 % 2 % 3`, `1 % 2 / 3`, etc. would be a compile error,
20 // and parentheses would be required to disambiguate.
21 }
22
23 // Bitwise operators have ambiguous precedence with other bitwise operators.
24 // However, non-shifting bitwise operators (&, |, ^) can be chained with themselves.
25 {
26 const a = 1 ^ 2 ^ 3;
27 const b = (1 ^ 2) ^ 3;
28 try std.testing.expectEqual(a, b);
29
30 // `1 ^ 2 | 3`, `1 << 2 << 3`, etc. would be a compile error,
31 // and parentheses would be required to disambiguate.
32
33 // To mix bitwise operators, parentheses must be used.
34 try std.testing.expectEqual(0x10101, (1 << 16) | (1 << 8) | 1);
35 }
36
37 // Comparison operators have lower precedence than both arithmetic and bitwise
38 // operators. Comparisons cannot be chained.
39 {
40 const a = 1 | 4 <= 1 + 4;
41 const b = (1 | 4) <= (1 + 4);
42 try std.testing.expectEqual(a, b);
43
44 // `1 == 2 >= 3`, etc. would be a compile error,
45 // and parentheses would be required to disambiguate.
46 }
47
48 // Logical operators have lower precedence than comparison operators,
49 // and may only be chained homogeneously (`and` with `and`, but not
50 // with `or`, and vice versa).
51 {
52 const false_expr: bool = 7 < 2;
53 const true_expr: bool = 1 + 1 == 2;
54
55 const a = false_expr or false_expr or true_expr;
56 const b = 7 < 2 or 7 < 2 or 1 + 1 == 2;
57 const c = ((7 < 2) or (7 < 2)) or (1 + 1 == 2);
58 try std.testing.expect(a and b and c);
59
60 // `a or b and c`, etc. would be a compile error,
61 // and parentheses would be required to disambiguate.
62 }
63
64 // `orelse` and `catch` may be chained with themselves, but not each other.
65 {
66 const some_null: ?u8 = null;
67
68 const a = some_null orelse some_null orelse 2;
69 const b = (some_null orelse some_null) orelse 2;
70 try std.testing.expectEqual(a, b);
71
72 // `a catch b orelse c`, etc. would be a compile error,
73 // and parentheses would be required to disambiguate.
74
75 // Prefix operators like `try` have higher precedence than `orelse`/`catch`.
76 const c = try maybe() orelse 1;
77 const d = (try maybe()) orelse 1;
78 try std.testing.expectEqual(c, d);
79 }
80}
81
82fn maybe() error{Fail}!?u8 {
83 return null;
84}
85
86// test