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