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}