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