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::prelude::StructTypeField;
8use crate::supporting_types::{AnonymousStructType, EnumType, NamedStructType, Signature};
9use crate::type_kind::{TypeKind, TypeRef};
10use crate::{Type, TypeId};
11use seq_map::SeqMap;
12use std::rc::Rc;
13
14/// Type cache for interning and deduplicating types in the system
15#[derive(Debug, Clone)]
16pub struct TypeCache {
17    pub(crate) type_id_to_type: SeqMap<TypeId, Rc<Type>>,
18    pub(crate) kind_to_type_id: SeqMap<TypeKind, TypeId>,
19    pub(crate) compatible_cache: SeqMap<(TypeId, TypeId), bool>,
20    pub(crate) next_id: u32,
21}
22
23impl TypeCache {}
24
25impl Default for TypeCache {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl TypeCache {
32    /// Create a new empty type cache
33    #[must_use]
34    pub fn new() -> Self {
35        Self {
36            type_id_to_type: SeqMap::new(),
37            kind_to_type_id: SeqMap::new(),
38            compatible_cache: SeqMap::new(),
39            next_id: 0,
40        }
41    }
42
43    #[must_use]
44    pub const fn type_id_to_type(&self) -> &SeqMap<TypeId, Rc<Type>> {
45        &self.type_id_to_type
46    }
47
48    #[must_use]
49    pub const fn compatible_cache(&self) -> &SeqMap<(TypeId, TypeId), bool> {
50        &self.compatible_cache
51    }
52
53    const fn next_type_id(&mut self) -> TypeId {
54        let id = TypeId(self.next_id);
55        self.next_id += 1;
56        id
57    }
58
59    /// Create a new type instance with the given kind
60    fn create_type(&mut self, kind: TypeKind) -> Rc<Type> {
61        let id = self.next_type_id();
62
63        let flags = TypeFlags::compute_for_type_kind(&kind);
64
65        let type_instance = Type {
66            id,
67            flags,
68            kind: Rc::new(kind),
69        };
70
71        let rc_type = Rc::new(type_instance);
72        self.type_id_to_type
73            .insert(id, Rc::clone(&rc_type))
74            .unwrap();
75
76        rc_type
77    }
78
79    /// Find an existing type in the cache by its kind
80    #[inline]
81    fn find_type(&self, kind: &TypeKind) -> Option<Rc<Type>> {
82        self.kind_to_type_id
83            .get(kind)
84            .map(|id| self.type_id_to_type[id].clone())
85    }
86
87    /// Add a type to the cache for future lookups
88    #[inline]
89    fn add_type_to_cache(&mut self, type_: &Rc<Type>) {
90        self.kind_to_type_id
91            .insert((*type_.kind).clone(), type_.id)
92            .unwrap();
93    }
94
95    /// Get a type by its ID
96    #[inline]
97    #[must_use]
98    pub fn get_by_id(&self, id: TypeId) -> Option<Rc<Type>> {
99        self.type_id_to_type.get(&id).cloned()
100    }
101
102    /// Check if two types are compatible
103    #[allow(clippy::too_many_lines)]
104    pub fn compatible_with(&mut self, a: &Type, b: &Type) -> bool {
105        if a.id == b.id {
106            return true;
107        }
108
109        let key = (a.id, b.id);
110
111        if let Some(&result) = self.compatible_cache.get(&key) {
112            return result;
113        }
114
115        // HACK: Mark as being processed (optimistically), this is to avoid recursion
116        self.compatible_cache
117            .insert(key, false)
118            .expect("should work");
119
120        // Make the slow compatible check
121        let base_compatible = a.do_compatible_with(b, self);
122
123        // If not base compatible, we can return early
124        if !base_compatible {
125            self.compatible_cache.remove(&key);
126            self.compatible_cache
127                .insert(key, false)
128                .expect("should work to insert again");
129            return false;
130        }
131
132        // Now check inner types if needed
133        let result = match (&*a.kind, &*b.kind) {
134            (TypeKind::Optional(inner_a), TypeKind::Optional(inner_b)) => {
135                self.compatible_with(inner_a, inner_b)
136            }
137
138            (TypeKind::VecStorage(elem_a, _), TypeKind::VecStorage(elem_b, _)) => {
139                self.compatible_with(elem_a, elem_b)
140            }
141
142            (TypeKind::SparseStorage(elem_a, _), TypeKind::SparseStorage(elem_b, _)) => {
143                self.compatible_with(elem_a, elem_b)
144            }
145
146            (TypeKind::QueueStorage(elem_a, _), TypeKind::QueueStorage(elem_b, _)) => {
147                self.compatible_with(elem_a, elem_b)
148            }
149
150            (TypeKind::StackStorage(elem_a, _), TypeKind::StackStorage(elem_b, _)) => {
151                self.compatible_with(elem_a, elem_b)
152            }
153
154            (TypeKind::SliceView(elem_a), TypeKind::SliceView(elem_b)) => {
155                self.compatible_with(elem_a, elem_b)
156            }
157
158            (TypeKind::SparseView(elem_a), TypeKind::SparseView(elem_b)) => {
159                self.compatible_with(elem_a, elem_b)
160            }
161
162            (TypeKind::QueueView(elem_a), TypeKind::QueueView(elem_b)) => {
163                self.compatible_with(elem_a, elem_b)
164            }
165
166            (TypeKind::StackView(elem_a), TypeKind::StackView(elem_b)) => {
167                self.compatible_with(elem_a, elem_b)
168            }
169
170            (TypeKind::DynamicLengthVecView(elem_a), TypeKind::DynamicLengthVecView(elem_b)) => {
171                self.compatible_with(elem_a, elem_b)
172            }
173
174            (TypeKind::MapStorage(key_a, val_a, _), TypeKind::MapStorage(key_b, val_b, _)) => {
175                self.compatible_with(key_a, key_b) && self.compatible_with(val_a, val_b)
176            }
177
178            (
179                TypeKind::DynamicLengthMapView(key_a, val_a),
180                TypeKind::DynamicLengthMapView(key_b, val_b),
181            ) => self.compatible_with(key_a, key_b) && self.compatible_with(val_a, val_b),
182
183            (TypeKind::GridStorage(elem_a, _, _), TypeKind::GridStorage(elem_b, _, _)) => {
184                self.compatible_with(elem_a, elem_b)
185            }
186
187            (TypeKind::GridView(elem_a), TypeKind::GridView(elem_b)) => {
188                self.compatible_with(elem_a, elem_b)
189            }
190
191            (TypeKind::Tuple(elems_a), TypeKind::Tuple(elems_b)) => {
192                if elems_a.len() == elems_b.len() {
193                    elems_a
194                        .iter()
195                        .zip(elems_b.iter())
196                        .all(|(a, b)| self.compatible_with(a, b))
197                } else {
198                    false
199                }
200            }
201
202            (
203                TypeKind::FixedCapacityAndLengthArray(elem_a, size_a),
204                TypeKind::FixedCapacityAndLengthArray(elem_b, size_b),
205            ) => size_a == size_b && self.compatible_with(elem_a, elem_b),
206
207            (TypeKind::AnonymousStruct(anon_a), TypeKind::AnonymousStruct(anon_b)) => {
208                // Check if fields match
209                anon_a.field_name_sorted_fields.len() == anon_b.field_name_sorted_fields.len()
210                    && anon_a.field_name_sorted_fields.keys().all(|key| {
211                    anon_b.field_name_sorted_fields.contains_key(key)
212                        && self.compatible_with(
213                        &anon_a.field_name_sorted_fields[key].field_type,
214                        &anon_b.field_name_sorted_fields[key].field_type,
215                    )
216                })
217            }
218
219            (TypeKind::Range(range_a), TypeKind::Range(range_b)) => {
220                // Extract NamedStructType from TypeRef, then AnonymousStructType from that
221                let named_a = match &*range_a.kind {
222                    TypeKind::NamedStruct(named_struct) => named_struct,
223                    _ => return false,
224                };
225                let named_b = match &*range_b.kind {
226                    TypeKind::NamedStruct(named_struct) => named_struct,
227                    _ => return false,
228                };
229
230                let anon_a = match &*named_a.anon_struct_type.kind {
231                    TypeKind::AnonymousStruct(anon_struct) => anon_struct,
232                    _ => return false,
233                };
234                let anon_b = match &*named_b.anon_struct_type.kind {
235                    TypeKind::AnonymousStruct(anon_struct) => anon_struct,
236                    _ => return false,
237                };
238
239                // Compare range types
240                anon_a.field_name_sorted_fields.len() == anon_b.field_name_sorted_fields.len()
241                    && anon_a.field_name_sorted_fields.keys().all(|key| {
242                    anon_b.field_name_sorted_fields.contains_key(key)
243                        && self.compatible_with(
244                        &anon_a.field_name_sorted_fields[key].field_type,
245                        &anon_b.field_name_sorted_fields[key].field_type,
246                    )
247                })
248            }
249
250            (TypeKind::NamedStruct(named_a), TypeKind::NamedStruct(named_b)) => {
251                // Check named struct compatibility
252                if named_a.assigned_name != named_b.assigned_name
253                    || named_a.instantiated_type_parameters.len()
254                    != named_b.instantiated_type_parameters.len()
255                {
256                    false
257                } else {
258                    // Check type parameters compatibility
259                    named_a
260                        .instantiated_type_parameters
261                        .iter()
262                        .zip(named_b.instantiated_type_parameters.iter())
263                        .all(|(a, b)| self.compatible_with(a, b))
264                }
265            }
266
267            (TypeKind::Enum(enum_a), TypeKind::Enum(enum_b)) => {
268                // Check enum compatibility
269                if enum_a.assigned_name != enum_b.assigned_name
270                    || enum_a.instantiated_type_parameters.len()
271                    != enum_b.instantiated_type_parameters.len()
272                {
273                    false
274                } else {
275                    // Check type parameters compatibility
276                    enum_a
277                        .instantiated_type_parameters
278                        .iter()
279                        .zip(enum_b.instantiated_type_parameters.iter())
280                        .all(|(a, b)| self.compatible_with(a, b))
281                }
282            }
283
284            (TypeKind::Function(sig_a), TypeKind::Function(sig_b)) => {
285                // Compare function signatures
286                if sig_a.parameters.len() == sig_b.parameters.len() {
287                    // Check parameters and return type
288                    let params_match = sig_a
289                        .parameters
290                        .iter()
291                        .zip(sig_b.parameters.iter())
292                        .all(|(a, b)| self.compatible_with(&a.resolved_type, &b.resolved_type));
293
294                    params_match && self.compatible_with(&sig_a.return_type, &sig_b.return_type)
295                } else {
296                    false
297                }
298            }
299
300            _ => true,
301        };
302
303        self.compatible_cache.remove(&key);
304        self.compatible_cache
305            .insert(key, result)
306            .unwrap_or_else(|_| panic!("should be able to insert into cache {key:?}"));
307
308        result
309    }
310
311    /// Clear the compatibility cache
312    pub fn clear_compatibility_cache(&mut self) {
313        self.compatible_cache.clear();
314    }
315
316    //
317    // Primitive helpers
318    // TODO: Maybe just add the primitives at creation instead
319    //
320
321    pub fn byte(&mut self) -> Rc<Type> {
322        let byte_kind = TypeKind::Byte;
323
324        if let Some(existing) = self.find_type(&byte_kind) {
325            return existing;
326        }
327
328        let byte_type = self.create_type(byte_kind);
329        self.add_type_to_cache(&byte_type);
330        byte_type
331    }
332
333    pub fn int(&mut self) -> Rc<Type> {
334        let int_kind = TypeKind::Int;
335
336        if let Some(existing) = self.find_type(&int_kind) {
337            return existing;
338        }
339
340        let int_type = self.create_type(int_kind);
341        self.add_type_to_cache(&int_type);
342        int_type
343    }
344
345    pub fn codepoint(&mut self) -> Rc<Type> {
346        let char_kind = TypeKind::Codepoint;
347
348        if let Some(existing) = self.find_type(&char_kind) {
349            return existing;
350        }
351
352        let char_type = self.create_type(char_kind);
353        self.add_type_to_cache(&char_type);
354        char_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 bool(&mut self) -> Rc<Type> {
370        let bool_kind = TypeKind::Bool;
371
372        if let Some(existing) = self.find_type(&bool_kind) {
373            return existing;
374        }
375
376        let bool_type = self.create_type(bool_kind);
377        self.add_type_to_cache(&bool_type);
378        bool_type
379    }
380
381    pub fn unit(&mut self) -> Rc<Type> {
382        let unit_kind = TypeKind::Unit;
383
384        if let Some(existing) = self.find_type(&unit_kind) {
385            return existing;
386        }
387
388        let unit_type = self.create_type(unit_kind);
389        self.add_type_to_cache(&unit_type);
390        unit_type
391    }
392
393    //
394    // Container type helpers
395    //
396
397    pub fn optional(&mut self, inner_type: &Rc<Type>) -> Rc<Type> {
398        let optional_kind = TypeKind::Optional(Rc::clone(inner_type));
399
400        if let Some(existing) = self.find_type(&optional_kind) {
401            return existing;
402        }
403
404        let optional_type = self.create_type(optional_kind);
405        self.add_type_to_cache(&optional_type);
406        optional_type
407    }
408
409    pub fn tuple(&mut self, element_types: Vec<Rc<Type>>) -> Rc<Type> {
410        let tuple_kind = TypeKind::Tuple(element_types);
411
412        if let Some(existing) = self.find_type(&tuple_kind) {
413            return existing;
414        }
415
416        let tuple_type = self.create_type(tuple_kind);
417        self.add_type_to_cache(&tuple_type);
418        tuple_type
419    }
420
421    pub fn string_storage(&mut self, capacity: usize) -> Rc<Type> {
422        let string_kind = TypeKind::StringStorage(self.byte(), self.codepoint(), capacity);
423
424        if let Some(existing) = self.find_type(&string_kind) {
425            return existing;
426        }
427
428        let string_type = self.create_type(string_kind);
429        self.add_type_to_cache(&string_type);
430        string_type
431    }
432
433    pub fn string(&mut self) -> Rc<Type> {
434        let string_kind = TypeKind::String(self.byte(), self.codepoint());
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 range_int(&mut self) -> Rc<Type> {
650        let int_type = self.int();
651        let bool_type = self.bool();
652
653        // Create an anonymous struct for the Range type: {min: int, max: int, inclusive: bool}
654        let mut range_fields = SeqMap::new();
655        let _ = range_fields.insert(
656            "start".to_string(),
657            StructTypeField {
658                identifier: None,
659                field_type: int_type.clone(),
660            },
661        );
662        let _ = range_fields.insert(
663            "end".to_string(),
664            StructTypeField {
665                identifier: None,
666                field_type: int_type,
667            },
668        );
669        let _ = range_fields.insert(
670            "is_inclusive".to_string(),
671            StructTypeField {
672                identifier: None,
673                field_type: bool_type,
674            },
675        );
676
677        let anon_struct = AnonymousStructType::new(range_fields);
678        let anon_struct_ref = self.anonymous_struct(anon_struct);
679        /*
680                // Create a NamedStructType for Range
681                let range_named_struct = NamedStructType::new(
682                    Node::default(),
683                    "Range",
684                    anon_struct_ref,
685                    &["core".to_string()],
686                );
687
688         */
689
690        //let named_struct_ref1 = self.named_struct(range_named_struct.clone());
691
692        self.range(anon_struct_ref)
693    }
694
695    pub fn named_struct(&mut self, named_struct: NamedStructType) -> Rc<Type> {
696        let struct_kind = TypeKind::NamedStruct(named_struct);
697
698        if let Some(existing) = self.find_type(&struct_kind) {
699            return existing;
700        }
701
702        let struct_type = self.create_type(struct_kind);
703        self.add_type_to_cache(&struct_type);
704        struct_type
705    }
706
707    pub fn enum_type(&mut self, enum_type: EnumType) -> Rc<Type> {
708        let enum_kind = TypeKind::Enum(enum_type);
709
710        if let Some(existing) = self.find_type(&enum_kind) {
711            return existing;
712        }
713
714        let enum_type = self.create_type(enum_kind);
715        self.add_type_to_cache(&enum_type);
716        enum_type
717    }
718
719    pub fn function(&mut self, signature: Signature) -> Rc<Type> {
720        let function_kind = TypeKind::Function(signature);
721
722        if let Some(existing) = self.find_type(&function_kind) {
723            return existing;
724        }
725
726        let function_type = self.create_type(function_kind);
727        self.add_type_to_cache(&function_type);
728        function_type
729    }
730}