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