swamp_types/
cache.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use crate::flags::TypeFlags;
7use crate::supporting_types::{AnonymousStructType, EnumType, NamedStructType, Signature};
8use crate::type_kind::{TypeKind, TypeRef};
9use crate::{Type, TypeId};
10use seq_map::SeqMap;
11use std::rc::Rc;
12
13/// Type cache for interning and deduplicating types in the system
14#[derive(Debug, Clone)]
15pub struct TypeCache {
16    pub(crate) type_id_to_type: SeqMap<TypeId, Rc<Type>>,
17    pub(crate) kind_to_type_id: SeqMap<TypeKind, TypeId>,
18    pub(crate) compatible_cache: SeqMap<(TypeId, TypeId), bool>,
19    pub(crate) next_id: u32,
20}
21
22impl TypeCache {}
23
24impl Default for TypeCache {
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30impl TypeCache {
31    /// Create a new empty type cache
32    #[must_use]
33    pub fn new() -> Self {
34        Self {
35            type_id_to_type: SeqMap::new(),
36            kind_to_type_id: SeqMap::new(),
37            compatible_cache: SeqMap::new(),
38            next_id: 0,
39        }
40    }
41
42    #[must_use]
43    pub const fn type_id_to_type(&self) -> &SeqMap<TypeId, Rc<Type>> {
44        &self.type_id_to_type
45    }
46
47    #[must_use]
48    pub const fn compatible_cache(&self) -> &SeqMap<(TypeId, TypeId), bool> {
49        &self.compatible_cache
50    }
51
52    const fn next_type_id(&mut self) -> TypeId {
53        let id = TypeId(self.next_id);
54        self.next_id += 1;
55        id
56    }
57
58    /// Create a new type instance with the given kind
59    fn create_type(&mut self, kind: TypeKind) -> Rc<Type> {
60        let id = self.next_type_id();
61
62        let flags = TypeFlags::compute_for_type_kind(&kind);
63
64        let type_instance = Type {
65            id,
66            flags,
67            kind: Rc::new(kind),
68        };
69
70        let rc_type = Rc::new(type_instance);
71        self.type_id_to_type.insert(id, Rc::clone(&rc_type));
72
73        rc_type
74    }
75
76    fn create_type_mutable(&mut self, kind: TypeKind, is_mutable: bool) -> Rc<Type> {
77        let id = self.next_type_id();
78
79        let flags = TypeFlags::compute_for_type_kind(&kind);
80
81        let type_instance = Type {
82            id,
83            flags,
84            kind: Rc::new(kind),
85        };
86
87        let rc_type = Rc::new(type_instance);
88        self.type_id_to_type.insert(id, Rc::clone(&rc_type));
89
90        rc_type
91    }
92
93    /// Find an existing type in the cache by its kind
94    #[inline]
95    fn find_type(&self, kind: &TypeKind) -> Option<Rc<Type>> {
96        self.kind_to_type_id
97            .get(kind)
98            .map(|id| self.type_id_to_type[id].clone())
99    }
100
101    /// Add a type to the cache for future lookups
102    #[inline]
103    fn add_type_to_cache(&mut self, type_: &Rc<Type>) {
104        self.kind_to_type_id.insert((*type_.kind).clone(), type_.id);
105    }
106
107    /// Get a type by its ID
108    #[inline]
109    #[must_use]
110    pub fn get_by_id(&self, id: TypeId) -> Option<Rc<Type>> {
111        self.type_id_to_type.get(&id).cloned()
112    }
113
114    /// Check if two types are compatible
115    #[allow(clippy::too_many_lines)]
116    pub fn compatible_with(&mut self, a: &Type, b: &Type) -> bool {
117        if a.id == b.id {
118            return true;
119        }
120
121        let key = (a.id, b.id);
122
123        if let Some(&result) = self.compatible_cache.get(&key) {
124            return result;
125        }
126
127        // HACK: Mark as being processed (optimistically), this is to avoid recursion
128        self.compatible_cache
129            .insert(key, false)
130            .expect("should work");
131
132        // Make the slow compatible check
133        let base_compatible = a.do_compatible_with(b, self);
134
135        // If not base compatible, we can return early
136        if !base_compatible {
137            self.compatible_cache.remove(&key);
138            self.compatible_cache
139                .insert(key, false)
140                .expect("should work to insert again");
141            return false;
142        }
143
144        // Now check inner types if needed
145        let result = match (&*a.kind, &*b.kind) {
146            (TypeKind::Optional(inner_a), TypeKind::Optional(inner_b)) => {
147                self.compatible_with(inner_a, inner_b)
148            }
149
150            (TypeKind::VecStorage(elem_a, _), TypeKind::VecStorage(elem_b, _)) => {
151                self.compatible_with(elem_a, elem_b)
152            }
153
154            (TypeKind::SparseStorage(elem_a, _), TypeKind::SparseStorage(elem_b, _)) => {
155                self.compatible_with(elem_a, elem_b)
156            }
157
158            (TypeKind::QueueStorage(elem_a, _), TypeKind::QueueStorage(elem_b, _)) => {
159                self.compatible_with(elem_a, elem_b)
160            }
161
162            (TypeKind::StackStorage(elem_a, _), TypeKind::StackStorage(elem_b, _)) => {
163                self.compatible_with(elem_a, elem_b)
164            }
165
166            (TypeKind::SliceView(elem_a), TypeKind::SliceView(elem_b)) => {
167                self.compatible_with(elem_a, elem_b)
168            }
169
170            (TypeKind::SparseView(elem_a), TypeKind::SparseView(elem_b)) => {
171                self.compatible_with(elem_a, elem_b)
172            }
173
174            (TypeKind::QueueView(elem_a), TypeKind::QueueView(elem_b)) => {
175                self.compatible_with(elem_a, elem_b)
176            }
177
178            (TypeKind::StackView(elem_a), TypeKind::StackView(elem_b)) => {
179                self.compatible_with(elem_a, elem_b)
180            }
181
182            (TypeKind::DynamicLengthVecView(elem_a), TypeKind::DynamicLengthVecView(elem_b)) => {
183                self.compatible_with(elem_a, elem_b)
184            }
185
186            (TypeKind::MapStorage(key_a, val_a, _), TypeKind::MapStorage(key_b, val_b, _)) => {
187                self.compatible_with(key_a, key_b) && self.compatible_with(val_a, val_b)
188            }
189
190            (
191                TypeKind::DynamicLengthMapView(key_a, val_a),
192                TypeKind::DynamicLengthMapView(key_b, val_b),
193            ) => self.compatible_with(key_a, key_b) && self.compatible_with(val_a, val_b),
194
195            (TypeKind::GridStorage(elem_a, _, _), TypeKind::GridStorage(elem_b, _, _)) => {
196                self.compatible_with(elem_a, elem_b)
197            }
198
199            (TypeKind::GridView(elem_a), TypeKind::GridView(elem_b)) => {
200                self.compatible_with(elem_a, elem_b)
201            }
202
203            (TypeKind::Tuple(elems_a), TypeKind::Tuple(elems_b)) => {
204                if elems_a.len() == elems_b.len() {
205                    elems_a
206                        .iter()
207                        .zip(elems_b.iter())
208                        .all(|(a, b)| self.compatible_with(a, b))
209                } else {
210                    false
211                }
212            }
213
214            (
215                TypeKind::FixedCapacityAndLengthArray(elem_a, size_a),
216                TypeKind::FixedCapacityAndLengthArray(elem_b, size_b),
217            ) => size_a == size_b && self.compatible_with(elem_a, elem_b),
218
219            (TypeKind::AnonymousStruct(anon_a), TypeKind::AnonymousStruct(anon_b)) => {
220                // Check if fields match
221                anon_a.field_name_sorted_fields.len() == anon_b.field_name_sorted_fields.len()
222                    && anon_a.field_name_sorted_fields.keys().all(|key| {
223                        anon_b.field_name_sorted_fields.contains_key(key)
224                            && self.compatible_with(
225                                &anon_a.field_name_sorted_fields[key].field_type,
226                                &anon_b.field_name_sorted_fields[key].field_type,
227                            )
228                    })
229            }
230
231            (TypeKind::Range(range_a), TypeKind::Range(range_b)) => {
232                // Extract NamedStructType from TypeRef, then AnonymousStructType from that
233                let named_a = match &*range_a.kind {
234                    TypeKind::NamedStruct(named_struct) => named_struct,
235                    _ => return false,
236                };
237                let named_b = match &*range_b.kind {
238                    TypeKind::NamedStruct(named_struct) => named_struct,
239                    _ => return false,
240                };
241
242                let anon_a = match &*named_a.anon_struct_type.kind {
243                    TypeKind::AnonymousStruct(anon_struct) => anon_struct,
244                    _ => return false,
245                };
246                let anon_b = match &*named_b.anon_struct_type.kind {
247                    TypeKind::AnonymousStruct(anon_struct) => anon_struct,
248                    _ => return false,
249                };
250
251                // Compare range types
252                anon_a.field_name_sorted_fields.len() == anon_b.field_name_sorted_fields.len()
253                    && anon_a.field_name_sorted_fields.keys().all(|key| {
254                        anon_b.field_name_sorted_fields.contains_key(key)
255                            && self.compatible_with(
256                                &anon_a.field_name_sorted_fields[key].field_type,
257                                &anon_b.field_name_sorted_fields[key].field_type,
258                            )
259                    })
260            }
261
262            (TypeKind::NamedStruct(named_a), TypeKind::NamedStruct(named_b)) => {
263                // Check named struct compatibility
264                if named_a.assigned_name != named_b.assigned_name
265                    || named_a.instantiated_type_parameters.len()
266                        != named_b.instantiated_type_parameters.len()
267                {
268                    false
269                } else {
270                    // Check type parameters compatibility
271                    named_a
272                        .instantiated_type_parameters
273                        .iter()
274                        .zip(named_b.instantiated_type_parameters.iter())
275                        .all(|(a, b)| self.compatible_with(a, b))
276                }
277            }
278
279            (TypeKind::Enum(enum_a), TypeKind::Enum(enum_b)) => {
280                // Check enum compatibility
281                if enum_a.assigned_name != enum_b.assigned_name
282                    || enum_a.instantiated_type_parameters.len()
283                        != enum_b.instantiated_type_parameters.len()
284                {
285                    false
286                } else {
287                    // Check type parameters compatibility
288                    enum_a
289                        .instantiated_type_parameters
290                        .iter()
291                        .zip(enum_b.instantiated_type_parameters.iter())
292                        .all(|(a, b)| self.compatible_with(a, b))
293                }
294            }
295
296            (TypeKind::Function(sig_a), TypeKind::Function(sig_b)) => {
297                // Compare function signatures
298                if sig_a.parameters.len() == sig_b.parameters.len() {
299                    // Check parameters and return type
300                    let params_match = sig_a
301                        .parameters
302                        .iter()
303                        .zip(sig_b.parameters.iter())
304                        .all(|(a, b)| self.compatible_with(&a.resolved_type, &b.resolved_type));
305
306                    params_match && self.compatible_with(&sig_a.return_type, &sig_b.return_type)
307                } else {
308                    false
309                }
310            }
311
312            _ => true,
313        };
314
315        self.compatible_cache.remove(&key);
316        self.compatible_cache
317            .insert(key, result)
318            .unwrap_or_else(|_| panic!("should be able to insert into cache {key:?}"));
319
320        result
321    }
322
323    /// Clear the compatibility cache
324    pub fn clear_compatibility_cache(&mut self) {
325        self.compatible_cache.clear();
326    }
327
328    //
329    // Primitive helpers
330    // TODO: Maybe just add the primitives at creation instead
331    //
332
333    pub fn byte(&mut self) -> Rc<Type> {
334        let byte_kind = TypeKind::Byte;
335
336        if let Some(existing) = self.find_type(&byte_kind) {
337            return existing;
338        }
339
340        let byte_type = self.create_type(byte_kind);
341        self.add_type_to_cache(&byte_type);
342        byte_type
343    }
344
345    pub fn int(&mut self) -> Rc<Type> {
346        let int_kind = TypeKind::Int;
347
348        if let Some(existing) = self.find_type(&int_kind) {
349            return existing;
350        }
351
352        let int_type = self.create_type(int_kind);
353        self.add_type_to_cache(&int_type);
354        int_type
355    }
356
357    pub fn float(&mut self) -> Rc<Type> {
358        let float_kind = TypeKind::Float;
359
360        if let Some(existing) = self.find_type(&float_kind) {
361            return existing;
362        }
363
364        let float_type = self.create_type(float_kind);
365        self.add_type_to_cache(&float_type);
366        float_type
367    }
368
369    pub fn string(&mut self) -> Rc<Type> {
370        let string_kind = TypeKind::String;
371
372        if let Some(existing) = self.find_type(&string_kind) {
373            return existing;
374        }
375
376        let string_type = self.create_type(string_kind);
377        self.add_type_to_cache(&string_type);
378        string_type
379    }
380
381    pub fn bool(&mut self) -> Rc<Type> {
382        let bool_kind = TypeKind::Bool;
383
384        if let Some(existing) = self.find_type(&bool_kind) {
385            return existing;
386        }
387
388        let bool_type = self.create_type(bool_kind);
389        self.add_type_to_cache(&bool_type);
390        bool_type
391    }
392
393    pub fn unit(&mut self) -> Rc<Type> {
394        let unit_kind = TypeKind::Unit;
395
396        if let Some(existing) = self.find_type(&unit_kind) {
397            return existing;
398        }
399
400        let unit_type = self.create_type(unit_kind);
401        self.add_type_to_cache(&unit_type);
402        unit_type
403    }
404
405    //
406    // Container type helpers
407    //
408
409    pub fn optional(&mut self, inner_type: &Rc<Type>) -> Rc<Type> {
410        let optional_kind = TypeKind::Optional(Rc::clone(inner_type));
411
412        if let Some(existing) = self.find_type(&optional_kind) {
413            return existing;
414        }
415
416        let optional_type = self.create_type(optional_kind);
417        self.add_type_to_cache(&optional_type);
418        optional_type
419    }
420
421    pub fn tuple(&mut self, element_types: Vec<Rc<Type>>) -> Rc<Type> {
422        let tuple_kind = TypeKind::Tuple(element_types);
423
424        if let Some(existing) = self.find_type(&tuple_kind) {
425            return existing;
426        }
427
428        let tuple_type = self.create_type(tuple_kind);
429        self.add_type_to_cache(&tuple_type);
430        tuple_type
431    }
432
433    pub fn string_storage(&mut self, capacity: usize) -> Rc<Type> {
434        let string_kind = TypeKind::StringStorage(self.byte(), capacity);
435
436        if let Some(existing) = self.find_type(&string_kind) {
437            return existing;
438        }
439
440        let string_type = self.create_type(string_kind);
441        self.add_type_to_cache(&string_type);
442        string_type
443    }
444
445    // TODO: Maybe use a shared function for types with one element type
446    pub fn vec_storage(&mut self, element_type: &Rc<Type>, capacity: usize) -> Rc<Type> {
447        let vec_kind = TypeKind::VecStorage(Rc::clone(element_type), capacity);
448
449        if let Some(existing) = self.find_type(&vec_kind) {
450            return existing;
451        }
452
453        let vec_type = self.create_type(vec_kind);
454        self.add_type_to_cache(&vec_type);
455        vec_type
456    }
457
458    pub fn sparse_storage(&mut self, element_type: &Rc<Type>, capacity: usize) -> Rc<Type> {
459        let sparse_kind = TypeKind::SparseStorage(Rc::clone(element_type), capacity);
460
461        if let Some(existing) = self.find_type(&sparse_kind) {
462            return existing;
463        }
464
465        let sparse_type = self.create_type(sparse_kind);
466        self.add_type_to_cache(&sparse_type);
467        sparse_type
468    }
469
470    pub fn queue_storage(&mut self, element_type: &Rc<Type>, capacity: usize) -> Rc<Type> {
471        let queue_kind = TypeKind::QueueStorage(Rc::clone(element_type), capacity);
472
473        if let Some(existing) = self.find_type(&queue_kind) {
474            return existing;
475        }
476
477        let queue_type = self.create_type(queue_kind);
478        self.add_type_to_cache(&queue_type);
479        queue_type
480    }
481
482    pub fn stack_storage(&mut self, element_type: &Rc<Type>, capacity: usize) -> Rc<Type> {
483        let stack_kind = TypeKind::StackStorage(Rc::clone(element_type), capacity);
484
485        if let Some(existing) = self.find_type(&stack_kind) {
486            return existing;
487        }
488
489        let stack_type = self.create_type(stack_kind);
490        self.add_type_to_cache(&stack_type);
491        stack_type
492    }
493
494    pub fn map_storage(
495        &mut self,
496        key_type: &Rc<Type>,
497        value_type: &Rc<Type>,
498        capacity: usize,
499    ) -> Rc<Type> {
500        let map_kind = TypeKind::MapStorage(Rc::clone(key_type), Rc::clone(value_type), capacity);
501
502        if let Some(existing) = self.find_type(&map_kind) {
503            return existing;
504        }
505
506        let map_type = self.create_type(map_kind);
507        self.add_type_to_cache(&map_type);
508        map_type
509    }
510
511    pub fn grid_storage(&mut self, element_type: &Rc<Type>, rows: usize, cols: usize) -> Rc<Type> {
512        let grid_kind = TypeKind::GridStorage(Rc::clone(element_type), rows, cols);
513
514        if let Some(existing) = self.find_type(&grid_kind) {
515            return existing;
516        }
517
518        let grid_type = self.create_type(grid_kind);
519        self.add_type_to_cache(&grid_type);
520        grid_type
521    }
522
523    pub fn fixed_array(&mut self, element_type: &Rc<Type>, size: usize) -> Rc<Type> {
524        let array_kind = TypeKind::FixedCapacityAndLengthArray(Rc::clone(element_type), size);
525
526        if let Some(existing) = self.find_type(&array_kind) {
527            return existing;
528        }
529
530        let array_type = self.create_type(array_kind);
531        self.add_type_to_cache(&array_type);
532        array_type
533    }
534
535    pub fn slice_view(&mut self, element_type: &Rc<Type>) -> Rc<Type> {
536        let slice_kind = TypeKind::SliceView(Rc::clone(element_type));
537
538        if let Some(existing) = self.find_type(&slice_kind) {
539            return existing;
540        }
541
542        let slice_type = self.create_type(slice_kind);
543        self.add_type_to_cache(&slice_type);
544        slice_type
545    }
546
547    pub fn sparse_view(&mut self, element_type: &Rc<Type>) -> Rc<Type> {
548        let sparse_kind = TypeKind::SparseView(Rc::clone(element_type));
549
550        if let Some(existing) = self.find_type(&sparse_kind) {
551            return existing;
552        }
553
554        let sparse_type = self.create_type(sparse_kind);
555        self.add_type_to_cache(&sparse_type);
556        sparse_type
557    }
558
559    pub fn queue_view(&mut self, element_type: &Rc<Type>) -> Rc<Type> {
560        let queue_kind = TypeKind::QueueView(Rc::clone(element_type));
561
562        if let Some(existing) = self.find_type(&queue_kind) {
563            return existing;
564        }
565
566        let queue_type = self.create_type(queue_kind);
567        self.add_type_to_cache(&queue_type);
568        queue_type
569    }
570
571    pub fn stack_view(&mut self, element_type: &Rc<Type>) -> Rc<Type> {
572        let stack_kind = TypeKind::StackView(Rc::clone(element_type));
573
574        if let Some(existing) = self.find_type(&stack_kind) {
575            return existing;
576        }
577
578        let stack_type = self.create_type(stack_kind);
579        self.add_type_to_cache(&stack_type);
580        stack_type
581    }
582
583    pub fn dynamic_vec_view(&mut self, element_type: &Rc<Type>) -> Rc<Type> {
584        let vec_view_kind = TypeKind::DynamicLengthVecView(Rc::clone(element_type));
585
586        if let Some(existing) = self.find_type(&vec_view_kind) {
587            return existing;
588        }
589
590        let vec_view_type = self.create_type(vec_view_kind);
591        self.add_type_to_cache(&vec_view_type);
592        vec_view_type
593    }
594
595    pub fn dynamic_map_view(&mut self, key_type: &Rc<Type>, value_type: &Rc<Type>) -> Rc<Type> {
596        let map_view_kind =
597            TypeKind::DynamicLengthMapView(Rc::clone(key_type), Rc::clone(value_type));
598
599        if let Some(existing) = self.find_type(&map_view_kind) {
600            return existing;
601        }
602
603        let map_view_type = self.create_type(map_view_kind);
604        self.add_type_to_cache(&map_view_type);
605        map_view_type
606    }
607
608    pub fn grid_view(&mut self, element_type: &Rc<Type>) -> Rc<Type> {
609        let grid_view_kind = TypeKind::GridView(Rc::clone(element_type));
610
611        if let Some(existing) = self.find_type(&grid_view_kind) {
612            return existing;
613        }
614
615        let grid_view_type = self.create_type(grid_view_kind);
616        self.add_type_to_cache(&grid_view_type);
617        grid_view_type
618    }
619
620    //
621    // Complex type helpers
622    //
623
624    /// Create an anonymous struct type
625    pub fn anonymous_struct(&mut self, anon_struct: AnonymousStructType) -> Rc<Type> {
626        let struct_kind = TypeKind::AnonymousStruct(anon_struct);
627
628        if let Some(existing) = self.find_type(&struct_kind) {
629            return existing;
630        }
631
632        let struct_type = self.create_type(struct_kind);
633        self.add_type_to_cache(&struct_type);
634        struct_type
635    }
636
637    pub fn range(&mut self, range_struct_ref: TypeRef) -> Rc<Type> {
638        let range_kind = TypeKind::Range(range_struct_ref);
639
640        if let Some(existing) = self.find_type(&range_kind) {
641            return existing;
642        }
643
644        let range_type = self.create_type(range_kind);
645        self.add_type_to_cache(&range_type);
646        range_type
647    }
648
649    pub fn named_struct(&mut self, named_struct: NamedStructType) -> Rc<Type> {
650        let struct_kind = TypeKind::NamedStruct(named_struct);
651
652        if let Some(existing) = self.find_type(&struct_kind) {
653            return existing;
654        }
655
656        let struct_type = self.create_type(struct_kind);
657        self.add_type_to_cache(&struct_type);
658        struct_type
659    }
660
661    pub fn enum_type(&mut self, enum_type: EnumType) -> Rc<Type> {
662        let enum_kind = TypeKind::Enum(enum_type);
663
664        if let Some(existing) = self.find_type(&enum_kind) {
665            return existing;
666        }
667
668        let enum_type = self.create_type(enum_kind);
669        self.add_type_to_cache(&enum_type);
670        enum_type
671    }
672
673    pub fn function(&mut self, signature: Signature) -> Rc<Type> {
674        let function_kind = TypeKind::Function(signature);
675
676        if let Some(existing) = self.find_type(&function_kind) {
677            return existing;
678        }
679
680        let function_type = self.create_type(function_kind);
681        self.add_type_to_cache(&function_type);
682        function_type
683    }
684}