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