swamp_script_types/
lib.rs

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