Skip to main content

toasty_core/stmt/
op_binary.rs

1use std::fmt;
2
3/// A binary operator: comparison or arithmetic.
4///
5/// Used by [`ExprBinaryOp`](super::ExprBinaryOp) to specify the operation
6/// applied between two expressions.
7///
8/// # Examples
9///
10/// ```
11/// use toasty_core::stmt::BinaryOp;
12///
13/// let op = BinaryOp::Eq;
14/// assert!(op.is_eq());
15/// assert_eq!(op.to_string(), "=");
16///
17/// // Negation
18/// assert_eq!(op.negate(), Some(BinaryOp::Ne));
19///
20/// // Commutation (swapping operands)
21/// assert_eq!(BinaryOp::Lt.commute(), Some(BinaryOp::Gt));
22/// assert_eq!(BinaryOp::Add.commute(), Some(BinaryOp::Add));
23/// assert_eq!(BinaryOp::Sub.commute(), None);
24/// ```
25#[derive(Copy, Clone, PartialEq, Eq, Hash)]
26pub enum BinaryOp {
27    /// Equality (`=`).
28    Eq,
29    /// Inequality (`!=`).
30    Ne,
31    /// Greater than or equal (`>=`).
32    Ge,
33    /// Greater than (`>`).
34    Gt,
35    /// Less than or equal (`<=`).
36    Le,
37    /// Less than (`<`).
38    Lt,
39    /// Arithmetic addition (`+`).
40    Add,
41    /// Arithmetic subtraction (`-`).
42    Sub,
43}
44
45impl BinaryOp {
46    /// Returns `true` if this is the equality operator.
47    pub fn is_eq(self) -> bool {
48        matches!(self, Self::Eq)
49    }
50
51    /// Returns `true` if this is the inequality operator.
52    pub fn is_ne(self) -> bool {
53        matches!(self, Self::Ne)
54    }
55
56    /// Returns `true` if this is an arithmetic operator (`+`, `-`).
57    pub fn is_arithmetic(self) -> bool {
58        matches!(self, Self::Add | Self::Sub)
59    }
60
61    /// Returns the logical negation of this operator, if one exists.
62    ///
63    /// Only comparison operators have a logical negation; arithmetic
64    /// operators return `None`.
65    ///
66    /// - `=` → `!=`
67    /// - `!=` → `=`
68    /// - `<` → `>=`
69    /// - `>=` → `<`
70    /// - `>` → `<=`
71    /// - `<=` → `>`
72    pub fn negate(self) -> Option<Self> {
73        match self {
74            Self::Eq => Some(Self::Ne),
75            Self::Ne => Some(Self::Eq),
76            Self::Lt => Some(Self::Ge),
77            Self::Ge => Some(Self::Lt),
78            Self::Gt => Some(Self::Le),
79            Self::Le => Some(Self::Gt),
80            Self::Add | Self::Sub => None,
81        }
82    }
83
84    /// Returns the operator that gives an equivalent result when the operands
85    /// are swapped, or `None` if the operator is not commutative.
86    ///
87    /// For example, `5 < x` becomes `x > 5`, so `Lt.commute()` returns
88    /// `Some(Gt)`. Symmetric operators (`Eq`, `Ne`, `Add`) return themselves.
89    /// `Sub` is not commutative (`a - b ≠ b - a`) and returns `None`.
90    pub fn commute(self) -> Option<Self> {
91        match self {
92            Self::Eq => Some(Self::Eq),
93            Self::Ne => Some(Self::Ne),
94            Self::Ge => Some(Self::Le),
95            Self::Gt => Some(Self::Lt),
96            Self::Le => Some(Self::Ge),
97            Self::Lt => Some(Self::Gt),
98            Self::Add => Some(Self::Add),
99            Self::Sub => None,
100        }
101    }
102}
103
104impl fmt::Display for BinaryOp {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        match self {
107            BinaryOp::Eq => "=".fmt(f),
108            BinaryOp::Ne => "!=".fmt(f),
109            BinaryOp::Ge => ">=".fmt(f),
110            BinaryOp::Gt => ">".fmt(f),
111            BinaryOp::Le => "<=".fmt(f),
112            BinaryOp::Lt => "<".fmt(f),
113            BinaryOp::Add => "+".fmt(f),
114            BinaryOp::Sub => "-".fmt(f),
115        }
116    }
117}
118
119impl fmt::Debug for BinaryOp {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        fmt::Display::fmt(self, f)
122    }
123}