1use super::*;
18use leo_span::{Symbol, sym};
19
20use std::cmp::Ordering;
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub enum BinaryOperation {
27 Add,
29 AddWrapped,
31 And,
33 BitwiseAnd,
35 Div,
37 DivWrapped,
39 Eq,
41 Gte,
43 Gt,
45 Lte,
47 Lt,
49 Mod,
51 Mul,
53 MulWrapped,
55 Nand,
57 Neq,
59 Nor,
61 Or,
63 BitwiseOr,
65 Pow,
67 PowWrapped,
69 Rem,
71 RemWrapped,
73 Shl,
75 ShlWrapped,
77 Shr,
79 ShrWrapped,
81 Sub,
83 SubWrapped,
85 Xor,
87}
88
89impl fmt::Display for BinaryOperation {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 write!(f, "{}", match self {
92 Self::Add => "+",
93 Self::AddWrapped => "add_wrapped",
94 Self::And => "&&",
95 Self::BitwiseAnd => "&",
96 Self::Div => "/",
97 Self::DivWrapped => "div_wrapped",
98 Self::Eq => "==",
99 Self::Gte => ">=",
100 Self::Gt => ">",
101 Self::Lte => "<=",
102 Self::Lt => "<",
103 Self::Mod => "mod",
104 Self::Mul => "*",
105 Self::MulWrapped => "mul_wrapped",
106 Self::Nand => "NAND",
107 Self::Neq => "!=",
108 Self::Nor => "NOR",
109 Self::Or => "||",
110 Self::BitwiseOr => "|",
111 Self::Pow => "**",
112 Self::PowWrapped => "pow_wrapped",
113 Self::Rem => "%",
114 Self::RemWrapped => "rem_wrapped",
115 Self::Shl => "<<",
116 Self::ShlWrapped => "shl_wrapped",
117 Self::Shr => ">>",
118 Self::ShrWrapped => "shr_wrapped",
119 Self::Sub => "-",
120 Self::SubWrapped => "sub_wrapped",
121 Self::Xor => "^",
122 })
123 }
124}
125
126impl BinaryOperation {
127 pub fn from_symbol(symbol: Symbol) -> Option<Self> {
130 Some(match symbol {
131 sym::add => Self::Add,
132 sym::add_wrapped => Self::AddWrapped,
133 sym::and => Self::BitwiseAnd,
134 sym::div => Self::Div,
135 sym::div_wrapped => Self::DivWrapped,
136 sym::eq => Self::Eq,
137 sym::gte => Self::Gte,
138 sym::gt => Self::Gt,
139 sym::lte => Self::Lte,
140 sym::lt => Self::Lt,
141 sym::Mod => Self::Mod,
142 sym::mul => Self::Mul,
143 sym::mul_wrapped => Self::MulWrapped,
144 sym::nand => Self::Nand,
145 sym::neq => Self::Neq,
146 sym::nor => Self::Nor,
147 sym::or => Self::BitwiseOr,
148 sym::pow => Self::Pow,
149 sym::pow_wrapped => Self::PowWrapped,
150 sym::rem => Self::Rem,
151 sym::rem_wrapped => Self::RemWrapped,
152 sym::shl => Self::Shl,
153 sym::shl_wrapped => Self::ShlWrapped,
154 sym::shr => Self::Shr,
155 sym::shr_wrapped => Self::ShrWrapped,
156 sym::sub => Self::Sub,
157 sym::sub_wrapped => Self::SubWrapped,
158 sym::xor => Self::Xor,
159 _ => return None,
160 })
161 }
162}
163
164#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
167pub struct BinaryExpression {
168 pub left: Expression,
170 pub right: Expression,
172 pub op: BinaryOperation,
174 pub span: Span,
176 pub id: NodeID,
178}
179
180impl fmt::Display for BinaryExpression {
181 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
182 use Associativity::*;
183 use BinaryOperation::*;
184
185 if matches!(
186 self.op,
187 AddWrapped
188 | DivWrapped
189 | Mod
190 | MulWrapped
191 | Nand
192 | Nor
193 | PowWrapped
194 | RemWrapped
195 | ShlWrapped
196 | ShrWrapped
197 | SubWrapped
198 ) {
199 if self.left.precedence() < 20 {
200 write!(f, "({})", self.left)?;
201 } else {
202 write!(f, "{}", self.left)?;
203 }
204 write!(f, ".{}({})", self.op, self.right)
205 } else {
206 let my_precedence = self.precedence();
207 let my_associativity = self.associativity();
208 match (self.left.precedence().cmp(&my_precedence), my_associativity, self.left.associativity()) {
209 (Ordering::Greater, _, _) | (Ordering::Equal, Left, Left) => write!(f, "{}", self.left)?,
210 _ => write!(f, "({})", self.left)?,
211 }
212 write!(f, " {} ", self.op)?;
213 match (self.right.precedence().cmp(&my_precedence), my_associativity, self.right.associativity()) {
214 (Ordering::Greater, _, _) | (Ordering::Equal, Right, Right) => write!(f, "{}", self.right)?,
215 _ => write!(f, "({})", self.right)?,
216 }
217 Ok(())
218 }
219 }
220}
221
222impl BinaryExpression {
223 pub(crate) fn precedence(&self) -> u32 {
224 use BinaryOperation::*;
225
226 match self.op {
227 BitwiseOr => 1,
228 BitwiseAnd => 2,
229 Eq | Neq | Lt | Gt | Lte | Gte => 3,
230 Or => 4,
231 Xor => 5,
232 And => 6,
233 Shl => 7,
234 Shr => 8,
235 Add | Sub => 9,
236 Mul | Div | Rem => 10,
237 Pow => 11,
238 AddWrapped | DivWrapped | Mod | MulWrapped | Nand | Nor | PowWrapped | RemWrapped | ShlWrapped
239 | ShrWrapped | SubWrapped => 20,
240 }
241 }
242
243 pub(crate) fn associativity(&self) -> Associativity {
244 use Associativity::*;
245 use BinaryOperation::*;
246
247 match self.op {
248 Pow => Right,
249 BitwiseOr | BitwiseAnd | Eq | Neq | Lt | Gt | Lte | Gte | Or | Xor | And | Shl | Shr | Add | Sub | Mul
250 | Div | Rem => Left,
251 AddWrapped | DivWrapped | Mod | MulWrapped | Nand | Nor | PowWrapped | RemWrapped | ShlWrapped
252 | ShrWrapped | SubWrapped => None,
253 }
254 }
255}
256
257impl From<BinaryExpression> for Expression {
258 fn from(value: BinaryExpression) -> Self {
259 Expression::Binary(Box::new(value))
260 }
261}
262
263crate::simple_node_impl!(BinaryExpression);