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