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