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