Skip to main content

aiken_lang/
tipo.rs

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    /// A nominal (named) type such as `Int`, `Float`, or a programmer defined
35    /// custom type such as `Person`. The type can take other types as
36    /// arguments (aka "generics" or "parametric polymorphism").
37    ///
38    /// If the type is defined in the Aiken prelude the `module` field will be
39    /// empty, otherwise it will contain the name of the module that
40    /// defines the type.
41    ///
42    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    /// The type of a function. It takes arguments and returns a value.
52    ///
53    Fn {
54        args: Vec<Rc<Type>>,
55        ret: Rc<Type>,
56        alias: Option<Rc<TypeAliasAnnotation>>,
57    },
58
59    /// A type variable. See the contained `TypeVar` enum for more information.
60    ///
61    Var {
62        tipo: Rc<RefCell<TypeVar>>,
63        alias: Option<Rc<TypeAliasAnnotation>>,
64    },
65    // /// A tuple is an ordered collection of 0 or more values, each of which
66    // /// can have a different type, so the `tuple` type is the sum of all the
67    // /// contained types.
68    // ///
69    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    ///  Check whether a given type is fully specialized and has only one possible
424    ///  form. Said differently, this recursively checks if the type still contains
425    ///  unbound or generic variables.
426    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    // TODO: Self::App { args, ..} looks fishy, because App's args are referring
470    // to _type parameters_ not to value types unlike Fn's args. So this function
471    // definition is probably wrong. Luckily, we likely never hit the `Self::App`
472    // case at all.
473    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    /// Get the args for the type if the type is a specific `Type::App`.
557    /// Returns None if the type is not a `Type::App` or is an incorrect `Type:App`
558    ///
559    /// This function is currently only used for finding the `List` type.
560    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                // We are an unbound type variable! So convert us to a type link
597                // to the desired type.
598                *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, &param));
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            // BIG WARNING: Adding any kind decorator
827            // will make the opaque type not replaceable
828            && 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 is an unbound variable. It is one specific type but we don't
921    /// know what yet in the inference process. It has a unique id which can be used to
922    /// identify if two unbound variable Rust values are the same Aiken type variable
923    /// instance or not.
924    ///
925    Unbound { id: u64 },
926    /// Link is type variable where it was an unbound variable but we worked out
927    /// that it is some other type and now we point to that one.
928    ///
929    Link { tipo: Rc<Type> },
930    /// A Generic variable stands in for any possible type and cannot be
931    /// specialised to any one type
932    ///
933    /// # Example
934    ///
935    /// ```aiken
936    /// type Cat(a) {
937    ///   Cat(name: a)
938    /// }
939    /// // a is TypeVar::Generic
940    /// ```
941    ///
942    Generic { id: u64 },
943}
944
945impl TypeVar {
946    ///  Check whether a given type is fully specialized and has only one possible
947    ///  form. Said differently, this recursively checks if the type still contains
948    ///  unbound or generic variables.
949    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    /// A locally defined variable or function parameter
1223    LocalVariable { location: Span },
1224
1225    /// A module constant
1226    ModuleConstant {
1227        location: Span,
1228        module: String,
1229        name: String,
1230    },
1231
1232    /// A function belonging to the module
1233    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    /// A constructor for a custom type
1243    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    /// Returns `true` if the variant is [`LocalVariable`].
1315    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    // TODO: smaller int. Doesn't need to be this big
1378    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        /// The name of the module and the function
1404        /// Typically this will be the module that this constructor belongs to
1405        /// and the name that was used for the function. However it could also
1406        /// point to some other module and function when this is an `external fn`.
1407        ///
1408        /// This function has module "themodule" and name "wibble"
1409        ///     pub fn wibble() { Void }
1410        ///
1411        /// This function has module "other" and name "whoop"
1412        ///     pub external fn wibble() -> Void =
1413        ///       "other" "whoop"
1414        ///
1415        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}