1use crate::ast::{Bool, Float, IntoAst};
2use std::iter::Product;
3use std::iter::Sum;
4use std::ops::{
5 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
6 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Sub, SubAssign,
7};
8
9use crate::ast::{BV, Int, Real};
10
11macro_rules! impl_unary_op_raw {
12 ($ty:ty, $output:ty, $base_trait:ident, $base_fn:ident, $function:ident) => {
13 impl $base_trait for $ty {
14 type Output = $output;
15
16 fn $base_fn(self) -> Self::Output {
17 (&self as &$output).$function()
18 }
19 }
20 };
21}
22
23macro_rules! impl_unary_op {
24 ($ty:ident::$function:ident = $base_trait:ident::$base_fn:ident) => {
25 impl_unary_op_raw!($ty, $ty, $base_trait, $base_fn, $function);
26 impl_unary_op_raw!(&$ty, $ty, $base_trait, $base_fn, $function);
27 };
28}
29
30impl_unary_op!(BV::bvnot = Not::not);
31impl_unary_op!(BV::bvneg = Neg::neg);
32
33macro_rules! impl_bin_trait {
34 ($t:ident::$op:ident = $tr:ident::$trop:ident) => {
35 impl<T: IntoAst<$t>> $tr<T> for $t {
36 type Output = $t;
37 fn $trop(self, rhs: T) -> Self::Output {
38 let rhs = rhs.into_ast(&self);
39 <$t>::$op(&self, rhs)
40 }
41 }
42
43 impl<T: IntoAst<$t>> $tr<T> for &$t {
44 type Output = $t;
45 fn $trop(self, rhs: T) -> Self::Output {
46 let rhs = rhs.into_ast(&self);
47 <$t>::$op(&self, rhs)
48 }
49 }
50 };
51}
52
53macro_rules! impl_bin_assign_trait {
54 ($t:ident::$op:ident = $tr:ident::$trop:ident) => {
55 impl<T: IntoAst<$t>> $tr<T> for $t {
56 fn $trop(&mut self, rhs: T) {
57 let res = (self as &mut $t).clone().$op(rhs);
58 *self = res
59 }
60 }
61 };
62}
63
64macro_rules! impl_var_trait {
65 ($t:ident::$op:ident = $tr:ident::$trop:ident) => {
66 impl<T: IntoAst<$t>> $tr<T> for $t {
67 type Output = $t;
68 fn $trop(self, rhs: T) -> Self::Output {
69 let rhs = rhs.into_ast(&self);
70 <$t>::$op(&[self.clone(), rhs])
71 }
72 }
73
74 impl<T: IntoAst<$t>> $tr<T> for &$t {
75 type Output = $t;
76 fn $trop(self, rhs: T) -> Self::Output {
77 let rhs = rhs.into_ast(&self);
78 <$t>::$op(&[self.clone(), rhs])
79 }
80 }
81 };
82}
83
84impl_var_trait!(Bool::and = BitAnd::bitand);
85impl_var_trait!(Bool::or = BitOr::bitor);
86impl_bin_trait!(Bool::xor = BitXor::bitxor);
87
88impl_bin_assign_trait!(Bool::bitand = BitAndAssign::bitand_assign);
89impl_bin_assign_trait!(Bool::bitor = BitOrAssign::bitor_assign);
90impl_bin_assign_trait!(Bool::bitxor = BitXorAssign::bitxor_assign);
91
92impl_bin_trait!(BV::bvadd = Add::add);
93impl_bin_trait!(BV::bvsub = Sub::sub);
94impl_bin_trait!(BV::bvmul = Mul::mul);
95impl_bin_trait!(BV::bvand = BitAnd::bitand);
96impl_bin_trait!(BV::bvor = BitOr::bitor);
97impl_bin_trait!(BV::bvxor = BitXor::bitxor);
98impl_bin_trait!(BV::bvshl = Shl::shl);
99
100impl_bin_assign_trait!(BV::bvadd = AddAssign::add_assign);
101impl_bin_assign_trait!(BV::bvsub = SubAssign::sub_assign);
102impl_bin_assign_trait!(BV::bvmul = MulAssign::mul_assign);
103impl_bin_assign_trait!(BV::bvand = BitAndAssign::bitand_assign);
104impl_bin_assign_trait!(BV::bvor = BitOrAssign::bitor_assign);
105impl_bin_assign_trait!(BV::bvxor = BitXorAssign::bitxor_assign);
106impl_bin_assign_trait!(BV::bvshl = ShlAssign::shl_assign);
107
108impl_unary_op!(Int::unary_minus = Neg::neg);
109
110impl_var_trait!(Int::add = Add::add);
111impl_var_trait!(Int::sub = Sub::sub);
112impl_var_trait!(Int::mul = Mul::mul);
113impl_bin_trait!(Int::div = Div::div);
114impl_bin_trait!(Int::rem = Rem::rem);
115
116impl_bin_assign_trait!(Int::add = AddAssign::add_assign);
117impl_bin_assign_trait!(Int::sub = SubAssign::sub_assign);
118impl_bin_assign_trait!(Int::mul = MulAssign::mul_assign);
119impl_bin_assign_trait!(Int::div = DivAssign::div_assign);
120impl_bin_assign_trait!(Int::rem = RemAssign::rem_assign);
121
122impl_var_trait!(Real::add = Add::add);
123impl_var_trait!(Real::sub = Sub::sub);
124impl_var_trait!(Real::mul = Mul::mul);
125impl_bin_trait!(Real::div = Div::div);
126impl_unary_op!(Real::unary_minus = Neg::neg);
127
128impl_bin_assign_trait!(Real::add = AddAssign::add_assign);
129impl_bin_assign_trait!(Real::sub = SubAssign::sub_assign);
130impl_bin_assign_trait!(Real::mul = MulAssign::mul_assign);
131impl_bin_assign_trait!(Real::div = DivAssign::div_assign);
132
133impl_unary_op!(Float::unary_neg = Neg::neg);
137impl_unary_op!(Bool::not = Not::not);
140
141macro_rules! impl_trait_number_types {
148 ($Z3ty:ty, $tr:ident::$op:ident, [$($num:ty),+]) => {
149 $(
150 impl_trait_number_types!($Z3ty, $tr::$op, $num);
151 )+
152 };
153 ($Z3ty:ty, $tr:ident::$op:ident, $num:ty) => {
154 impl $tr<$Z3ty> for $num {
155 type Output = $Z3ty;
156 fn $op(self, rhs: $Z3ty) -> Self::Output {
157 let lhs = self.into_ast(&rhs);
158 lhs.$op(&rhs)
159 }
160 }
161
162 impl<'a> $tr<&'a $Z3ty> for $num {
163 type Output = $Z3ty;
164 fn $op(self, rhs: &'a $Z3ty) -> Self::Output {
165 let lhs = self.into_ast(rhs);
166 lhs.$op(rhs)
167 }
168 }
169 };
170}
171
172impl_trait_number_types!(Int, Add::add, [u8, i8, u16, i16, u32, i32, u64, i64]);
173impl_trait_number_types!(Int, Sub::sub, [u8, i8, u16, i16, u32, i32, u64, i64]);
174impl_trait_number_types!(Int, Mul::mul, [u8, i8, u16, i16, u32, i32, u64, i64]);
175impl_trait_number_types!(Int, Div::div, [u8, i8, u16, i16, u32, i32, u64, i64]);
176
177impl_trait_number_types!(BV, Add::add, [u8, i8, u16, i16, u32, i32, u64, i64]);
178impl_trait_number_types!(BV, Sub::sub, [u8, i8, u16, i16, u32, i32, u64, i64]);
179impl_trait_number_types!(BV, Mul::mul, [u8, i8, u16, i16, u32, i32, u64, i64]);
180impl_trait_number_types!(BV, BitXor::bitxor, [u8, i8, u16, i16, u32, i32, u64, i64]);
181impl_trait_number_types!(BV, BitAnd::bitand, [u8, i8, u16, i16, u32, i32, u64, i64]);
182impl_trait_number_types!(BV, BitOr::bitor, [u8, i8, u16, i16, u32, i32, u64, i64]);
183
184macro_rules! integer_sum_product {
185 ($zero:expr, $one:expr, $($a:ty)*) => ($(
186 impl Sum for $a {
187 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
188 iter.reduce(
189 |a, b| a + b,
190 ).unwrap_or($zero)
191 }
192 }
193
194 impl Product for $a {
195 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
196 iter.reduce(
197 |a, b| a * b,
198 ).unwrap_or($one)
199 }
200 }
201
202 impl<'a> Sum<&'a $a> for $a {
203 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
204 iter.cloned().reduce(
205 |a, b| a + b,
206 ).unwrap_or($zero)
207 }
208 }
209
210 impl<'a> Product<&'a $a> for $a {
211 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
212 iter.cloned().reduce(
213 |a, b| a * b,
214 ).unwrap_or($one)
215 }
216 }
217 )*);
218}
219
220integer_sum_product!(Int::from_u64(0), Int::from_u64(1), Int);
221integer_sum_product!(Real::from_rational(0, 1), Real::from_rational(1, 1), Real);