kodept_ast/node/
term.rs

1use derive_more::{From};
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4
5use kodept_core::structure::rlt;
6use kodept_core::structure::span::CodeHolder;
7
8use crate::graph::NodeId;
9use crate::graph::{SyntaxTreeBuilder};
10use crate::traits::Linker;
11use crate::traits::PopulateTree;
12use crate::{node, node_sub_enum};
13
14node_sub_enum! {
15    #[derive(Debug, PartialEq)]
16    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17    pub enum Term {
18        Ref(Ref)
19    }
20}
21
22#[derive(Debug, PartialEq, Default)]
23#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
24pub struct ReferenceContext {
25    global: bool,
26    items: Vec<String>
27}
28
29node! {
30    #[derive(Debug, PartialEq)]
31    #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
32    pub struct Ref {
33        pub context: ReferenceContext,
34        pub ident: Identifier,;
35    }
36}
37
38#[derive(Debug, PartialEq, From)]
39#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
40pub enum Identifier {
41    #[from(ignore)]
42    TypeReference { name: String },
43    #[from(ignore)]
44    Reference { name: String },
45}
46
47impl ReferenceContext {
48    pub fn global(items: impl IntoIterator<Item: Into<String>>) -> Self {
49        Self {
50            global: true,
51            items: items.into_iter().map(|it| it.into()).collect(),
52        }
53    }
54    
55    pub fn local(items: impl IntoIterator<Item: Into<String>>) -> Self {
56        Self {
57            global: false,
58            items: items.into_iter().map(|it| it.into()).collect(),
59        }
60    }
61}
62
63impl PopulateTree for rlt::Term {
64    type Output = Term;
65
66    fn convert(
67        &self,
68        builder: &mut SyntaxTreeBuilder,
69        context: &mut (impl Linker + CodeHolder),
70    ) -> NodeId<Self::Output> {
71        match self {
72            rlt::Term::Reference(x) => x.convert(builder, context).cast(),
73            rlt::Term::Contextual(x) => x.inner.convert(builder, context).cast()
74        }
75    }
76}
77
78impl PopulateTree for rlt::ContextualReference {
79    type Output = Ref;
80
81    fn convert(&self, builder: &mut SyntaxTreeBuilder, context: &mut (impl Linker + CodeHolder)) -> NodeId<Self::Output> {
82        let ident = match &self.inner {
83            rlt::Reference::Type(x) => Identifier::TypeReference {
84                name: context.get_chunk_located(x).to_string(),
85            },
86            rlt::Reference::Identifier(x) => Identifier::Reference {
87                name: context.get_chunk_located(x).to_string(),
88            },
89        };
90        let (from_root, refs) = self.context.clone().unfold();
91        let ctx = ReferenceContext {
92            global: from_root.is_some(),
93            items: refs.into_iter().map(|it| match it {
94                rlt::Reference::Type(x) => context.get_chunk_located(&x).to_string(),
95                rlt::Reference::Identifier(_) => panic!("Context built with ordinary references is unsupported")
96            }).collect(),
97        };
98        builder.add_node(Ref::uninit(ctx, ident))
99            .with_rlt(context, self)
100            .id()
101    }
102}
103
104impl PopulateTree for rlt::Reference {
105    type Output = Ref;
106
107    fn convert(
108        &self,
109        builder: &mut SyntaxTreeBuilder,
110        context: &mut (impl Linker + CodeHolder),
111    ) -> NodeId<Self::Output> {
112        let ident = match self {
113            rlt::Reference::Type(x) => Identifier::TypeReference {
114                name: context.get_chunk_located(x).to_string(),
115            },
116            rlt::Reference::Identifier(x) => Identifier::Reference {
117                name: context.get_chunk_located(x).to_string(),
118            },
119        };
120        builder
121            .add_node(Ref::uninit(Default::default(), ident))
122            .with_rlt(context, self)
123            .id()
124    }
125}