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 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    /// A nominal (named) type such as `Int`, `Float`, or a programmer defined
36    /// custom type such as `Person`. The type can take other types as
37    /// arguments (aka "generics" or "parametric polymorphism").
38    ///
39    /// If the type is defined in the Aiken prelude the `module` field will be
40    /// empty, otherwise it will contain the name of the module that
41    /// defines the type.
42    ///
43    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    /// The type of a function. It takes arguments and returns a value.
53    ///
54    Fn {
55        args: Vec<Rc<Type>>,
56        ret: Rc<Type>,
57        alias: Option<Rc<TypeAliasAnnotation>>,
58    },
59
60    /// A type variable. See the contained `TypeVar` enum for more information.
61    ///
62    Var {
63        tipo: Rc<RefCell<TypeVar>>,
64        alias: Option<Rc<TypeAliasAnnotation>>,
65    },
66    // /// A tuple is an ordered collection of 0 or more values, each of which
67    // /// can have a different type, so the `tuple` type is the sum of all the
68    // /// contained types.
69    // ///
70    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    ///  Check whether a given type is fully specialized and has only one possible
425    ///  form. Said differently, this recursively checks if the type still contains
426    ///  unbound or generic variables.
427    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    // TODO: Self::App { args, ..} looks fishy, because App's args are referring
471    // to _type parameters_ not to value types unlike Fn's args. So this function
472    // definition is probably wrong. Luckily, we likely never hit the `Self::App`
473    // case at all.
474    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    /// Get the args for the type if the type is a specific `Type::App`.
558    /// Returns None if the type is not a `Type::App` or is an incorrect `Type:App`
559    ///
560    /// This function is currently only used for finding the `List` type.
561    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                // We are an unbound type variable! So convert us to a type link
598                // to the desired type.
599                *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, &param));
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                // BIG WARNING: Adding any kind decorator
852                // will make the opaque type not replaceable
853                && 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 is an unbound variable. It is one specific type but we don't
953    /// know what yet in the inference process. It has a unique id which can be used to
954    /// identify if two unbound variable Rust values are the same Aiken type variable
955    /// instance or not.
956    ///
957    Unbound { id: u64 },
958    /// Link is type variable where it was an unbound variable but we worked out
959    /// that it is some other type and now we point to that one.
960    ///
961    Link { tipo: Rc<Type> },
962    /// A Generic variable stands in for any possible type and cannot be
963    /// specialised to any one type
964    ///
965    /// # Example
966    ///
967    /// ```aiken
968    /// type Cat(a) {
969    ///   Cat(name: a)
970    /// }
971    /// // a is TypeVar::Generic
972    /// ```
973    ///
974    Generic { id: u64 },
975}
976
977impl TypeVar {
978    ///  Check whether a given type is fully specialized and has only one possible
979    ///  form. Said differently, this recursively checks if the type still contains
980    ///  unbound or generic variables.
981    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    /// A locally defined variable or function parameter
1235    LocalVariable { location: Span },
1236
1237    /// A module constant
1238    ModuleConstant {
1239        location: Span,
1240        module: String,
1241        name: String,
1242    },
1243
1244    /// A function belonging to the module
1245    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    /// A constructor for a custom type
1255    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    /// Returns `true` if the variant is [`LocalVariable`].
1327    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    // TODO: smaller int. Doesn't need to be this big
1390    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        /// The name of the module and the function
1416        /// Typically this will be the module that this constructor belongs to
1417        /// and the name that was used for the function. However it could also
1418        /// point to some other module and function when this is an `external fn`.
1419        ///
1420        /// This function has module "themodule" and name "wibble"
1421        ///     pub fn wibble() { Void }
1422        ///
1423        /// This function has module "other" and name "whoop"
1424        ///     pub external fn wibble() -> Void =
1425        ///       "other" "whoop"
1426        ///
1427        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}