src/metaprogramming.rs

branch
dev
changeset 57
1b3b1687b9ed
child 59
9226980e45a7
equal deleted inserted replaced
56:5e3c1874797d 57:1b3b1687b9ed
1 /*!
2 Metaprogramming tools
3 */
4
5 /// Reference `x` if so indicated by the first parameter.
6 /// Typically to be used from another macro. See the implementation of
7 /// [power][crate::vectorspace::powerspace] and [product spaces][crate::vectorspace::productspace].
8 ///
9 /// ```ignore
10 /// maybe_ref!(ref, V) // ➡ &V
11 /// maybe_ref!(noref, V) // ➡ V
12 /// ```
13 #[macro_export]
14 macro_rules! maybe_ref {
15 (ref, $x:expr) => { &$x };
16 (noref, $x:expr) => { $x };
17 (ref, $x:ty) => { &$x };
18 (noref, $x:ty) => { $x };
19 }
20
21 /// Choose `a` if first argument is the literal `ref`, otherwise `b`.
22 #[macro_export]
23 macro_rules! ifref {
24 (noref, $a:expr, $b:expr) => { $b };
25 (ref, $a:expr, $b:expr) => { $a };
26 }
27
28
29 /// Annotate `x` with a lifetime if the first parameter
30 /// Typically to be used from another macro. See the implementation of
31 /// [power][crate::vectorspace::powerspace] and [product spaces][crate::vectorspace::productspace].
32 ///
33 /// ```ignore
34 /// maybe_ref!(ref, &'a V) // ➡ &'a V
35 /// maybe_ref!(noref, &'a V) // ➡ V
36 /// ```
37 #[macro_export]
38 macro_rules! maybe_lifetime {
39 (ref, $x:ty) => { $x };
40 (noref, &$lt:lifetime $x:ty) => { $x };
41 (noref, &$x:ty) => { $x };
42 }
43
44 /// Use as
45 /// ```ignore
46 /// impl_vectorspace_ops!(impl_binop, impl_assignop, impl_scalarop, impl_scalar_assignop, impl_unaryop);
47 /// ```
48 /// with `impl_binop`, `impl_assignop`, `impl_scalarop`, and `impl_unaryop` macros provided.
49 /// For example usage see the [power][crate::vectorspace::powerspace] and
50 /// [product spaces][crate::vectorspace::productspace] implementations.
51 #[macro_export]
52 macro_rules! impl_vectorspace_ops {
53 ($impl_binop:ident, $impl_assignop:ident, $impl_scalarop:ident, $impl_scalarlhs_op:ident,
54 $impl_scalar_assignop:ident, $impl_unaryop:ident) => {
55 impl_vectorspace_ops!($impl_binop, $impl_assignop, $impl_scalarop, $impl_scalarlhs_op,
56 $impl_scalar_assignop, $impl_unaryop,
57 (f32, f64,
58 num::complex::Complex<f32>,
59 num::complex::Complex<f64>));
60 };
61 ($impl_binop:ident, $impl_assignop:ident, $impl_scalarop:ident, $impl_scalarlhs_op:ident,
62 $impl_scalar_assignop:ident, $impl_unaryop:ident, ($($field:ty),+)) => {
63 impl_vectorspace_ops!(@binary, $impl_binop, Add, add);
64 impl_vectorspace_ops!(@binary, $impl_binop, Sub, sub);
65 impl_vectorspace_ops!(@assign, $impl_assignop, AddAssign, add_assign);
66 impl_vectorspace_ops!(@assign, $impl_assignop, SubAssign, sub_assign);
67 impl_vectorspace_ops!(@scalar, $impl_scalarop, Mul, mul);
68 impl_vectorspace_ops!(@scalar, $impl_scalarop, Div, div);
69 // Compiler overflow
70 // $(
71 // impl_vectorspace_ops!(@scalar_lhs, $impl_scalarlhs_op, Mul, mul, $field);
72 // )*
73 impl_vectorspace_ops!(@scalar_assign, $impl_scalar_assignop, MulAssign, mul_assign);
74 impl_vectorspace_ops!(@scalar_assign, $impl_scalar_assignop, DivAssign, div_assign);
75 impl_vectorspace_ops!(@unary, $impl_unaryop, Neg, neg);
76 };
77 (@binary, $impl:ident, $trait : ident, $fn : ident) => {
78 $impl!($trait, $fn, ref, ref);
79 $impl!($trait, $fn, ref, noref);
80 $impl!($trait, $fn, noref, ref);
81 $impl!($trait, $fn, noref, noref);
82 };
83 (@assign, $impl:ident, $trait : ident, $fn :ident) => {
84 $impl!($trait, $fn, ref);
85 $impl!($trait, $fn, noref);
86 };
87 (@scalar, $impl:ident, $trait : ident, $fn :ident) => {
88 $impl!($trait, $fn, ref);
89 $impl!($trait, $fn, noref);
90 };
91 (@scalar_lhs, $impl:ident, $trait : ident, $fn : ident, $field: ty) => {
92 // These operators need workarounds
93 $impl!($trait, $fn, ref, $field);
94 $impl!($trait, $fn, noref, $field);
95 };
96 (@scalar_assign, $impl:ident, $trait : ident, $fn :ident) => {
97 $impl!($trait, $fn);
98 };
99 (@unary, $impl:ident, $trait : ident, $fn :ident) => {
100 $impl!($trait, $fn, ref);
101 $impl!($trait, $fn, noref);
102 };
103 }

mercurial