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}