Skip to main content

rs_teststand/expression/operator/
logical.rs

1//! Logical operators.
2
3use super::Arity;
4
5/// A logical operator, working on truth values.
6///
7/// These are the symbol forms only. The word forms `AND`, `OR`, `XOR` and `NOT`
8/// are **bitwise**, see [`BitwiseOperator`](super::BitwiseOperator), which is
9/// the single most common misreading of the expression language.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum LogicalOperator {
12    /// Logical and, `&&`.
13    And,
14    /// Logical or, `||`.
15    Or,
16    /// Logical not, `!`.
17    Not,
18}
19
20impl LogicalOperator {
21    /// Every logical operator.
22    pub const ALL: [Self; 3] = [Self::And, Self::Or, Self::Not];
23
24    /// How the operator is written.
25    #[must_use]
26    pub const fn symbol(self) -> &'static str {
27        match self {
28            Self::And => "&&",
29            Self::Or => "||",
30            Self::Not => "!",
31        }
32    }
33
34    /// How many operands it takes.
35    #[must_use]
36    pub const fn arity(self) -> Arity {
37        match self {
38            Self::Not => Arity::Unary,
39            _ => Arity::Binary,
40        }
41    }
42
43    /// Binding strength; lower binds tighter. Measured, see [`super`].
44    #[must_use]
45    pub const fn precedence(self) -> u8 {
46        match self {
47            Self::Not => 1,
48            Self::And => 9,
49            Self::Or => 10,
50        }
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::LogicalOperator;
57
58    #[test]
59    fn and_binds_tighter_than_or() {
60        // Measured: 0 || 1 && 0 evaluates to False.
61        assert!(LogicalOperator::And.precedence() < LogicalOperator::Or.precedence());
62    }
63
64    #[test]
65    fn logical_operators_bind_looser_than_every_bitwise_one() {
66        // Measured: 1 == 1 && 2 == 2 is True, so && sits outside comparison,
67        // and the bitwise family sits between the two.
68        use crate::expression::BitwiseOperator;
69        assert!(BitwiseOperator::Or.precedence() < LogicalOperator::And.precedence());
70    }
71
72    #[test]
73    fn the_symbols_are_doubled_to_distinguish_them_from_bitwise() {
74        assert_eq!(LogicalOperator::And.symbol(), "&&");
75        assert_eq!(LogicalOperator::Or.symbol(), "||");
76    }
77}