kodept_ast/
macros.rs

1pub mod implementation {
2    #[macro_export]
3    macro_rules! node_sub_enum {
4        ($(#[$config:meta])* $vis:vis enum $wrapper:ident {
5            $($name:ident($modifier:tt $($t:tt)?)$(,)?)*
6        }) => {$crate::paste! {
7            #[derive($crate::RefCast)]
8            #[repr(transparent)]
9            $(
10            #[$config]
11            )*
12            $vis struct $wrapper($crate::graph::AnyNode);
13
14            $vis enum [<$wrapper Enum>]<'lt> {
15                $(
16                    $name(&'lt $crate::ty!($modifier $($t)?)),
17                )*
18            }
19
20            $vis enum [<$wrapper EnumMut>]<'lt> {
21                $(
22                    $name(&'lt mut $crate::ty!($modifier $($t)?)),
23                )*
24            }
25
26            impl $crate::graph::SubEnum for $wrapper {
27                const VARIANTS: &'static [$crate::graph::AnyNodeD] =
28                    $crate::concat_slices!([$crate::graph::AnyNodeD]: $($crate::node_sub_enum_entry!($modifier $($t)?), )*);
29            }
30
31            $(impl From<$crate::ty!($modifier $($t)?)> for $wrapper {
32                #[inline]
33                fn from(value: $crate::ty!($modifier $($t)?)) -> Self {
34                    Self(value.into())
35                }
36            })*
37
38            impl From<$wrapper> for $crate::graph::AnyNode {
39                #[inline]
40                fn from(value: $wrapper) -> Self {
41                    value.0
42                }
43            }
44            
45            impl<'a> TryFrom<&'a $crate::graph::AnyNode> for &'a $wrapper {
46                type Error = $crate::utils::Skip<std::convert::Infallible>;
47                #[inline]
48                fn try_from(value: &'a $crate::graph::AnyNode) -> Result<Self, Self::Error> {
49                    if <$wrapper as $crate::graph::SubEnum>::contains(value) {
50                        Ok(<$wrapper as $crate::RefCast>::ref_cast(value))
51                    } else {
52                        Err($crate::utils::Skip::Skipped)
53                    }
54                }
55            }
56            
57            impl<'a> TryFrom<&'a mut $crate::graph::AnyNode> for &'a mut $wrapper {
58                type Error = $crate::utils::Skip<std::convert::Infallible>;
59                #[inline]
60                fn try_from(value: &'a mut $crate::graph::AnyNode) -> Result<Self, Self::Error> {
61                    if <$wrapper as $crate::graph::SubEnum>::contains(value) {
62                        Ok(<$wrapper as $crate::RefCast>::ref_cast_mut(value))
63                    } else {
64                        Err($crate::utils::Skip::Skipped)
65                    }
66                }
67            }
68
69            impl $crate::traits::Identifiable for $wrapper {
70                #[inline]
71                fn get_id(&self) -> $crate::graph::NodeId<Self> {
72                    self.0.get_id().coerce()
73                }
74            }
75            
76            impl<'lt> $crate::traits::AsEnum for &'lt $wrapper {
77                type Enum = [<$wrapper Enum>]<'lt>;
78                
79                #[inline]
80                fn as_enum(self) -> Self::Enum {
81                    $(
82                        $crate::node_sub_enum_match_entry!(self.0 => $name, $modifier $($t)?);
83                    )*
84                    unreachable!()
85                }
86            }
87            
88            impl<'lt> $crate::traits::AsEnum for &'lt mut $wrapper {
89                type Enum = [<$wrapper EnumMut>]<'lt>;
90                
91                #[inline]
92                fn as_enum(self) -> Self::Enum {
93                    $(
94                        $crate::node_sub_enum_match_entry!(self.0 => mut $name, $modifier $($t)?);
95                    )*
96                    unreachable!()
97                }
98            }
99        }};
100    }
101    
102    #[macro_export]
103    macro_rules! node_sub_enum_match_entry {
104        ($this:expr => $name:ident, $t:ident) => { 
105            if let $crate::graph::AnyNode::$t(ref x) = $this {
106                return Self::Enum::$name(x);
107            } 
108        };
109        ($this:expr => mut $name:ident, $t:ident) => { 
110            if let $crate::graph::AnyNode::$t(ref mut x) = $this {
111                return Self::Enum::$name(x);
112            } 
113        };
114        ($this:expr => $name:ident, forward $t:ty) => { 
115            if <$t as $crate::graph::SubEnum>::contains(&$this) {
116                return Self::Enum::$name(<$t as $crate::RefCast>::ref_cast(&$this))
117            }
118        };
119        ($this:expr => mut $name:ident, forward $t:ty) => { 
120            if <$t as $crate::graph::SubEnum>::contains(&$this) {
121                return Self::Enum::$name(<$t as $crate::RefCast>::ref_cast_mut(&mut $this))
122            }
123        };
124    }
125
126    #[macro_export]
127    macro_rules! ty {
128        ($t:ty) => { $t };
129        (forward $t:ty) => { $t };
130    }
131
132    #[macro_export]
133    macro_rules! node_sub_enum_entry {
134        ($t:ident) => { &[$crate::graph::AnyNodeD::$t] };
135        (forward $t:ty) => { <$t as $crate::graph::SubEnum>::VARIANTS };
136    }
137
138    macro_rules! node {
139    ($(#[$config:meta])* $vis:vis struct $name:ident {
140        $($field_vis:vis $field_name:ident: $field_type:ty,)*;
141        $($graph_vis:vis $graph_name:ident: $graph_type:ty$( as $tag:tt)?,)*
142    }) => {
143        #[cfg(feature = "serde")]
144        $(#[$config])*
145        $vis struct $name {
146            id: once_cell_serde::unsync::OnceCell<$crate::graph::NodeId<$name>>,
147            $($field_vis $field_name: $field_type,)*
148        }
149
150        #[cfg(not(feature = "serde"))]
151        $(#[$config])*
152        $vis struct $name {
153            id: std::cell::OnceCell<$crate::graph::NodeId<$name>>,
154            $($field_vis $field_name: $field_type,)*
155        }
156
157        impl $crate::node_properties::Node for $name {}
158
159        impl $name {
160            pub fn uninit($($field_name: $field_type,)*) -> $crate::Uninit<Self> {
161                $crate::Uninit::new(Self {
162                    id: Default::default(),
163                    $(
164                    $field_name,
165                    )*
166                })
167            }
168
169            pub fn into_uninit(self) -> $crate::Uninit<Self> {
170                Self::uninit($(self.$field_name, )*)
171            }
172        }
173
174        impl $crate::graph::Identifiable for $name {
175            fn get_id(&self) -> $crate::graph::NodeId<Self> {
176                self.id.get().copied().expect("Unreachable")
177            }
178
179            fn set_id(&self, value: $crate::graph::NodeId<Self>) {
180                if let Err(_) = self.id.set(value) {
181                    tracing::warn!("Tried to set id twice");
182                }
183            }
184        }
185
186        $crate::with_children! [$name => {
187            $($graph_vis $graph_name: $graph_type $( as $tag)?,)*
188        }];
189    };
190    ($(#[$config:meta])* $vis:vis struct $name:ident;) => {
191        node!($(#[$config])* $vis struct $name {;});
192    }
193}
194
195    pub(crate) use node;
196}