swamp_types/
lib.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 */
5pub mod prelude;
6
7use fmt::{Debug, Display};
8use seq_fmt::comma;
9use seq_map::SeqMap;
10use source_map_node::Node;
11use std::cmp::PartialEq;
12use std::fmt;
13use std::hash::Hash;
14
15#[derive(Eq, PartialEq, Hash, Clone)]
16pub enum Type {
17    // Primitives
18    Int,
19    Float,
20    String,
21    Bool,
22
23    Unit,  // Empty or nothing
24    Never, // Not even empty since control flow has escaped with break or return.
25
26    Slice(Box<Type>),
27    SlicePair(Box<Type>, Box<Type>),
28
29    // Containers
30    Tuple(Vec<Type>),
31    NamedStruct(NamedStructType),
32    AnonymousStruct(AnonymousStructType),
33
34    Enum(EnumType),
35
36    Function(Signature),
37
38    Optional(Box<Type>),
39
40    Generic(ParameterizedTypeBlueprint, Vec<Type>),
41    Blueprint(ParameterizedTypeBlueprint),
42    Variable(String),
43
44    MutableReference(Box<Type>),
45
46    External(ExternalType),
47}
48
49impl Type {
50    pub fn inner_optional_mut_or_immutable(&self) -> Option<&Type> {
51        if let Self::Optional(normal) = self {
52            Some(normal)
53        } else if let Self::MutableReference(mutable_reference) = self {
54            mutable_reference.inner_optional_mut_or_immutable()
55        } else {
56            None
57        }
58    }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, Hash)]
62pub enum ParameterizedTypeKind {
63    Struct(NamedStructType),
64    Enum(EnumType),
65}
66
67impl ParameterizedTypeKind {
68    pub fn name(&self) -> String {
69        match self {
70            Self::Struct(struct_type_ref) => struct_type_ref.assigned_name.clone(),
71            Self::Enum(enum_type_ref) => enum_type_ref.assigned_name.clone(),
72        }
73    }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Hash)]
77pub struct ParameterizedTypeBlueprintInfo {
78    pub name: String,
79    pub defined_in_module_path: Vec<String>,
80}
81
82#[derive(Debug, PartialEq, Eq, Hash, Clone)]
83pub struct ParameterizedTypeBlueprint {
84    pub kind: ParameterizedTypeKind,
85    pub type_variables: Vec<String>,
86
87    pub defined_in_module_path: Vec<String>,
88}
89
90impl ParameterizedTypeBlueprint {
91    pub fn info(&self) -> ParameterizedTypeBlueprintInfo {
92        ParameterizedTypeBlueprintInfo {
93            name: self.name(),
94            defined_in_module_path: self.defined_in_module_path.clone(),
95        }
96    }
97    pub fn name(&self) -> String {
98        self.kind.name()
99    }
100}
101
102#[derive(Clone, Eq, PartialEq, Hash)]
103pub struct ParameterNode {
104    pub name: Node,
105    pub is_mutable: Option<Node>,
106}
107
108impl Debug for ParameterNode {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        write!(f, "Parameter")
111    }
112}
113
114impl ParameterNode {
115    #[inline]
116    #[must_use]
117    pub const fn is_mutable(&self) -> bool {
118        self.is_mutable.is_some()
119    }
120}
121
122#[derive(Debug, Clone, Eq, PartialEq, Hash)]
123pub struct ExternalType {
124    pub type_name: String, // To identify the specific Rust type
125    pub number: u32,       // For type comparison
126}
127
128#[derive(Debug, Eq, PartialEq, Clone, Hash)]
129pub struct TypeForParameter {
130    pub name: String,
131    pub resolved_type: Type,
132    pub is_mutable: bool,
133    pub node: Option<ParameterNode>,
134}
135
136impl Display for TypeForParameter {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
138        write!(
139            f,
140            "{}{}: {:?}",
141            if self.is_mutable { "mut " } else { "" },
142            self.name,
143            self.resolved_type
144        )
145    }
146}
147
148#[derive(Debug, Eq, PartialEq, Clone, Hash)]
149pub struct TypeVariable(pub String);
150
151#[derive(Debug, Eq, PartialEq, Clone, Hash)]
152pub struct GenericAwareSignature {
153    pub signature: Signature,
154    pub generic_type_variables: Vec<TypeVariable>,
155}
156
157#[derive(Debug, Eq, PartialEq, Clone, Hash)]
158pub struct Signature {
159    pub parameters: Vec<TypeForParameter>,
160    pub return_type: Box<Type>,
161}
162
163impl Display for Signature {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
165        write!(f, "({})->{}", comma(&self.parameters), self.return_type)
166    }
167}
168
169impl Signature {
170    #[must_use]
171    pub fn same_type(&self, other: &Self) -> bool {
172        if self.parameters.len() != other.parameters.len()
173            || !self.return_type.compatible_with(&other.return_type)
174        {
175            return false;
176        }
177
178        for (param, other_param) in self.parameters.iter().zip(other.parameters.clone()) {
179            if !&param
180                .resolved_type
181                .compatible_with(&other_param.resolved_type)
182            {
183                return false;
184            }
185
186            if param.is_mutable != other_param.is_mutable {
187                return false;
188            }
189        }
190
191        true
192    }
193}
194
195impl Type {
196    #[must_use]
197    pub const fn is_concrete(&self) -> bool {
198        !matches!(
199            self,
200            Self::Unit | Self::Never | Self::Variable(_) | Self::Generic(_, _) | Self::Blueprint(_)
201        )
202    }
203}
204
205impl Debug for Type {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        match self {
208            Self::Int => write!(f, "Int"),
209            Self::Float => write!(f, "Float"),
210            Self::String => write!(f, "String"),
211            Self::Bool => write!(f, "Bool"),
212            Self::Unit => write!(f, "()"),
213            Self::Never => write!(f, "!"),
214            Self::Tuple(tuple_type_ref) => write!(f, "( {tuple_type_ref:?} )"),
215            Self::NamedStruct(struct_type_ref) => {
216                write!(f, "{}", struct_type_ref.assigned_name)
217            }
218            Self::AnonymousStruct(anonymous_struct_type) => {
219                write!(f, "{anonymous_struct_type:?}")
220            }
221            Self::Enum(enum_type_ref) => write!(f, "{:?}", enum_type_ref.assigned_name),
222            Self::Function(function_type_signature) => {
223                write!(f, "{function_type_signature:?}")
224            }
225            Self::Optional(base_type) => write!(f, "{base_type:?}?"),
226            Self::MutableReference(base_type) => write!(f, "mut ref {base_type:?}?"),
227            Self::External(rust_type) => write!(f, "{:?}?", rust_type.type_name),
228            Self::Variable(variable_name) => write!(f, "<|{variable_name}|>"),
229            Self::Generic(blueprint, non_concrete_arguments) => {
230                write!(f, "{blueprint:?}<{non_concrete_arguments:?}>")
231            }
232            Self::Slice(value_type) => {
233                write!(f, "Slice<{value_type:?}>")
234            }
235            Self::SlicePair(key_type, value_type) => {
236                write!(f, "SlicePair<{key_type:?}, {value_type:?}>")
237            }
238            Self::Blueprint(blueprint) => {
239                write!(f, "{blueprint:?}")
240            }
241        }
242    }
243}
244
245impl Display for Type {
246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
247        match self {
248            Self::Int => write!(f, "Int"),
249            Self::Float => write!(f, "Float"),
250            Self::String => write!(f, "String"),
251            Self::Bool => write!(f, "Bool"),
252            Self::Unit => write!(f, "()"),
253            Self::Never => write!(f, "!"),
254            Self::Tuple(tuple) => write!(f, "({})", comma(tuple)),
255            Self::NamedStruct(struct_ref) => write!(f, "{}", struct_ref.assigned_name),
256            Self::AnonymousStruct(struct_ref) => write!(f, "{struct_ref:?}"),
257            Self::Enum(enum_type) => write!(f, "{}", enum_type.assigned_name),
258            Self::Function(signature) => write!(f, "function {signature}"),
259            Self::Optional(base_type) => write!(f, "{base_type}?"),
260            Self::MutableReference(base_type) => write!(f, "mut ref {base_type:?}?"),
261            Self::External(rust_type) => write!(f, "RustType {}", rust_type.type_name),
262            Self::Variable(variable_name) => write!(f, "<|{variable_name}|>"),
263
264            Self::Generic(blueprint, non_concrete_arguments) => {
265                write!(f, "{blueprint:?}<{non_concrete_arguments:?}>")
266            }
267            Self::Slice(value_type) => {
268                write!(f, "Slice<{value_type:?}>")
269            }
270            Self::SlicePair(key_type, value_type) => {
271                write!(f, "SlicePair<{key_type:?}, {value_type:?}>")
272            }
273            Self::Blueprint(blueprint) => {
274                write!(f, "{blueprint:?}")
275            }
276        }
277    }
278}
279
280impl Type {
281    #[must_use]
282    pub fn assignable_type(&self, other: &Self) -> bool {
283        if self.compatible_with(other) {
284            true
285        } else if let Self::Optional(inner_type) = self {
286            inner_type.compatible_with(other)
287        } else {
288            false
289        }
290    }
291
292    pub fn compatible_ignore_mutability_of(&self, other: &Self) -> bool {
293        if let Self::MutableReference(other_reference) = other {
294            self.compatible_with(other_reference)
295        } else {
296            self.compatible_with(other)
297        }
298    }
299
300    #[must_use]
301    pub fn compatible_with(&self, other: &Self) -> bool {
302        match (self, other) {
303            (Self::Function(a), Self::Function(b)) => a.same_type(b),
304
305            (_, Self::Never)
306            | (Self::Never, _)
307            | (Self::Int, Self::Int)
308            | (Self::Float, Self::Float)
309            | (Self::String, Self::String)
310            | (Self::Bool, Self::Bool)
311            | (Self::Unit, Self::Unit) => true,
312
313            (Self::Enum(a), Self::Enum(b)) => a == b,
314
315            (Self::NamedStruct(a), Self::NamedStruct(b)) => compare_struct_types(a, b),
316
317            (Self::AnonymousStruct(a), Self::AnonymousStruct(b)) => {
318                compare_anonymous_struct_types(a, b)
319            }
320            (Self::MutableReference(a), Self::MutableReference(b)) => a.compatible_with(b),
321
322            (Self::Tuple(a), Self::Tuple(b)) => {
323                if a.len() != b.len() {
324                    return false;
325                }
326                a.iter().zip(b.iter()).all(|(a, b)| a.compatible_with(b))
327            }
328
329            (Self::Optional(inner_type_a), Self::Optional(inner_type_b)) => {
330                inner_type_a.compatible_with(inner_type_b)
331            }
332
333            (Self::Generic(blueprint_a, args_a), Self::Generic(blueprint_b, args_b)) => {
334                blueprint_a == blueprint_b && (args_a == args_b)
335            }
336
337            (
338                Self::SlicePair(a_key_type, a_value_type),
339                Self::SlicePair(b_key_type, b_value_type),
340            ) => a_key_type == b_key_type && (a_value_type == b_value_type),
341            (Self::Slice(inner_type_a), Self::Slice(inner_type_b)) => {
342                inner_type_a.compatible_with(inner_type_b)
343            }
344
345            (Self::Blueprint(a), Self::Blueprint(b)) => a == b,
346
347            (Self::Variable(a), Self::Variable(b)) => a == b,
348
349            (Self::External(type_ref_a), Self::External(type_ref_b)) => {
350                type_ref_a.number == type_ref_b.number
351            }
352
353            _ => false,
354        }
355    }
356}
357
358fn compare_struct_types(a: &NamedStructType, b: &NamedStructType) -> bool {
359    let a_borrow = a;
360    let b_borrow = b;
361
362    if a_borrow.assigned_name != b_borrow.assigned_name {
363        return false;
364    }
365
366    compare_anonymous_struct_types(&a_borrow.anon_struct_type, &b_borrow.anon_struct_type)
367}
368
369#[must_use]
370pub fn same_anon_struct_ref(a: &AnonymousStructType, b: &AnonymousStructType) -> bool {
371    compare_anonymous_struct_types(a, b)
372}
373
374pub fn same_named_struct_ref(a: &NamedStructType, b: &NamedStructType) -> bool {
375    if a.assigned_name != b.assigned_name {
376        return false;
377    }
378
379    compare_anonymous_struct_types(&a.anon_struct_type, &b.anon_struct_type)
380}
381
382#[must_use]
383pub fn compare_anonymous_struct_types(a: &AnonymousStructType, b: &AnonymousStructType) -> bool {
384    if a.field_name_sorted_fields.len() != b.field_name_sorted_fields.len() {
385        return false;
386    }
387
388    for ((a_name, a_type), (b_name, b_type)) in a
389        .field_name_sorted_fields
390        .iter()
391        .zip(b.field_name_sorted_fields.clone())
392    {
393        if *a_name != b_name {
394            return false;
395        }
396
397        if !a_type.field_type.compatible_with(&b_type.field_type) {
398            return false;
399        }
400    }
401
402    true
403}
404
405#[must_use]
406pub fn check_assignable_anonymous_struct_types(
407    a: &AnonymousStructType,
408    b: &AnonymousStructType,
409) -> bool {
410    if a.field_name_sorted_fields.len() != b.field_name_sorted_fields.len() {
411        return false;
412    }
413
414    for (name, field) in &a.field_name_sorted_fields {
415        if let Some(found_field) = b.field_name_sorted_fields.get(name) {
416            if !found_field.field_type.compatible_with(&field.field_type) {
417                return false;
418            }
419        } else {
420            return false;
421        }
422    }
423
424    true
425}
426
427#[must_use]
428pub fn comma_seq<K: Clone + Hash + Eq + Display, V: Display>(values: &SeqMap<K, V>) -> String {
429    let mut result = String::new();
430    for (i, (key, value)) in values.iter().enumerate() {
431        if i > 0 {
432            result.push_str(", ");
433        }
434        result.push_str(format!("{key}: {value}").as_str());
435    }
436    result
437}
438
439#[must_use]
440pub fn comma_seq_nl<K: Clone + Hash + Eq + Display, V: Display>(
441    values: &SeqMap<K, V>,
442    prefix: &str,
443) -> String {
444    let mut result = String::new();
445    for (key, value) in values.iter() {
446        result.push_str(format!("{prefix}{key}: {value}\n").as_str());
447    }
448    result
449}
450
451#[derive(Clone, Eq, PartialEq, Hash)]
452pub struct StructTypeField {
453    pub identifier: Option<Node>,
454    pub field_type: Type,
455}
456
457impl Display for StructTypeField {
458    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
459        write!(f, "{:?}:{}", self.identifier, self.field_type)
460    }
461}
462
463#[derive(Clone, Eq, PartialEq, Hash)]
464pub struct AnonymousStructType {
465    //pub source_ordered_fields: SeqMap<String, StructTypeField>,
466    pub field_name_sorted_fields: SeqMap<String, StructTypeField>,
467}
468
469impl Debug for AnonymousStructType {
470    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
471        write!(f, "{}", comma_seq(&self.field_name_sorted_fields))
472    }
473}
474
475#[must_use]
476pub fn sort_struct_fields2(
477    unordered_seq_map: &SeqMap<String, StructTypeField>,
478) -> SeqMap<String, StructTypeField> {
479    let mut sorted_pairs: Vec<(&String, &StructTypeField)> = unordered_seq_map.iter().collect();
480    sorted_pairs.sort_by(|a, b| a.0.cmp(b.0));
481
482    sorted_pairs
483        .into_iter()
484        .map(|(name, field)| (name.clone(), field.clone()))
485        .collect()
486}
487
488impl AnonymousStructType {
489    #[must_use]
490    pub fn new_and_sort_fields(source_ordered_fields: &SeqMap<String, StructTypeField>) -> Self {
491        Self {
492            field_name_sorted_fields: sort_struct_fields2(source_ordered_fields),
493        }
494    }
495
496    #[must_use]
497    pub const fn new(defined_order: SeqMap<String, StructTypeField>) -> Self {
498        Self {
499            field_name_sorted_fields: defined_order,
500        }
501    }
502}
503
504#[derive(Clone, Debug, Eq, PartialEq, Hash)]
505pub struct EnumVariantStructType {
506    pub common: EnumVariantCommon,
507    pub anon_struct: AnonymousStructType,
508}
509
510#[derive(Clone, Debug, Eq, PartialEq, Hash)]
511pub struct EnumVariantTupleType {
512    pub common: EnumVariantCommon,
513    pub fields_in_order: Vec<Type>,
514}
515
516#[derive(Clone, Eq, PartialEq, Hash)]
517pub struct EnumType {
518    pub name: Node,
519    pub assigned_name: String,
520    pub module_path: Vec<String>,
521    pub variants: SeqMap<String, EnumVariantType>,
522    pub instantiated_type_parameters: Vec<Type>,
523}
524
525impl Debug for EnumType {
526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
527        write!(f, "{}", self.assigned_name)?;
528        let s = comma(
529            &self
530                .variants
531                .iter()
532                .map(|(name, _variant)| name)
533                .collect::<Vec<&String>>(),
534        );
535        write!(f, "{{ {s} }}")
536    }
537}
538
539impl EnumType {
540    #[must_use]
541    pub fn new(name: Node, assigned_name: &str, module_path: Vec<String>) -> Self {
542        Self {
543            name,
544            assigned_name: assigned_name.to_string(),
545            module_path,
546            variants: SeqMap::new(),
547            instantiated_type_parameters: Vec::default(),
548        }
549    }
550
551    #[must_use]
552    pub const fn name(&self) -> &Node {
553        &self.name
554    }
555
556    #[must_use]
557    pub fn get_variant(&self, name: &str) -> Option<&EnumVariantType> {
558        self.variants.get(&name.to_string())
559    }
560
561    #[must_use]
562    pub fn get_variant_from_index(&self, index: usize) -> Option<&EnumVariantType> {
563        Some(self.variants.values().collect::<Vec<_>>()[index])
564    }
565}
566
567#[derive(Clone, Eq, PartialEq, Hash)]
568pub struct EnumVariantCommon {
569    pub name: Node,
570    pub assigned_name: String,
571    pub container_index: u8,
572}
573
574impl Debug for EnumVariantCommon {
575    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
576        write!(f, "{}::{}", self.assigned_name, self.assigned_name)
577    }
578}
579
580#[derive(Debug)]
581pub struct EnumVariantStructFieldType {
582    pub name: Node,
583    pub enum_variant: EnumVariantType,
584    pub resolved_type: Type,
585
586    pub field_index: usize,
587}
588
589#[derive(Debug, Eq, PartialEq)]
590pub struct EnumVariantTupleFieldType {
591    pub name: Node,
592    pub enum_variant: EnumVariantType,
593    pub resolved_type: Type,
594
595    pub field_index: usize,
596}
597
598#[derive(Clone, Debug, Eq, PartialEq, Hash)]
599pub struct EnumVariantSimpleType {
600    pub common: EnumVariantCommon,
601}
602
603#[derive(Clone, Eq, PartialEq, Hash)]
604pub enum EnumVariantType {
605    Struct(EnumVariantStructType),
606    Tuple(EnumVariantTupleType),
607    Nothing(EnumVariantSimpleType),
608}
609impl EnumVariantType {
610    #[must_use]
611    pub const fn common(&self) -> &EnumVariantCommon {
612        match self {
613            Self::Tuple(tuple) => &tuple.common,
614            Self::Struct(c) => &c.common,
615            Self::Nothing(c) => &c.common,
616        }
617    }
618}
619
620impl Debug for EnumVariantType {
621    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
622        match self {
623            Self::Struct(x) => write!(f, "{{ {x:?} }}"),
624            Self::Tuple(x) => write!(f, "({x:?})"),
625            Self::Nothing(_x) => Ok(()),
626        }
627    }
628}
629
630#[derive(Debug, Clone)]
631pub struct AliasType {
632    pub name: Node,
633    pub assigned_name: String,
634    pub referenced_type: Type,
635}
636
637#[derive(Clone, PartialEq, Eq, Hash)]
638pub struct NamedStructType {
639    pub name: Node,
640    pub module_path: Vec<String>,
641    pub assigned_name: String,
642    pub anon_struct_type: AnonymousStructType,
643    pub instantiated_type_parameters: Vec<Type>,
644    pub blueprint_info: Option<ParameterizedTypeBlueprintInfo>,
645}
646
647impl Debug for NamedStructType {
648    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
649        write!(
650            f,
651            "struct {} anon: {:?}",
652            self.assigned_name, self.anon_struct_type
653        )
654    }
655}
656
657impl NamedStructType {
658    #[must_use]
659    pub fn new(
660        name: Node,
661        assigned_name: &str,
662        anon_struct_type: AnonymousStructType,
663        module_path: &[String],
664        blueprint_info: Option<ParameterizedTypeBlueprintInfo>,
665    ) -> Self {
666        Self {
667            //defined_in_module,
668            anon_struct_type,
669            name,
670            module_path: module_path.to_vec(),
671            assigned_name: assigned_name.to_string(),
672            instantiated_type_parameters: Vec::default(),
673            blueprint_info,
674        }
675    }
676
677    #[must_use]
678    pub fn field_index(&self, field_name: &str) -> Option<usize> {
679        self.anon_struct_type
680            .field_name_sorted_fields
681            .get_index(&field_name.to_string())
682    }
683
684    #[must_use]
685    pub const fn name(&self) -> &Node {
686        &self.name
687    }
688}
689
690pub fn all_types_are_concrete(types: &[Type]) -> bool {
691    for ty in types {
692        if !ty.is_concrete() {
693            return false;
694        }
695    }
696    true
697}
698
699pub fn all_types_are_concrete_or_unit(types: &[Type]) -> bool {
700    for ty in types {
701        if !ty.is_concrete() && *ty != Type::Unit {
702            return false;
703        }
704    }
705    true
706}
707
708pub fn all_types_are_variables(types: &[Type]) -> bool {
709    for ty in types {
710        if let Type::Variable(_) = ty {
711        } else {
712            return false;
713        }
714    }
715    true
716}