1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::collections::HashMap;
use std::hash::Hash;

use derive_more::{From, TryInto};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "size-of")]
use size_of::SizeOf;

use kodept_core::structure::rlt;

use crate::graph::NodeId;
use crate::traits::Identifiable;
use crate::*;

make_ast_node_adaptor!(ASTFamily, lifetimes: [], NodeId, configs: [
    derive(Hash, PartialEq, Eq, From, Debug, TryInto),
    cfg_attr(feature = "size-of", derive(SizeOf)),
    cfg_attr(feature = "serde", derive(Serialize, Deserialize)),
    cfg_attr(feature = "serde", serde(tag = "owner", content = "id"))
]);

#[derive(Clone, From, TryInto, Debug)]
#[cfg_attr(feature = "size-of", derive(SizeOf))]
pub enum RLTFamily<'n> {
    File(&'n rlt::File),
    Module(&'n rlt::Module),
    Struct(&'n rlt::Struct),
    Enum(&'n rlt::Enum),
    Type(&'n rlt::Type),
    TypeName(&'n rlt::new_types::TypeName),
    TypedParameter(&'n rlt::TypedParameter),
    UntypedParameter(&'n rlt::UntypedParameter),
    Variable(&'n rlt::Variable),
    InitializedVariable(&'n rlt::InitializedVariable),
    BodiedFunction(&'n rlt::BodiedFunction),
    Body(&'n rlt::Body),
    BlockLevel(&'n rlt::BlockLevelNode),
    ExpressionBlock(&'n rlt::ExpressionBlock),
    Operation(&'n rlt::Operation),
    Application(&'n rlt::Application),
    Expression(&'n rlt::Expression),
    Term(&'n rlt::Term),
    Reference(&'n rlt::Reference),
    Literal(&'n rlt::Literal),
    CodeFlow(&'n rlt::CodeFlow),
    If(&'n rlt::IfExpr),
    Elif(&'n rlt::ElifExpr),
    Else(&'n rlt::ElseExpr),
}

#[derive(Default, Debug)]
#[cfg_attr(feature = "size-of", derive(SizeOf))]
pub struct RLTAccessor<'n> {
    links: HashMap<ASTFamily, RLTFamily<'n>>,
}

impl<'n> RLTAccessor<'n> {
    pub fn access<A, B>(&self, node: &A) -> Option<&'n B>
    where
        NodeId<A>: Into<ASTFamily>,
        A: Identifiable + 'static,
        &'n B: TryFrom<RLTFamily<'n>> + 'n,
    {
        self.links
            .get(&node.get_id().clone().into())
            .and_then(|it| it.clone().try_into().ok())
    }

    pub fn access_unknown<A>(&self, node: &A) -> Option<&RLTFamily>
    where
        NodeId<A>: Into<ASTFamily>,
        A: Identifiable + 'static,
    {
        self.links.get(&node.get_id().clone().into())
    }

    pub fn save_existing<A, B>(&mut self, new: &A, existing: &B)
    where
        B: Identifiable + 'static,
        NodeId<B>: Into<ASTFamily>,
        A: Identifiable + 'static,
        NodeId<A>: Into<ASTFamily>,
    {
        match self.links.get(&existing.get_id().clone().into()) {
            None => None,
            Some(x) => self.links.insert(new.get_id().clone().into(), x.clone()),
        };
    }

    pub fn keys(&self) -> Vec<&ASTFamily> {
        self.links.keys().collect()
    }

    pub fn save<A, B>(&mut self, key: NodeId<A>, value: B)
    where
        B: Into<RLTFamily<'n>>,
        NodeId<A>: Into<ASTFamily>,
    {
        self.links.insert(key.into(), value.into());
    }
}

impl<'a, 'b> From<&'a RLTFamily<'b>> for RLTFamily<'b> {
    fn from(value: &'a RLTFamily<'b>) -> Self {
        value.clone()
    }
}