use super::ops::{binary, unary};
use crate::ir_inner::model::expr::Expr;
use crate::ir_inner::model::types::{BinOp, UnOp};
macro_rules! binary_builders {
($($(#[$meta:meta])* $name:ident => $op:expr;)*) => {
$(
$(#[$meta])*
#[must_use]
#[inline]
pub fn $name(left: Expr, right: Expr) -> Expr {
binary($op, left, right)
}
)*
};
}
macro_rules! unary_builders {
($($(#[$meta:meta])* $name:ident => $op:expr;)*) => {
$(
$(#[$meta])*
#[must_use]
#[inline]
pub fn $name(operand: Expr) -> Expr {
unary($op, operand)
}
)*
};
}
impl Expr {
binary_builders! {
add => BinOp::Add;
sub => BinOp::Sub;
mul => BinOp::Mul;
div => BinOp::Div;
mulhi => BinOp::MulHigh;
rem => BinOp::Mod;
abs_diff => BinOp::AbsDiff;
bitxor => BinOp::BitXor;
bitand => BinOp::BitAnd;
bitor => BinOp::BitOr;
shl => BinOp::Shl;
shr => BinOp::Shr;
eq => BinOp::Eq;
lt => BinOp::Lt;
ne => BinOp::Ne;
gt => BinOp::Gt;
le => BinOp::Le;
ge => BinOp::Ge;
and => BinOp::And;
or => BinOp::Or;
min => BinOp::Min;
max => BinOp::Max;
}
unary_builders! {
negate => UnOp::Negate;
bitnot => UnOp::BitNot;
reverse_bits => UnOp::ReverseBits;
popcount => UnOp::Popcount;
clz => UnOp::Clz;
ctz => UnOp::Ctz;
not => UnOp::LogicalNot;
sin => UnOp::Sin;
cos => UnOp::Cos;
abs => UnOp::Abs;
sqrt => UnOp::Sqrt;
inverse_sqrt => UnOp::InverseSqrt;
reciprocal => UnOp::Reciprocal;
floor => UnOp::Floor;
ceil => UnOp::Ceil;
round => UnOp::Round;
trunc => UnOp::Trunc;
sign => UnOp::Sign;
is_nan => UnOp::IsNan;
is_inf => UnOp::IsInf;
is_finite => UnOp::IsFinite;
}
#[must_use]
#[inline]
pub fn saturating_sub(left: Expr, right: Expr) -> Expr {
binary(BinOp::Sub, left.clone(), binary(BinOp::Min, left, right))
}
#[must_use]
#[inline]
pub fn wrapping_add(self, other: impl Into<Expr>) -> Self {
binary(BinOp::WrappingAdd, self, other.into())
}
#[must_use]
#[inline]
pub fn wrapping_sub(self, other: impl Into<Expr>) -> Self {
binary(BinOp::WrappingSub, self, other.into())
}
}