1pub 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 Int,
21 Float,
22 String,
23 Bool,
24
25 Unit, Never, Slice(Box<Type>),
29 SlicePair(Box<Type>, Box<Type>),
30
31 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, pub number: u32, }
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 !¶m
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 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 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}