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