1#![allow(unused_macros)]
6
7#[macro_export]
9macro_rules! nested {
10 ($($i:ident in $iter:expr)=>* => $body:block ) => {
11 nested!(@loop $body, $($i in $iter),*);
12 };
13 (@loop $body:block, $i:ident in $iter:expr) => {
15 for $i in $iter $body
16 };
17 (@loop $body:block, $i:ident in $iter:expr) => {
19 for $i in $iter.into_iter() $body
20 };
21 (@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
309struct 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::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);