1use crate::term::{Term, Value};
2use core::num::{Wrapping, Saturating};
3
4pub unsafe trait ConstOps {}
7
8macro_rules! impl_const_ops {
9 ($($T:ty)*) => {
10 $(unsafe impl ConstOps for $T {})*
11 };
12 (@int $($T:ty)*) => {
13 $(impl_const_ops! {$T Wrapping<$T> Saturating<$T>})*
14 }
15}
16
17impl_const_ops! {
18 ()
19 bool char
20 f32 f64
21}
22
23impl_const_ops! {
24 @int
25 u8 u16 u32 u64 u128 usize
26 i8 i16 i32 i64 i128 isize
27}
28
29#[cfg(feature = "never")]
30impl_const_ops! {!}
31
32macro_rules! impl_op2 {
33 ($($term:ident = $op:ident::$func:ident)*) => {
34 $(
35 term! {
36 pub fn $term(a, b) -> unsafe <a::Type as core::ops::$op<b::Type>>::Output
38 where a::Type: core::ops::$op<b::Type> + ConstOps {
39 core::ops::$op::$func(a, b)
40 }
41 }
42
43 impl<A: Term, B: Term> core::ops::$op<Value<B>> for Value<A>
44 where A::Type: core::ops::$op<B::Type> + ConstOps {
45 type Output = Value<$term<A, B>>;
46
47 fn $func(self, b: Value<B>) -> Self::Output {
48 $term(self, b)
49 }
50 }
51 )*
52 };
53}
54
55macro_rules! impl_op2_overflowing {
56 ($($xterm:ident $term:ident = $op:ident::$func:ident $cop:ident::$cfunc:ident)*) => {
57 $(
58 term! {
59 pub fn $xterm(a, b) -> unsafe <a::Type as core::ops::$op<b::Type>>::Output
63 where a::Type: core::ops::$op<b::Type> + ConstOps {
64 core::ops::$op::$func(a, b)
65 }
66 }
67
68 term! {
69 pub fn $term(a, b) -> unsafe a::Type
71 where b: Term<Type = a::Type>, a::Type: num_traits::ops::checked::$cop + ConstOps {
72 num_traits::ops::checked::$cop::$cfunc(&a, &b).expect("Overflow in arithmetic operation in term evaluation")
73 }
74 }
75
76 impl<A: Term, B: Term<Type = A::Type>> core::ops::$op<Value<B>> for Value<A>
77 where A::Type: num_traits::ops::checked::$cop + ConstOps {
78 type Output = Value<$term<A, B>>;
79
80 fn $func(self, b: Value<B>) -> Self::Output {
81 $term(self, b)
82 }
83 }
84 )*
85 };
86}
87
88macro_rules! impl_op1 {
89 ($($op:ident::$func:ident)*) => {
90 $(
91 term! {
92 pub fn $op(a) -> unsafe <a::Type as core::ops::$op>::Output
93 where a::Type: core::ops::$op + ConstOps {
94 core::ops::$op::$func(a)
95 }
96 }
97
98 impl<A: Term> core::ops::$op for Value<A>
99 where A::Type: core::ops::$op + ConstOps {
100 type Output = Value<$op<A>>;
101
102 fn $func(self) -> Self::Output {
103 $op(self)
104 }
105 }
106 )*
107 };
108}
109
110macro_rules! impl_op1_overflowing {
111 ($($xterm:ident $term:ident = $op:ident::$func:ident $cop:ident::$cfunc:ident)*) => {
112 $(
113 term! {
114 pub fn $xterm(a) -> unsafe <a::Type as core::ops::$op>::Output
118 where a::Type: core::ops::$op + ConstOps {
119 core::ops::$op::$func(a)
120 }
121 }
122
123 term! {
124 pub fn $term(a) -> unsafe a::Type
126 where a::Type: num_traits::ops::checked::$cop + ConstOps {
127 num_traits::ops::checked::$cop::$cfunc(&a).expect("Overflow in arithmetic operation in term evaluation")
128 }
129 }
130
131 impl<A: Term> core::ops::$op for Value<A>
132 where A::Type: num_traits::ops::checked::$cop + ConstOps {
133 type Output = Value<$term<A>>;
134
135 fn $func(self) -> Self::Output {
136 $term(self)
137 }
138 }
139 )*
140 };
141}
142
143impl_op2_overflowing! {
144 XAdd Add = Add::add CheckedAdd::checked_add
145 XSub Sub = Sub::sub CheckedSub::checked_sub
146 XMul Mul = Mul::mul CheckedMul::checked_mul
147 XDiv Div = Div::div CheckedDiv::checked_div
148 XRem Rem = Rem::rem CheckedRem::checked_rem
149}
150
151impl_op2! {
152 And = BitAnd::bitand
153 Or = BitOr::bitor
154 Xor = BitXor::bitxor
155}
156
157impl_op1! {
161 Not::not
162}
163
164impl_op1_overflowing! {
165 XNeg Neg = Neg::neg CheckedNeg::checked_neg
166}