typr_core/components/context/
graph.rs1use crate::components::context::Context;
2use crate::components::r#type::type_system::TypeSystem;
3use std::collections::HashMap;
4use std::collections::HashSet;
5use std::fmt::Debug;
6use std::ops::Add;
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct Graph<T: TypeSystem> {
10 memory: HashSet<T>,
11 root: Node<T>,
12 subtype_cache: HashMap<(T, T), bool>,
13}
14
15impl<T: TypeSystem> Graph<T> {
16 pub fn new() -> Self {
17 Graph {
18 memory: HashSet::new(),
19 root: Node::new(),
20 subtype_cache: HashMap::new(),
21 }
22 }
23
24 pub fn check_subtype_cache(&self, t1: &T, t2: &T) -> Option<bool> {
26 self.subtype_cache.get(&(t1.clone(), t2.clone())).copied()
27 }
28
29 pub fn cache_subtype(self, t1: T, t2: T, result: bool) -> Self {
31 let mut new_cache = self.subtype_cache.clone();
32 new_cache.insert((t1, t2), result);
33 Graph {
34 subtype_cache: new_cache,
35 ..self
36 }
37 }
38
39 pub fn add_type(self, typ: T, context: &Context) -> Self {
40 if self.memory.contains(&typ) {
41 self
42 } else {
43 let new_memory = self
44 .memory
45 .iter()
46 .chain([typ.clone()].iter())
47 .cloned()
48 .collect();
49 let new_root = self.root.add_type(typ.clone(), context);
50 Graph {
51 memory: new_memory,
52 root: new_root,
53 subtype_cache: self.subtype_cache,
54 }
55 }
56 }
57
58 pub fn add_type_trace(self, typ: T, context: &Context) -> Self {
59 if self.memory.contains(&typ) {
60 self
61 } else {
62 Graph {
63 memory: self
64 .memory
65 .iter()
66 .chain([typ.clone()].iter())
67 .cloned()
68 .collect(),
69 root: self.root.add_type_trace(typ, context),
70 subtype_cache: self.subtype_cache,
71 }
72 }
73 }
74
75 pub fn get_hierarchy(&self) -> String {
76 self.root.get_hierarchy()
77 }
78
79 pub fn get_type_list(&self) -> String {
80 format!(
81 "{}",
82 T::prettys(&self.memory.iter().cloned().collect::<Vec<_>>())
83 )
84 }
85
86 pub fn print_hierarchy(&self) {
87 eprintln!("{}", self.get_hierarchy());
88 }
89
90 pub fn get_supertypes(&self, typ: &T, context: &Context) -> Vec<T> {
91 self.root
92 .get_supertypes(typ, context)
93 .iter()
94 .cloned()
95 .collect::<HashSet<_>>()
96 .iter()
97 .cloned()
98 .collect::<Vec<_>>()
99 }
100
101 pub fn get_supertypes_trace(&self, typ: &T, context: &Context) -> Vec<T> {
102 self.root
103 .get_supertypes_trace(typ, context)
104 .iter()
105 .cloned()
106 .collect::<HashSet<_>>()
107 .iter()
108 .cloned()
109 .collect::<Vec<_>>()
110 }
111
112 pub fn add_types(self, typs: &[T], context: &Context) -> Self {
113 typs.iter()
114 .cloned()
115 .fold(self, |acc, x| acc.add_type(x, context))
116 }
117}
118
119#[derive(Debug, Clone, PartialEq)]
120pub struct Node<T: TypeSystem> {
121 value: T,
122 subtypes: Vec<Node<T>>,
123}
124
125impl<T: TypeSystem> From<T> for Node<T> {
126 fn from(val: T) -> Self {
127 Node {
128 value: val,
129 subtypes: vec![],
130 }
131 }
132}
133
134impl<T: TypeSystem> Node<T> {
135 pub fn new() -> Self {
136 Node {
137 value: T::default(),
138 subtypes: vec![],
139 }
140 }
141
142 pub fn propagate(self, typ: T, context: &Context) -> Self {
143 let graph = Node {
144 value: self.value.clone(),
145 subtypes: self
146 .subtypes
147 .iter()
148 .cloned()
149 .map(|x| x.add_type(typ.clone(), context))
150 .collect(),
151 };
152 if graph == self {
153 self.add_subtype(typ)
154 } else {
155 graph
156 }
157 }
158
159 pub fn propagate_trace(self, typ: T, context: &Context) -> Self {
160 let graph = Node {
161 value: self.value.clone(),
162 subtypes: self
163 .subtypes
164 .iter()
165 .cloned()
166 .map(|x| x.add_type(typ.clone(), context))
167 .collect(),
168 };
169 if graph == self {
170 eprintln!(
171 "add {} to one of the children of {}",
172 typ.pretty(),
173 self.value.pretty()
174 );
175 self.add_subtype(typ)
176 } else {
177 eprintln!(
178 "{} is not a subtype of {}'s subtypes: {}",
179 typ.pretty(),
180 self.value.pretty(),
181 self.show_subtypes()
182 );
183 graph
184 }
185 }
186
187 pub fn show_subtypes(&self) -> String {
188 "[".to_string()
189 + &self
190 .subtypes
191 .iter()
192 .map(|typ| format!("{}", typ.value.pretty()))
193 .collect::<Vec<_>>()
194 .join(",")
195 + "]"
196 }
197
198 pub fn add_subtype(self, typ: T) -> Self {
199 Node {
200 value: self.value,
201 subtypes: self
202 .subtypes
203 .iter()
204 .chain([Node::from(typ)].iter())
205 .cloned()
206 .collect(),
207 }
208 }
209
210 pub fn set_subtypes(self, subtypes: Vec<Node<T>>) -> Self {
211 Node {
212 value: self.value,
213 subtypes,
214 }
215 }
216
217 fn switch_if_reverse_subtype(self, typ: T, context: &Context) -> Self {
218 if self.value.is_subtype_raw(&typ, context) {
219 Node {
220 value: typ,
221 subtypes: vec![Node::from(self.value).set_subtypes(self.subtypes)],
222 }
223 } else {
224 self
225 }
226 }
227
228 fn switch_if_reverse_subtype_trace(self, typ: T, context: &Context) -> Self {
229 if self.value.is_subtype_raw(&typ, context) {
230 eprintln!(
231 "{} is a subtype of the entry {}",
232 self.value.pretty(),
233 typ.pretty()
234 );
235 Node {
236 value: typ,
237 subtypes: vec![Node::from(self.value).set_subtypes(self.subtypes)],
238 }
239 } else {
240 eprintln!(
241 "{} is not a subtype of {} abort this branch",
242 typ.pretty(),
243 self.value.pretty()
244 );
245 self
246 }
247 }
248
249 pub fn add_type(self, typ: T, context: &Context) -> Self {
250 if self.value == typ {
251 self
252 } else {
253 match (
254 typ.is_subtype_raw(&self.value, context),
255 self.subtypes.len(),
256 ) {
257 (true, 0) => self.add_subtype(typ),
258 (true, _) => self.propagate(typ, context),
259 _ => self.switch_if_reverse_subtype(typ, context),
260 }
261 }
262 }
263
264 pub fn add_type_trace(self, typ: T, context: &Context) -> Self {
265 match (
266 typ.is_subtype_raw(&self.value, context),
267 self.subtypes.len(),
268 ) {
269 (true, 0) => {
270 eprintln!(
271 "{} is a subtype of the leaf {}",
272 typ.pretty(),
273 self.value.pretty()
274 );
275 self.add_subtype(typ)
276 }
277 (true, _) => {
278 eprintln!(
279 "{} is a subtype of the node {}",
280 typ.pretty(),
281 self.value.pretty()
282 );
283 self.propagate_trace(typ, context)
284 }
285 _ => self.switch_if_reverse_subtype_trace(typ, context),
286 }
287 }
288
289 pub fn get_supertypes(&self, target_type: &T, context: &Context) -> Vec<T> {
290 if target_type == &self.value {
291 vec![]
292 } else if target_type.is_subtype_raw(&self.value, context) {
293 self.subtypes
294 .iter()
295 .flat_map(|x| x.get_supertypes(target_type, context))
296 .chain([self.value.clone()].iter().cloned())
297 .collect::<Vec<T>>()
298 } else {
299 vec![]
300 }
301 }
302
303 pub fn get_supertypes_trace(&self, target_type: &T, context: &Context) -> Vec<T> {
304 if target_type == &self.value {
305 eprintln!("found the root of {} we backtrack", target_type.pretty());
306 vec![]
307 } else if target_type.is_subtype_raw(&self.value, context) {
308 eprintln!(
309 "{} is subtype of {} we check the subtypes",
310 target_type.pretty(),
311 self.value.pretty()
312 );
313 self.subtypes
314 .iter()
315 .flat_map(|x| x.get_supertypes_trace(target_type, context))
316 .chain([self.value.clone()].iter().cloned())
317 .collect::<Vec<T>>()
318 } else {
319 eprintln!(
320 "{} is not subtype of {} ABORT this branch",
321 target_type.pretty(),
322 self.value.pretty()
323 );
324 vec![]
325 }
326 }
327
328 pub fn get_hierarchy(&self) -> String {
329 self.get_hierarchy_helper(0)
330 }
331
332 fn tabulation_from_level(level: i32) -> String {
333 (0..level)
334 .into_iter()
335 .map(|_| " ")
336 .collect::<Vec<_>>()
337 .join("")
338 }
339
340 pub fn get_hierarchy_helper(&self, level: i32) -> String {
341 let tab = Node::<T>::tabulation_from_level(level);
342 let children = self
343 .subtypes
344 .iter()
345 .map(|x| x.get_hierarchy_helper(level + 1))
346 .collect::<Vec<_>>()
347 .join("\n");
348 tab + &self.value.pretty() + "\n" + &children
349 }
350}
351
352use std::fmt;
353impl<T: TypeSystem> fmt::Display for Node<T> {
354 fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 write!(f, "{}", self.get_hierarchy())
356 }
357}
358
359impl<T: TypeSystem> Add for Graph<T> {
360 type Output = Self;
361
362 fn add(self, other: Self) -> Self {
363 let context = Context::default(); let merged = other
365 .memory
366 .iter()
367 .cloned()
368 .fold(self.clone(), |acc, typ| acc.add_type(typ, &context));
369 let mut new_cache = self.subtype_cache;
371 new_cache.extend(other.subtype_cache);
372 Graph {
373 subtype_cache: new_cache,
374 ..merged
375 }
376 }
377}