swamp_types/
supporting_types.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/types
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::cache::TypeCache;
6use crate::{Type, TypeKind, TypeRef};
7use seq_map::SeqMap;
8use source_map_node::Node;
9use std::fmt::{Debug, Display};
10use std::hash::{Hash, Hasher};
11use swamp_symbol::TopLevelSymbolId;
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct NamedStructType {
15    pub symbol_id: TopLevelSymbolId,
16    pub name: Node,
17    pub module_path: Vec<String>,
18    pub assigned_name: String,
19    pub anon_struct_type: TypeRef,
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    }
27}
28
29impl NamedStructType {
30    #[must_use]
31    pub fn new(
32        name: Node,
33        assigned_name: &str,
34        symbol_id: TopLevelSymbolId,
35        anon_struct_type: TypeRef,
36        module_path: &[String],
37    ) -> Self {
38        Self {
39            symbol_id,
40            anon_struct_type,
41            name,
42            module_path: module_path.to_vec(),
43            assigned_name: assigned_name.to_string(),
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 symbol_id: TopLevelSymbolId,
96    pub identifier: Option<Node>,
97    pub field_type: TypeRef,
98}
99
100impl Display for StructTypeField {
101    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
102        write!(f, "{:?}", self.field_type)
103    }
104}
105
106#[derive(Debug, Eq, PartialEq, Clone, Hash)]
107pub struct Signature {
108    pub parameters: Vec<TypeForParameter>,
109    pub return_type: TypeRef,
110}
111
112impl Signature {
113    #[must_use]
114    pub fn is_member_signature(&self) -> bool {
115        !self.parameters.is_empty() && self.parameters[0].name == "self"
116    }
117
118    #[must_use]
119    pub fn human_readable_string(&self) -> String {
120        let parameters = if self.is_member_signature() {
121            self.parameters[1..].to_vec()
122        } else {
123            self.parameters.clone()
124        };
125
126        if TypeKind::Unit == *self.return_type.kind {
127            format!("({})", seq_fmt::comma(&parameters))
128        } else {
129            format!("({}) -> {}", seq_fmt::comma(&parameters), self.return_type)
130        }
131    }
132
133    #[must_use]
134    pub fn same_type(&self, other: &Self, type_cache: &mut TypeCache) -> bool {
135        if !self
136            .return_type
137            .do_compatible_with(&other.return_type, type_cache)
138        {
139            return false;
140        }
141
142        if self.parameters.len() != other.parameters.len() {
143            return false;
144        }
145
146        for (i, self_param) in self.parameters.iter().enumerate() {
147            let other_param = &other.parameters[i];
148
149            if !self_param
150                .resolved_type
151                .do_compatible_with(&other_param.resolved_type, type_cache)
152            {
153                return false;
154            }
155
156            if self_param.is_mutable != other_param.is_mutable {
157                return false;
158            }
159        }
160
161        true
162    }
163
164    #[must_use]
165    pub fn is_self_mutable(&self) -> bool {
166        self.parameters
167            .first()
168            .is_some_and(|x| x.name == "self" && x.is_mutable)
169    }
170}
171
172#[derive(Debug, Eq, Clone)]
173pub struct TypeForParameter {
174    pub name: String,
175    pub resolved_type: TypeRef,
176    pub is_mutable: bool,
177    pub node: Option<ParameterNode>,
178}
179
180impl PartialEq for TypeForParameter {
181    fn eq(&self, other: &Self) -> bool {
182        self.resolved_type == other.resolved_type && self.is_mutable == other.is_mutable
183    }
184}
185
186impl std::hash::Hash for TypeForParameter {
187    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
188        self.resolved_type.hash(state);
189        self.is_mutable.hash(state);
190    }
191}
192
193impl Display for TypeForParameter {
194    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
195        write!(
196            f,
197            "{}{}: {}",
198            if self.is_mutable { "mut " } else { "" },
199            self.name,
200            self.resolved_type
201        )
202    }
203}
204
205#[derive(Clone, Eq, PartialEq, Hash)]
206pub struct ParameterNode {
207    pub name: Node,
208    pub is_mutable: Option<Node>,
209}
210
211impl Debug for ParameterNode {
212    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
213        write!(f, "Parameter")
214    }
215}
216
217impl ParameterNode {
218    #[inline]
219    #[must_use]
220    pub const fn is_mutable(&self) -> bool {
221        self.is_mutable.is_some()
222    }
223}
224
225#[derive(Debug, Clone, Eq, PartialEq, Hash)]
226pub struct EnumType {
227    pub symbol_id: TopLevelSymbolId,
228    pub name: Node,
229    pub assigned_name: String,
230    pub module_path: Vec<String>,
231    pub variants: SeqMap<String, EnumVariantType>,
232    pub instantiated_type_parameters: Vec<Type>,
233}
234
235impl EnumType {}
236
237impl EnumType {
238    #[must_use]
239    pub fn new(
240        name: Node,
241        assigned_name: &str,
242        symbol_id: TopLevelSymbolId,
243        module_path: Vec<String>,
244    ) -> Self {
245        Self {
246            symbol_id,
247            name,
248            assigned_name: assigned_name.to_string(),
249            module_path,
250            variants: SeqMap::new(),
251            instantiated_type_parameters: Vec::default(),
252        }
253    }
254
255    #[must_use]
256    pub const fn name(&self) -> &Node {
257        &self.name
258    }
259
260    #[must_use]
261    pub fn get_variant(&self, name: &str) -> Option<&EnumVariantType> {
262        self.variants.get(&name.to_string())
263    }
264
265    #[must_use]
266    pub fn are_all_variants_with_blittable_payload(&self) -> bool {
267        self.variants.iter().all(|(_name, variant)| {
268            assert!(
269                variant.payload_type.allowed_for_scoped_borrow(),
270                "what is wrong with this variant {variant}"
271            );
272            variant.payload_type.allowed_for_scoped_borrow()
273        })
274    }
275
276    pub(crate) fn are_all_variants_with_storage_payload(&self) -> bool {
277        self.variants.iter().all(|(_name, variant)| {
278            if !variant.payload_type.is_storage() {
279                eprintln!("this variant can not be stored, please verify why {self}::{variant}");
280            }
281            variant.payload_type.is_storage()
282        })
283    }
284
285    #[must_use]
286    pub fn get_variant_from_index(&self, index: usize) -> Option<&EnumVariantType> {
287        Some(self.variants.values().collect::<Vec<_>>()[index])
288    }
289}
290
291#[derive(Debug, Clone, Eq, PartialEq, Hash)]
292pub struct EnumVariantType {
293    pub common: EnumVariantCommon,
294    pub payload_type: TypeRef, // AnonymousStruct, Unit, or Tuple
295}
296
297impl EnumVariantType {
298    #[must_use]
299    pub const fn common(&self) -> &EnumVariantCommon {
300        &self.common
301    }
302}
303
304#[derive(Clone, Eq, PartialEq, Hash, Debug)]
305pub struct EnumVariantCommon {
306    pub symbol_id: TopLevelSymbolId,
307    pub name: Node,
308    pub assigned_name: String,
309    pub container_index: u8,
310}
311
312impl EnumVariantCommon {
313    #[must_use]
314    pub const fn index(&self) -> u8 {
315        self.container_index
316    }
317}
318
319#[must_use]
320pub fn sort_struct_fields2(
321    unordered_seq_map: &SeqMap<String, StructTypeField>,
322) -> SeqMap<String, StructTypeField> {
323    let mut sorted_pairs: Vec<(&String, &StructTypeField)> = unordered_seq_map.iter().collect();
324    sorted_pairs.sort_by(|a, b| a.0.cmp(b.0));
325
326    sorted_pairs
327        .into_iter()
328        .map(|(name, field)| (name.clone(), field.clone()))
329        .collect()
330}
331
332impl Display for NamedStructType {
333    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
334        write!(f, "{}", self.assigned_name)
335    }
336}
337
338impl Display for AnonymousStructType {
339    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340        write!(
341            f,
342            "{{ {} }}",
343            seq_fmt::comma(
344                &self
345                    .field_name_sorted_fields
346                    .iter()
347                    .map(|(name, field)| format!("{}: {}", name, field.field_type))
348                    .collect::<Vec<_>>()
349            )
350        )
351    }
352}
353
354impl Display for Signature {
355    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
356        write!(
357            f,
358            "({}) -> {}",
359            seq_fmt::comma(&self.parameters),
360            self.return_type
361        )
362    }
363}
364
365impl Display for EnumType {
366    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
367        if self.instantiated_type_parameters.is_empty() {
368            write!(f, "{}", self.assigned_name)
369        } else {
370            write!(
371                f,
372                "{}<{}>",
373                self.assigned_name,
374                seq_fmt::comma(&self.instantiated_type_parameters)
375            )
376        }
377    }
378}
379
380impl Display for EnumVariantType {
381    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
382        write!(f, "{}", self.payload_type)
383    }
384}