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