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