Skip to main content

typr_core/components/context/
graph.rs

1use crate::components::context::Context;
2use crate::components::r#type::type_system::TypeSystem;
3use serde::Deserialize;
4use serde::Serialize;
5use std::collections::HashMap;
6use std::collections::HashSet;
7use std::fmt::Debug;
8use std::ops::Add;
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(bound = "T: Serialize + for<'a> Deserialize<'a>")]
12pub struct Graph<T: TypeSystem> {
13    memory: HashSet<T>,
14    root: Node<T>,
15    #[serde(skip)]
16    subtype_cache: HashMap<(T, T), bool>,
17}
18
19impl<T: TypeSystem> Default for Graph<T> {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl<T: TypeSystem> Graph<T> {
26    pub fn new() -> Self {
27        Graph {
28            memory: HashSet::new(),
29            root: Node::new(),
30            subtype_cache: HashMap::new(),
31        }
32    }
33
34    /// Vérifie si le résultat de sous-typage est en cache
35    pub fn check_subtype_cache(&self, t1: &T, t2: &T) -> Option<bool> {
36        self.subtype_cache.get(&(t1.clone(), t2.clone())).copied()
37    }
38
39    /// Enregistre un résultat de sous-typage dans le cache
40    pub fn cache_subtype(self, t1: T, t2: T, result: bool) -> Self {
41        let mut new_cache = self.subtype_cache.clone();
42        new_cache.insert((t1, t2), result);
43        Graph {
44            subtype_cache: new_cache,
45            ..self
46        }
47    }
48
49    pub fn add_type(self, typ: T, context: &Context) -> Self {
50        if self.memory.contains(&typ) {
51            self
52        } else {
53            let new_memory = self
54                .memory
55                .iter()
56                .chain([typ.clone()].iter())
57                .cloned()
58                .collect();
59            let new_root = self.root.add_type(typ.clone(), context);
60            Graph {
61                memory: new_memory,
62                root: new_root,
63                subtype_cache: self.subtype_cache,
64            }
65        }
66    }
67
68    pub fn get_hierarchy(&self) -> String {
69        self.root.get_hierarchy()
70    }
71
72    pub fn get_supertypes(&self, typ: &T, context: &Context) -> Vec<T> {
73        self.root
74            .get_supertypes(typ, context)
75            .iter()
76            .cloned()
77            .collect::<HashSet<_>>()
78            .iter()
79            .cloned()
80            .collect::<Vec<_>>()
81    }
82
83    pub fn get_ordered_supertypes(&self, typ: &T, context: &Context) -> Vec<T> {
84        let raw = self.root.get_supertypes(typ, context);
85        let mut seen = HashSet::new();
86        let mut result = Vec::new();
87        for item in raw {
88            if seen.insert(item.clone()) {
89                result.push(item);
90            }
91        }
92        result
93    }
94
95    pub fn add_types(self, typs: &[T], context: &Context) -> Self {
96        typs.iter()
97            .cloned()
98            .fold(self, |acc, x| acc.add_type(x, context))
99    }
100}
101
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
103#[serde(bound = "T: Serialize + for<'a> Deserialize<'a>")]
104pub struct Node<T: TypeSystem> {
105    value: T,
106    subtypes: Vec<Node<T>>,
107}
108
109impl<T: TypeSystem> From<T> for Node<T> {
110    fn from(val: T) -> Self {
111        Node {
112            value: val,
113            subtypes: vec![],
114        }
115    }
116}
117
118impl<T: TypeSystem> Default for Node<T> {
119    fn default() -> Self {
120        Self::new()
121    }
122}
123
124impl<T: TypeSystem> Node<T> {
125    pub fn new() -> Self {
126        Node {
127            value: T::default(),
128            subtypes: vec![],
129        }
130    }
131
132    pub fn propagate(self, typ: T, context: &Context) -> Self {
133        let graph = Node {
134            value: self.value.clone(),
135            subtypes: self
136                .subtypes
137                .iter()
138                .cloned()
139                .map(|x| x.add_type(typ.clone(), context))
140                .collect(),
141        };
142        if graph == self {
143            self.add_subtype(typ)
144        } else {
145            graph
146        }
147    }
148
149    pub fn add_subtype(self, typ: T) -> Self {
150        Node {
151            value: self.value,
152            subtypes: self
153                .subtypes
154                .iter()
155                .chain([Node::from(typ)].iter())
156                .cloned()
157                .collect(),
158        }
159    }
160
161    pub fn set_subtypes(self, subtypes: Vec<Node<T>>) -> Self {
162        Node {
163            value: self.value,
164            subtypes,
165        }
166    }
167
168    fn switch_if_reverse_subtype(self, typ: T, context: &Context) -> Self {
169        if self.value.is_subtype_raw(&typ, context) {
170            Node {
171                value: typ,
172                subtypes: vec![Node::from(self.value).set_subtypes(self.subtypes)],
173            }
174        } else {
175            self
176        }
177    }
178
179    pub fn add_type(self, typ: T, context: &Context) -> Self {
180        if self.value == typ {
181            self
182        } else {
183            match (
184                typ.is_subtype_raw(&self.value, context),
185                self.subtypes.len(),
186            ) {
187                (true, 0) => self.add_subtype(typ),
188                (true, _) => self.propagate(typ, context),
189                _ => self.switch_if_reverse_subtype(typ, context),
190            }
191        }
192    }
193
194    pub fn get_supertypes(&self, target_type: &T, context: &Context) -> Vec<T> {
195        if target_type == &self.value {
196            vec![]
197        } else if target_type.is_subtype_raw(&self.value, context) {
198            self.subtypes
199                .iter()
200                .flat_map(|x| x.get_supertypes(target_type, context))
201                .chain([self.value.clone()].iter().cloned())
202                .collect::<Vec<T>>()
203        } else {
204            vec![]
205        }
206    }
207
208    pub fn get_hierarchy(&self) -> String {
209        self.get_hierarchy_helper(0)
210    }
211
212    fn tabulation_from_level(level: i32) -> String {
213        (0..level).map(|_| "  ").collect::<Vec<_>>().join("")
214    }
215
216    pub fn get_hierarchy_helper(&self, level: i32) -> String {
217        let tab = Node::<T>::tabulation_from_level(level);
218        let children = self
219            .subtypes
220            .iter()
221            .map(|x| x.get_hierarchy_helper(level + 1))
222            .collect::<Vec<_>>()
223            .join("\n");
224        tab + &self.value.pretty() + "\n" + &children
225    }
226}
227
228use std::fmt;
229impl<T: TypeSystem> fmt::Display for Node<T> {
230    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231        write!(f, "{}", self.get_hierarchy())
232    }
233}
234
235impl<T: TypeSystem> Add for Graph<T> {
236    type Output = Self;
237
238    fn add(self, other: Self) -> Self {
239        let context = Context::default(); // Or apply a parameter if necessary
240        let merged = other
241            .memory
242            .iter()
243            .cloned()
244            .fold(self.clone(), |acc, typ| acc.add_type(typ, &context));
245        // Fusionner les caches de sous-typage
246        let mut new_cache = self.subtype_cache;
247        new_cache.extend(other.subtype_cache);
248        Graph {
249            subtype_cache: new_cache,
250            ..merged
251        }
252    }
253}