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, 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, pub number: u32, }
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 !¶m
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 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 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}