welly_parser/expr/op.rs
1/// Represents the binding precedence of an operator.
2/// No left-`Precedence` is ever equal to a right-`Precedence`.
3#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
4pub struct Precedence(u8);
5
6impl Precedence {
7 pub const MIN: Self = Precedence(0);
8 pub const MAX: Self = Precedence(34);
9}
10
11/// Represents one of Welly's arithmetic operations. See also [`Operator`].
12///
13/// [`Operator`]: super::Operator
14#[derive(Debug, Copy, Clone, PartialEq)]
15pub enum Op {
16 /// `OK(x)?` is `x`; `ERR(x)?` returns `ERR(x)`.
17 Query,
18
19 /// `(-7) ** 2` is `49`.
20 Pow,
21
22 /// `~3` is `-4`.
23 BitNot,
24
25 /// `+3` is `3`.
26 Plus,
27
28 /// `-3` is `-3`.
29 Minus,
30
31 /// `&x` is borrowed.
32 Borrow,
33
34 /// `$x` is shared.
35 Share,
36
37 /// `*x` is a fresh copy of `x`.
38 Clone,
39
40 /// `-7 * 2` is `-14`.
41 Mul,
42
43 /// `-7 / 2` is `-4`.
44 Div,
45
46 /// `-7 % 2` is `1`.
47 Rem,
48
49 /// `3 + 5` is `8`.
50 Add,
51
52 /// `3 - 5` is `-2`.
53 Sub,
54
55 /// `-7 << 2` is `-28`.
56 SL,
57
58 /// `-7 >> 2` is `-2`.
59 ASR,
60
61 /// `-7 >>> 2` is `(1 << 62) - 2`.
62 LSR,
63
64 /// `3 & 5` is `1`.
65 BitAnd,
66
67 /// `3 ^ 5` is `6`.
68 BitXor,
69
70 /// `3 | 5` is `7`.
71 BitOr,
72
73 /// `x: t` - A value `x` cast to a type `t`.
74 Cast,
75
76 /// `0..3` means `0, 1, 2`.
77 Exclusive,
78
79 /// `0...3` means `0, 1, 2, 3`.
80 Inclusive,
81
82 /// `3 < 5` is true.
83 LT,
84
85 /// `5 > 3` is true.
86 GT,
87
88 /// `3 <= 5` is true.
89 LE,
90
91 /// `5 >= 3` is true.
92 GE,
93
94 /// `3 <> 5` is `true`.
95 LG,
96
97 /// `3 == 5` is `false`.
98 EQ,
99
100 /// `3 != 5` is `true`.
101 NE,
102
103 /// `item in collection` - Membership test.
104 ///
105 /// Also abused as part of `for item in collection { ... }`.
106 In,
107
108 /// `not false` is `true`.
109 BoolNot,
110
111 /// `false and true` is `false`.
112 BoolAnd,
113
114 /// `false or true` is `true`.
115 BoolOr,
116
117 /// Used when two expressions are juxtaposed. Always an error.
118 Missing,
119}
120
121impl Op {
122 /// Returns the left and right [`Precedence`] of `self`.
123 ///
124 /// Differences from Rust and Python:
125 /// - `x in low .. high and b` means `(x in (low .. high)) and b`.
126 /// - In Rust, there is no `in`.
127 /// `low .. high && b` means `low .. (high && b)`.
128 /// - In Python, `:` is part of array subscription.
129 /// `a[x in low : high and b]` means `a[(x in low) : (high and b)]`.
130 ///
131 /// Differences from C, Java and Javascript:
132 /// - `x & 1 == 0` means `(x & 1) == 0`.
133 /// - In C, Java and Javascript it means `x & (1 == 0)`.
134 /// - `-x ** 2` means `-(x ** 2)`
135 /// - In Javascript it means `(-x) ** 2`.
136 pub const fn precedence(self) -> (Option<Precedence>, Option<Precedence>) {
137 const fn p(n: u8) -> Option<Precedence> { Some(Precedence(n)) }
138 use Op::*;
139 match self {
140 Query => (p(34), None),
141 Pow => (p(32), p(33)),
142 BitNot | Plus | Minus | Borrow | Share | Clone => (None, p(30)),
143 Mul | Div | Rem => (p(29), p(28)),
144 Add | Sub => (p(27), p(26)),
145 SL | ASR | LSR => (p(24), p(25)),
146 BitAnd => (p(23), p(22)),
147 BitXor => (p(21), p(20)),
148 BitOr => (p(19), p(18)),
149 Cast => (p(16), p(17)),
150 Exclusive | Inclusive => (p(15), p(14)),
151 LT | GT | LE | GE | LG => (p(13), p(12)),
152 EQ | NE => (p(11), p(10)),
153 In => (p(9), p(8)),
154 BoolNot => (None, p(6)),
155 BoolAnd => (p(5), p(4)),
156 BoolOr => (p(3), p(2)),
157 Missing => (p(1), p(0)),
158 }
159 }
160}
161
162// ----------------------------------------------------------------------------
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn limits() {
170 let (_, right) = Op::Missing.precedence();
171 assert_eq!(right.unwrap(), Precedence::MIN);
172 let (left, _) = Op::Query.precedence();
173 assert_eq!(left.unwrap(), Precedence::MAX);
174 }
175}