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