1use std::sync::OnceLock;
2
3use rexlang_ast::expr::{Decl, Program};
4use rexlang_lexer::Token;
5use rexlang_parser::Parser;
6use rexlang_util::GasMeter;
7
8use crate::{AdtDecl, BuiltinTypeId, Predicate, Scheme, Type, TypeError, TypeSystem};
9use rexlang_ast::expr::sym;
10
11fn inject_prelude_classes_and_instances(ts: &mut TypeSystem) -> Result<(), TypeError> {
12 let program = prelude_typeclasses_program()?;
13 for decl in &program.decls {
14 match decl {
15 Decl::Class(class_decl) => ts.inject_class_decl(class_decl)?,
16 Decl::Instance(inst_decl) => {
17 ts.inject_instance_decl(inst_decl)?;
18 }
19 Decl::Type(..) | Decl::Fn(..) | Decl::DeclareFn(..) | Decl::Import(..) => {}
20 }
21 }
22 Ok(())
23}
24
25pub fn prelude_typeclasses_program() -> Result<&'static Program, TypeError> {
26 static PROGRAM: OnceLock<Result<Program, String>> = OnceLock::new();
27 let parsed = PROGRAM.get_or_init(|| {
28 let source = include_str!("prelude_typeclasses.rex");
29 let tokens =
30 Token::tokenize(source).map_err(|e| format!("prelude_typeclasses: lex error: {e}"))?;
31 let mut parser = Parser::new(tokens);
32 match parser.parse_program(&mut GasMeter::default()) {
33 Ok(program) => Ok(program),
34 Err(errs) => {
35 let mut out = String::from("prelude_typeclasses: parse error:");
36 for err in errs {
37 out.push_str(&format!("\n {err}"));
38 }
39 Err(out)
40 }
41 }
42 });
43 match parsed {
44 Ok(program) => Ok(program),
45 Err(msg) => Err(TypeError::Internal(msg.clone())),
46 }
47}
48
49fn inject_prelude_primops(ts: &mut TypeSystem) {
50 let bool_ty = Type::builtin(BuiltinTypeId::Bool);
55 let i32_ty = Type::builtin(BuiltinTypeId::I32);
56 let string_ty = Type::builtin(BuiltinTypeId::String);
57
58 {
65 let eq_types = [
66 BuiltinTypeId::Bool,
67 BuiltinTypeId::U8,
68 BuiltinTypeId::U16,
69 BuiltinTypeId::U32,
70 BuiltinTypeId::U64,
71 BuiltinTypeId::I8,
72 BuiltinTypeId::I16,
73 BuiltinTypeId::I32,
74 BuiltinTypeId::I64,
75 BuiltinTypeId::F32,
76 BuiltinTypeId::F64,
77 BuiltinTypeId::String,
78 BuiltinTypeId::Uuid,
79 BuiltinTypeId::DateTime,
80 ];
81 for builtin in eq_types {
82 let t = Type::builtin(builtin);
83 ts.add_overload(
84 "prim_eq",
85 Scheme::new(
86 vec![],
87 vec![],
88 Type::fun(t.clone(), Type::fun(t.clone(), bool_ty.clone())),
89 ),
90 );
91 ts.add_overload(
92 "prim_ne",
93 Scheme::new(
94 vec![],
95 vec![],
96 Type::fun(t.clone(), Type::fun(t, bool_ty.clone())),
97 ),
98 );
99 }
100 }
101
102 {
106 let a_tv = ts.supply.fresh(Some(sym("a")));
107 let a = Type::var(a_tv.clone());
108 let array_a = Type::app(Type::builtin(BuiltinTypeId::Array), a.clone());
109 ts.add_value(
110 "prim_array_eq",
111 Scheme::new(
112 vec![a_tv.clone()],
113 vec![],
114 Type::fun(array_a.clone(), Type::fun(array_a.clone(), bool_ty.clone())),
115 ),
116 );
117 ts.add_value(
118 "prim_array_ne",
119 Scheme::new(
120 vec![a_tv],
121 vec![],
122 Type::fun(array_a.clone(), Type::fun(array_a, bool_ty.clone())),
123 ),
124 );
125 }
126
127 {
129 let additive = [
130 BuiltinTypeId::String,
131 BuiltinTypeId::U8,
132 BuiltinTypeId::U16,
133 BuiltinTypeId::U32,
134 BuiltinTypeId::U64,
135 BuiltinTypeId::I8,
136 BuiltinTypeId::I16,
137 BuiltinTypeId::I32,
138 BuiltinTypeId::I64,
139 BuiltinTypeId::F32,
140 BuiltinTypeId::F64,
141 ];
142 for builtin in additive {
143 let t = Type::builtin(builtin);
144 ts.add_overload("prim_zero", Scheme::new(vec![], vec![], t.clone()));
145 ts.add_overload(
146 "prim_add",
147 Scheme::new(
148 vec![],
149 vec![],
150 Type::fun(t.clone(), Type::fun(t.clone(), t.clone())),
151 ),
152 );
153 }
154
155 let multiplicative = [
156 BuiltinTypeId::U8,
157 BuiltinTypeId::U16,
158 BuiltinTypeId::U32,
159 BuiltinTypeId::U64,
160 BuiltinTypeId::I8,
161 BuiltinTypeId::I16,
162 BuiltinTypeId::I32,
163 BuiltinTypeId::I64,
164 BuiltinTypeId::F32,
165 BuiltinTypeId::F64,
166 ];
167 for builtin in multiplicative {
168 let t = Type::builtin(builtin);
169 ts.add_overload("prim_one", Scheme::new(vec![], vec![], t.clone()));
170 ts.add_overload(
171 "prim_mul",
172 Scheme::new(
173 vec![],
174 vec![],
175 Type::fun(t.clone(), Type::fun(t.clone(), t.clone())),
176 ),
177 );
178 }
179
180 let signed = [
181 BuiltinTypeId::I8,
182 BuiltinTypeId::I16,
183 BuiltinTypeId::I32,
184 BuiltinTypeId::I64,
185 BuiltinTypeId::F32,
186 BuiltinTypeId::F64,
187 ];
188 for builtin in signed {
189 let t = Type::builtin(builtin);
190 ts.add_overload(
191 "prim_sub",
192 Scheme::new(
193 vec![],
194 vec![],
195 Type::fun(t.clone(), Type::fun(t.clone(), t.clone())),
196 ),
197 );
198 ts.add_overload(
199 "prim_negate",
200 Scheme::new(vec![], vec![], Type::fun(t.clone(), t.clone())),
201 );
202 }
203
204 for builtin in [BuiltinTypeId::F32, BuiltinTypeId::F64] {
205 let t = Type::builtin(builtin);
206 ts.add_overload(
207 "prim_div",
208 Scheme::new(
209 vec![],
210 vec![],
211 Type::fun(t.clone(), Type::fun(t.clone(), t.clone())),
212 ),
213 );
214 }
215
216 let integral = [
217 BuiltinTypeId::U8,
218 BuiltinTypeId::U16,
219 BuiltinTypeId::U32,
220 BuiltinTypeId::U64,
221 BuiltinTypeId::I8,
222 BuiltinTypeId::I16,
223 BuiltinTypeId::I32,
224 BuiltinTypeId::I64,
225 ];
226 for builtin in integral {
227 let t = Type::builtin(builtin);
228 ts.add_overload(
229 "prim_mod",
230 Scheme::new(
231 vec![],
232 vec![],
233 Type::fun(t.clone(), Type::fun(t.clone(), t.clone())),
234 ),
235 );
236 }
237 }
238
239 {
241 let ord = [
242 BuiltinTypeId::U8,
243 BuiltinTypeId::U16,
244 BuiltinTypeId::U32,
245 BuiltinTypeId::U64,
246 BuiltinTypeId::I8,
247 BuiltinTypeId::I16,
248 BuiltinTypeId::I32,
249 BuiltinTypeId::I64,
250 BuiltinTypeId::F32,
251 BuiltinTypeId::F64,
252 BuiltinTypeId::String,
253 ];
254 for builtin in ord {
255 let t = Type::builtin(builtin);
256 ts.add_overload(
257 "prim_cmp",
258 Scheme::new(
259 vec![],
260 vec![],
261 Type::fun(t.clone(), Type::fun(t.clone(), i32_ty.clone())),
262 ),
263 );
264 for name in ["prim_lt", "prim_le", "prim_gt", "prim_ge"] {
265 ts.add_overload(
266 name,
267 Scheme::new(
268 vec![],
269 vec![],
270 Type::fun(t.clone(), Type::fun(t.clone(), bool_ty.clone())),
271 ),
272 );
273 }
274 }
275 }
276
277 {
279 let show_types = [
280 BuiltinTypeId::Bool,
281 BuiltinTypeId::U8,
282 BuiltinTypeId::U16,
283 BuiltinTypeId::U32,
284 BuiltinTypeId::U64,
285 BuiltinTypeId::I8,
286 BuiltinTypeId::I16,
287 BuiltinTypeId::I32,
288 BuiltinTypeId::I64,
289 BuiltinTypeId::F32,
290 BuiltinTypeId::F64,
291 BuiltinTypeId::String,
292 BuiltinTypeId::Uuid,
293 BuiltinTypeId::DateTime,
294 ];
295 for builtin in show_types {
296 let t = Type::builtin(builtin);
297 ts.add_overload(
298 "prim_show",
299 Scheme::new(vec![], vec![], Type::fun(t, string_ty.clone())),
300 );
301 }
302 }
303
304 {
309 let a_tv = ts.supply.fresh(Some(sym("a")));
310 let a = Type::var(a_tv.clone());
311 ts.add_value(
312 "prim_json_stringify",
313 Scheme::new(vec![a_tv], vec![], Type::fun(a, string_ty.clone())),
314 );
315 }
316
317 {
323 let a_tv = ts.supply.fresh(Some(sym("a")));
324 let a = Type::var(a_tv.clone());
325 let result_con = Type::builtin(BuiltinTypeId::Result);
326 let result_as = Type::app(Type::app(result_con, string_ty.clone()), a);
327 ts.add_value(
328 "prim_json_parse",
329 Scheme::new(vec![a_tv], vec![], Type::fun(string_ty.clone(), result_as)),
330 );
331 }
332
333 {
338 let list_con = Type::builtin(BuiltinTypeId::List);
339 let array_con = Type::builtin(BuiltinTypeId::Array);
340 let option_con = Type::builtin(BuiltinTypeId::Option);
341 let result_con = Type::builtin(BuiltinTypeId::Result);
342
343 let list_of = |t: Type| Type::app(list_con.clone(), t);
344 let array_of = |t: Type| Type::app(array_con.clone(), t);
345 let option_of = |t: Type| Type::app(option_con.clone(), t);
346 let result_of = |ok: Type, err: Type| Type::app(Type::app(result_con.clone(), err), ok);
347
348 {
350 let a_tv = ts.supply.fresh(Some(sym("a")));
351 let b_tv = ts.supply.fresh(Some(sym("b")));
352 let a = Type::var(a_tv.clone());
353 let b = Type::var(b_tv.clone());
354 ts.add_overload(
355 "prim_map",
356 Scheme::new(
357 vec![a_tv.clone(), b_tv.clone()],
358 vec![],
359 Type::fun(
360 Type::fun(a.clone(), b.clone()),
361 Type::fun(list_of(a.clone()), list_of(b.clone())),
362 ),
363 ),
364 );
365 ts.add_overload(
366 "prim_map",
367 Scheme::new(
368 vec![a_tv.clone(), b_tv.clone()],
369 vec![],
370 Type::fun(
371 Type::fun(a.clone(), b.clone()),
372 Type::fun(array_of(a.clone()), array_of(b.clone())),
373 ),
374 ),
375 );
376 ts.add_overload(
377 "prim_map",
378 Scheme::new(
379 vec![a_tv.clone(), b_tv.clone()],
380 vec![],
381 Type::fun(
382 Type::fun(a.clone(), b.clone()),
383 Type::fun(option_of(a.clone()), option_of(b.clone())),
384 ),
385 ),
386 );
387 let e_tv = ts.supply.fresh(Some(sym("e")));
388 let e = Type::var(e_tv.clone());
389 ts.add_overload(
390 "prim_map",
391 Scheme::new(
392 vec![a_tv, b_tv, e_tv],
393 vec![],
394 Type::fun(
395 Type::fun(a.clone(), b.clone()),
396 Type::fun(result_of(a.clone(), e.clone()), result_of(b.clone(), e)),
397 ),
398 ),
399 );
400 }
401
402 {
404 let a_tv = ts.supply.fresh(Some(sym("a")));
405 let a = Type::var(a_tv.clone());
406 ts.add_value(
407 "prim_array_singleton",
408 Scheme::new(vec![a_tv], vec![], Type::fun(a.clone(), array_of(a))),
409 );
410 }
411
412 {
414 let a_tv = ts.supply.fresh(Some(sym("a")));
415 let b_tv = ts.supply.fresh(Some(sym("b")));
416 let a = Type::var(a_tv.clone());
417 let b = Type::var(b_tv.clone());
418 let step_l = Type::fun(b.clone(), Type::fun(a.clone(), b.clone()));
419 let step_r = Type::fun(a.clone(), Type::fun(b.clone(), b.clone()));
420 let mut add_for = |fa: Type| {
421 ts.add_overload(
422 "prim_foldl",
423 Scheme::new(
424 vec![a_tv.clone(), b_tv.clone()],
425 vec![],
426 Type::fun(
427 step_l.clone(),
428 Type::fun(b.clone(), Type::fun(fa.clone(), b.clone())),
429 ),
430 ),
431 );
432 ts.add_overload(
433 "prim_foldr",
434 Scheme::new(
435 vec![a_tv.clone(), b_tv.clone()],
436 vec![],
437 Type::fun(
438 step_r.clone(),
439 Type::fun(b.clone(), Type::fun(fa.clone(), b.clone())),
440 ),
441 ),
442 );
443 ts.add_overload(
444 "prim_fold",
445 Scheme::new(
446 vec![a_tv.clone(), b_tv.clone()],
447 vec![],
448 Type::fun(
449 step_l.clone(),
450 Type::fun(b.clone(), Type::fun(fa, b.clone())),
451 ),
452 ),
453 );
454 };
455
456 add_for(list_of(a.clone()));
457 add_for(array_of(a.clone()));
458 add_for(option_of(a.clone()));
459 }
460
461 {
463 let a_tv = ts.supply.fresh(Some(sym("a")));
464 let b_tv = ts.supply.fresh(Some(sym("b")));
465 let a = Type::var(a_tv.clone());
466 let b = Type::var(b_tv.clone());
467 let pred = Type::fun(a.clone(), bool_ty.clone());
468 let mapper = Type::fun(a.clone(), option_of(b.clone()));
469 let mut add_for = |fa: Type, fb: Type| {
470 ts.add_overload(
471 "prim_filter",
472 Scheme::new(
473 vec![a_tv.clone()],
474 vec![],
475 Type::fun(pred.clone(), Type::fun(fa.clone(), fa.clone())),
476 ),
477 );
478 ts.add_overload(
479 "prim_filter_map",
480 Scheme::new(
481 vec![a_tv.clone(), b_tv.clone()],
482 vec![],
483 Type::fun(mapper.clone(), Type::fun(fa, fb)),
484 ),
485 );
486 };
487
488 add_for(list_of(a.clone()), list_of(b.clone()));
489 add_for(array_of(a.clone()), array_of(b.clone()));
490 add_for(option_of(a.clone()), option_of(b.clone()));
491 }
492
493 {
495 let a_tv = ts.supply.fresh(Some(sym("a")));
497 let b_tv = ts.supply.fresh(Some(sym("b")));
498 let a = Type::var(a_tv.clone());
499 let b = Type::var(b_tv.clone());
500 let mut add_for = |fa: Type, fb: Type| {
501 ts.add_overload(
502 "prim_flat_map",
503 Scheme::new(
504 vec![a_tv.clone(), b_tv.clone()],
505 vec![],
506 Type::fun(Type::fun(a.clone(), fb.clone()), Type::fun(fa, fb)),
507 ),
508 );
509 };
510
511 add_for(list_of(a.clone()), list_of(b.clone()));
512 add_for(array_of(a.clone()), array_of(b.clone()));
513 add_for(option_of(a.clone()), option_of(b.clone()));
514
515 let e_tv = ts.supply.fresh(Some(sym("e")));
517 let e = Type::var(e_tv.clone());
518 let ra = result_of(a.clone(), e.clone());
519 let rb = result_of(b.clone(), e.clone());
520 ts.add_overload(
521 "prim_flat_map",
522 Scheme::new(
523 vec![a_tv, b_tv, e_tv],
524 vec![],
525 Type::fun(Type::fun(a.clone(), rb.clone()), Type::fun(ra, rb)),
526 ),
527 );
528 }
529
530 {
532 let a_tv = ts.supply.fresh(Some(sym("a")));
533 let a = Type::var(a_tv.clone());
534 let mut add_for = |fa: Type| {
535 let fa2 = fa.clone();
536 ts.add_overload(
537 "prim_or_else",
538 Scheme::new(
539 vec![a_tv.clone()],
540 vec![],
541 Type::fun(Type::fun(fa.clone(), fa.clone()), Type::fun(fa2, fa)),
542 ),
543 );
544 };
545
546 add_for(list_of(a.clone()));
547 add_for(array_of(a.clone()));
548 add_for(option_of(a.clone()));
549
550 let e_tv = ts.supply.fresh(Some(sym("e")));
551 let e = Type::var(e_tv.clone());
552 let ra = result_of(a.clone(), e);
553 ts.add_overload(
554 "prim_or_else",
555 Scheme::new(
556 vec![a_tv, e_tv],
557 vec![],
558 Type::fun(Type::fun(ra.clone(), ra.clone()), Type::fun(ra.clone(), ra)),
559 ),
560 );
561 }
562
563 {
565 let a_tv = ts.supply.fresh(Some(sym("a")));
566 let a = Type::var(a_tv.clone());
567 let mut add_for = |fa: Type| {
568 let scheme = Scheme::new(
569 vec![a_tv.clone()],
570 vec![],
571 Type::fun(i32_ty.clone(), Type::fun(fa.clone(), fa)),
572 );
573 ts.add_overload("prim_take", scheme.clone());
574 ts.add_overload("prim_skip", scheme);
575 };
576 add_for(list_of(a.clone()));
577 add_for(array_of(a.clone()));
578 }
579
580 {
582 let a_tv = ts.supply.fresh(Some(sym("a")));
583 let b_tv = ts.supply.fresh(Some(sym("b")));
584 let a = Type::var(a_tv.clone());
585 let b = Type::var(b_tv.clone());
586 let pair = Type::tuple(vec![a.clone(), b.clone()]);
587 let mut add_for = |fa: Type, fb: Type, fp: Type| {
588 ts.add_overload(
589 "prim_zip",
590 Scheme::new(
591 vec![a_tv.clone(), b_tv.clone()],
592 vec![],
593 Type::fun(fa.clone(), Type::fun(fb.clone(), fp.clone())),
594 ),
595 );
596 ts.add_overload(
597 "prim_unzip",
598 Scheme::new(
599 vec![a_tv.clone(), b_tv.clone()],
600 vec![],
601 Type::fun(fp, Type::tuple(vec![fa, fb])),
602 ),
603 );
604 };
605
606 add_for(
607 list_of(a.clone()),
608 list_of(b.clone()),
609 list_of(pair.clone()),
610 );
611 add_for(array_of(a.clone()), array_of(b.clone()), array_of(pair));
612 }
613
614 {
616 let a_tv = ts.supply.fresh(Some(sym("a")));
617 let a = Type::var(a_tv.clone());
618 let idx = i32_ty.clone();
619 ts.add_overload(
620 "prim_get",
621 Scheme::new(
622 vec![a_tv.clone()],
623 vec![],
624 Type::fun(idx.clone(), Type::fun(list_of(a.clone()), a.clone())),
625 ),
626 );
627 ts.add_overload(
628 "prim_get",
629 Scheme::new(
630 vec![a_tv.clone()],
631 vec![],
632 Type::fun(idx.clone(), Type::fun(array_of(a.clone()), a.clone())),
633 ),
634 );
635 for size in 2..=32 {
636 ts.add_overload(
637 "prim_get",
638 Scheme::new(
639 vec![a_tv.clone()],
640 vec![],
641 Type::fun(
642 idx.clone(),
643 Type::fun(Type::tuple(vec![a.clone(); size]), a.clone()),
644 ),
645 ),
646 );
647 }
648 }
649
650 {
652 let a_tv = ts.supply.fresh(Some(sym("a")));
653 let a = Type::var(a_tv.clone());
654 let list_a = list_of(a.clone());
655 let array_a = array_of(a.clone());
656 ts.add_value(
657 "prim_array_from_list",
658 Scheme::new(
659 vec![a_tv.clone()],
660 vec![],
661 Type::fun(list_a.clone(), array_a.clone()),
662 ),
663 );
664 ts.add_value(
665 "prim_list_from_array",
666 Scheme::new(
667 vec![a_tv.clone()],
668 vec![],
669 Type::fun(array_a.clone(), list_a.clone()),
670 ),
671 );
672 ts.add_value(
673 "to_array",
674 Scheme::new(
675 vec![a_tv.clone()],
676 vec![],
677 Type::fun(list_a.clone(), array_a.clone()),
678 ),
679 );
680 ts.add_value(
681 "to_list",
682 Scheme::new(vec![a_tv], vec![], Type::fun(array_a, list_a)),
683 );
684 }
685
686 {
688 let a_tv = ts.supply.fresh(Some(sym("a")));
689 let b_tv = ts.supply.fresh(Some(sym("b")));
690 let a = Type::var(a_tv.clone());
691 let b = Type::var(b_tv.clone());
692 let dict_a = Type::app(Type::builtin(BuiltinTypeId::Dict), a.clone());
693 let dict_b = Type::app(Type::builtin(BuiltinTypeId::Dict), b.clone());
694 ts.add_value(
695 "prim_dict_map",
696 Scheme::new(
697 vec![a_tv, b_tv],
698 vec![],
699 Type::fun(Type::fun(a, b), Type::fun(dict_a, dict_b)),
700 ),
701 );
702 }
703
704 {
706 let a_tv = ts.supply.fresh(Some(sym("a")));
707 let b_tv = ts.supply.fresh(Some(sym("b")));
708 let e_tv = ts.supply.fresh(Some(sym("e")));
709 let a = Type::var(a_tv.clone());
710 let b = Type::var(b_tv.clone());
711 let e = Type::var(e_tv.clone());
712 let dict_a = Type::app(Type::builtin(BuiltinTypeId::Dict), a.clone());
713 let dict_b = Type::app(Type::builtin(BuiltinTypeId::Dict), b.clone());
714 let result_eb = result_of(b.clone(), e.clone());
715 let result_edictb = result_of(dict_b, e);
716 ts.add_value(
717 "prim_dict_traverse_result",
718 Scheme::new(
719 vec![a_tv, b_tv, e_tv],
720 vec![],
721 Type::fun(Type::fun(a, result_eb), Type::fun(dict_a, result_edictb)),
722 ),
723 );
724 }
725
726 for src in [
731 BuiltinTypeId::U8,
732 BuiltinTypeId::U16,
733 BuiltinTypeId::U32,
734 BuiltinTypeId::U64,
735 BuiltinTypeId::I8,
736 BuiltinTypeId::I16,
737 BuiltinTypeId::I32,
738 BuiltinTypeId::I64,
739 BuiltinTypeId::F32,
740 BuiltinTypeId::F64,
741 ] {
742 let t = Type::builtin(src);
743 ts.add_overload(
744 "prim_to_f64",
745 Scheme::new(
746 vec![],
747 vec![],
748 Type::fun(t, Type::builtin(BuiltinTypeId::F64)),
749 ),
750 );
751 }
752
753 for (name, dst) in [
754 ("prim_f64_to_u8", BuiltinTypeId::U8),
755 ("prim_f64_to_u16", BuiltinTypeId::U16),
756 ("prim_f64_to_u32", BuiltinTypeId::U32),
757 ("prim_f64_to_u64", BuiltinTypeId::U64),
758 ("prim_f64_to_i8", BuiltinTypeId::I8),
759 ("prim_f64_to_i16", BuiltinTypeId::I16),
760 ("prim_f64_to_i32", BuiltinTypeId::I32),
761 ("prim_f64_to_i64", BuiltinTypeId::I64),
762 ("prim_f64_to_f32", BuiltinTypeId::F32),
763 ] {
764 let dst_ty = Type::builtin(dst);
765 ts.add_value(
766 name,
767 Scheme::new(
768 vec![],
769 vec![],
770 Type::fun(Type::builtin(BuiltinTypeId::F64), option_of(dst_ty)),
771 ),
772 );
773 }
774
775 ts.add_value(
776 "prim_parse_uuid",
777 Scheme::new(
778 vec![],
779 vec![],
780 Type::fun(
781 Type::builtin(BuiltinTypeId::String),
782 option_of(Type::builtin(BuiltinTypeId::Uuid)),
783 ),
784 ),
785 );
786 ts.add_value(
787 "prim_parse_datetime",
788 Scheme::new(
789 vec![],
790 vec![],
791 Type::fun(
792 Type::builtin(BuiltinTypeId::String),
793 option_of(Type::builtin(BuiltinTypeId::DateTime)),
794 ),
795 ),
796 );
797 }
798}
799
800pub(crate) fn build_prelude(ts: &mut TypeSystem) -> Result<(), TypeError> {
801 let prims = [
803 BuiltinTypeId::U8,
804 BuiltinTypeId::U16,
805 BuiltinTypeId::U32,
806 BuiltinTypeId::U64,
807 BuiltinTypeId::I8,
808 BuiltinTypeId::I16,
809 BuiltinTypeId::I32,
810 BuiltinTypeId::I64,
811 BuiltinTypeId::F32,
812 BuiltinTypeId::F64,
813 BuiltinTypeId::Bool,
814 BuiltinTypeId::String,
815 BuiltinTypeId::Uuid,
816 BuiltinTypeId::DateTime,
817 ];
818 for prim in prims {
819 ts.env.extend(
820 prim.as_symbol(),
821 Scheme::new(vec![], vec![], Type::builtin(prim)),
822 );
823 }
824
825 let result_con = Type::builtin(BuiltinTypeId::Result);
827 let option_con = Type::builtin(BuiltinTypeId::Option);
828
829 {
831 let list_name = sym("List");
832 let a_name = sym("a");
833 let list_params = vec![a_name.clone()];
834 let mut list_adt = AdtDecl::new(&list_name, &list_params, &mut ts.supply);
835 let a = list_adt.param_type(&a_name).ok_or_else(|| {
836 TypeError::Internal("prelude: List is missing type parameter `a`".into())
837 })?;
838 let list_a = list_adt.result_type();
839 list_adt.add_variant(sym("Empty"), vec![]);
840 list_adt.add_variant(sym("Cons"), vec![a.clone(), list_a.clone()]);
841 ts.inject_adt(&list_adt);
842 }
843 {
844 let option_name = sym("Option");
845 let t_name = sym("t");
846 let option_params = vec![t_name.clone()];
847 let mut option_adt = AdtDecl::new(&option_name, &option_params, &mut ts.supply);
848 let t = option_adt.param_type(&t_name).ok_or_else(|| {
849 TypeError::Internal("prelude: Option is missing type parameter `t`".into())
850 })?;
851 option_adt.add_variant(sym("Some"), vec![t]);
852 option_adt.add_variant(sym("None"), vec![]);
853 ts.inject_adt(&option_adt);
854 }
855 {
856 let result_name = sym("Result");
857 let e_name = sym("e");
858 let t_name = sym("t");
859 let result_params = vec![e_name.clone(), t_name.clone()];
860 let mut result_adt = AdtDecl::new(&result_name, &result_params, &mut ts.supply);
861 let e = result_adt.param_type(&e_name).ok_or_else(|| {
862 TypeError::Internal("prelude: Result is missing type parameter `e`".into())
863 })?;
864 let t = result_adt.param_type(&t_name).ok_or_else(|| {
865 TypeError::Internal("prelude: Result is missing type parameter `t`".into())
866 })?;
867 result_adt.add_variant(sym("Err"), vec![e]);
868 result_adt.add_variant(sym("Ok"), vec![t]);
869 ts.inject_adt(&result_adt);
870 }
871
872 inject_prelude_primops(ts);
873 inject_prelude_classes_and_instances(ts)?;
874
875 let fresh_tv = |ts: &mut TypeSystem, name: &str| ts.supply.fresh(Some(sym(name)));
877 let option_of = |t: Type| Type::app(option_con.clone(), t);
878 let result_of = |t: Type, e: Type| Type::app(Type::app(result_con.clone(), e), t);
879
880 let bool_ty = Type::builtin(BuiltinTypeId::Bool);
884 ts.add_value(
885 "&&",
886 Scheme::new(
887 vec![],
888 vec![],
889 Type::fun(bool_ty.clone(), Type::fun(bool_ty.clone(), bool_ty.clone())),
890 ),
891 );
892 ts.add_value(
893 "||",
894 Scheme::new(
895 vec![],
896 vec![],
897 Type::fun(bool_ty.clone(), Type::fun(bool_ty.clone(), bool_ty.clone())),
898 ),
899 );
900
901 {
903 let f_tv = fresh_tv(ts, "f");
904 let a_tv = fresh_tv(ts, "a");
905 let f = Type::var(f_tv.clone());
906 let a = Type::var(a_tv.clone());
907 let fa = Type::app(f.clone(), a.clone());
908
909 ts.add_value(
910 "sum",
911 Scheme::new(
912 vec![f_tv.clone(), a_tv.clone()],
913 vec![
914 Predicate::new("Foldable", f.clone()),
915 Predicate::new("AdditiveMonoid", a.clone()),
916 ],
917 Type::fun(fa.clone(), a.clone()),
918 ),
919 );
920 ts.add_value(
921 "mean",
922 Scheme::new(
923 vec![f_tv.clone(), a_tv.clone()],
924 vec![
925 Predicate::new("Foldable", f.clone()),
926 Predicate::new("Field", a.clone()),
927 ],
928 Type::fun(fa.clone(), a.clone()),
929 ),
930 );
931 ts.add_value(
932 "count",
933 Scheme::new(
934 vec![f_tv.clone(), a_tv.clone()],
935 vec![Predicate::new("Foldable", f.clone())],
936 Type::fun(fa.clone(), Type::builtin(BuiltinTypeId::I32)),
937 ),
938 );
939 ts.add_value(
940 "min",
941 Scheme::new(
942 vec![f_tv.clone(), a_tv.clone()],
943 vec![
944 Predicate::new("Foldable", f.clone()),
945 Predicate::new("Ord", a.clone()),
946 ],
947 Type::fun(fa.clone(), a.clone()),
948 ),
949 );
950 ts.add_value(
951 "max",
952 Scheme::new(
953 vec![f_tv, a_tv],
954 vec![
955 Predicate::new("Foldable", f.clone()),
956 Predicate::new("Ord", a.clone()),
957 ],
958 Type::fun(fa.clone(), a.clone()),
959 ),
960 );
961 }
962
963 {
965 let a_tv = fresh_tv(ts, "a");
966 let a = Type::var(a_tv.clone());
967 let opt_a = option_of(a.clone());
968 ts.add_value(
969 "is_some",
970 Scheme::new(
971 vec![a_tv.clone()],
972 vec![],
973 Type::fun(opt_a.clone(), bool_ty.clone()),
974 ),
975 );
976 ts.add_value(
977 "is_none",
978 Scheme::new(
979 vec![a_tv.clone()],
980 vec![],
981 Type::fun(opt_a.clone(), bool_ty.clone()),
982 ),
983 );
984 }
985
986 {
988 let t_tv = fresh_tv(ts, "t");
989 let e_tv = fresh_tv(ts, "e");
990 let t = Type::var(t_tv.clone());
991 let e = Type::var(e_tv.clone());
992 let res_te = result_of(t.clone(), e.clone());
993 ts.add_value(
994 "is_ok",
995 Scheme::new(
996 vec![t_tv.clone(), e_tv.clone()],
997 vec![],
998 Type::fun(res_te.clone(), bool_ty.clone()),
999 ),
1000 );
1001 ts.add_value(
1002 "is_err",
1003 Scheme::new(
1004 vec![t_tv.clone(), e_tv.clone()],
1005 vec![],
1006 Type::fun(res_te.clone(), bool_ty.clone()),
1007 ),
1008 );
1009 }
1010
1011 Ok(())
1012}