Skip to main content

aiken_lang/
builtins.rs

1use crate::{
2    IdGenerator, aiken_fn,
3    ast::{
4        Annotation, ArgName, CallArg, DataType, DataTypeKey, Function, FunctionAccessKey,
5        ModuleKind, OnTestFailure, RecordConstructor, RecordConstructorArg, Span, TypedArg,
6        TypedDataType, TypedFunction, UnOp, well_known,
7    },
8    expr::TypedExpr,
9    tipo::{
10        Type, TypeConstructor, TypeInfo, ValueConstructor, ValueConstructorVariant,
11        fields::FieldMap,
12    },
13};
14use std::{collections::BTreeSet, sync::LazyLock};
15
16use indexmap::IndexMap;
17use std::{collections::HashMap, rc::Rc};
18use strum::IntoEnumIterator;
19
20use uplc::{
21    builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER},
22    builtins::DefaultFunction,
23};
24
25pub const PRELUDE: &str = "aiken";
26pub const BUILTIN: &str = "aiken/builtin";
27
28pub static INTERNAL_FUNCTIONS: LazyLock<BTreeSet<&'static str>> = LazyLock::new(|| {
29    let mut set = BTreeSet::new();
30    set.insert("diagnostic");
31    set.insert("do_from_int");
32    set.insert("encode_base16");
33    set.insert("enumerate");
34    set.insert("from_int");
35    set
36});
37
38/// Build a prelude that can be injected
39/// into a compiler pipeline
40pub fn prelude(id_gen: &IdGenerator) -> TypeInfo {
41    let mut prelude = TypeInfo {
42        name: PRELUDE.to_string(),
43        package: "".to_string(),
44        kind: ModuleKind::Lib,
45        types: HashMap::new(),
46        types_constructors: HashMap::new(),
47        values: HashMap::new(),
48        accessors: HashMap::new(),
49        annotations: HashMap::new(),
50    };
51
52    // Data
53    prelude.types.insert(
54        well_known::DATA.to_string(),
55        TypeConstructor::primitive(Type::data()),
56    );
57
58    // Int
59    prelude.types.insert(
60        well_known::INT.to_string(),
61        TypeConstructor::primitive(Type::int()),
62    );
63
64    // ByteArray
65    prelude.types.insert(
66        well_known::BYTE_ARRAY.to_string(),
67        TypeConstructor::primitive(Type::byte_array()),
68    );
69
70    // Bool
71    prelude.types.insert(
72        well_known::BOOL.to_string(),
73        TypeConstructor::primitive(Type::bool()),
74    );
75    prelude.types_constructors.insert(
76        well_known::BOOL.to_string(),
77        ValueConstructor::known_enum(
78            &mut prelude.values,
79            Type::bool(),
80            well_known::BOOL_CONSTRUCTORS,
81        ),
82    );
83
84    // G1Element
85    prelude.types.insert(
86        well_known::G1_ELEMENT.to_string(),
87        TypeConstructor::primitive(Type::g1_element()),
88    );
89
90    // G2Element
91    prelude.types.insert(
92        well_known::G2_ELEMENT.to_string(),
93        TypeConstructor::primitive(Type::g2_element()),
94    );
95
96    // MillerLoopResult
97    prelude.types.insert(
98        well_known::MILLER_LOOP_RESULT.to_string(),
99        TypeConstructor::primitive(Type::miller_loop_result()),
100    );
101
102    // Ordering
103    prelude.types.insert(
104        well_known::ORDERING.to_string(),
105        TypeConstructor::primitive(Type::ordering()),
106    );
107    prelude.types_constructors.insert(
108        well_known::ORDERING.to_string(),
109        ValueConstructor::known_enum(
110            &mut prelude.values,
111            Type::ordering(),
112            well_known::ORDERING_CONSTRUCTORS,
113        ),
114    );
115
116    // String
117    prelude.types.insert(
118        well_known::STRING.to_string(),
119        TypeConstructor::primitive(Type::string()),
120    );
121
122    // Void
123    prelude.types.insert(
124        well_known::VOID.to_string(),
125        TypeConstructor::primitive(Type::void()),
126    );
127    prelude.types_constructors.insert(
128        well_known::VOID.to_string(),
129        ValueConstructor::known_enum(
130            &mut prelude.values,
131            Type::void(),
132            well_known::VOID_CONSTRUCTORS,
133        ),
134    );
135
136    // List(a)
137    prelude.types.insert(
138        well_known::LIST.to_string(),
139        TypeConstructor::primitive(Type::list(Type::generic_var(id_gen.next()))),
140    );
141
142    // Pair(a, b)
143    let pair_left = Type::generic_var(id_gen.next());
144    let pair_right = Type::generic_var(id_gen.next());
145    prelude.types.insert(
146        well_known::PAIR.to_string(),
147        TypeConstructor::primitive(Type::pair(pair_left.clone(), pair_right.clone())),
148    );
149    prelude.types_constructors.insert(
150        well_known::PAIR.to_string(),
151        ValueConstructor::known_adt(
152            &mut prelude.values,
153            &[(
154                well_known::PAIR,
155                Type::function(
156                    vec![pair_left.clone(), pair_right.clone()],
157                    Type::pair(pair_left, pair_right),
158                ),
159            )],
160        ),
161    );
162
163    // Pairs<k, v> = List<Pair<k, v>>
164    prelude.types.insert(
165        well_known::PAIRS.to_string(),
166        TypeConstructor::primitive(Type::map(
167            Type::generic_var(id_gen.next()),
168            Type::generic_var(id_gen.next()),
169        )),
170    );
171
172    // Option(value)
173    let option_value = Type::generic_var(id_gen.next());
174    prelude.types.insert(
175        well_known::OPTION.to_string(),
176        TypeConstructor::primitive(Type::option(option_value.clone())),
177    );
178    let some_type = Type::function(
179        vec![option_value.clone()],
180        Type::option(option_value.clone()),
181    );
182    let none_type = Type::option(option_value);
183    prelude.types_constructors.insert(
184        well_known::OPTION.to_string(),
185        ValueConstructor::known_adt(
186            &mut prelude.values,
187            &[
188                (well_known::OPTION_CONSTRUCTORS[0], some_type),
189                (well_known::OPTION_CONSTRUCTORS[1], none_type),
190            ],
191        ),
192    );
193
194    // Never
195    prelude.types.insert(
196        well_known::NEVER.to_string(),
197        TypeConstructor::primitive(Type::never()),
198    );
199    prelude.types_constructors.insert(
200        well_known::NEVER.to_string(),
201        ValueConstructor::known_adt(
202            &mut prelude.values,
203            &[(well_known::NEVER_CONSTRUCTORS[1], Type::never())],
204        ),
205    );
206
207    // Cardano ScriptContext
208    prelude.types.insert(
209        well_known::SCRIPT_CONTEXT.to_string(),
210        TypeConstructor::primitive(Type::script_context()),
211    );
212    prelude.types_constructors.insert(
213        well_known::SCRIPT_CONTEXT.to_string(),
214        vec![
215            well_known::SCRIPT_CONTEXT_TRANSACTION.to_string(),
216            well_known::SCRIPT_CONTEXT_REDEEMER.to_string(),
217            well_known::SCRIPT_CONTEXT_PURPOSE.to_string(),
218        ],
219    );
220
221    // Cardano ScriptPurpose
222    prelude.types.insert(
223        well_known::SCRIPT_PURPOSE.to_string(),
224        TypeConstructor::primitive(Type::script_purpose()),
225    );
226
227    prelude.types_constructors.insert(
228        well_known::SCRIPT_PURPOSE.to_string(),
229        ValueConstructor::known_adt(
230            &mut prelude.values,
231            &[
232                (
233                    well_known::SCRIPT_PURPOSE_MINT,
234                    Type::function(vec![Type::data()], Type::script_purpose()),
235                ),
236                (
237                    well_known::SCRIPT_PURPOSE_SPEND,
238                    Type::function(
239                        vec![Type::data(), Type::option(Type::data())],
240                        Type::script_purpose(),
241                    ),
242                ),
243                (
244                    well_known::SCRIPT_PURPOSE_WITHDRAW,
245                    Type::function(vec![Type::data()], Type::script_purpose()),
246                ),
247                (
248                    well_known::SCRIPT_PURPOSE_PUBLISH,
249                    Type::function(vec![Type::int(), Type::data()], Type::script_purpose()),
250                ),
251                (
252                    well_known::SCRIPT_PURPOSE_VOTE,
253                    Type::function(vec![Type::data()], Type::script_purpose()),
254                ),
255                (
256                    well_known::SCRIPT_PURPOSE_PROPOSE,
257                    Type::function(vec![Type::int(), Type::data()], Type::script_purpose()),
258                ),
259            ],
260        ),
261    );
262
263    // not
264    prelude.values.insert(
265        "not".to_string(),
266        ValueConstructor::public(
267            Type::function(vec![Type::bool()], Type::bool()),
268            ValueConstructorVariant::ModuleFn {
269                name: "not".to_string(),
270                field_map: None,
271                module: "".to_string(),
272                arity: 1,
273                location: Span::empty(),
274                builtin: None,
275            },
276        ),
277    );
278
279    // identity
280    let identity_var = Type::generic_var(id_gen.next());
281    prelude.values.insert(
282        "identity".to_string(),
283        ValueConstructor::public(
284            Type::function(vec![identity_var.clone()], identity_var),
285            ValueConstructorVariant::ModuleFn {
286                name: "identity".to_string(),
287                field_map: None,
288                module: "".to_string(),
289                arity: 1,
290                location: Span::empty(),
291                builtin: None,
292            },
293        ),
294    );
295
296    // as_data
297    prelude.values.insert(
298        "as_data".to_string(),
299        ValueConstructor::public(
300            Type::function(vec![Type::data()], Type::data()),
301            ValueConstructorVariant::ModuleFn {
302                name: "as_data".to_string(),
303                field_map: None,
304                module: "".to_string(),
305                arity: 1,
306                location: Span::empty(),
307                builtin: None,
308            },
309        ),
310    );
311
312    // enumerate
313    let enumerate_a = Type::generic_var(id_gen.next());
314    let enumerate_b = Type::generic_var(id_gen.next());
315    prelude.values.insert(
316        "enumerate".to_string(),
317        ValueConstructor::public(
318            Type::function(
319                vec![
320                    Type::list(enumerate_a.clone()),
321                    enumerate_b.clone(),
322                    Type::function(
323                        vec![enumerate_a.clone(), enumerate_b.clone()],
324                        enumerate_b.clone(),
325                    ),
326                    Type::function(
327                        vec![enumerate_a.clone(), enumerate_b.clone()],
328                        enumerate_b.clone(),
329                    ),
330                ],
331                enumerate_b,
332            ),
333            ValueConstructorVariant::ModuleFn {
334                name: "enumerate".to_string(),
335                field_map: None,
336                module: "".to_string(),
337                arity: 4,
338                location: Span::empty(),
339                builtin: None,
340            },
341        ),
342    );
343
344    // encode_base16
345    prelude.values.insert(
346        "encode_base16".to_string(),
347        ValueConstructor::public(
348            Type::function(
349                vec![Type::byte_array(), Type::int(), Type::byte_array()],
350                Type::byte_array(),
351            ),
352            ValueConstructorVariant::ModuleFn {
353                name: "encode_base16".to_string(),
354                field_map: None,
355                module: "".to_string(),
356                arity: 3,
357                location: Span::empty(),
358                builtin: None,
359            },
360        ),
361    );
362
363    // from_int
364    prelude.values.insert(
365        "from_int".to_string(),
366        ValueConstructor::public(
367            Type::function(vec![Type::int(), Type::byte_array()], Type::byte_array()),
368            ValueConstructorVariant::ModuleFn {
369                name: "from_int".to_string(),
370                field_map: None,
371                module: "".to_string(),
372                arity: 2,
373                location: Span::empty(),
374                builtin: None,
375            },
376        ),
377    );
378
379    // do_from_int
380    prelude.values.insert(
381        "do_from_int".to_string(),
382        ValueConstructor::public(
383            Type::function(vec![Type::int(), Type::byte_array()], Type::byte_array()),
384            ValueConstructorVariant::ModuleFn {
385                name: "do_from_int".to_string(),
386                field_map: None,
387                module: "".to_string(),
388                arity: 2,
389                location: Span::empty(),
390                builtin: None,
391            },
392        ),
393    );
394
395    // diagnostic
396    prelude.values.insert(
397        "diagnostic".to_string(),
398        ValueConstructor::public(
399            Type::function(vec![Type::data(), Type::byte_array()], Type::byte_array()),
400            ValueConstructorVariant::ModuleFn {
401                name: "diagnostic".to_string(),
402                field_map: None,
403                module: "".to_string(),
404                arity: 2,
405                location: Span::empty(),
406                builtin: None,
407            },
408        ),
409    );
410
411    // always
412    let always_a_var = Type::generic_var(id_gen.next());
413    let always_b_var = Type::generic_var(id_gen.next());
414    prelude.values.insert(
415        "always".to_string(),
416        ValueConstructor::public(
417            Type::function(vec![always_a_var.clone(), always_b_var], always_a_var),
418            ValueConstructorVariant::ModuleFn {
419                name: "always".to_string(),
420                field_map: None,
421                module: "".to_string(),
422                arity: 2,
423                location: Span::empty(),
424                builtin: None,
425            },
426        ),
427    );
428
429    // tautology
430    let tautology_var = Type::generic_var(id_gen.next());
431    prelude.values.insert(
432        "tautology".to_string(),
433        ValueConstructor::public(
434            Type::function(vec![tautology_var], Type::void()),
435            ValueConstructorVariant::ModuleFn {
436                name: "tautology".to_string(),
437                field_map: None,
438                module: "".to_string(),
439                arity: 1,
440                location: Span::empty(),
441                builtin: None,
442            },
443        ),
444    );
445
446    // flip
447    let flip_a_var = Type::generic_var(id_gen.next());
448    let flip_b_var = Type::generic_var(id_gen.next());
449    let flip_c_var = Type::generic_var(id_gen.next());
450
451    let input_type = Type::function(
452        vec![flip_a_var.clone(), flip_b_var.clone()],
453        flip_c_var.clone(),
454    );
455
456    let return_type = Type::function(vec![flip_b_var, flip_a_var], flip_c_var);
457
458    prelude.values.insert(
459        "flip".to_string(),
460        ValueConstructor::public(
461            Type::function(vec![input_type], return_type),
462            ValueConstructorVariant::ModuleFn {
463                name: "flip".to_string(),
464                field_map: None,
465                module: "".to_string(),
466                arity: 1,
467                location: Span::empty(),
468                builtin: None,
469            },
470        ),
471    );
472
473    // PRNG
474    //
475    // pub type PRNG {
476    //   Seeded { seed: ByteArray, choices: ByteArray }
477    //   Replayed { cursor: Int, choices: ByteArray }
478    // }
479    prelude.types.insert(
480        well_known::PRNG.to_string(),
481        TypeConstructor::primitive(Type::prng()),
482    );
483
484    prelude.types_constructors.insert(
485        well_known::PRNG.to_string(),
486        vec!["Seeded".to_string(), "Replayed".to_string()],
487    );
488
489    let mut seeded_fields = HashMap::new();
490    seeded_fields.insert("seed".to_string(), (0, Span::empty()));
491    seeded_fields.insert("choices".to_string(), (1, Span::empty()));
492    prelude.values.insert(
493        "Seeded".to_string(),
494        ValueConstructor::public(
495            Type::function(vec![Type::byte_array(), Type::byte_array()], Type::prng()),
496            ValueConstructorVariant::Record {
497                module: "".into(),
498                name: "Seeded".to_string(),
499                field_map: Some(FieldMap {
500                    arity: 2,
501                    fields: seeded_fields,
502                    is_function: false,
503                }),
504                arity: 2,
505                location: Span::empty(),
506                constructors_count: 2,
507            },
508        ),
509    );
510
511    let mut replayed_fields = HashMap::new();
512    replayed_fields.insert("cursor".to_string(), (0, Span::empty()));
513    replayed_fields.insert("choices".to_string(), (1, Span::empty()));
514    prelude.values.insert(
515        "Replayed".to_string(),
516        ValueConstructor::public(
517            Type::function(vec![Type::int(), Type::byte_array()], Type::prng()),
518            ValueConstructorVariant::Record {
519                module: "".into(),
520                name: "Replayed".to_string(),
521                field_map: Some(FieldMap {
522                    arity: 2,
523                    fields: replayed_fields,
524                    is_function: false,
525                }),
526                arity: 2,
527                location: Span::empty(),
528                constructors_count: 2,
529            },
530        ),
531    );
532
533    // Fuzzer
534    //
535    // pub type Fuzzer<a> =
536    //   fn(PRNG) -> Option<(PRNG, a)>
537    let fuzzer_generic = Type::generic_var(id_gen.next());
538    prelude.types.insert(
539        well_known::FUZZER.to_string(),
540        TypeConstructor {
541            location: Span::empty(),
542            parameters: vec![fuzzer_generic.clone()],
543            tipo: Type::fuzzer(fuzzer_generic),
544            module: "".to_string(),
545            public: true,
546        },
547    );
548
549    // Sampler
550    //
551    // pub type Sampler<a> =
552    //   fn(Int) -> Fuzzer<a>
553    let sampler_generic = Type::generic_var(id_gen.next());
554    prelude.types.insert(
555        well_known::SAMPLER.to_string(),
556        TypeConstructor {
557            location: Span::empty(),
558            parameters: vec![sampler_generic.clone()],
559            tipo: Type::sampler(sampler_generic),
560            module: "".to_string(),
561            public: true,
562        },
563    );
564
565    prelude
566}
567
568pub fn plutus(id_gen: &IdGenerator) -> TypeInfo {
569    let mut plutus = TypeInfo {
570        name: BUILTIN.to_string(),
571        package: "".to_string(),
572        kind: ModuleKind::Lib,
573        types: HashMap::new(),
574        types_constructors: HashMap::new(),
575        values: HashMap::new(),
576        accessors: HashMap::new(),
577        annotations: HashMap::new(),
578    };
579
580    for builtin in DefaultFunction::iter() {
581        let value = from_default_function(builtin, id_gen);
582        plutus.values.insert(builtin.aiken_name(), value);
583    }
584
585    let index_tipo = Type::function(vec![Type::data()], Type::int());
586    plutus.values.insert(
587        "unconstr_index".to_string(),
588        ValueConstructor::public(
589            index_tipo,
590            ValueConstructorVariant::ModuleFn {
591                name: "unconstr_index".to_string(),
592                field_map: None,
593                module: BUILTIN.to_string(),
594                arity: 1,
595                location: Span::empty(),
596                builtin: None,
597            },
598        ),
599    );
600
601    let fields_tipo = Type::function(vec![Type::data()], Type::list(Type::data()));
602    plutus.values.insert(
603        "unconstr_fields".to_string(),
604        ValueConstructor::public(
605            fields_tipo,
606            ValueConstructorVariant::ModuleFn {
607                name: "unconstr_fields".to_string(),
608                field_map: None,
609                module: BUILTIN.to_string(),
610                arity: 1,
611                location: Span::empty(),
612                builtin: None,
613            },
614        ),
615    );
616
617    plutus
618}
619
620pub fn from_default_function(builtin: DefaultFunction, id_gen: &IdGenerator) -> ValueConstructor {
621    let (tipo, arity) = match builtin {
622        DefaultFunction::AddInteger
623        | DefaultFunction::SubtractInteger
624        | DefaultFunction::MultiplyInteger
625        | DefaultFunction::DivideInteger
626        | DefaultFunction::QuotientInteger
627        | DefaultFunction::RemainderInteger
628        | DefaultFunction::ModInteger => {
629            let tipo = Type::function(vec![Type::int(), Type::int()], Type::int());
630            (tipo, 2)
631        }
632
633        DefaultFunction::EqualsInteger
634        | DefaultFunction::LessThanInteger
635        | DefaultFunction::LessThanEqualsInteger => {
636            let tipo = Type::function(vec![Type::int(), Type::int()], Type::bool());
637
638            (tipo, 2)
639        }
640        DefaultFunction::AppendByteString => {
641            let tipo = Type::function(
642                vec![Type::byte_array(), Type::byte_array()],
643                Type::byte_array(),
644            );
645
646            (tipo, 2)
647        }
648        DefaultFunction::ConsByteString => {
649            let tipo = Type::function(vec![Type::int(), Type::byte_array()], Type::byte_array());
650
651            (tipo, 2)
652        }
653        DefaultFunction::SliceByteString => {
654            let tipo = Type::function(
655                vec![Type::int(), Type::int(), Type::byte_array()],
656                Type::byte_array(),
657            );
658
659            (tipo, 3)
660        }
661        DefaultFunction::LengthOfByteString => {
662            let tipo = Type::function(vec![Type::byte_array()], Type::int());
663
664            (tipo, 1)
665        }
666        DefaultFunction::IndexByteString => {
667            let tipo = Type::function(vec![Type::byte_array(), Type::int()], Type::int());
668
669            (tipo, 2)
670        }
671        DefaultFunction::EqualsByteString
672        | DefaultFunction::LessThanByteString
673        | DefaultFunction::LessThanEqualsByteString => {
674            let tipo = Type::function(vec![Type::byte_array(), Type::byte_array()], Type::bool());
675
676            (tipo, 2)
677        }
678        DefaultFunction::Sha2_256
679        | DefaultFunction::Sha3_256
680        | DefaultFunction::Blake2b_224
681        | DefaultFunction::Blake2b_256
682        | DefaultFunction::Keccak_256 => {
683            let tipo = Type::function(vec![Type::byte_array()], Type::byte_array());
684
685            (tipo, 1)
686        }
687
688        DefaultFunction::VerifyEd25519Signature => {
689            let tipo = Type::function(
690                vec![Type::byte_array(), Type::byte_array(), Type::byte_array()],
691                Type::bool(),
692            );
693
694            (tipo, 3)
695        }
696
697        DefaultFunction::VerifyEcdsaSecp256k1Signature => {
698            let tipo = Type::function(
699                vec![Type::byte_array(), Type::byte_array(), Type::byte_array()],
700                Type::bool(),
701            );
702
703            (tipo, 3)
704        }
705        DefaultFunction::VerifySchnorrSecp256k1Signature => {
706            let tipo = Type::function(
707                vec![Type::byte_array(), Type::byte_array(), Type::byte_array()],
708                Type::bool(),
709            );
710
711            (tipo, 3)
712        }
713
714        DefaultFunction::AppendString => {
715            let tipo = Type::function(vec![Type::string(), Type::string()], Type::string());
716
717            (tipo, 2)
718        }
719        DefaultFunction::EqualsString => {
720            let tipo = Type::function(vec![Type::string(), Type::string()], Type::bool());
721
722            (tipo, 2)
723        }
724        DefaultFunction::EncodeUtf8 => {
725            let tipo = Type::function(vec![Type::string()], Type::byte_array());
726
727            (tipo, 1)
728        }
729        DefaultFunction::DecodeUtf8 => {
730            let tipo = Type::function(vec![Type::byte_array()], Type::string());
731
732            (tipo, 1)
733        }
734        DefaultFunction::IfThenElse => {
735            let ret = Type::generic_var(id_gen.next());
736
737            let tipo = Type::function(vec![Type::bool(), ret.clone(), ret.clone()], ret);
738
739            (tipo, 3)
740        }
741        DefaultFunction::HeadList => {
742            let ret = Type::generic_var(id_gen.next());
743
744            let tipo = Type::function(vec![Type::list(ret.clone())], ret);
745
746            (tipo, 1)
747        }
748        DefaultFunction::TailList => {
749            let ret = Type::list(Type::generic_var(id_gen.next()));
750
751            let tipo = Type::function(vec![ret.clone()], ret);
752
753            (tipo, 1)
754        }
755        DefaultFunction::NullList => {
756            let ret = Type::list(Type::generic_var(id_gen.next()));
757
758            let tipo = Type::function(vec![ret], Type::bool());
759
760            (tipo, 1)
761        }
762        DefaultFunction::ConstrData => {
763            let tipo = Type::function(vec![Type::int(), Type::list(Type::data())], Type::data());
764
765            (tipo, 2)
766        }
767        DefaultFunction::MapData => {
768            let tipo = Type::function(
769                vec![Type::list(Type::pair(Type::data(), Type::data()))],
770                Type::data(),
771            );
772
773            (tipo, 1)
774        }
775        DefaultFunction::ListData => {
776            let tipo = Type::function(vec![Type::list(Type::data())], Type::data());
777
778            (tipo, 1)
779        }
780        DefaultFunction::IData => {
781            let tipo = Type::function(vec![Type::int()], Type::data());
782
783            (tipo, 1)
784        }
785        DefaultFunction::BData => {
786            let tipo = Type::function(vec![Type::byte_array()], Type::data());
787
788            (tipo, 1)
789        }
790        DefaultFunction::UnConstrData => {
791            let tipo = Type::function(
792                vec![Type::data()],
793                Type::pair(Type::int(), Type::list(Type::data())),
794            );
795
796            (tipo, 1)
797        }
798        DefaultFunction::UnMapData => {
799            let tipo = Type::function(
800                vec![Type::data()],
801                Type::list(Type::pair(Type::data(), Type::data())),
802            );
803
804            (tipo, 1)
805        }
806        DefaultFunction::UnListData => {
807            let tipo = Type::function(vec![Type::data()], Type::list(Type::data()));
808
809            (tipo, 1)
810        }
811        DefaultFunction::UnIData => {
812            let tipo = Type::function(vec![Type::data()], Type::int());
813
814            (tipo, 1)
815        }
816        DefaultFunction::UnBData => {
817            let tipo = Type::function(vec![Type::data()], Type::byte_array());
818
819            (tipo, 1)
820        }
821        DefaultFunction::EqualsData => {
822            let tipo = Type::function(vec![Type::data(), Type::data()], Type::bool());
823
824            (tipo, 2)
825        }
826        DefaultFunction::SerialiseData => {
827            let tipo = Type::function(vec![Type::data()], Type::byte_array());
828
829            (tipo, 1)
830        }
831        DefaultFunction::ChooseData => {
832            let a = Type::generic_var(id_gen.next());
833            let tipo = Type::function(
834                vec![
835                    Type::data(),
836                    a.clone(),
837                    a.clone(),
838                    a.clone(),
839                    a.clone(),
840                    a.clone(),
841                ],
842                a,
843            );
844            (tipo, 6)
845        }
846        DefaultFunction::MkPairData => {
847            let tipo = Type::function(
848                vec![Type::data(), Type::data()],
849                Type::pair(Type::data(), Type::data()),
850            );
851            (tipo, 2)
852        }
853        DefaultFunction::MkNilData => {
854            let tipo = Type::function(vec![], Type::list(Type::data()));
855            (tipo, 0)
856        }
857        DefaultFunction::MkNilPairData => {
858            let tipo = Type::function(vec![], Type::list(Type::pair(Type::data(), Type::data())));
859            (tipo, 0)
860        }
861        DefaultFunction::ChooseUnit => {
862            let a = Type::generic_var(id_gen.next());
863            let tipo = Type::function(vec![Type::data(), a.clone()], a);
864            (tipo, 2)
865        }
866        DefaultFunction::Trace => {
867            let a = Type::generic_var(id_gen.next());
868            let tipo = Type::function(vec![Type::string(), a.clone()], a);
869            (tipo, 2)
870        }
871        DefaultFunction::FstPair => {
872            let a = Type::generic_var(id_gen.next());
873            let b = Type::generic_var(id_gen.next());
874            let tipo = Type::function(vec![Type::pair(a.clone(), b)], a);
875            (tipo, 1)
876        }
877        DefaultFunction::SndPair => {
878            let a = Type::generic_var(id_gen.next());
879            let b = Type::generic_var(id_gen.next());
880            let tipo = Type::function(vec![Type::pair(a, b.clone())], b);
881            (tipo, 1)
882        }
883        DefaultFunction::ChooseList => {
884            let a = Type::generic_var(id_gen.next());
885            let b = Type::generic_var(id_gen.next());
886            let tipo = Type::function(vec![Type::list(a), b.clone(), b.clone()], b);
887            (tipo, 3)
888        }
889        DefaultFunction::MkCons => {
890            let a = Type::generic_var(id_gen.next());
891            let tipo = Type::function(vec![a.clone(), Type::list(a.clone())], Type::list(a));
892            (tipo, 2)
893        }
894        DefaultFunction::Bls12_381_G1_Add => {
895            let tipo = Type::function(
896                vec![Type::g1_element(), Type::g1_element()],
897                Type::g1_element(),
898            );
899
900            (tipo, 2)
901        }
902        DefaultFunction::Bls12_381_G1_Equal => {
903            let tipo = Type::function(vec![Type::g1_element(), Type::g1_element()], Type::bool());
904
905            (tipo, 2)
906        }
907        DefaultFunction::Bls12_381_G1_Neg => {
908            let tipo = Type::function(vec![Type::g1_element()], Type::g1_element());
909
910            (tipo, 1)
911        }
912        DefaultFunction::Bls12_381_G1_ScalarMul => {
913            let tipo = Type::function(vec![Type::int(), Type::g1_element()], Type::g1_element());
914
915            (tipo, 2)
916        }
917        DefaultFunction::Bls12_381_G1_Compress => {
918            let tipo = Type::function(vec![Type::g1_element()], Type::byte_array());
919
920            (tipo, 1)
921        }
922        DefaultFunction::Bls12_381_G1_Uncompress => {
923            let tipo = Type::function(vec![Type::byte_array()], Type::g1_element());
924
925            (tipo, 1)
926        }
927        DefaultFunction::Bls12_381_G1_HashToGroup => {
928            let tipo = Type::function(
929                vec![Type::byte_array(), Type::byte_array()],
930                Type::g1_element(),
931            );
932
933            (tipo, 2)
934        }
935
936        DefaultFunction::Bls12_381_G2_Add => {
937            let tipo = Type::function(
938                vec![Type::g2_element(), Type::g2_element()],
939                Type::g2_element(),
940            );
941
942            (tipo, 2)
943        }
944        DefaultFunction::Bls12_381_G2_Equal => {
945            let tipo = Type::function(vec![Type::g2_element(), Type::g2_element()], Type::bool());
946
947            (tipo, 2)
948        }
949        DefaultFunction::Bls12_381_G2_Neg => {
950            let tipo = Type::function(vec![Type::g2_element()], Type::g2_element());
951
952            (tipo, 1)
953        }
954        DefaultFunction::Bls12_381_G2_ScalarMul => {
955            let tipo = Type::function(vec![Type::int(), Type::g2_element()], Type::g2_element());
956
957            (tipo, 2)
958        }
959        DefaultFunction::Bls12_381_G2_Compress => {
960            let tipo = Type::function(vec![Type::g2_element()], Type::byte_array());
961
962            (tipo, 1)
963        }
964        DefaultFunction::Bls12_381_G2_Uncompress => {
965            let tipo = Type::function(vec![Type::byte_array()], Type::g2_element());
966
967            (tipo, 1)
968        }
969        DefaultFunction::Bls12_381_G2_HashToGroup => {
970            let tipo = Type::function(
971                vec![Type::byte_array(), Type::byte_array()],
972                Type::g2_element(),
973            );
974
975            (tipo, 2)
976        }
977        DefaultFunction::Bls12_381_MillerLoop => {
978            let tipo = Type::function(
979                vec![Type::g1_element(), Type::g2_element()],
980                Type::miller_loop_result(),
981            );
982
983            (tipo, 2)
984        }
985        DefaultFunction::Bls12_381_MulMlResult => {
986            let tipo = Type::function(
987                vec![Type::miller_loop_result(), Type::miller_loop_result()],
988                Type::miller_loop_result(),
989            );
990
991            (tipo, 2)
992        }
993        DefaultFunction::Bls12_381_FinalVerify => {
994            let tipo = Type::function(
995                vec![Type::miller_loop_result(), Type::miller_loop_result()],
996                Type::bool(),
997            );
998
999            (tipo, 2)
1000        }
1001        DefaultFunction::IntegerToByteString => {
1002            let tipo = Type::function(
1003                vec![Type::bool(), Type::int(), Type::int()],
1004                Type::byte_array(),
1005            );
1006
1007            (tipo, 3)
1008        }
1009        DefaultFunction::ByteStringToInteger => {
1010            let tipo = Type::function(vec![Type::bool(), Type::byte_array()], Type::int());
1011
1012            (tipo, 2)
1013        }
1014        DefaultFunction::AndByteString => {
1015            let tipo = Type::function(
1016                vec![Type::bool(), Type::byte_array(), Type::byte_array()],
1017                Type::byte_array(),
1018            );
1019
1020            (tipo, 3)
1021        }
1022        DefaultFunction::OrByteString => {
1023            let tipo = Type::function(
1024                vec![Type::bool(), Type::byte_array(), Type::byte_array()],
1025                Type::byte_array(),
1026            );
1027
1028            (tipo, 3)
1029        }
1030        DefaultFunction::XorByteString => {
1031            let tipo = Type::function(
1032                vec![Type::bool(), Type::byte_array(), Type::byte_array()],
1033                Type::byte_array(),
1034            );
1035
1036            (tipo, 3)
1037        }
1038        DefaultFunction::ComplementByteString => {
1039            let tipo = Type::function(vec![Type::byte_array()], Type::byte_array());
1040
1041            (tipo, 1)
1042        }
1043        DefaultFunction::ReadBit => {
1044            let tipo = Type::function(vec![Type::byte_array(), Type::int()], Type::bool());
1045
1046            (tipo, 2)
1047        }
1048        DefaultFunction::WriteBits => {
1049            let tipo = Type::function(
1050                vec![Type::byte_array(), Type::list(Type::int()), Type::bool()],
1051                Type::byte_array(),
1052            );
1053
1054            (tipo, 3)
1055        }
1056        DefaultFunction::ReplicateByte => {
1057            let tipo = Type::function(vec![Type::int(), Type::int()], Type::byte_array());
1058
1059            (tipo, 2)
1060        }
1061        DefaultFunction::ShiftByteString => {
1062            let tipo = Type::function(vec![Type::byte_array(), Type::int()], Type::byte_array());
1063
1064            (tipo, 2)
1065        }
1066        DefaultFunction::RotateByteString => {
1067            let tipo = Type::function(vec![Type::byte_array(), Type::int()], Type::byte_array());
1068
1069            (tipo, 2)
1070        }
1071        DefaultFunction::CountSetBits => {
1072            let tipo = Type::function(vec![Type::byte_array()], Type::int());
1073
1074            (tipo, 1)
1075        }
1076        DefaultFunction::FindFirstSetBit => {
1077            let tipo = Type::function(vec![Type::byte_array()], Type::int());
1078
1079            (tipo, 1)
1080        }
1081        DefaultFunction::Ripemd_160 => {
1082            let tipo = Type::function(vec![Type::byte_array()], Type::byte_array());
1083
1084            (tipo, 1)
1085        } // DefaultFunction::ExpModInteger => {
1086          //     let tipo = Type::function(vec![Type::int(), Type::int(), Type::int()], Type::int());
1087
1088          //     (tipo, 3)
1089          // }
1090    };
1091
1092    ValueConstructor::public(
1093        tipo,
1094        ValueConstructorVariant::ModuleFn {
1095            name: builtin.aiken_name(),
1096            field_map: None,
1097            module: "".to_string(),
1098            arity,
1099            location: Span::empty(),
1100            builtin: Some(builtin),
1101        },
1102    )
1103}
1104
1105pub fn prelude_functions(
1106    id_gen: &IdGenerator,
1107    module_types: &HashMap<String, TypeInfo>,
1108) -> IndexMap<FunctionAccessKey, TypedFunction> {
1109    let mut functions = IndexMap::new();
1110
1111    let unconstr_index_body = TypedExpr::Call {
1112        location: Span::empty(),
1113        tipo: Type::int(),
1114        fun: TypedExpr::local_var(
1115            CONSTR_INDEX_EXPOSER,
1116            Type::function(vec![Type::data()], Type::int()),
1117            Span::empty(),
1118        )
1119        .into(),
1120        args: vec![CallArg {
1121            label: None,
1122            location: Span::empty(),
1123            value: TypedExpr::Var {
1124                location: Span::empty(),
1125                constructor: ValueConstructor {
1126                    public: true,
1127                    tipo: Type::data(),
1128                    variant: ValueConstructorVariant::LocalVariable {
1129                        location: Span::empty(),
1130                    },
1131                },
1132                name: "constr".to_string(),
1133            },
1134        }],
1135    };
1136
1137    let unconstr_index_func = Function {
1138        arguments: vec![TypedArg {
1139            arg_name: ArgName::Named {
1140                name: "constr".to_string(),
1141                label: "constr".to_string(),
1142                location: Span::empty(),
1143            },
1144            is_validator_param: false,
1145            doc: None,
1146            location: Span::empty(),
1147            annotation: None,
1148            tipo: Type::data(),
1149        }],
1150        on_test_failure: OnTestFailure::FailImmediately,
1151        doc: Some(
1152            indoc::indoc! {
1153                r#"
1154                /// Access the index of a constr typed as Data. Fails if the Data object is not a constr.
1155                "#
1156            }.to_string()
1157        ),
1158        location: Span::empty(),
1159        name: "unconstr_index".to_string(),
1160        public: true,
1161        return_annotation: None,
1162        return_type: Type::int(),
1163        end_position: 0,
1164        body: unconstr_index_body,
1165    };
1166
1167    functions.insert(
1168        FunctionAccessKey {
1169            module_name: BUILTIN.to_string(),
1170            function_name: "unconstr_index".to_string(),
1171        },
1172        unconstr_index_func,
1173    );
1174
1175    let unconstr_fields_body = TypedExpr::Call {
1176        location: Span::empty(),
1177        tipo: Type::list(Type::data()),
1178        fun: TypedExpr::local_var(
1179            CONSTR_FIELDS_EXPOSER,
1180            Type::function(vec![Type::data()], Type::list(Type::data())),
1181            Span::empty(),
1182        )
1183        .into(),
1184        args: vec![CallArg {
1185            label: None,
1186            location: Span::empty(),
1187            value: TypedExpr::Var {
1188                location: Span::empty(),
1189                constructor: ValueConstructor {
1190                    public: true,
1191                    tipo: Type::data(),
1192                    variant: ValueConstructorVariant::LocalVariable {
1193                        location: Span::empty(),
1194                    },
1195                },
1196                name: "constr".to_string(),
1197            },
1198        }],
1199    };
1200
1201    let unconstr_fields_func = Function {
1202        arguments: vec![TypedArg {
1203            arg_name: ArgName::Named {
1204                name: "constr".to_string(),
1205                label: "constr".to_string(),
1206                location: Span::empty(),
1207            },
1208            is_validator_param: false,
1209            doc: None,
1210            location: Span::empty(),
1211            annotation: None,
1212            tipo: Type::data(),
1213        }],
1214        on_test_failure: OnTestFailure::FailImmediately,
1215        doc: Some(
1216            indoc::indoc! {
1217                r#"
1218                /// Access the fields of a constr typed as Data. Fails if the Data object is not a constr.
1219                "#
1220            }.to_string()
1221        ),
1222        location: Span::empty(),
1223        name: "unconstr_fields".to_string(),
1224        public: true,
1225        return_annotation: None,
1226        return_type: Type::list(Type::data()),
1227        end_position: 0,
1228        body: unconstr_fields_body,
1229    };
1230
1231    functions.insert(
1232        FunctionAccessKey {
1233            module_name: BUILTIN.to_string(),
1234            function_name: "unconstr_fields".to_string(),
1235        },
1236        unconstr_fields_func,
1237    );
1238
1239    functions.insert(
1240        FunctionAccessKey {
1241            module_name: "".to_string(),
1242            function_name: "as_data".to_string(),
1243        },
1244        Function {
1245            arguments: vec![TypedArg {
1246                arg_name: ArgName::Named {
1247                    name: "data".to_string(),
1248                    label: "data".to_string(),
1249                    location: Span::empty(),
1250                },
1251                is_validator_param: false,
1252                location: Span::empty(),
1253                annotation: None,
1254                doc: None,
1255                tipo: Type::data(),
1256            }],
1257            on_test_failure: OnTestFailure::FailImmediately,
1258            body: TypedExpr::Var {
1259                location: Span::empty(),
1260                constructor: ValueConstructor {
1261                    public: true,
1262                    tipo: Type::data(),
1263                    variant: ValueConstructorVariant::LocalVariable {
1264                        location: Span::empty(),
1265                    },
1266                },
1267                name: "data".to_string(),
1268            },
1269            doc: Some(
1270                indoc::indoc! {
1271                    r#"
1272                    A function for explicitly upcasting any serialisable type into `Data`.
1273                    "#
1274                }
1275                .to_string(),
1276            ),
1277            location: Span::empty(),
1278            name: "as_data".to_string(),
1279            public: true,
1280            return_annotation: None,
1281            return_type: Type::data(),
1282            end_position: 0,
1283        },
1284    );
1285
1286    // /// Negate the argument. Useful for map/fold and pipelines.
1287    // pub fn not(self: Bool) -> Bool {
1288    //   !self
1289    // }
1290    functions.insert(
1291        FunctionAccessKey {
1292            module_name: "".to_string(),
1293            function_name: "not".to_string(),
1294        },
1295        Function {
1296            arguments: vec![TypedArg {
1297                arg_name: ArgName::Named {
1298                    name: "self".to_string(),
1299                    label: "self".to_string(),
1300                    location: Span::empty(),
1301                },
1302                is_validator_param: false,
1303                doc: None,
1304                location: Span::empty(),
1305                annotation: None,
1306                tipo: Type::bool(),
1307            }],
1308            on_test_failure: OnTestFailure::FailImmediately,
1309            doc: Some(
1310                indoc::indoc! {
1311                    r#"
1312                    /// Like `!`, but as a function. Handy for chaining using the pipe operator `|>` or to pass as a function.
1313                    "#
1314                }.to_string()
1315            ),
1316            location: Span::empty(),
1317            name: "not".to_string(),
1318            public: true,
1319            return_annotation: None,
1320            return_type: Type::bool(),
1321            end_position: 0,
1322            body: TypedExpr::UnOp {
1323                location: Span::empty(),
1324                tipo: Type::bool(),
1325                op: UnOp::Not,
1326                value: Box::new(TypedExpr::Var {
1327                    location: Span::empty(),
1328                    constructor: ValueConstructor {
1329                        public: true,
1330                        tipo: Type::bool(),
1331                        variant: ValueConstructorVariant::LocalVariable {
1332                            location: Span::empty(),
1333                        },
1334                    },
1335                    name: "self".to_string(),
1336                }),
1337            },
1338        },
1339    );
1340
1341    // /// A function that returns its argument. Handy as a default behavior sometimes.
1342    // pub fn identity(a: a) -> a {
1343    //   a
1344    // }
1345    let a_var = Type::generic_var(id_gen.next());
1346
1347    functions.insert(
1348        FunctionAccessKey {
1349            module_name: "".to_string(),
1350            function_name: "identity".to_string(),
1351        },
1352        Function {
1353            arguments: vec![TypedArg {
1354                arg_name: ArgName::Named {
1355                    name: "a".to_string(),
1356                    label: "a".to_string(),
1357                    location: Span::empty(),
1358                },
1359                is_validator_param: false,
1360                location: Span::empty(),
1361                annotation: None,
1362                doc: None,
1363                tipo: a_var.clone(),
1364            }],
1365            on_test_failure: OnTestFailure::FailImmediately,
1366            body: TypedExpr::Var {
1367                location: Span::empty(),
1368                constructor: ValueConstructor {
1369                    public: true,
1370                    tipo: a_var.clone(),
1371                    variant: ValueConstructorVariant::LocalVariable {
1372                        location: Span::empty(),
1373                    },
1374                },
1375                name: "a".to_string(),
1376            },
1377            doc: Some(
1378                indoc::indoc! {
1379                    r#"
1380                    A function that returns its argument. Handy as a default behavior sometimes.
1381                    "#
1382                }
1383                .to_string(),
1384            ),
1385            location: Span::empty(),
1386            name: "identity".to_string(),
1387            public: true,
1388            return_annotation: None,
1389            return_type: a_var,
1390            end_position: 0,
1391        },
1392    );
1393
1394    // /// A function that always return its first argument. Handy in folds and maps.
1395    // pub fn always(a: a, b _b: b) -> a {
1396    //   a
1397    // }
1398    let a_var = Type::generic_var(id_gen.next());
1399    let b_var = Type::generic_var(id_gen.next());
1400
1401    functions.insert(
1402        FunctionAccessKey {
1403            module_name: "".to_string(),
1404            function_name: "always".to_string(),
1405        },
1406        Function {
1407            on_test_failure: OnTestFailure::FailImmediately,
1408            arguments: vec![
1409                TypedArg {
1410                    arg_name: ArgName::Named {
1411                        name: "a".to_string(),
1412                        label: "a".to_string(),
1413                        location: Span::empty(),
1414                    },
1415                    is_validator_param: false,
1416                    location: Span::empty(),
1417                    annotation: None,
1418                    doc: None,
1419                    tipo: a_var.clone(),
1420                },
1421                TypedArg {
1422                    arg_name: ArgName::Discarded {
1423                        name: "_b".to_string(),
1424                        label: "_b".to_string(),
1425                        location: Span::empty(),
1426                    },
1427                    is_validator_param: false,
1428                    location: Span::empty(),
1429                    annotation: None,
1430                    doc: None,
1431                    tipo: b_var,
1432                },
1433            ],
1434            body: TypedExpr::Var {
1435                location: Span::empty(),
1436                constructor: ValueConstructor {
1437                    public: true,
1438                    tipo: a_var.clone(),
1439                    variant: ValueConstructorVariant::LocalVariable {
1440                        location: Span::empty(),
1441                    },
1442                },
1443                name: "a".to_string(),
1444            },
1445            doc: Some(
1446                indoc::indoc! {
1447                    r#"
1448                    A function that always return its first argument. Handy in folds and maps.
1449
1450                    ```aiken
1451                    let always_14 = always(14, _)
1452                    always_14(42) == 14
1453                    always_14(1337) == 14
1454                    always_14(0) == 14
1455                    ```
1456                    "#
1457                }
1458                .to_string(),
1459            ),
1460            location: Span::empty(),
1461            name: "always".to_string(),
1462            public: true,
1463            return_annotation: None,
1464            return_type: a_var,
1465            end_position: 0,
1466        },
1467    );
1468
1469    // /// A function that absorbs any expression and returns true. Useful to write failing test
1470    // /// scenarios regardless of the output of a function.
1471    // pub fn tautology(a: a) -> Bool {
1472    //   a == a
1473    // }
1474    functions.insert(
1475        FunctionAccessKey {
1476            module_name: "".to_string(),
1477            function_name: "tautology".to_string(),
1478        },
1479        aiken_fn!(
1480            &module_types,
1481            &id_gen,
1482            r#"
1483                pub fn tautology(a: a) -> Bool {
1484                  a == a
1485                }
1486            "#
1487        ),
1488    );
1489
1490    // /// A function that absorbs any expression and returns true. Useful to write failing test
1491    // // scenarios regardless of the output of a function.
1492    // pub fn tautology(a: a) -> Bool {
1493    //   a == a
1494    // }
1495    functions.insert(
1496        FunctionAccessKey {
1497            module_name: "".to_string(),
1498            function_name: "tautology".to_string(),
1499        },
1500        aiken_fn!(
1501            &module_types,
1502            &id_gen,
1503            r#"
1504                pub fn tautology(a: a) -> Bool {
1505                  a == a
1506                }
1507            "#
1508        ),
1509    );
1510
1511    // /// A function that flips the arguments of a function.
1512    // pub fn flip(f: fn(a, b) -> c) -> fn(b, a) -> c {
1513    //   fn(b, a) { f(a, b) }
1514    // }
1515    let a_var = Type::generic_var(id_gen.next());
1516    let b_var = Type::generic_var(id_gen.next());
1517    let c_var = Type::generic_var(id_gen.next());
1518
1519    let input_type = Type::function(vec![a_var.clone(), b_var.clone()], c_var.clone());
1520    let return_type = Type::function(vec![b_var.clone(), a_var.clone()], c_var.clone());
1521
1522    functions.insert(
1523        FunctionAccessKey {
1524            module_name: "".to_string(),
1525            function_name: "flip".to_string(),
1526        },
1527        Function {
1528            on_test_failure: OnTestFailure::FailImmediately,
1529            arguments: vec![TypedArg {
1530                arg_name: ArgName::Named {
1531                    name: "f".to_string(),
1532                    label: "f".to_string(),
1533                    location: Span::empty(),
1534                },
1535                is_validator_param: false,
1536                location: Span::empty(),
1537                annotation: None,
1538                doc: None,
1539                tipo: input_type.clone(),
1540            }],
1541            body: TypedExpr::Fn {
1542                location: Span::empty(),
1543                tipo: return_type.clone(),
1544                is_capture: false,
1545                args: vec![
1546                    TypedArg {
1547                        arg_name: ArgName::Named {
1548                            name: "b".to_string(),
1549                            label: "b".to_string(),
1550                            location: Span::empty(),
1551                        },
1552                        is_validator_param: false,
1553                        location: Span::empty(),
1554                        annotation: None,
1555                        doc: None,
1556                        tipo: b_var.clone(),
1557                    },
1558                    TypedArg {
1559                        arg_name: ArgName::Named {
1560                            name: "a".to_string(),
1561                            label: "a".to_string(),
1562                            location: Span::empty(),
1563                        },
1564                        is_validator_param: false,
1565                        location: Span::empty(),
1566                        annotation: None,
1567                        doc: None,
1568                        tipo: a_var.clone(),
1569                    },
1570                ],
1571                body: Box::new(TypedExpr::Call {
1572                    location: Span::empty(),
1573                    tipo: c_var,
1574                    fun: Box::new(TypedExpr::Var {
1575                        location: Span::empty(),
1576                        constructor: ValueConstructor {
1577                            public: true,
1578                            tipo: input_type,
1579                            variant: ValueConstructorVariant::LocalVariable {
1580                                location: Span::empty(),
1581                            },
1582                        },
1583                        name: "f".to_string(),
1584                    }),
1585                    args: vec![
1586                        CallArg {
1587                            label: None,
1588                            location: Span::empty(),
1589                            value: TypedExpr::Var {
1590                                location: Span::empty(),
1591                                constructor: ValueConstructor {
1592                                    public: true,
1593                                    tipo: a_var,
1594                                    variant: ValueConstructorVariant::LocalVariable {
1595                                        location: Span::empty(),
1596                                    },
1597                                },
1598                                name: "a".to_string(),
1599                            },
1600                        },
1601                        CallArg {
1602                            label: None,
1603                            location: Span::empty(),
1604                            value: TypedExpr::Var {
1605                                location: Span::empty(),
1606                                constructor: ValueConstructor {
1607                                    public: true,
1608                                    tipo: b_var,
1609                                    variant: ValueConstructorVariant::LocalVariable {
1610                                        location: Span::empty(),
1611                                    },
1612                                },
1613                                name: "b".to_string(),
1614                            },
1615                        },
1616                    ],
1617                }),
1618                return_annotation: None,
1619            },
1620            doc: Some(
1621                indoc::indoc! {
1622                    r#"
1623                    A function that flips the arguments of a function.
1624
1625                    ```aiken
1626                    pub fn titleize(left: String, right: String) {}
1627
1628                    titleize("Hello", "World") // "Hello, World!"
1629
1630                    flip(titleize)("Hello", "World") // "World, Hello!"
1631                    ```
1632                    "#
1633                }
1634                .to_string(),
1635            ),
1636            location: Span::empty(),
1637            name: "flip".to_string(),
1638            public: true,
1639            return_annotation: None,
1640            return_type,
1641            end_position: 0,
1642        },
1643    );
1644
1645    functions.insert(
1646        FunctionAccessKey {
1647            module_name: "".to_string(),
1648            function_name: "enumerate".to_string(),
1649        },
1650        aiken_fn!(
1651            &module_types,
1652            &id_gen,
1653            r#"
1654                fn enumerate(
1655                  self: List<a>,
1656                  zero: b,
1657                  with: fn(a, b) -> b,
1658                  last: fn(a, b) -> b,
1659                ) -> b {
1660                  when self is {
1661                    [] -> zero
1662                    [x] -> last(x, zero)
1663                    [x, ..xs] -> with(x, enumerate(xs, zero, with, last))
1664                  }
1665                }
1666            "#
1667        ),
1668    );
1669
1670    functions.insert(
1671        FunctionAccessKey {
1672            module_name: "".to_string(),
1673            function_name: "encode_base16".to_string(),
1674        },
1675        aiken_fn!(
1676            &module_types,
1677            &id_gen,
1678            r#"
1679                use aiken/builtin
1680
1681                fn encode_base16(bytes: ByteArray, ix: Int, builder: ByteArray) -> ByteArray {
1682                  if ix < 0 {
1683                    builder
1684                  } else {
1685                    let byte = builtin.index_bytearray(bytes, ix)
1686                    let msb = byte / 16
1687                    let lsb = byte % 16
1688                    let builder =
1689                      builtin.cons_bytearray(
1690                        msb + if msb < 10 {
1691                          48
1692                        } else {
1693                          55
1694                        },
1695                        builtin.cons_bytearray(
1696                          lsb + if lsb < 10 {
1697                            48
1698                          } else {
1699                            55
1700                          },
1701                          builder,
1702                        ),
1703                      )
1704                    encode_base16(bytes, ix - 1, builder)
1705                  }
1706                }
1707            "#
1708        ),
1709    );
1710
1711    functions.insert(
1712        FunctionAccessKey {
1713            module_name: "".to_string(),
1714            function_name: "do_from_int".to_string(),
1715        },
1716        aiken_fn!(
1717            &module_types,
1718            &id_gen,
1719            r#"
1720                use aiken/builtin
1721
1722                fn do_from_int(i: Int, digits: ByteArray) -> ByteArray {
1723                  if i <= 0 {
1724                    digits
1725                  } else {
1726                    do_from_int(
1727                      builtin.quotient_integer(i, 10),
1728                      builtin.cons_bytearray(builtin.remainder_integer(i, 10) + 48, digits),
1729                    )
1730                  }
1731                }
1732            "#
1733        ),
1734    );
1735
1736    functions.insert(
1737        FunctionAccessKey {
1738            module_name: "".to_string(),
1739            function_name: "from_int".to_string(),
1740        },
1741        aiken_fn!(
1742            &module_types,
1743            &id_gen,
1744            r#"
1745                use aiken/builtin
1746
1747                /// Encode an integer into UTF-8.
1748                fn from_int(i: Int, digits: ByteArray) -> ByteArray {
1749                  if i == 0 {
1750                    builtin.append_bytearray(#"30", digits)
1751                  } else if i < 0 {
1752                    builtin.append_bytearray(#"2d", from_int(-i, digits))
1753                  } else {
1754                    do_from_int(
1755                      builtin.quotient_integer(i, 10),
1756                      builtin.cons_bytearray(builtin.remainder_integer(i, 10) + 48, digits),
1757                    )
1758                  }
1759                }
1760            "#
1761        ),
1762    );
1763
1764    functions.insert(
1765        FunctionAccessKey {
1766            module_name: "".to_string(),
1767            function_name: "diagnostic".to_string(),
1768        },
1769        aiken_fn!(
1770            &module_types,
1771            &id_gen,
1772            r#"
1773              use aiken/builtin
1774
1775              fn diagnostic(self: Data, builder: ByteArray) -> ByteArray {
1776                builtin.choose_data(
1777                  self,
1778                  {
1779                    let Pair(constr, fields) = builtin.un_constr_data(self)
1780
1781                    let builder =
1782                      when fields is {
1783                        [] -> builtin.append_bytearray(#"5b5d29", builder)
1784                        _ -> {
1785                          let bytes =
1786                            enumerate(
1787                              fields,
1788                              builtin.append_bytearray(#"5d29", builder),
1789                              fn(e: Data, st: ByteArray) {
1790                                diagnostic(e, builtin.append_bytearray(#"2c20", st))
1791                              },
1792                              fn(e: Data, st: ByteArray) { diagnostic(e, st) },
1793                            )
1794                          builtin.append_bytearray(#"5b5f20", bytes)
1795                        }
1796                      }
1797
1798                    let constr_tag =
1799                      if constr < 7 {
1800                        121 + constr
1801                      } else if constr < 128 {
1802                        1280 + constr - 7
1803                      } else {
1804                        fail @"What are you doing? No I mean, seriously."
1805                      }
1806
1807                    builder
1808                      |> builtin.append_bytearray(#"28", _)
1809                      |> from_int(constr_tag, _)
1810                  },
1811                  {
1812                    let elems = builtin.un_map_data(self)
1813                    when elems is {
1814                      [] -> builtin.append_bytearray(#"7b7d", builder)
1815                      _ -> {
1816                        let bytes =
1817                          enumerate(
1818                            elems,
1819                            builtin.append_bytearray(#"207d", builder),
1820                            fn(e: Pair<Data, Data>, st: ByteArray) {
1821                              let value = diagnostic(e.2nd, builtin.append_bytearray(#"2c20", st))
1822                              diagnostic(e.1st, builtin.append_bytearray(#"3a20", value))
1823                            },
1824                            fn(e: Pair<Data, Data>, st: ByteArray) {
1825                              let value = diagnostic(e.2nd, st)
1826                              diagnostic(e.1st, builtin.append_bytearray(#"3a20", value))
1827                            },
1828                          )
1829                        builtin.append_bytearray(#"7b5f20", bytes)
1830                      }
1831                    }
1832                  },
1833                  {
1834                    let elems = builtin.un_list_data(self)
1835                    when elems is {
1836                      [] -> builtin.append_bytearray(#"5b5d", builder)
1837                      _ -> {
1838                        let bytes =
1839                          enumerate(
1840                            elems,
1841                            builtin.append_bytearray(#"5d", builder),
1842                            fn(e: Data, st: ByteArray) {
1843                              diagnostic(e, builtin.append_bytearray(#"2c20", st))
1844                            },
1845                            fn(e: Data, st: ByteArray) { diagnostic(e, st) },
1846                          )
1847                        builtin.append_bytearray(#"5b5f20", bytes)
1848                      }
1849                    }
1850                  },
1851                  self
1852                    |> builtin.un_i_data
1853                    |> from_int(builder),
1854                  {
1855                    let bytes = builtin.un_b_data(self)
1856                    bytes
1857                      |> encode_base16(
1858                          builtin.length_of_bytearray(bytes) - 1,
1859                          builtin.append_bytearray(#"27", builder),
1860                        )
1861                      |> builtin.append_bytearray(#"6827", _)
1862                  },
1863                )
1864              }
1865            "#
1866        ),
1867    );
1868
1869    functions
1870}
1871
1872pub fn prelude_data_types(id_gen: &IdGenerator) -> IndexMap<DataTypeKey, TypedDataType> {
1873    let mut data_types = IndexMap::new();
1874
1875    // Data
1876    let data_data_type = TypedDataType::data();
1877    data_types.insert(
1878        DataTypeKey {
1879            module_name: "".to_string(),
1880            defined_type: well_known::DATA.to_string(),
1881        },
1882        data_data_type,
1883    );
1884
1885    // Void
1886    let void_data_type = TypedDataType::void();
1887    data_types.insert(
1888        DataTypeKey {
1889            module_name: "".to_string(),
1890            defined_type: well_known::VOID.to_string(),
1891        },
1892        void_data_type,
1893    );
1894
1895    // Ordering
1896    let ordering_data_type = TypedDataType::ordering();
1897    data_types.insert(
1898        DataTypeKey {
1899            module_name: "".to_string(),
1900            defined_type: well_known::ORDERING.to_string(),
1901        },
1902        ordering_data_type,
1903    );
1904
1905    // Bool
1906    let bool_data_type = TypedDataType::bool();
1907    data_types.insert(
1908        DataTypeKey {
1909            module_name: "".to_string(),
1910            defined_type: well_known::BOOL.to_string(),
1911        },
1912        bool_data_type,
1913    );
1914
1915    // Option
1916    let option_data_type = TypedDataType::option(Type::generic_var(id_gen.next()));
1917    data_types.insert(
1918        DataTypeKey {
1919            module_name: "".to_string(),
1920            defined_type: well_known::OPTION.to_string(),
1921        },
1922        option_data_type,
1923    );
1924
1925    // Pair
1926    let pair_data_type = TypedDataType::pair(
1927        Type::generic_var(id_gen.next()),
1928        Type::generic_var(id_gen.next()),
1929    );
1930    data_types.insert(
1931        DataTypeKey {
1932            module_name: "".to_string(),
1933            defined_type: well_known::PAIR.to_string(),
1934        },
1935        pair_data_type,
1936    );
1937
1938    // Never
1939    data_types.insert(
1940        DataTypeKey {
1941            module_name: "".to_string(),
1942            defined_type: well_known::NEVER.to_string(),
1943        },
1944        TypedDataType::never(),
1945    );
1946
1947    // PRNG
1948    let prng_data_type = TypedDataType::prng();
1949    data_types.insert(
1950        DataTypeKey {
1951            module_name: "".to_string(),
1952            defined_type: well_known::PRNG.to_string(),
1953        },
1954        prng_data_type,
1955    );
1956
1957    // __ScriptPurpose
1958    let script_purpose_data_type = TypedDataType::script_purpose();
1959    data_types.insert(
1960        DataTypeKey {
1961            module_name: "".to_string(),
1962            defined_type: well_known::SCRIPT_PURPOSE.to_string(),
1963        },
1964        script_purpose_data_type,
1965    );
1966
1967    // __ScriptContext
1968    let script_context_data_type = TypedDataType::script_context();
1969    data_types.insert(
1970        DataTypeKey {
1971            module_name: "".to_string(),
1972            defined_type: well_known::SCRIPT_CONTEXT.to_string(),
1973        },
1974        script_context_data_type,
1975    );
1976
1977    data_types
1978}
1979
1980// ----------------------------------------------------------------------------
1981// TypedDataTypes
1982//
1983// TODO: Rewrite in terms of ValueConstructor to avoid duplication and ensure
1984// consistency with prelude definitions.
1985
1986impl TypedDataType {
1987    pub fn data() -> Self {
1988        DataType::known_enum(well_known::DATA, &[])
1989    }
1990
1991    pub fn void() -> Self {
1992        DataType::known_enum(well_known::VOID, well_known::VOID_CONSTRUCTORS)
1993    }
1994
1995    pub fn bool() -> Self {
1996        DataType::known_enum(well_known::BOOL, well_known::BOOL_CONSTRUCTORS)
1997    }
1998
1999    pub fn script_purpose() -> Self {
2000        DataType::known_enum(
2001            well_known::SCRIPT_PURPOSE,
2002            well_known::SCRIPT_PURPOSE_CONSTRUCTORS,
2003        )
2004    }
2005
2006    pub fn script_context() -> Self {
2007        DataType::known_enum(
2008            well_known::SCRIPT_CONTEXT,
2009            well_known::SCRIPT_CONTEXT_CONSTRUCTORS,
2010        )
2011    }
2012
2013    pub fn prng() -> Self {
2014        let bytearray_arg = |label: &str| RecordConstructorArg {
2015            label: Some(label.to_string()),
2016            doc: None,
2017            annotation: Annotation::bytearray(Span::empty()),
2018            location: Span::empty(),
2019            tipo: Type::byte_array(),
2020        };
2021
2022        let int_arg = |label: &str| RecordConstructorArg {
2023            label: Some(label.to_string()),
2024            doc: None,
2025            annotation: Annotation::int(Span::empty()),
2026            location: Span::empty(),
2027            tipo: Type::int(),
2028        };
2029
2030        DataType::known_data_type(
2031            well_known::PRNG,
2032            &[
2033                RecordConstructor::known_record(
2034                    well_known::PRNG_CONSTRUCTORS[0],
2035                    &[bytearray_arg("seed"), bytearray_arg("choices")],
2036                ),
2037                RecordConstructor::known_record(
2038                    well_known::PRNG_CONSTRUCTORS[1],
2039                    &[int_arg("cursor"), bytearray_arg("choices")],
2040                ),
2041            ],
2042        )
2043    }
2044
2045    pub fn ordering() -> Self {
2046        DataType::known_enum(well_known::ORDERING, well_known::ORDERING_CONSTRUCTORS)
2047    }
2048
2049    pub fn option(tipo: Rc<Type>) -> Self {
2050        DataType {
2051            decorators: vec![],
2052            constructors: vec![
2053                RecordConstructor {
2054                    decorators: vec![],
2055                    location: Span::empty(),
2056                    name: well_known::OPTION_CONSTRUCTORS[0].to_string(),
2057                    arguments: vec![RecordConstructorArg {
2058                        label: None,
2059                        annotation: Annotation::Var {
2060                            location: Span::empty(),
2061                            name: "a".to_string(),
2062                        },
2063                        location: Span::empty(),
2064                        tipo: tipo.clone(),
2065                        doc: None,
2066                    }],
2067                    doc: None,
2068                    sugar: false,
2069                },
2070                RecordConstructor {
2071                    decorators: vec![],
2072                    location: Span::empty(),
2073                    name: well_known::OPTION_CONSTRUCTORS[1].to_string(),
2074                    arguments: vec![],
2075                    doc: None,
2076                    sugar: false,
2077                },
2078            ],
2079            doc: None,
2080            location: Span::empty(),
2081            name: well_known::OPTION.to_string(),
2082            opaque: false,
2083            parameters: vec!["a".to_string()],
2084            public: true,
2085            typed_parameters: vec![tipo],
2086        }
2087    }
2088
2089    pub fn pair(left: Rc<Type>, right: Rc<Type>) -> Self {
2090        DataType {
2091            decorators: vec![],
2092            constructors: vec![RecordConstructor {
2093                decorators: vec![],
2094                location: Span::empty(),
2095                name: well_known::PAIR.to_string(),
2096                arguments: vec![
2097                    RecordConstructorArg {
2098                        label: None,
2099                        annotation: Annotation::Var {
2100                            location: Span::empty(),
2101                            name: "left".to_string(),
2102                        },
2103                        location: Span::empty(),
2104                        tipo: left.clone(),
2105                        doc: None,
2106                    },
2107                    RecordConstructorArg {
2108                        label: None,
2109                        annotation: Annotation::Var {
2110                            location: Span::empty(),
2111                            name: "right".to_string(),
2112                        },
2113                        location: Span::empty(),
2114                        tipo: right.clone(),
2115                        doc: None,
2116                    },
2117                ],
2118                doc: None,
2119                sugar: false,
2120            }],
2121            doc: None,
2122            location: Span::empty(),
2123            name: well_known::PAIR.to_string(),
2124            opaque: false,
2125            parameters: vec!["left".to_string(), "right".to_string()],
2126            public: true,
2127            typed_parameters: vec![left, right],
2128        }
2129    }
2130
2131    pub fn never() -> Self {
2132        DataType::known_enum(well_known::NEVER, well_known::NEVER_CONSTRUCTORS)
2133    }
2134}