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