kodept_ast/graph/
any_node.rs

1use std::fmt::Debug;
2
3use derive_more::{Display, From, TryInto};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6use strum::{EnumDiscriminants, IntoStaticStr, VariantArray, VariantNames};
7
8use kodept_core::{ConvertibleToMut, ConvertibleToRef};
9
10use crate::*;
11use crate::graph::Identifiable;
12use crate::graph::node_id::GenericNodeId;
13
14#[derive(Debug, PartialEq, From, TryInto, EnumDiscriminants, IntoStaticStr, VariantNames)]
15#[strum_discriminants(derive(VariantArray, Display))]
16#[strum_discriminants(cfg_attr(feature = "serde", derive(Serialize, Deserialize)))]
17#[strum_discriminants(name(AnyNodeD))]
18#[try_into(owned, ref, ref_mut)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20pub enum AnyNode {
21    FileDecl(FileDecl),
22    ModDecl(ModDecl),
23    StructDecl(StructDecl),
24    EnumDecl(EnumDecl),
25    TyParam(TyParam),
26    NonTyParam(NonTyParam),
27    TyName(TyName),
28    VarDecl(VarDecl),
29    InitVar(InitVar),
30    BodyFnDecl(BodyFnDecl),
31    Exprs(Exprs),
32    Appl(Appl),
33    Lambda(Lambda),
34    Ref(Ref),
35    Acc(Acc),
36    NumLit(NumLit),
37    CharLit(CharLit),
38    StrLit(StrLit),
39    TupleLit(TupleLit),
40    IfExpr(IfExpr),
41    ElifExpr(ElifExpr),
42    ElseExpr(ElseExpr),
43    BinExpr(BinExpr),
44    UnExpr(UnExpr),
45    AbstFnDecl(AbstFnDecl),
46    ProdTy(ProdTy),
47}
48
49macro_rules! folding {
50    ($this:expr; $bind:ident => $usage:expr) => {
51        match $this {
52            AnyNode::FileDecl($bind) => $usage,
53            AnyNode::ModDecl($bind) => $usage,
54            AnyNode::StructDecl($bind) => $usage,
55            AnyNode::EnumDecl($bind) => $usage,
56            AnyNode::TyParam($bind) => $usage,
57            AnyNode::NonTyParam($bind) => $usage,
58            AnyNode::TyName($bind) => $usage,
59            AnyNode::VarDecl($bind) => $usage,
60            AnyNode::InitVar($bind) => $usage,
61            AnyNode::BodyFnDecl($bind) => $usage,
62            AnyNode::Exprs($bind) => $usage,
63            AnyNode::Appl($bind) => $usage,
64            AnyNode::Lambda($bind) => $usage,
65            AnyNode::Ref($bind) => $usage,
66            AnyNode::Acc($bind) => $usage,
67            AnyNode::NumLit($bind) => $usage,
68            AnyNode::CharLit($bind) => $usage,
69            AnyNode::StrLit($bind) => $usage,
70            AnyNode::TupleLit($bind) => $usage,
71            AnyNode::IfExpr($bind) => $usage,
72            AnyNode::ElifExpr($bind) => $usage,
73            AnyNode::ElseExpr($bind) => $usage,
74            AnyNode::BinExpr($bind) => $usage,
75            AnyNode::UnExpr($bind) => $usage,
76            AnyNode::AbstFnDecl($bind) => $usage,
77            AnyNode::ProdTy($bind) => $usage,
78        }
79    };
80}
81
82#[deprecated]
83pub type GenericASTNode = AnyNode;
84
85pub trait SubEnum {
86    const VARIANTS: &'static [AnyNodeD];
87
88    #[inline]
89    fn contains(node: &AnyNode) -> bool {
90        Self::VARIANTS.contains(&node.describe())
91    }
92}
93
94impl SubEnum for AnyNode {
95    const VARIANTS: &'static [AnyNodeD] = AnyNodeD::VARIANTS;
96}
97
98impl Identifiable for AnyNode {
99    #[inline]
100    fn get_id(&self) -> GenericNodeId {
101        folding!(self; x => x.get_id().widen())
102    }
103
104    #[inline]
105    fn set_id(&self, value: GenericNodeId) {
106        folding!(self; x => x.set_id(value.narrow()));
107    }
108}
109
110impl AnyNode {
111    #[inline]
112    pub fn describe(&self) -> AnyNodeD {
113        self.into()
114    }
115
116    #[inline]
117    pub fn name(&self) -> &'static str {
118        self.into()
119    }
120
121    pub fn try_cast<T>(&self) -> Option<&T>
122    where
123        AnyNode: ConvertibleToRef<T>,
124    {
125        self.try_as_ref()
126    }
127    
128    pub fn tru_cast_mut<T>(&mut self) -> Option<&mut T> where AnyNode: ConvertibleToMut<T> {
129        self.try_as_mut()
130    }
131}