mago_codex/ttype/
combination.rs

1use std::collections::BTreeMap;
2
3use ahash::HashSet;
4use ordered_float::OrderedFloat;
5
6use mago_atom::Atom;
7use mago_atom::AtomMap;
8use mago_atom::AtomSet;
9
10use crate::ttype::atomic::TAtomic;
11use crate::ttype::atomic::array::key::ArrayKey;
12use crate::ttype::atomic::derived::TDerived;
13use crate::ttype::atomic::scalar::int::TInteger;
14use crate::ttype::union::TUnion;
15
16#[derive(Debug)]
17pub struct TypeCombination {
18    pub value_types: AtomMap<TAtomic>,
19    pub has_object_top_type: bool,
20    pub enum_names: HashSet<(Atom, Option<Atom>)>,
21    pub object_type_params: AtomMap<(Atom, Vec<TUnion>)>,
22    pub object_static: AtomMap<bool>,
23    pub list_array_counts: Option<HashSet<usize>>,
24    pub list_array_sometimes_filled: bool,
25    pub list_array_always_filled: bool,
26    pub keyed_array_sometimes_filled: bool,
27    pub keyed_array_always_filled: bool,
28    pub has_empty_array: bool,
29    pub has_keyed_array: bool,
30    pub keyed_array_entries: BTreeMap<ArrayKey, (bool, TUnion)>,
31    pub list_array_entries: BTreeMap<usize, (bool, TUnion)>,
32    pub keyed_array_parameters: Option<(TUnion, TUnion)>,
33    pub list_array_parameter: Option<TUnion>,
34    pub falsy_mixed: Option<bool>,
35    pub truthy_mixed: Option<bool>,
36    pub nonnull_mixed: Option<bool>,
37    pub generic_mixed: bool,
38    pub has_mixed: bool,
39    pub mixed_from_loop_isset: Option<bool>,
40    pub integers: HashSet<TInteger>,
41    pub literal_strings: AtomSet,
42    pub literal_floats: HashSet<OrderedFloat<f64>>,
43    pub class_string_types: AtomMap<TAtomic>,
44    pub derived_types: HashSet<TDerived>,
45    pub resource: bool,
46    pub open_resource: bool,
47    pub closed_resource: bool,
48}
49
50impl Default for TypeCombination {
51    fn default() -> Self {
52        Self::new()
53    }
54}
55
56impl TypeCombination {
57    pub fn new() -> Self {
58        Self {
59            value_types: AtomMap::default(),
60            has_object_top_type: false,
61            object_type_params: AtomMap::default(),
62            object_static: AtomMap::default(),
63            list_array_counts: Some(HashSet::default()),
64            list_array_sometimes_filled: false,
65            list_array_always_filled: true,
66            keyed_array_sometimes_filled: false,
67            keyed_array_always_filled: true,
68            has_empty_array: false,
69            has_keyed_array: false,
70            keyed_array_entries: BTreeMap::new(),
71            list_array_entries: BTreeMap::new(),
72            keyed_array_parameters: None,
73            list_array_parameter: None,
74            falsy_mixed: None,
75            truthy_mixed: None,
76            nonnull_mixed: None,
77            generic_mixed: false,
78            has_mixed: false,
79            mixed_from_loop_isset: None,
80            literal_strings: AtomSet::default(),
81            integers: HashSet::default(),
82            literal_floats: HashSet::default(),
83            class_string_types: AtomMap::default(),
84            enum_names: HashSet::default(),
85            derived_types: HashSet::default(),
86            resource: false,
87            open_resource: false,
88            closed_resource: false,
89        }
90    }
91
92    #[inline]
93    pub fn is_simple(&self) -> bool {
94        if self.value_types.len() == 1
95            && !self.has_keyed_array
96            && !self.has_empty_array
97            && !self.resource
98            && !self.open_resource
99            && !self.closed_resource
100            && let (None, None) = (&self.keyed_array_parameters, &self.list_array_parameter)
101        {
102            return self.keyed_array_entries.is_empty()
103                && self.list_array_entries.is_empty()
104                && self.object_type_params.is_empty()
105                && self.enum_names.is_empty()
106                && self.literal_strings.is_empty()
107                && self.class_string_types.is_empty()
108                && self.integers.is_empty()
109                && self.derived_types.is_empty();
110        }
111
112        false
113    }
114}