binary.rs
1 // Copyright (C) 2019-2025 ADnet Contributors 2 // This file is part of the ADL library. 3 4 // The ADL library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 9 // The ADL library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 14 // You should have received a copy of the GNU General Public License 15 // along with the ADL library. If not, see <https://www.gnu.org/licenses/>. 16 17 use super::*; 18 use adl_span::{Symbol, sym}; 19 20 use std::cmp::Ordering; 21 22 /// A binary operator. 23 /// 24 /// Precedence is defined in the parser. 25 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)] 26 pub enum BinaryOperation { 27 /// Addition, i.e. `+`, `.add()`. 28 Add, 29 /// Wrapping addition, i.e. `.add_wrapped()`. 30 AddWrapped, 31 /// Logical AND, i.e. `&&`. 32 And, 33 /// Bitwise AND, i.e. `&`, `.and()`. 34 BitwiseAnd, 35 /// Division, i.e. `/`, `.div()`. 36 Div, 37 /// Wrapping division, i.e. `.div_wrapped()`. 38 DivWrapped, 39 /// Equality relation, i.e. `==`, `.eq()`. 40 Eq, 41 /// Greater-or-equal relation, i.e. `>=`, `.gte()`. 42 Gte, 43 /// Greater-than relation, i.e. `>`, `.gt()`. 44 Gt, 45 /// Lesser-or-equal relation, i.e. `<=`, `.lte()`. 46 Lte, 47 /// Lesser-than relation, i.e. `<`, `.lt()`. 48 Lt, 49 /// Arithmetic modulo, i.e. `.mod()` 50 Mod, 51 /// Multiplication, i.e. `*`, `.mul()`. 52 Mul, 53 /// Wrapping multiplication, i.e. `.mul_wrapped()`. 54 MulWrapped, 55 /// Boolean NAND, i.e. `.nand()`. 56 Nand, 57 /// In-equality relation, i.e. `!=`, `.neq()`. 58 Neq, 59 /// Boolean NOR, i.e. `.nor()`. 60 Nor, 61 /// Logical OR, i.e. `||`. 62 Or, 63 /// Bitwise OR, i.e. `|`, `.or()`. 64 BitwiseOr, 65 /// Exponentiation, i.e. `**` in `a ** b`, `.pow()`. 66 Pow, 67 /// Wrapping exponentiation, i.e. `.pow_wrapped()`. 68 PowWrapped, 69 /// Remainder, i.e. `%`, `.rem()`. 70 Rem, 71 /// Wrapping remainder, i.e. `.rem_wrapped()`. 72 RemWrapped, 73 /// Shift left operation, i.e. `<<`, `.shl()`. 74 Shl, 75 /// Wrapping shift left operation, i.e. `.shl_wrapped()`. 76 ShlWrapped, 77 /// Shift right operation, i.e. >>, `.shr()`. 78 Shr, 79 /// Wrapping shift right operation, i.e. `.shr_wrapped()`. 80 ShrWrapped, 81 /// Subtraction, i.e. `-`, `.sub()`. 82 Sub, 83 /// Wrapped subtraction, i.e. `.sub_wrapped()`. 84 SubWrapped, 85 /// Bitwise XOR, i.e. `.xor()`. 86 Xor, 87 } 88 89 impl 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 126 impl BinaryOperation { 127 /// Returns a `BinaryOperation` from the given `Symbol`. 128 /// This is used to resolve native operators invoked as method calls, e.g. `a.add_wrapped(b)`. 129 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 /// A binary expression `left op right` of two operands separated by some operator. 165 /// For example, `foo + bar`. 166 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 167 pub struct BinaryExpression { 168 /// The left operand of the expression. 169 pub left: Expression, 170 /// The right operand of the expression. 171 pub right: Expression, 172 /// The operand defining the meaning of the resulting binary expression. 173 pub op: BinaryOperation, 174 /// The span from `left` to `right`. 175 pub span: Span, 176 /// The ID of the expression. 177 pub id: NodeID, 178 } 179 180 impl 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 222 impl 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 257 impl From<BinaryExpression> for Expression { 258 fn from(value: BinaryExpression) -> Self { 259 Expression::Binary(Box::new(value)) 260 } 261 } 262 263 crate::simple_node_impl!(BinaryExpression);