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