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