kodept-ast 0.4.1

Simple compiler with dependent types support in mind
Documentation
pub mod implementation {
    #[macro_export]
    macro_rules! node_sub_enum {
        ($(#[$config:meta])* $vis:vis enum $wrapper:ident {
            $($name:ident($modifier:tt $($t:tt)?)$(,)?)*
        }) => {$crate::paste! {
            #[derive($crate::RefCast)]
            #[repr(transparent)]
            $(
            #[$config]
            )*
            $vis struct $wrapper($crate::graph::AnyNode);

            $vis enum [<$wrapper Enum>]<'lt> {
                $(
                    $name(&'lt $crate::ty!($modifier $($t)?)),
                )*
            }

            $vis enum [<$wrapper EnumMut>]<'lt> {
                $(
                    $name(&'lt mut $crate::ty!($modifier $($t)?)),
                )*
            }

            impl $crate::graph::SubEnum for $wrapper {
                const VARIANTS: &'static [$crate::graph::AnyNodeD] =
                    $crate::concat_slices!([$crate::graph::AnyNodeD]: $($crate::node_sub_enum_entry!($modifier $($t)?), )*);
            }

            $(impl From<$crate::ty!($modifier $($t)?)> for $wrapper {
                #[inline]
                fn from(value: $crate::ty!($modifier $($t)?)) -> Self {
                    Self(value.into())
                }
            })*

            impl From<$wrapper> for $crate::graph::AnyNode {
                #[inline]
                fn from(value: $wrapper) -> Self {
                    value.0
                }
            }
            
            impl<'a> TryFrom<&'a $crate::graph::AnyNode> for &'a $wrapper {
                type Error = $crate::utils::Skip<std::convert::Infallible>;
                #[inline]
                fn try_from(value: &'a $crate::graph::AnyNode) -> Result<Self, Self::Error> {
                    if <$wrapper as $crate::graph::SubEnum>::contains(value) {
                        Ok(<$wrapper as $crate::RefCast>::ref_cast(value))
                    } else {
                        Err($crate::utils::Skip::Skipped)
                    }
                }
            }
            
            impl<'a> TryFrom<&'a mut $crate::graph::AnyNode> for &'a mut $wrapper {
                type Error = $crate::utils::Skip<std::convert::Infallible>;
                #[inline]
                fn try_from(value: &'a mut $crate::graph::AnyNode) -> Result<Self, Self::Error> {
                    if <$wrapper as $crate::graph::SubEnum>::contains(value) {
                        Ok(<$wrapper as $crate::RefCast>::ref_cast_mut(value))
                    } else {
                        Err($crate::utils::Skip::Skipped)
                    }
                }
            }

            impl $crate::traits::Identifiable for $wrapper {
                #[inline]
                fn get_id(&self) -> $crate::graph::NodeId<Self> {
                    self.0.get_id().coerce()
                }
            }
            
            impl<'lt> $crate::traits::AsEnum for &'lt $wrapper {
                type Enum = [<$wrapper Enum>]<'lt>;
                
                #[inline]
                fn as_enum(self) -> Self::Enum {
                    $(
                        $crate::node_sub_enum_match_entry!(self.0 => $name, $modifier $($t)?);
                    )*
                    unreachable!()
                }
            }
            
            impl<'lt> $crate::traits::AsEnum for &'lt mut $wrapper {
                type Enum = [<$wrapper EnumMut>]<'lt>;
                
                #[inline]
                fn as_enum(self) -> Self::Enum {
                    $(
                        $crate::node_sub_enum_match_entry!(self.0 => mut $name, $modifier $($t)?);
                    )*
                    unreachable!()
                }
            }
        }};
    }
    
    #[macro_export]
    macro_rules! node_sub_enum_match_entry {
        ($this:expr => $name:ident, $t:ident) => { 
            if let $crate::graph::AnyNode::$t(ref x) = $this {
                return Self::Enum::$name(x);
            } 
        };
        ($this:expr => mut $name:ident, $t:ident) => { 
            if let $crate::graph::AnyNode::$t(ref mut x) = $this {
                return Self::Enum::$name(x);
            } 
        };
        ($this:expr => $name:ident, forward $t:ty) => { 
            if <$t as $crate::graph::SubEnum>::contains(&$this) {
                return Self::Enum::$name(<$t as $crate::RefCast>::ref_cast(&$this))
            }
        };
        ($this:expr => mut $name:ident, forward $t:ty) => { 
            if <$t as $crate::graph::SubEnum>::contains(&$this) {
                return Self::Enum::$name(<$t as $crate::RefCast>::ref_cast_mut(&mut $this))
            }
        };
    }

    #[macro_export]
    macro_rules! ty {
        ($t:ty) => { $t };
        (forward $t:ty) => { $t };
    }

    #[macro_export]
    macro_rules! node_sub_enum_entry {
        ($t:ident) => { &[$crate::graph::AnyNodeD::$t] };
        (forward $t:ty) => { <$t as $crate::graph::SubEnum>::VARIANTS };
    }

    macro_rules! node {
    ($(#[$config:meta])* $vis:vis struct $name:ident {
        $($field_vis:vis $field_name:ident: $field_type:ty,)*;
        $($graph_vis:vis $graph_name:ident: $graph_type:ty$( as $tag:tt)?,)*
    }) => {
        #[cfg(feature = "serde")]
        $(#[$config])*
        $vis struct $name {
            id: once_cell_serde::unsync::OnceCell<$crate::graph::NodeId<$name>>,
            $($field_vis $field_name: $field_type,)*
        }

        #[cfg(not(feature = "serde"))]
        $(#[$config])*
        $vis struct $name {
            id: std::cell::OnceCell<$crate::graph::NodeId<$name>>,
            $($field_vis $field_name: $field_type,)*
        }

        impl $crate::node_properties::Node for $name {}

        impl $name {
            pub fn uninit($($field_name: $field_type,)*) -> $crate::Uninit<Self> {
                $crate::Uninit::new(Self {
                    id: Default::default(),
                    $(
                    $field_name,
                    )*
                })
            }

            pub fn into_uninit(self) -> $crate::Uninit<Self> {
                Self::uninit($(self.$field_name, )*)
            }
        }

        impl $crate::graph::Identifiable for $name {
            fn get_id(&self) -> $crate::graph::NodeId<Self> {
                self.id.get().copied().expect("Unreachable")
            }

            fn set_id(&self, value: $crate::graph::NodeId<Self>) {
                if let Err(_) = self.id.set(value) {
                    tracing::warn!("Tried to set id twice");
                }
            }
        }

        $crate::with_children! [$name => {
            $($graph_vis $graph_name: $graph_type $( as $tag)?,)*
        }];
    };
    ($(#[$config:meta])* $vis:vis struct $name:ident;) => {
        node!($(#[$config])* $vis struct $name {;});
    }
}

    pub(crate) use node;
}