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