rsdiff_core/
macros.rs

1/*
2    Appellation: macros <mod>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5#![allow(unused_macros)]
6
7///
8#[macro_export]
9macro_rules! nested {
10    ($($i:ident in $iter:expr)=>* => $body:block ) => {
11        nested!(@loop $body, $($i in $iter),*);
12    };
13    // The primary base case for iterators
14    (@loop $body:block, $i:ident in $iter:expr) => {
15        for $i in $iter $body
16    };
17    // An alternative base case
18    (@loop $body:block, $i:ident in $iter:expr) => {
19        for $i in $iter.into_iter() $body
20    };
21    // This is the recursive case. It will expand to a nested loop.
22    (@loop $body:block, $i:ident in $iter:expr, $($tail:tt)*) => {
23        for $i in $iter {
24            nested!(@loop $body, $($tail)*);
25        }
26    };
27}
28
29macro_rules! impl_fmt {
30    ($target:ident, $name:ident($($args:tt)*)) => {
31        impl core::fmt::$name for $target {
32            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
33                write!(f, $($args)*)
34            }
35        }
36    };
37    (impl<$($t:ident),*> $name:ident($($args:tt)*) for $target:ident where $($arg:ident:$($bnd:tt)*),*) => {
38        impl<$($t),*> core::fmt::$name for $target<$($t),*> where $($arg:$($bnd)*),* {
39            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
40                write!(f, $($args)*)
41            }
42        }
43    };
44}
45
46macro_rules! impl_binary {
47    (impl $($path:ident)::*.$call:ident($lhs:ident, $rhs:ident) -> $res:ident {$body:expr}) => {
48        impl $($path)::*<$rhs> for $lhs {
49            type Output = $res;
50
51            fn $call(self, rhs: $rhs) -> Self::Output {
52                $body(self, rhs)
53            }
54        }
55    };
56    (impl $($path:ident)::*<$rhs:ident>.$call:ident for $lhs:ident -> $res:ident where $($t:ident:$($bnd:tt),*),* {$body:expr}) => {
57        impl<$($t),*> $($path)::*<$rhs> for $lhs where $($t:$($bnd),*)* {
58            type Output = $res;
59
60            fn $method(self, rhs: $rhs) -> Self::Output {
61                $body(self, rhs)
62            }
63        }
64    };
65    ($lhs:ty, $rhs:ty, $res:ty: [$(($($path:ident)::*.$method:ident, $e:expr)),*]) => {
66        $(
67            impl_binary!(@loop $lhs, $rhs, $res, $($path)::*.$method, $e);
68        )*
69    };
70    ($lhs:ty, $rhs:ty, $res:ty, $($path:ident)::*.$method:ident, $e:expr) => {
71        impl_binary!(@loop $lhs, $rhs, $res, $($path)::*.$method, $e);
72    };
73
74    (@loop $lhs:ty, $rhs:ty, $res:ty, $($path:ident)::*.$method:ident, $e:expr, where T: $($tr:tt)+*) => {
75        impl<T> $($path)::*<T> for $lhs where T: $($tr)* {
76            type Output = $res;
77
78            fn $method(self, rhs: $rhs) -> Self::Output {
79                $e(self, rhs)
80            }
81        }
82    };
83    (@loop $lhs:ty, $rhs:ty, $res:ty, $($path:ident)::*.$method:ident, $e:expr) => {
84        impl $($path)::*<$rhs> for $lhs {
85            type Output = $res;
86
87            fn $method(self, rhs: $rhs) -> Self::Output {
88                $e(self, rhs)
89            }
90        }
91    };
92}
93
94macro_rules! evaluator {
95    ($op:ident($($args:ident),*) -> $output:ty where $($t:ident: $($rest:tt)*),* $body:block) => {
96        impl<P, $($args)*> $crate::ops::Evaluate<P> for $op
97        where
98            P: $crate::ops::Params<Pattern = ($($arg),*)>,
99            $($t: $($rest)*),*
100        {
101            type Output = $output;
102
103            fn eval(&self, params: P) -> Self::Output $body
104        }
105    };
106    ($op:ident<$($pat:tt)*>($($args:ident),*) -> $output:ty where $($t:ident: $($rest:tt)*),* $body:block) => {
107        impl<P, $($args)*> $crate::ops::Evaluate<P> for $op
108        where
109            P: $crate::ops::Params<Pattern = $($pat)*>,
110            $($t: $($rest)*),*
111        {
112            type Output = $output;
113
114            fn eval(&self, params: P) -> Self::Output $body
115        }
116    };
117    (nary $op:ident<Vec<T>> -> $output:ident where $($t:ident: $($rest:tt)*),* {$body:expr}) => {
118        impl<P, T> $crate::ops::Evaluate<P> for $op
119        where
120            P: $crate::ops::Params<Pattern = Vec<T>>,
121            $($t:$($rest)*),*
122        {
123            type Output = $output;
124
125            fn eval(&self, params: P) -> Self::Output {
126                $body(params)
127            }
128        }
129    };
130}
131
132macro_rules! operand {
133    ($($op:ident<$kind:ident>),*) => {
134        $(
135            operand!(@base $op<$kind>.$op);
136        )*
137    };
138    ($($op:ident<$kind:ident>.$name:ident),*) => {
139        $(
140            operand!(@base $op<$kind>.$name);
141        )*
142    };
143    (@base $op:ident<$kind:ident>.$name:ident) => {
144        #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
145        #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize,))]
146        pub struct $op;
147
148        impl $op {
149            pub fn new() -> Self {
150                Self
151            }
152
153            pub fn kind(&self) -> $crate::ops::OpKind::$kind {
154                $crate::ops::OpKind::$kind
155            }
156
157            pub fn name(&self) -> &str {
158                stringify!($name)
159            }
160
161
162        }
163
164        operand!(@impl $op<$kind>.$name);
165    };
166    (@impl $op:ident<$kind:ident>.$name:ident) => {
167        impl core::fmt::Display for $op {
168            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
169                write!(f, "{}", self.name())
170            }
171        }
172
173        impl $crate::ops::Operand for $op {
174            type Kind = $crate::ops::$kind;
175
176            fn name(&self) -> &str {
177                self.name()
178            }
179
180            fn optype(&self) -> Self::Kind {
181                $crate::ops::$kind
182            }
183        }
184    };
185
186}
187
188macro_rules! operations {
189    ($group:ident<$kind:ident> {$($variant:ident($op:ident): $method:ident),*}) => {
190        $(
191            operation!($op<$kind>.$method);
192        )*
193
194        #[derive(
195            Clone,
196            Copy,
197            Debug,
198            Eq,
199            Hash,
200            Ord,
201            PartialEq,
202            PartialOrd,
203            strum::AsRefStr,
204            strum::Display,
205            strum::EnumCount,
206            strum::EnumIs,
207            strum::EnumIter,
208            strum::EnumString,
209            strum::VariantNames,
210        )]
211        #[cfg_attr(
212            feature = "serde",
213            derive(serde::Deserialize, serde::Serialize,),
214            serde(rename_all = "snake_case", untagged),
215        )]
216        #[repr(C)]
217        #[strum(serialize_all = "snake_case")]
218        pub enum $group {
219            $(
220                $variant($op),
221            )*
222        }
223
224        impl $group {
225            $(
226                pub fn $method() -> Self {
227                    Self::$variant($op::new())
228                }
229            )*
230
231            pub fn name(&self) -> &str {
232                self.as_ref()
233            }
234
235
236            pub fn op(self) -> Box<dyn $crate::ops::Operator> {
237                match self {
238                    $(
239                        $group::$variant(op) => Box::new(op),
240                    )*
241                }
242            }
243        }
244
245        impl $crate::ops::Operand for $group {
246            type Kind = $crate::ops::$kind;
247
248            fn name(&self) -> &str {
249                self.as_ref()
250            }
251
252            fn optype(&self) -> Self::Kind {
253                $crate::ops::$kind
254            }
255        }
256    };
257}
258
259macro_rules! operation {
260    ($($op:ident<$kind:ident>),*) => {
261        $(
262            operation!(@base $op<$kind>.$op);
263        )*
264    };
265    ($($op:ident<$kind:ident>.$name:ident),*) => {
266        $(
267            operation!(@base $op<$kind>.$name);
268        )*
269    };
270    (@base $op:ident<$kind:ident>.$name:ident) => {
271        #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
272        #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize,))]
273        pub struct $op;
274
275        impl $op {
276            pub fn new() -> Self {
277                Self
278            }
279
280            pub fn name(&self) -> &str {
281                stringify!($name)
282            }
283        }
284
285        operation!(@impl $op<$kind>.$name);
286    };
287    (@impl $op:ident<$kind:ident>.$name:ident) => {
288        impl core::fmt::Display for $op {
289            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
290                write!(f, "{}", self.name())
291            }
292        }
293
294        impl $crate::ops::Operand for $op {
295            type Kind = $crate::ops::$kind;
296
297            fn name(&self) -> &str {
298                self.name()
299            }
300
301            fn optype(&self) -> Self::Kind {
302                $crate::ops::$kind
303            }
304        }
305    };
306
307}
308
309/* *************** Samples *************** */
310struct U(usize);
311
312impl_binary!(impl core::ops::Add.add(U, U) -> U { | lhs: U, rhs: U | U(lhs.0 + rhs.0) });
313impl_binary!(
314    U, U, U: [
315        // (core::ops::Add, add, | lhs: U, rhs: U | U(lhs.0 + rhs.0)),
316        (core::ops::Div.div, | lhs: U, rhs: U | U(lhs.0 / rhs.0)),
317        (core::ops::Mul.mul, | lhs: U, rhs: U | U(lhs.0 * rhs.0)),
318        (core::ops::Sub.sub, | lhs: U, rhs: U | U(lhs.0 - rhs.0))
319    ]
320);