swamp_types/
supporting_types.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::cache::TypeCache;
7use crate::{Type, TypeRef};
8use seq_map::SeqMap;
9use source_map_node::Node;
10use std::fmt::{Debug, Display};
11use std::hash::{Hash, Hasher};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct NamedStructType {
15    pub name: Node,
16    pub module_path: Vec<String>,
17    pub assigned_name: String,
18    pub anon_struct_type: TypeRef,
19    pub instantiated_type_parameters: Vec<Type>,
20}
21
22impl Hash for NamedStructType {
23    fn hash<H: Hasher>(&self, state: &mut H) {
24        self.module_path.hash(state);
25        state.write(self.assigned_name.as_ref());
26        self.instantiated_type_parameters.hash(state);
27    }
28}
29
30impl NamedStructType {
31    #[must_use]
32    pub fn new(
33        name: Node,
34        assigned_name: &str,
35        anon_struct_type: TypeRef,
36        module_path: &[String],
37    ) -> Self {
38        Self {
39            anon_struct_type,
40            name,
41            module_path: module_path.to_vec(),
42            assigned_name: assigned_name.to_string(),
43            instantiated_type_parameters: Vec::default(),
44        }
45    }
46
47    #[must_use]
48    pub fn field_index(&self, field_name: &str) -> Option<usize> {
49        if let crate::TypeKind::AnonymousStruct(anon_struct) = &*self.anon_struct_type.kind {
50            anon_struct
51                .field_name_sorted_fields
52                .get_index(&field_name.to_string())
53        } else {
54            None
55        }
56    }
57
58    #[must_use]
59    pub const fn name(&self) -> &Node {
60        &self.name
61    }
62}
63
64#[derive(Debug, Clone, Eq, PartialEq)]
65pub struct AnonymousStructType {
66    pub field_name_sorted_fields: SeqMap<String, StructTypeField>,
67}
68impl Hash for AnonymousStructType {
69    fn hash<H: Hasher>(&self, state: &mut H) {
70        for (name, field) in &self.field_name_sorted_fields {
71            name.hash(state);
72            field.field_type.id.0.hash(state);
73        }
74    }
75}
76
77impl AnonymousStructType {
78    #[must_use]
79    pub fn new_and_sort_fields(source_ordered_fields: &SeqMap<String, StructTypeField>) -> Self {
80        Self {
81            field_name_sorted_fields: sort_struct_fields2(source_ordered_fields),
82        }
83    }
84
85    #[must_use]
86    pub const fn new(defined_order: SeqMap<String, StructTypeField>) -> Self {
87        Self {
88            field_name_sorted_fields: defined_order,
89        }
90    }
91}
92
93#[derive(Debug, Clone, Eq, PartialEq, Hash)]
94pub struct StructTypeField {
95    pub identifier: Option<Node>,
96    pub field_type: TypeRef,
97}
98
99impl Display for StructTypeField {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
101        write!(f, "{:?}", self.field_type)
102    }
103}
104
105#[derive(Debug, Eq, PartialEq, Clone, Hash)]
106pub struct Signature {
107    pub parameters: Vec<TypeForParameter>,
108    pub return_type: TypeRef,
109}
110
111impl Signature {
112    #[must_use]
113    pub fn same_type(&self, other: &Self, type_cache: &mut TypeCache) -> bool {
114        if !self
115            .return_type
116            .do_compatible_with(&other.return_type, type_cache)
117        {
118            return false;
119        }
120
121        if self.parameters.len() != other.parameters.len() {
122            return false;
123        }
124
125        for (i, self_param) in self.parameters.iter().enumerate() {
126            let other_param = &other.parameters[i];
127
128            if !self_param
129                .resolved_type
130                .do_compatible_with(&other_param.resolved_type, type_cache)
131            {
132                return false;
133            }
134
135            if self_param.is_mutable != other_param.is_mutable {
136                return false;
137            }
138        }
139
140        true
141    }
142
143    #[must_use]
144    pub fn is_self_mutable(&self) -> bool {
145        self.parameters
146            .first()
147            .is_some_and(|x| x.name == "self" && x.is_mutable)
148    }
149}
150
151#[derive(Debug, Eq, Clone)]
152pub struct TypeForParameter {
153    pub name: String,
154    pub resolved_type: TypeRef,
155    pub is_mutable: bool,
156    pub node: Option<ParameterNode>,
157}
158
159impl PartialEq for TypeForParameter {
160    fn eq(&self, other: &Self) -> bool {
161        self.resolved_type == other.resolved_type && self.is_mutable == other.is_mutable
162    }
163}
164
165impl std::hash::Hash for TypeForParameter {
166    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
167        self.resolved_type.hash(state);
168        self.is_mutable.hash(state);
169    }
170}
171
172impl Display for TypeForParameter {
173    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
174        write!(
175            f,
176            "{}{}: {:?}",
177            if self.is_mutable { "mut " } else { "" },
178            self.name,
179            self.resolved_type
180        )
181    }
182}
183
184#[derive(Clone, Eq, PartialEq, Hash)]
185pub struct ParameterNode {
186    pub name: Node,
187    pub is_mutable: Option<Node>,
188}
189
190impl Debug for ParameterNode {
191    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
192        write!(f, "Parameter")
193    }
194}
195
196impl ParameterNode {
197    #[inline]
198    #[must_use]
199    pub const fn is_mutable(&self) -> bool {
200        self.is_mutable.is_some()
201    }
202}
203
204#[derive(Debug, Clone, Eq, PartialEq, Hash)]
205pub struct EnumType {
206    pub name: Node,
207    pub assigned_name: String,
208    pub module_path: Vec<String>,
209    pub variants: SeqMap<String, EnumVariantType>,
210    pub instantiated_type_parameters: Vec<Type>,
211}
212
213impl EnumType {}
214
215impl EnumType {
216    #[must_use]
217    pub fn new(name: Node, assigned_name: &str, module_path: Vec<String>) -> Self {
218        Self {
219            name,
220            assigned_name: assigned_name.to_string(),
221            module_path,
222            variants: SeqMap::new(),
223            instantiated_type_parameters: Vec::default(),
224        }
225    }
226
227    #[must_use]
228    pub const fn name(&self) -> &Node {
229        &self.name
230    }
231
232    #[must_use]
233    pub fn get_variant(&self, name: &str) -> Option<&EnumVariantType> {
234        self.variants.get(&name.to_string())
235    }
236
237    #[must_use]
238    pub fn are_all_variants_with_blittable_payload(&self) -> bool {
239        self.variants.iter().all(|(_name, variant)| {
240            assert!(
241                variant.payload_type.is_blittable(),
242                "what is wrong with this variant {variant}"
243            );
244            variant.payload_type.is_blittable()
245        })
246    }
247
248    pub(crate) fn are_all_variants_with_storage_payload(&self) -> bool {
249        self.variants.iter().all(|(_name, variant)| {
250            if !variant.payload_type.is_storage() {
251                eprintln!("this variant can not be stored, please verify why {self}::{variant}");
252            }
253            variant.payload_type.is_storage()
254        })
255    }
256
257    #[must_use]
258    pub fn get_variant_from_index(&self, index: usize) -> Option<&EnumVariantType> {
259        Some(self.variants.values().collect::<Vec<_>>()[index])
260    }
261}
262
263#[derive(Debug, Clone, Eq, PartialEq, Hash)]
264pub struct EnumVariantType {
265    pub common: EnumVariantCommon,
266    pub payload_type: TypeRef, // AnonymousStruct, Unit, or Tuple
267}
268
269impl EnumVariantType {
270    #[must_use]
271    pub const fn common(&self) -> &EnumVariantCommon {
272        &self.common
273    }
274}
275
276#[derive(Clone, Eq, PartialEq, Hash, Debug)]
277pub struct EnumVariantCommon {
278    pub name: Node,
279    pub assigned_name: String,
280    pub container_index: u8,
281}
282
283impl EnumVariantCommon {
284    #[must_use]
285    pub const fn index(&self) -> u8 {
286        self.container_index
287    }
288}
289
290#[must_use]
291pub fn sort_struct_fields2(
292    unordered_seq_map: &SeqMap<String, StructTypeField>,
293) -> SeqMap<String, StructTypeField> {
294    let mut sorted_pairs: Vec<(&String, &StructTypeField)> = unordered_seq_map.iter().collect();
295    sorted_pairs.sort_by(|a, b| a.0.cmp(b.0));
296
297    sorted_pairs
298        .into_iter()
299        .map(|(name, field)| (name.clone(), field.clone()))
300        .collect()
301}
302
303impl Display for NamedStructType {
304    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
305        if self.instantiated_type_parameters.is_empty() {
306            write!(f, "{}", self.assigned_name)
307        } else {
308            write!(
309                f,
310                "{}<{}>",
311                self.assigned_name,
312                seq_fmt::comma(&self.instantiated_type_parameters)
313            )
314        }
315    }
316}
317
318impl Display for AnonymousStructType {
319    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
320        write!(
321            f,
322            "{{ {} }}",
323            seq_fmt::comma(
324                &self
325                    .field_name_sorted_fields
326                    .iter()
327                    .map(|(name, field)| format!("{}: {}", name, field.field_type))
328                    .collect::<Vec<_>>()
329            )
330        )
331    }
332}
333
334impl Display for Signature {
335    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
336        write!(
337            f,
338            "({}) -> {}",
339            seq_fmt::comma(&self.parameters),
340            self.return_type
341        )
342    }
343}
344
345impl Display for EnumType {
346    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
347        if self.instantiated_type_parameters.is_empty() {
348            write!(f, "{}", self.assigned_name)
349        } else {
350            write!(
351                f,
352                "{}<{}>",
353                self.assigned_name,
354                seq_fmt::comma(&self.instantiated_type_parameters)
355            )
356        }
357    }
358}
359
360impl Display for EnumVariantType {
361    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
362        write!(f, "{}", self.payload_type)
363    }
364}