petgraph/visit/macros.rs
1/// Define a trait as usual, and a macro that can be used to instantiate
2/// implementations of it.
3///
4/// There *must* be section markers in the trait definition:
5/// @section type for associated types
6/// @section self for methods
7/// @section nodelegate for arbitrary tail that is not forwarded.
8macro_rules! trait_template {
9 ($(#[$doc:meta])* pub trait $name:ident $($methods:tt)*) => {
10 macro_rules! $name {
11 ($m:ident $extra:tt) => {
12 $m! {
13 $extra
14 pub trait $name $($methods)*
15 }
16 }
17 }
18
19 remove_sections! { []
20 $(#[$doc])*
21 pub trait $name $($methods)*
22
23 // This is where the trait definition is reproduced by the macro.
24 // It makes the source links point to this place!
25 //
26 // I'm sorry, you'll have to find the source by looking at the
27 // source of the module the trait is defined in.
28 //
29 // We use this nifty macro so that we can automatically generate
30 // delegation trait impls and implement the graph traits for more
31 // types and combinators.
32 }
33 }
34}
35
36macro_rules! remove_sections_inner {
37 ([$($stack:tt)*]) => {
38 $($stack)*
39 };
40 // escape the following tt
41 ([$($stack:tt)*] @escape $_x:tt $($t:tt)*) => {
42 remove_sections_inner!([$($stack)*] $($t)*);
43 };
44 ([$($stack:tt)*] @section $x:ident $($t:tt)*) => {
45 remove_sections_inner!([$($stack)*] $($t)*);
46 };
47 ([$($stack:tt)*] $t:tt $($tail:tt)*) => {
48 remove_sections_inner!([$($stack)* $t] $($tail)*);
49 };
50}
51
52// This is the outer layer, just find the { } of the actual trait definition
53// recurse once into { }, but not more.
54macro_rules! remove_sections {
55 ([$($stack:tt)*]) => {
56 $($stack)*
57 };
58 ([$($stack:tt)*] { $($tail:tt)* }) => {
59 $($stack)* {
60 remove_sections_inner!([] $($tail)*);
61 }
62 };
63 ([$($stack:tt)*] $t:tt $($tail:tt)*) => {
64 remove_sections!([$($stack)* $t] $($tail)*);
65 };
66}
67
68macro_rules! deref {
69 ($e:expr) => {
70 *$e
71 };
72}
73macro_rules! deref_twice {
74 ($e:expr) => {
75 **$e
76 };
77}
78
79/// Implement a trait by delegation. By default as if we are delegating
80/// from &G to G.
81macro_rules! delegate_impl {
82 ([] $($rest:tt)*) => {
83 delegate_impl! { [['a, G], G, &'a G, deref] $($rest)* }
84 };
85 ([[$($param:tt)*], $self_type:ident, $self_wrap:ty, $self_map:ident]
86 pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* {
87
88 // "Escaped" associated types. Stripped before making the `trait`
89 // itself, but forwarded when delegating impls.
90 $(
91 @escape [type $assoc_name_ext:ident]
92 // Associated types. Forwarded.
93 )*
94 $(
95 @section type
96 $(
97 $(#[$_assoc_attr:meta])*
98 type $assoc_name:ident $(: $assoc_bound:ty)*;
99 )+
100 )*
101 // Methods. Forwarded. Using $self_map!(self) around the self argument.
102 // Methods must use receiver `self` or explicit type like `self: &Self`
103 // &self and &mut self are _not_ supported.
104 $(
105 @section self
106 $(
107 $(#[$_method_attr:meta])*
108 fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) $(-> $mret:ty)?;
109 )+
110 )*
111 // Arbitrary tail that is ignored when forwarding.
112 $(
113 @section nodelegate
114 $($tail:tt)*
115 )*
116 }) => {
117 impl<$($param)*> $name for $self_wrap where $self_type: $name {
118 $(
119 $(
120 type $assoc_name = $self_type::$assoc_name;
121 )*
122 )*
123 $(
124 type $assoc_name_ext = $self_type::$assoc_name_ext;
125 )*
126 $(
127 $(
128 fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) $(-> $mret)? {
129 $self_map!(self).$method_name($($marg),*)
130 }
131 )*
132 )*
133 }
134 }
135}