rs_teststand/expression/operator/
bitwise.rs1use super::Arity;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub enum BitwiseOperator {
18 And,
20 Or,
22 Xor,
24 Not,
26 ShiftLeft,
28 ShiftRight,
30 AndWord,
32 OrWord,
34 XorWord,
36 NotWord,
38}
39
40impl BitwiseOperator {
41 pub const ALL: [Self; 10] = [
43 Self::And,
44 Self::Or,
45 Self::Xor,
46 Self::Not,
47 Self::ShiftLeft,
48 Self::ShiftRight,
49 Self::AndWord,
50 Self::OrWord,
51 Self::XorWord,
52 Self::NotWord,
53 ];
54
55 #[must_use]
57 pub const fn symbol(self) -> &'static str {
58 match self {
59 Self::And => "&",
60 Self::Or => "|",
61 Self::Xor => "^",
62 Self::Not => "~",
63 Self::ShiftLeft => "<<",
64 Self::ShiftRight => ">>",
65 Self::AndWord => "AND",
66 Self::OrWord => "OR",
67 Self::XorWord => "XOR",
68 Self::NotWord => "NOT",
69 }
70 }
71
72 #[must_use]
74 pub const fn arity(self) -> Arity {
75 match self {
76 Self::Not | Self::NotWord => Arity::Unary,
77 _ => Arity::Binary,
78 }
79 }
80
81 #[must_use]
83 pub const fn precedence(self) -> u8 {
84 match self {
85 Self::Not | Self::NotWord => 1,
86 Self::ShiftLeft | Self::ShiftRight => 4,
87 Self::And | Self::AndWord => 6,
88 Self::Xor | Self::XorWord => 7,
89 Self::Or | Self::OrWord => 8,
90 }
91 }
92
93 #[must_use]
95 pub const fn alternate_spelling(self) -> Option<Self> {
96 Some(match self {
97 Self::And => Self::AndWord,
98 Self::AndWord => Self::And,
99 Self::Or => Self::OrWord,
100 Self::OrWord => Self::Or,
101 Self::Xor => Self::XorWord,
102 Self::XorWord => Self::Xor,
103 Self::Not => Self::NotWord,
104 Self::NotWord => Self::Not,
105 _ => return None,
106 })
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::BitwiseOperator;
113
114 #[test]
115 fn and_binds_tighter_than_xor_which_binds_tighter_than_or() {
116 assert!(BitwiseOperator::And.precedence() < BitwiseOperator::Xor.precedence());
118 assert!(BitwiseOperator::Xor.precedence() < BitwiseOperator::Or.precedence());
119 }
120
121 #[test]
122 fn word_and_symbol_spellings_agree() {
123 for operator in BitwiseOperator::ALL {
125 let Some(other) = operator.alternate_spelling() else {
126 continue;
127 };
128 assert_eq!(operator.precedence(), other.precedence(), "{operator:?}");
129 assert_eq!(operator.arity(), other.arity(), "{operator:?}");
130 }
131 }
132
133 #[test]
134 fn shifts_bind_looser_than_arithmetic_but_tighter_than_comparison() {
135 use crate::expression::{ArithmeticOperator, ComparisonOperator};
137 assert!(ArithmeticOperator::Add.precedence() < BitwiseOperator::ShiftLeft.precedence());
138 assert!(BitwiseOperator::ShiftLeft.precedence() < ComparisonOperator::Equal.precedence());
139 }
140}