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