petgraph/visit/
macros.rs

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