1use self::{environment::Environment, pretty::Printer};
2use crate::{
3 ast::{
4 Annotation, DataType, DataTypeKey, DefinitionLocation, ModuleKind, Span, TypedDataType,
5 well_known,
6 },
7 tipo::fields::FieldMap,
8};
9use indexmap::IndexMap;
10use itertools::Itertools;
11use std::{cell::RefCell, collections::HashMap, ops::Deref, rc::Rc};
12use uplc::{ast::Type as UplcType, builtins::DefaultFunction};
13
14pub(crate) mod environment;
15pub mod error;
16mod exhaustive;
17pub(crate) mod expr;
18pub mod fields;
19mod hydrator;
20mod infer;
21mod pattern;
22mod pipe;
23pub mod pretty;
24
25#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
26pub struct TypeAliasAnnotation {
27 pub module: Option<String>,
28 pub alias: String,
29 pub parameters: Vec<String>,
30 pub annotation: Annotation,
31}
32
33#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
34pub enum Type {
35 App {
44 public: bool,
45 contains_opaque: bool,
46 module: String,
47 name: String,
48 args: Vec<Rc<Type>>,
49 alias: Option<Rc<TypeAliasAnnotation>>,
50 },
51
52 Fn {
55 args: Vec<Rc<Type>>,
56 ret: Rc<Type>,
57 alias: Option<Rc<TypeAliasAnnotation>>,
58 },
59
60 Var {
63 tipo: Rc<RefCell<TypeVar>>,
64 alias: Option<Rc<TypeAliasAnnotation>>,
65 },
66 Tuple {
71 elems: Vec<Rc<Type>>,
72 alias: Option<Rc<TypeAliasAnnotation>>,
73 },
74
75 Pair {
76 fst: Rc<Type>,
77 snd: Rc<Type>,
78 alias: Option<Rc<TypeAliasAnnotation>>,
79 },
80}
81
82impl PartialEq for Type {
83 fn eq(&self, other: &Type) -> bool {
84 match self {
85 Type::App {
86 public,
87 module,
88 name,
89 args,
90 contains_opaque: _,
91 alias: _,
92 } => {
93 if let Type::App {
94 public: public2,
95 module: module2,
96 name: name2,
97 args: args2,
98 contains_opaque: _,
99 alias: _,
100 } = other
101 {
102 name == name2
103 && module == module2
104 && public == public2
105 && args.len() == args2.len()
106 && args.iter().zip(args2).all(|(left, right)| left == right)
107 } else {
108 false
109 }
110 }
111
112 Type::Fn { args, ret, .. } => {
113 if let Type::Fn {
114 args: args2,
115 ret: ret2,
116 alias: _,
117 } = other
118 {
119 ret == ret2
120 && args.len() == args2.len()
121 && args.iter().zip(args2).all(|(left, right)| left == right)
122 } else {
123 false
124 }
125 }
126
127 Type::Tuple { elems, alias: _ } => {
128 if let Type::Tuple { elems: elems2, .. } = other {
129 elems.len() == elems2.len()
130 && elems.iter().zip(elems2).all(|(left, right)| left == right)
131 } else {
132 false
133 }
134 }
135
136 Type::Var { tipo, alias: _ } => {
137 if let Type::Var {
138 tipo: tipo2,
139 alias: _,
140 } = other
141 {
142 tipo == tipo2
143 } else {
144 false
145 }
146 }
147 Type::Pair { fst, snd, .. } => {
148 if let Type::Pair {
149 fst: fst2,
150 snd: snd2,
151 ..
152 } = other
153 {
154 fst == fst2 && snd == snd2
155 } else {
156 false
157 }
158 }
159 }
160 }
161}
162
163impl Type {
164 pub fn collapse_links(t: Rc<Self>) -> Rc<Self> {
165 if let Type::Var { tipo, alias } = t.deref() {
166 if let TypeVar::Link { tipo } = tipo.borrow().deref() {
167 return Type::with_alias(tipo.clone(), alias.clone());
168 }
169 }
170 t
171 }
172
173 pub fn alias(&self) -> Option<Rc<TypeAliasAnnotation>> {
174 match self {
175 Type::App { alias, .. }
176 | Type::Fn { alias, .. }
177 | Type::Var { alias, .. }
178 | Type::Tuple { alias, .. }
179 | Type::Pair { alias, .. } => alias.clone(),
180 }
181 }
182
183 pub fn with_alias(tipo: Rc<Type>, alias: Option<Rc<TypeAliasAnnotation>>) -> Rc<Type> {
184 match alias {
185 None => tipo,
186 Some(alias) => tipo.deref().to_owned().set_alias(Some(alias)),
187 }
188 }
189
190 pub fn set_alias(self, alias: Option<Rc<TypeAliasAnnotation>>) -> Rc<Type> {
191 Rc::new(match self {
192 Type::App {
193 public,
194 contains_opaque: opaque,
195 module,
196 name,
197 args,
198 alias: _,
199 } => Type::App {
200 public,
201 contains_opaque: opaque,
202 module,
203 name,
204 args,
205 alias,
206 },
207 Type::Fn {
208 args,
209 ret,
210 alias: _,
211 } => Type::Fn { args, ret, alias },
212 Type::Var { tipo, alias: _ } => Type::Var { tipo, alias },
213 Type::Tuple { elems, alias: _ } => Type::Tuple { elems, alias },
214 Type::Pair { fst, snd, alias: _ } => Type::Pair { fst, snd, alias },
215 })
216 }
217
218 pub fn qualifier(&self) -> Option<(String, String)> {
219 match self {
220 Type::App { module, name, .. } => Some((module.to_string(), name.to_string())),
221 Type::Fn { .. } => None,
222 Type::Var { tipo, .. } => match &*tipo.borrow() {
223 TypeVar::Link { tipo } => tipo.qualifier(),
224 _ => None,
225 },
226 Type::Tuple { .. } => Some((String::new(), "Tuple".to_string())),
227 Type::Pair { .. } => Some((String::new(), "Pair".to_string())),
228 }
229 }
230
231 pub fn contains_opaque(&self) -> bool {
232 match self {
233 Type::Var { tipo, .. } => tipo.borrow().is_or_holds_opaque(),
234 Type::App {
235 contains_opaque: opaque,
236 args,
237 ..
238 } => *opaque || args.iter().any(|arg| arg.contains_opaque()),
239 Type::Tuple { elems, .. } => elems.iter().any(|elem| elem.contains_opaque()),
240 Type::Fn { .. } => false,
241 Type::Pair { fst, snd, .. } => fst.contains_opaque() || snd.contains_opaque(),
242 }
243 }
244
245 pub fn set_opaque(&mut self, opaque: bool) {
246 match self {
247 Type::App {
248 contains_opaque, ..
249 } => {
250 *contains_opaque = opaque;
251 }
252 Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } | Type::Pair { .. } => (),
253 }
254 }
255
256 pub fn is_unbound(&self) -> bool {
257 matches!(self, Self::Var { tipo, .. } if tipo.borrow().is_unbound())
258 }
259
260 pub fn is_function(&self) -> bool {
261 matches!(self, Self::Fn { .. })
262 }
263
264 pub fn return_type(&self) -> Option<Rc<Self>> {
265 match self {
266 Self::Fn { ret, .. } => Some(ret.clone()),
267 _ => None,
268 }
269 }
270
271 pub fn function_types(&self) -> Option<(Vec<Rc<Self>>, Rc<Self>)> {
272 match self {
273 Self::Fn { args, ret, .. } => Some((args.clone(), ret.clone())),
274 _ => None,
275 }
276 }
277
278 pub fn is_primitive(&self) -> bool {
279 let uplc_type = self.get_uplc_type();
280 match uplc_type {
281 Some(
282 UplcType::Bool
283 | UplcType::Integer
284 | UplcType::String
285 | UplcType::ByteString
286 | UplcType::Unit
287 | UplcType::Bls12_381G1Element
288 | UplcType::Bls12_381G2Element
289 | UplcType::Bls12_381MlResult
290 | UplcType::Data,
291 ) => true,
292
293 None => false,
294 Some(UplcType::List(_) | UplcType::Pair(_, _)) => false,
295 }
296 }
297
298 pub fn is_void(&self) -> bool {
299 match self {
300 Self::App { module, name, .. } if "Void" == name && module.is_empty() => true,
301 Self::Var { tipo, .. } => tipo.borrow().is_void(),
302 _ => false,
303 }
304 }
305
306 pub fn is_bool(&self) -> bool {
307 match self {
308 Self::App { module, name, .. } if "Bool" == name && module.is_empty() => true,
309 Self::Var { tipo, .. } => tipo.borrow().is_bool(),
310 _ => false,
311 }
312 }
313
314 pub fn is_int(&self) -> bool {
315 match self {
316 Self::App { module, name, .. } if well_known::INT == name && module.is_empty() => true,
317 Self::Var { tipo, .. } => tipo.borrow().is_int(),
318 _ => false,
319 }
320 }
321
322 pub fn is_bytearray(&self) -> bool {
323 match self {
324 Self::App { module, name, .. }
325 if well_known::BYTE_ARRAY == name && module.is_empty() =>
326 {
327 true
328 }
329 Self::Var { tipo, .. } => tipo.borrow().is_bytearray(),
330 _ => false,
331 }
332 }
333
334 pub fn is_bls381_12_g1(&self) -> bool {
335 match self {
336 Self::App { module, name, .. } => well_known::G1_ELEMENT == name && module.is_empty(),
337
338 Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g1(),
339 _ => false,
340 }
341 }
342
343 pub fn is_bls381_12_g2(&self) -> bool {
344 match self {
345 Self::App { module, name, .. } => well_known::G2_ELEMENT == name && module.is_empty(),
346
347 Self::Var { tipo, .. } => tipo.borrow().is_bls381_12_g2(),
348 _ => false,
349 }
350 }
351
352 pub fn is_ml_result(&self) -> bool {
353 match self {
354 Self::App { module, name, .. } => {
355 well_known::MILLER_LOOP_RESULT == name && module.is_empty()
356 }
357
358 Self::Var { tipo, .. } => tipo.borrow().is_ml_result(),
359 _ => false,
360 }
361 }
362
363 pub fn is_string(&self) -> bool {
364 match self {
365 Self::App { module, name, .. } if "String" == name && module.is_empty() => true,
366 Self::Var { tipo, .. } => tipo.borrow().is_string(),
367 _ => false,
368 }
369 }
370
371 pub fn is_list(&self) -> bool {
372 match self {
373 Self::App { module, name, .. } if "List" == name && module.is_empty() => true,
374 Self::Var { tipo, .. } => tipo.borrow().is_list(),
375 _ => false,
376 }
377 }
378
379 pub fn is_option(&self) -> bool {
380 match self {
381 Self::App { module, name, .. } if "Option" == name && module.is_empty() => true,
382 Self::Var { tipo, .. } => tipo.borrow().is_option(),
383 _ => false,
384 }
385 }
386
387 pub fn is_map(&self) -> bool {
388 match self {
389 Self::App {
390 module, name, args, ..
391 } if "List" == name && module.is_empty() => args
392 .first()
393 .expect("unreachable: List should have an inner type")
394 .is_pair(),
395 Self::Var { tipo, .. } => tipo.borrow().is_map(),
396 _ => false,
397 }
398 }
399
400 pub fn is_tuple(&self) -> bool {
401 match self {
402 Self::Var { tipo, .. } => tipo.borrow().is_tuple(),
403 Self::Tuple { .. } => true,
404 _ => false,
405 }
406 }
407
408 pub fn is_pair(&self) -> bool {
409 match self {
410 Self::Var { tipo, .. } => tipo.borrow().is_pair(),
411 Self::Pair { .. } => true,
412 _ => false,
413 }
414 }
415
416 pub fn is_data(&self) -> bool {
417 match self {
418 Self::App { module, name, .. } => "Data" == name && module.is_empty(),
419 Self::Var { tipo, .. } => tipo.borrow().is_data(),
420 _ => false,
421 }
422 }
423
424 pub fn is_monomorphic(&self) -> bool {
428 match self {
429 Self::App { args, .. } => args.iter().all(|arg| arg.is_monomorphic()),
430 Self::Fn { args, ret, .. } => {
431 args.iter().all(|arg| arg.is_monomorphic()) && ret.is_monomorphic()
432 }
433 Self::Tuple { elems, .. } => elems.iter().all(|arg| arg.is_monomorphic()),
434 Self::Pair { fst, snd, .. } => [fst, snd].iter().all(|arg| arg.is_monomorphic()),
435 Self::Var { tipo, .. } => tipo.borrow().is_monomorphic(),
436 }
437 }
438
439 pub fn is_generic(&self) -> bool {
440 !self.collect_generics().is_empty()
441 }
442
443 pub fn collect_generics(&self) -> Vec<Rc<Type>> {
444 match self {
445 Self::App { args, .. } => args.iter().flat_map(|arg| arg.collect_generics()).collect(),
446 Self::Var { tipo, .. } => {
447 if tipo.borrow().is_generic() {
448 vec![self.clone().into()]
449 } else {
450 Vec::new()
451 }
452 }
453 Self::Tuple { elems, .. } => elems
454 .iter()
455 .flat_map(|arg| arg.collect_generics())
456 .collect(),
457 Self::Fn { args, ret, .. } => args
458 .iter()
459 .chain(std::iter::once(ret))
460 .flat_map(|arg| arg.collect_generics())
461 .collect(),
462 Self::Pair { fst, snd, .. } => {
463 let mut generics = fst.collect_generics();
464 generics.extend(snd.collect_generics());
465 generics
466 }
467 }
468 }
469
470 pub fn arg_types(&self) -> Option<Vec<Rc<Self>>> {
475 match self {
476 Self::Fn { args, .. } => Some(args.clone()),
477 Self::App { args, .. } => Some(args.clone()),
478 Self::Var { tipo, .. } => tipo.borrow().arg_types(),
479 _ => None,
480 }
481 }
482
483 pub fn get_generic_id(&self) -> Option<u64> {
484 match self {
485 Self::Var { tipo, .. } => tipo.borrow().get_generic(),
486 _ => None,
487 }
488 }
489
490 pub fn get_inner_types(&self) -> Vec<Rc<Type>> {
491 if self.is_list() {
492 match self {
493 Self::App { args, .. } => args.clone(),
494 Self::Var { tipo, .. } => tipo.borrow().get_inner_types(),
495 _ => vec![],
496 }
497 } else if self.is_tuple() {
498 match self {
499 Self::Tuple { elems, .. } => elems.to_vec(),
500 Self::Var { tipo, .. } => tipo.borrow().get_inner_types(),
501 _ => vec![],
502 }
503 } else if self.is_pair() {
504 match self {
505 Self::Pair { fst, snd, .. } => vec![fst.clone(), snd.clone()],
506 Self::Var { tipo, .. } => tipo.borrow().get_inner_types(),
507 _ => vec![],
508 }
509 } else if self.get_uplc_type().is_none() {
510 match self {
511 Type::App { args, .. } => args.clone(),
512 Type::Fn { args, ret, .. } => {
513 let mut args = args.clone();
514 args.push(ret.clone());
515 args
516 }
517 Type::Var { tipo, .. } => tipo.borrow().get_inner_types(),
518 _ => unreachable!(),
519 }
520 } else {
521 vec![]
522 }
523 }
524
525 pub fn get_uplc_type(&self) -> Option<UplcType> {
526 if self.is_int() {
527 Some(UplcType::Integer)
528 } else if self.is_bytearray() {
529 Some(UplcType::ByteString)
530 } else if self.is_string() {
531 Some(UplcType::String)
532 } else if self.is_bool() {
533 Some(UplcType::Bool)
534 } else if self.is_void() {
535 Some(UplcType::Unit)
536 } else if self.is_map() {
537 Some(UplcType::List(
538 UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()).into(),
539 ))
540 } else if self.is_list() || self.is_tuple() {
541 Some(UplcType::List(UplcType::Data.into()))
542 } else if self.is_pair() {
543 Some(UplcType::Pair(UplcType::Data.into(), UplcType::Data.into()))
544 } else if self.is_bls381_12_g1() {
545 Some(UplcType::Bls12_381G1Element)
546 } else if self.is_bls381_12_g2() {
547 Some(UplcType::Bls12_381G2Element)
548 } else if self.is_ml_result() {
549 Some(UplcType::Bls12_381MlResult)
550 } else if self.is_data() {
551 Some(UplcType::Data)
552 } else {
553 None
554 }
555 }
556
557 pub fn get_app_args(
562 &self,
563 public: bool,
564 opaque: bool,
565 module: &str,
566 name: &str,
567 arity: usize,
568 environment: &mut Environment<'_>,
569 ) -> Option<Vec<Rc<Self>>> {
570 match self {
571 Self::App {
572 module: m,
573 name: n,
574 args,
575 ..
576 } => {
577 if module == m && name == n && args.len() == arity {
578 Some(args.clone())
579 } else {
580 None
581 }
582 }
583
584 Self::Var { tipo, alias } => {
585 let args: Vec<_> = match tipo.borrow().deref() {
586 TypeVar::Link { tipo } => {
587 return tipo.get_app_args(public, opaque, module, name, arity, environment);
588 }
589
590 TypeVar::Unbound { .. } => {
591 (0..arity).map(|_| environment.new_unbound_var()).collect()
592 }
593
594 TypeVar::Generic { .. } => return None,
595 };
596
597 *tipo.borrow_mut() = TypeVar::Link {
600 tipo: Rc::new(Self::App {
601 public,
602 contains_opaque: opaque,
603 name: name.to_string(),
604 module: module.to_owned(),
605 args: args.clone(),
606 alias: alias.to_owned(),
607 }),
608 };
609 Some(args)
610 }
611
612 _ => None,
613 }
614 }
615
616 pub fn find_private_type(&self) -> Option<Self> {
617 match self {
618 Self::App { public: false, .. } => Some(self.clone()),
619
620 Self::App { args, .. } => args.iter().find_map(|t| t.find_private_type()),
621
622 Self::Tuple { elems, .. } => elems.iter().find_map(|t| t.find_private_type()),
623 Self::Fn { ret, args, .. } => ret
624 .find_private_type()
625 .or_else(|| args.iter().find_map(|t| t.find_private_type())),
626
627 Self::Var { tipo, .. } => match tipo.borrow().deref() {
628 TypeVar::Unbound { .. } => None,
629
630 TypeVar::Generic { .. } => None,
631
632 TypeVar::Link { tipo, .. } => tipo.find_private_type(),
633 },
634 Self::Pair { fst, snd, .. } => {
635 if let Some(private_type) = fst.find_private_type() {
636 Some(private_type)
637 } else {
638 snd.find_private_type()
639 }
640 }
641 }
642 }
643
644 pub fn fn_arity(&self) -> Option<usize> {
645 match self {
646 Self::Fn { args, .. } => Some(args.len()),
647 _ => None,
648 }
649 }
650
651 pub fn to_pretty(&self, indent: usize) -> String {
652 Printer::new().pretty_print(self, indent)
653 }
654
655 pub fn to_pretty_with_names(&self, names: HashMap<u64, String>, indent: usize) -> String {
656 let mut printer = Printer::new();
657
658 printer.with_names(names);
659
660 printer.pretty_print(self, indent)
661 }
662}
663
664pub fn lookup_data_type_by_tipo(
665 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
666 tipo: &Type,
667) -> Option<DataType<Rc<Type>>> {
668 match tipo {
669 Type::Fn { ret, .. } => match ret.as_ref() {
670 Type::App { module, name, .. } => {
671 let data_type_key = DataTypeKey {
672 module_name: module.clone(),
673 defined_type: name.clone(),
674 };
675 data_types.get(&data_type_key).map(|item| (*item).clone())
676 }
677 _ => None,
678 },
679 Type::App { module, name, .. } => {
680 let data_type_key = DataTypeKey {
681 module_name: module.clone(),
682 defined_type: name.clone(),
683 };
684
685 data_types.get(&data_type_key).map(|item| (*item).clone())
686 }
687 Type::Var { tipo, .. } => {
688 if let TypeVar::Link { tipo } = &*tipo.borrow() {
689 lookup_data_type_by_tipo(data_types, tipo)
690 } else {
691 None
692 }
693 }
694 _ => None,
695 }
696}
697
698pub fn get_generic_id_and_type(tipo: &Type, param: &Type) -> Vec<(u64, Rc<Type>)> {
699 let mut generics_ids = vec![];
700
701 if let Some(id) = tipo.get_generic_id() {
702 generics_ids.push((id, param.clone().into()));
703 return generics_ids;
704 }
705
706 for (tipo, param_type) in tipo
707 .get_inner_types()
708 .iter()
709 .zip(param.get_inner_types().iter())
710 {
711 generics_ids.append(&mut get_generic_id_and_type(tipo, param_type));
712 }
713 generics_ids
714}
715
716pub fn get_arg_type_name(tipo: &Type) -> String {
717 match tipo {
718 Type::App { name, args, .. } => {
719 let inner_args = args.iter().map(|arg| get_arg_type_name(arg)).collect_vec();
720 format!("{}_{}", name, inner_args.join("_"))
721 }
722 Type::Var { tipo, .. } => match tipo.borrow().clone() {
723 TypeVar::Link { tipo } => get_arg_type_name(tipo.as_ref()),
724 _ => unreachable!(),
725 },
726 Type::Tuple { elems, .. } => {
727 let inner_args = elems.iter().map(|arg| get_arg_type_name(arg)).collect_vec();
728 inner_args.join("_")
729 }
730 Type::Pair { fst, snd, .. } => {
731 let inner_args = [fst, snd]
732 .iter()
733 .map(|arg| get_arg_type_name(arg))
734 .collect_vec();
735 inner_args.join("_")
736 }
737 _ => unreachable!("WTF {:#?}", tipo),
738 }
739}
740
741pub fn convert_opaque_type(
742 t: &Rc<Type>,
743 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
744 deep: bool,
745) -> Rc<Type> {
746 if check_replaceable_opaque_type(t, data_types) && matches!(t.as_ref(), Type::App { .. }) {
747 let data_type = lookup_data_type_by_tipo(data_types, t).unwrap();
748
749 let new_type_fields = data_type.typed_parameters;
750
751 let mut mono_type_vec = vec![];
752
753 for (tipo, param) in new_type_fields.iter().zip(t.arg_types().unwrap()) {
754 mono_type_vec.append(&mut get_generic_id_and_type(tipo, ¶m));
755 }
756 let mono_types = mono_type_vec.into_iter().collect();
757
758 let generic_type = &data_type.constructors[0].arguments[0].tipo;
759
760 let mono_type = find_and_replace_generics(generic_type, &mono_types);
761
762 if deep {
763 convert_opaque_type(&mono_type, data_types, deep)
764 } else {
765 mono_type
766 }
767 } else {
768 match t.as_ref() {
769 Type::App {
770 public,
771 contains_opaque: opaque,
772 module,
773 name,
774 args,
775 alias,
776 } => {
777 let mut new_args = vec![];
778 for arg in args {
779 let arg = convert_opaque_type(arg, data_types, deep);
780 new_args.push(arg);
781 }
782 Type::App {
783 public: *public,
784 contains_opaque: *opaque,
785 module: module.clone(),
786 name: name.clone(),
787 args: new_args,
788 alias: alias.clone(),
789 }
790 .into()
791 }
792 Type::Fn { args, ret, alias } => {
793 let mut new_args = vec![];
794 for arg in args {
795 let arg = convert_opaque_type(arg, data_types, deep);
796 new_args.push(arg);
797 }
798
799 let ret = convert_opaque_type(ret, data_types, deep);
800
801 Type::Fn {
802 args: new_args,
803 ret,
804 alias: alias.clone(),
805 }
806 .into()
807 }
808 Type::Var { tipo: var_tipo, .. } => {
809 if let TypeVar::Link { tipo } = &var_tipo.borrow().clone() {
810 convert_opaque_type(tipo, data_types, deep)
811 } else {
812 t.clone()
813 }
814 }
815 Type::Tuple { elems, alias } => {
816 let mut new_elems = vec![];
817 for arg in elems {
818 let arg = convert_opaque_type(arg, data_types, deep);
819 new_elems.push(arg);
820 }
821 Type::Tuple {
822 elems: new_elems,
823 alias: alias.clone(),
824 }
825 .into()
826 }
827 Type::Pair { fst, snd, alias } => {
828 let fst = convert_opaque_type(fst, data_types, deep);
829 let snd = convert_opaque_type(snd, data_types, deep);
830 Type::Pair {
831 fst,
832 snd,
833 alias: alias.clone(),
834 }
835 .into()
836 }
837 }
838 }
839}
840
841pub fn check_replaceable_opaque_type(
842 t: &Type,
843 data_types: &IndexMap<&DataTypeKey, &TypedDataType>,
844) -> bool {
845 let data_type = lookup_data_type_by_tipo(data_types, t);
846
847 if let Some(data_type) = data_type {
848 if let [constructor] = &data_type.constructors[..] {
849 return constructor.arguments.len() == 1
850 && data_type.opaque
851 && data_type
854 .decorators.is_empty();
855 }
856 }
857
858 false
859}
860
861pub fn find_and_replace_generics(
862 tipo: &Rc<Type>,
863 mono_types: &IndexMap<u64, Rc<Type>>,
864) -> Rc<Type> {
865 if let Some(id) = tipo.get_generic_id() {
866 mono_types
867 .get(&id)
868 .unwrap_or_else(|| {
869 panic!("Unknown generic id {id:?} for type {tipo:?} in mono_types {mono_types:#?}");
870 })
871 .clone()
872 } else if tipo.is_generic() {
873 match &**tipo {
874 Type::App {
875 args,
876 public,
877 contains_opaque: opaque,
878 module,
879 name,
880 alias,
881 } => {
882 let mut new_args = vec![];
883 for arg in args {
884 let arg = find_and_replace_generics(arg, mono_types);
885 new_args.push(arg);
886 }
887 let t = Type::App {
888 args: new_args,
889 public: *public,
890 contains_opaque: *opaque,
891 module: module.clone(),
892 name: name.clone(),
893 alias: alias.clone(),
894 };
895 t.into()
896 }
897 Type::Fn { args, ret, alias } => {
898 let mut new_args = vec![];
899 for arg in args {
900 let arg = find_and_replace_generics(arg, mono_types);
901 new_args.push(arg);
902 }
903
904 let ret = find_and_replace_generics(ret, mono_types);
905
906 let t = Type::Fn {
907 args: new_args,
908 ret,
909 alias: alias.clone(),
910 };
911
912 t.into()
913 }
914 Type::Tuple { elems, alias } => {
915 let mut new_elems = vec![];
916 for elem in elems {
917 let elem = find_and_replace_generics(elem, mono_types);
918 new_elems.push(elem);
919 }
920 let t = Type::Tuple {
921 elems: new_elems,
922 alias: alias.clone(),
923 };
924 t.into()
925 }
926 Type::Var { tipo: var_tipo, .. } => {
927 let var_type = var_tipo.as_ref().borrow().clone();
928
929 match var_type {
930 TypeVar::Link { tipo } => find_and_replace_generics(&tipo, mono_types),
931 TypeVar::Generic { .. } | TypeVar::Unbound { .. } => unreachable!(),
932 }
933 }
934 Type::Pair { fst, snd, alias } => {
935 let fst = find_and_replace_generics(fst, mono_types);
936 let snd = find_and_replace_generics(snd, mono_types);
937 Type::Pair {
938 fst,
939 snd,
940 alias: alias.clone(),
941 }
942 .into()
943 }
944 }
945 } else {
946 tipo.clone()
947 }
948}
949
950#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
951pub enum TypeVar {
952 Unbound { id: u64 },
958 Link { tipo: Rc<Type> },
962 Generic { id: u64 },
975}
976
977impl TypeVar {
978 pub fn is_monomorphic(&self) -> bool {
982 match self {
983 Self::Link { tipo } => tipo.is_monomorphic(),
984 Self::Unbound { .. } | Self::Generic { .. } => false,
985 }
986 }
987
988 pub fn is_unbound(&self) -> bool {
989 matches!(self, Self::Unbound { .. })
990 }
991
992 pub fn is_or_holds_opaque(&self) -> bool {
993 match self {
994 Self::Link { tipo } => tipo.contains_opaque(),
995 _ => false,
996 }
997 }
998
999 pub fn is_void(&self) -> bool {
1000 match self {
1001 Self::Link { tipo } => tipo.is_void(),
1002 _ => false,
1003 }
1004 }
1005
1006 pub fn is_bool(&self) -> bool {
1007 match self {
1008 Self::Link { tipo } => tipo.is_bool(),
1009 _ => false,
1010 }
1011 }
1012
1013 pub fn is_int(&self) -> bool {
1014 match self {
1015 Self::Link { tipo } => tipo.is_int(),
1016 _ => false,
1017 }
1018 }
1019
1020 pub fn is_bytearray(&self) -> bool {
1021 match self {
1022 Self::Link { tipo } => tipo.is_bytearray(),
1023 _ => false,
1024 }
1025 }
1026
1027 pub fn is_bls381_12_g1(&self) -> bool {
1028 match self {
1029 Self::Link { tipo } => tipo.is_bls381_12_g1(),
1030 _ => false,
1031 }
1032 }
1033
1034 pub fn is_bls381_12_g2(&self) -> bool {
1035 match self {
1036 Self::Link { tipo } => tipo.is_bls381_12_g2(),
1037 _ => false,
1038 }
1039 }
1040 pub fn is_ml_result(&self) -> bool {
1041 match self {
1042 Self::Link { tipo } => tipo.is_ml_result(),
1043 _ => false,
1044 }
1045 }
1046
1047 pub fn is_string(&self) -> bool {
1048 match self {
1049 Self::Link { tipo } => tipo.is_string(),
1050 _ => false,
1051 }
1052 }
1053
1054 pub fn is_list(&self) -> bool {
1055 match self {
1056 Self::Link { tipo } => tipo.is_list(),
1057 _ => false,
1058 }
1059 }
1060
1061 pub fn is_option(&self) -> bool {
1062 match self {
1063 Self::Link { tipo } => tipo.is_option(),
1064 _ => false,
1065 }
1066 }
1067
1068 pub fn is_map(&self) -> bool {
1069 match self {
1070 Self::Link { tipo } => tipo.is_map(),
1071 _ => false,
1072 }
1073 }
1074
1075 pub fn is_tuple(&self) -> bool {
1076 match self {
1077 Self::Link { tipo } => tipo.is_tuple(),
1078 _ => false,
1079 }
1080 }
1081
1082 pub fn is_pair(&self) -> bool {
1083 match self {
1084 Self::Link { tipo } => tipo.is_pair(),
1085 _ => false,
1086 }
1087 }
1088
1089 pub fn is_data(&self) -> bool {
1090 match self {
1091 Self::Link { tipo } => tipo.is_data(),
1092 _ => false,
1093 }
1094 }
1095
1096 pub fn is_generic(&self) -> bool {
1097 match self {
1098 TypeVar::Generic { .. } => true,
1099 TypeVar::Link { tipo } => tipo.is_generic(),
1100 TypeVar::Unbound { .. } => false,
1101 }
1102 }
1103
1104 pub fn get_generic(&self) -> Option<u64> {
1105 match self {
1106 TypeVar::Generic { id } => Some(*id),
1107 TypeVar::Link { tipo } => tipo.get_generic_id(),
1108 _ => None,
1109 }
1110 }
1111
1112 pub fn arg_types(&self) -> Option<Vec<Rc<Type>>> {
1113 match self {
1114 Self::Link { tipo } => tipo.arg_types(),
1115 _ => None,
1116 }
1117 }
1118
1119 pub fn get_inner_types(&self) -> Vec<Rc<Type>> {
1120 match self {
1121 Self::Link { tipo } => tipo.get_inner_types(),
1122 Self::Unbound { .. } => vec![],
1123 var => {
1124 vec![
1125 Type::Var {
1126 tipo: RefCell::new(var.clone()).into(),
1127 alias: None,
1128 }
1129 .into(),
1130 ]
1131 }
1132 }
1133 }
1134}
1135
1136#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1137pub struct ValueConstructor {
1138 pub public: bool,
1139 pub variant: ValueConstructorVariant,
1140 pub tipo: Rc<Type>,
1141}
1142
1143impl ValueConstructor {
1144 pub fn public(tipo: Rc<Type>, variant: ValueConstructorVariant) -> ValueConstructor {
1145 ValueConstructor {
1146 public: true,
1147 variant,
1148 tipo,
1149 }
1150 }
1151
1152 pub fn known_enum(
1153 values: &mut HashMap<String, Self>,
1154 tipo: Rc<Type>,
1155 constructors: &[&str],
1156 ) -> Vec<String> {
1157 for constructor in constructors {
1158 values.insert(
1159 constructor.to_string(),
1160 ValueConstructor::public(
1161 tipo.clone(),
1162 ValueConstructorVariant::known_enum_variant(constructor, constructors.len(), 0),
1163 ),
1164 );
1165 }
1166
1167 constructors
1168 .iter()
1169 .map(|constructor| constructor.to_string())
1170 .collect()
1171 }
1172
1173 pub fn known_adt(
1174 values: &mut HashMap<String, Self>,
1175 constructors: &[(&str, Rc<Type>)],
1176 ) -> Vec<String> {
1177 for (constructor, tipo) in constructors {
1178 values.insert(
1179 constructor.to_string(),
1180 ValueConstructor::public(
1181 tipo.clone(),
1182 ValueConstructorVariant::known_enum_variant(
1183 constructor,
1184 constructors.len(),
1185 tipo.fn_arity().unwrap_or(0),
1186 ),
1187 ),
1188 );
1189 }
1190
1191 constructors
1192 .iter()
1193 .map(|(constructor, _)| constructor.to_string())
1194 .collect()
1195 }
1196
1197 fn field_map(&self) -> Option<&FieldMap> {
1198 match &self.variant {
1199 ValueConstructorVariant::ModuleFn { field_map, .. }
1200 | ValueConstructorVariant::Record { field_map, .. } => field_map.as_ref(),
1201 _ => None,
1202 }
1203 }
1204
1205 pub fn is_local_variable(&self) -> bool {
1206 self.variant.is_local_variable()
1207 }
1208
1209 pub fn definition_location(&self) -> DefinitionLocation<'_> {
1210 match &self.variant {
1211 ValueConstructorVariant::Record {
1212 module, location, ..
1213 }
1214 | ValueConstructorVariant::ModuleFn {
1215 module, location, ..
1216 }
1217 | ValueConstructorVariant::ModuleConstant {
1218 location, module, ..
1219 } => DefinitionLocation {
1220 module: Some(module.as_str()),
1221 span: *location,
1222 },
1223
1224 ValueConstructorVariant::LocalVariable { location } => DefinitionLocation {
1225 module: None,
1226 span: *location,
1227 },
1228 }
1229 }
1230}
1231
1232#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1233pub enum ValueConstructorVariant {
1234 LocalVariable { location: Span },
1236
1237 ModuleConstant {
1239 location: Span,
1240 module: String,
1241 name: String,
1242 },
1243
1244 ModuleFn {
1246 name: String,
1247 field_map: Option<FieldMap>,
1248 module: String,
1249 arity: usize,
1250 location: Span,
1251 builtin: Option<DefaultFunction>,
1252 },
1253
1254 Record {
1256 name: String,
1257 arity: usize,
1258 field_map: Option<FieldMap>,
1259 location: Span,
1260 module: String,
1261 constructors_count: u16,
1262 },
1263}
1264
1265impl ValueConstructorVariant {
1266 fn to_module_value_constructor(
1267 &self,
1268 tipo: Rc<Type>,
1269 module_name: &str,
1270 function_name: &str,
1271 ) -> ModuleValueConstructor {
1272 match self {
1273 Self::Record {
1274 name,
1275 arity,
1276 field_map,
1277 location,
1278 ..
1279 } => ModuleValueConstructor::Record {
1280 name: name.clone(),
1281 field_map: field_map.clone(),
1282 arity: *arity,
1283 tipo,
1284 location: *location,
1285 },
1286
1287 Self::ModuleConstant {
1288 name,
1289 module,
1290 location,
1291 ..
1292 } => ModuleValueConstructor::Constant {
1293 name: name.clone(),
1294 module: module.clone(),
1295 location: *location,
1296 },
1297
1298 Self::LocalVariable { location, .. } => ModuleValueConstructor::Fn {
1299 name: function_name.to_string(),
1300 module: module_name.to_string(),
1301 location: *location,
1302 },
1303
1304 Self::ModuleFn {
1305 name,
1306 module,
1307 location,
1308 ..
1309 } => ModuleValueConstructor::Fn {
1310 name: name.clone(),
1311 module: module.clone(),
1312 location: *location,
1313 },
1314 }
1315 }
1316
1317 pub fn location(&self) -> Span {
1318 match self {
1319 ValueConstructorVariant::LocalVariable { location }
1320 | ValueConstructorVariant::ModuleConstant { location, .. }
1321 | ValueConstructorVariant::ModuleFn { location, .. }
1322 | ValueConstructorVariant::Record { location, .. } => *location,
1323 }
1324 }
1325
1326 pub fn is_local_variable(&self) -> bool {
1328 matches!(self, Self::LocalVariable { .. })
1329 }
1330
1331 pub fn known_enum_variant(name: &str, constructors_count: usize, arity: usize) -> Self {
1332 ValueConstructorVariant::Record {
1333 module: "".into(),
1334 name: name.to_string(),
1335 field_map: None::<FieldMap>,
1336 arity,
1337 location: Span::empty(),
1338 constructors_count: constructors_count as u16,
1339 }
1340 }
1341}
1342
1343#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1344pub struct TypeInfo {
1345 pub name: String,
1346 pub kind: ModuleKind,
1347 pub package: String,
1348 pub types: HashMap<String, TypeConstructor>,
1349 pub types_constructors: HashMap<String, Vec<String>>,
1350 pub values: HashMap<String, ValueConstructor>,
1351 pub accessors: HashMap<String, AccessorsMap>,
1352 pub annotations: HashMap<Annotation, Rc<Type>>,
1353}
1354
1355#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1356pub struct TypeConstructor {
1357 pub public: bool,
1358 pub location: Span,
1359 pub module: String,
1360 pub parameters: Vec<Rc<Type>>,
1361 pub tipo: Rc<Type>,
1362}
1363
1364impl TypeConstructor {
1365 pub fn primitive(tipo: Rc<Type>) -> Self {
1366 TypeConstructor {
1367 location: Span::empty(),
1368 parameters: tipo.collect_generics(),
1369 tipo,
1370 module: "".to_string(),
1371 public: true,
1372 }
1373 }
1374
1375 pub fn might_be(name: &str) -> bool {
1376 name.chars().next().unwrap().is_uppercase()
1377 }
1378}
1379
1380#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1381pub struct AccessorsMap {
1382 pub public: bool,
1383 pub tipo: Rc<Type>,
1384 pub accessors: HashMap<String, RecordAccessor>,
1385}
1386
1387#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1388pub struct RecordAccessor {
1389 pub index: u64,
1391 pub label: String,
1392 pub tipo: Rc<Type>,
1393}
1394
1395#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1396pub enum PatternConstructor {
1397 Record {
1398 name: String,
1399 field_map: Option<FieldMap>,
1400 },
1401}
1402
1403#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1404pub enum ModuleValueConstructor {
1405 Record {
1406 name: String,
1407 arity: usize,
1408 tipo: Rc<Type>,
1409 field_map: Option<FieldMap>,
1410 location: Span,
1411 },
1412
1413 Fn {
1414 location: Span,
1415 module: String,
1428 name: String,
1429 },
1430
1431 Constant {
1432 location: Span,
1433 module: String,
1434 name: String,
1435 },
1436}
1437
1438impl ModuleValueConstructor {
1439 pub fn location(&self) -> Span {
1440 match self {
1441 ModuleValueConstructor::Fn { location, .. }
1442 | ModuleValueConstructor::Record { location, .. }
1443 | ModuleValueConstructor::Constant { location, .. } => *location,
1444 }
1445 }
1446}