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