1use crate::context::Context;
11use crate::term::{Literal, Term, Universe};
12
13pub struct StandardLibrary;
15
16impl StandardLibrary {
17 pub fn register(ctx: &mut Context) {
19 Self::register_entity(ctx);
20 Self::register_nat(ctx);
21 Self::register_monolist(ctx);
22 Self::register_bool(ctx);
23 Self::register_tlist(ctx);
24 Self::register_true(ctx);
25 Self::register_false(ctx);
26 Self::register_not(ctx);
27 Self::register_classical(ctx);
28 Self::register_eq(ctx);
29 Self::register_and(ctx);
30 Self::register_or(ctx);
31 Self::register_ex(ctx);
32 Self::register_decidable(ctx);
33 Self::register_of_decide(ctx);
34 Self::register_dec_eq_bool(ctx);
35 Self::register_dec_eq_nat(ctx);
36 Self::register_native_decide(ctx);
37 Self::register_quot(ctx);
38 Self::register_acc(ctx);
39 Self::register_primitives(ctx);
40 Self::register_int_ring_axioms(ctx);
41 Self::register_int_order_axioms(ctx);
42 Self::register_reflection(ctx);
43 Self::register_hardware(ctx);
44 }
45
46 fn register_classical(ctx: &mut Context) {
54 let false_t = || Term::Global("False".to_string());
55 let p = || Term::Var("P".to_string());
56 let not_p = Term::Pi {
58 param: "_".to_string(),
59 param_type: Box::new(p()),
60 body_type: Box::new(false_t()),
61 };
62 let not_not_p = Term::Pi {
64 param: "_".to_string(),
65 param_type: Box::new(not_p),
66 body_type: Box::new(false_t()),
67 };
68 let dne_type = Term::Pi {
70 param: "P".to_string(),
71 param_type: Box::new(Term::Sort(Universe::Prop)),
72 body_type: Box::new(Term::Pi {
73 param: "_".to_string(),
74 param_type: Box::new(not_not_p),
75 body_type: Box::new(p()),
76 }),
77 };
78 ctx.add_declaration("dne", dne_type);
79 }
80
81 fn register_int_ring_axioms(ctx: &mut Context) {
93 let int = || Term::Global("Int".to_string());
94 let lit = |n: i64| Term::Lit(Literal::Int(n));
95 let bin = |op: &str, a: Term, b: Term| {
97 Term::App(
98 Box::new(Term::App(Box::new(Term::Global(op.to_string())), Box::new(a))),
99 Box::new(b),
100 )
101 };
102 let eq_int = |l: Term, r: Term| {
104 Term::App(
105 Box::new(Term::App(
106 Box::new(Term::App(
107 Box::new(Term::Global("Eq".to_string())),
108 Box::new(Term::Global("Int".to_string())),
109 )),
110 Box::new(l),
111 )),
112 Box::new(r),
113 )
114 };
115 let forall_ints = |names: &[&str], body: Term| {
117 names.iter().rev().fold(body, |acc, name| Term::Pi {
118 param: name.to_string(),
119 param_type: Box::new(int()),
120 body_type: Box::new(acc),
121 })
122 };
123 let v = |s: &str| Term::Var(s.to_string());
124
125 ctx.add_declaration(
127 "add_comm",
128 forall_ints(
129 &["a", "b"],
130 eq_int(bin("add", v("a"), v("b")), bin("add", v("b"), v("a"))),
131 ),
132 );
133 ctx.add_declaration(
135 "add_assoc",
136 forall_ints(
137 &["a", "b", "c"],
138 eq_int(
139 bin("add", bin("add", v("a"), v("b")), v("c")),
140 bin("add", v("a"), bin("add", v("b"), v("c"))),
141 ),
142 ),
143 );
144 ctx.add_declaration(
146 "add_zero",
147 forall_ints(&["a"], eq_int(bin("add", v("a"), lit(0)), v("a"))),
148 );
149 ctx.add_declaration(
151 "mul_comm",
152 forall_ints(
153 &["a", "b"],
154 eq_int(bin("mul", v("a"), v("b")), bin("mul", v("b"), v("a"))),
155 ),
156 );
157 ctx.add_declaration(
159 "mul_assoc",
160 forall_ints(
161 &["a", "b", "c"],
162 eq_int(
163 bin("mul", bin("mul", v("a"), v("b")), v("c")),
164 bin("mul", v("a"), bin("mul", v("b"), v("c"))),
165 ),
166 ),
167 );
168 ctx.add_declaration(
170 "mul_one",
171 forall_ints(&["a"], eq_int(bin("mul", v("a"), lit(1)), v("a"))),
172 );
173 ctx.add_declaration(
177 "mul_zero",
178 forall_ints(&["a"], eq_int(bin("mul", v("a"), lit(0)), lit(0))),
179 );
180 ctx.add_declaration(
182 "mul_distrib_add",
183 forall_ints(
184 &["a", "b", "c"],
185 eq_int(
186 bin("mul", v("a"), bin("add", v("b"), v("c"))),
187 bin("add", bin("mul", v("a"), v("b")), bin("mul", v("a"), v("c"))),
188 ),
189 ),
190 );
191 }
192
193 fn register_int_order_axioms(ctx: &mut Context) {
203 let int = || Term::Global("Int".to_string());
204 let v = |s: &str| Term::Var(s.to_string());
205 let g = |s: &str| Term::Global(s.to_string());
206 let lit = |n: i64| Term::Lit(Literal::Int(n));
207 let bin = |op: &str, a: Term, b: Term| {
208 Term::App(
209 Box::new(Term::App(Box::new(Term::Global(op.to_string())), Box::new(a))),
210 Box::new(b),
211 )
212 };
213 let le_prop = |a: Term, b: Term| {
215 Term::App(
216 Box::new(Term::App(
217 Box::new(Term::App(Box::new(g("Eq")), Box::new(g("Bool")))),
218 Box::new(bin("le", a, b)),
219 )),
220 Box::new(g("true")),
221 )
222 };
223 let arrow = |dom: Term, cod: Term| Term::Pi {
224 param: "_".to_string(),
225 param_type: Box::new(dom),
226 body_type: Box::new(cod),
227 };
228 let forall_ints = |names: &[&str], body: Term| {
229 names.iter().rev().fold(body, |acc, name| Term::Pi {
230 param: name.to_string(),
231 param_type: Box::new(int()),
232 body_type: Box::new(acc),
233 })
234 };
235
236 ctx.add_declaration("le_refl", forall_ints(&["a"], le_prop(v("a"), v("a"))));
238 ctx.add_declaration(
240 "le_trans",
241 forall_ints(
242 &["a", "b", "c"],
243 arrow(
244 le_prop(v("a"), v("b")),
245 arrow(le_prop(v("b"), v("c")), le_prop(v("a"), v("c"))),
246 ),
247 ),
248 );
249 ctx.add_declaration(
251 "le_add_mono",
252 forall_ints(
253 &["a", "b", "c", "d"],
254 arrow(
255 le_prop(v("a"), v("b")),
256 arrow(
257 le_prop(v("c"), v("d")),
258 le_prop(bin("add", v("a"), v("c")), bin("add", v("b"), v("d"))),
259 ),
260 ),
261 ),
262 );
263 ctx.add_declaration(
265 "le_mul_nonneg",
266 forall_ints(
267 &["k", "a", "b"],
268 arrow(
269 le_prop(lit(0), v("k")),
270 arrow(
271 le_prop(v("a"), v("b")),
272 le_prop(bin("mul", v("k"), v("a")), bin("mul", v("k"), v("b"))),
273 ),
274 ),
275 ),
276 );
277 ctx.add_declaration(
281 "le_sub",
282 forall_ints(
283 &["a", "b"],
284 arrow(
285 le_prop(v("a"), v("b")),
286 le_prop(lit(0), bin("add", v("b"), bin("mul", lit(-1), v("a")))),
287 ),
288 ),
289 );
290
291 let lt_prop = |a: Term, b: Term| {
293 Term::App(
294 Box::new(Term::App(
295 Box::new(Term::App(Box::new(g("Eq")), Box::new(g("Bool")))),
296 Box::new(bin("lt", a, b)),
297 )),
298 Box::new(g("true")),
299 )
300 };
301 ctx.add_declaration(
307 "lt_succ_le",
308 forall_ints(
309 &["a", "b"],
310 arrow(lt_prop(v("a"), v("b")), le_prop(bin("add", v("a"), lit(1)), v("b"))),
311 ),
312 );
313 ctx.add_declaration(
318 "lt_add1_le",
319 forall_ints(
320 &["a", "b"],
321 arrow(lt_prop(v("a"), bin("add", v("b"), lit(1))), le_prop(v("a"), v("b"))),
322 ),
323 );
324 let or = |p: Term, q: Term| {
328 Term::App(
329 Box::new(Term::App(Box::new(g("Or")), Box::new(p))),
330 Box::new(q),
331 )
332 };
333 ctx.add_declaration(
334 "le_total",
335 forall_ints(
336 &["a", "b"],
337 or(le_prop(v("a"), v("b")), le_prop(v("b"), v("a"))),
338 ),
339 );
340 }
341
342 fn register_primitives(ctx: &mut Context) {
353 ctx.add_inductive("Int", Term::Sort(Universe::Type(0)));
355 ctx.add_inductive("Float", Term::Sort(Universe::Type(0)));
356 ctx.add_inductive("Text", Term::Sort(Universe::Type(0)));
357
358 ctx.add_inductive("Duration", Term::Sort(Universe::Type(0)));
360 ctx.add_inductive("Date", Term::Sort(Universe::Type(0)));
361 ctx.add_inductive("Moment", Term::Sort(Universe::Type(0)));
362
363 let int = Term::Global("Int".to_string());
364
365 let bin_int_type = Term::Pi {
367 param: "_".to_string(),
368 param_type: Box::new(int.clone()),
369 body_type: Box::new(Term::Pi {
370 param: "_".to_string(),
371 param_type: Box::new(int.clone()),
372 body_type: Box::new(int.clone()),
373 }),
374 };
375
376 ctx.add_declaration("add", bin_int_type.clone());
378 ctx.add_declaration("sub", bin_int_type.clone());
379 ctx.add_declaration("mul", bin_int_type.clone());
380 ctx.add_declaration("div", bin_int_type.clone());
381 ctx.add_declaration("mod", bin_int_type);
382
383 let bin_int_bool_type = Term::Pi {
387 param: "_".to_string(),
388 param_type: Box::new(int.clone()),
389 body_type: Box::new(Term::Pi {
390 param: "_".to_string(),
391 param_type: Box::new(int.clone()),
392 body_type: Box::new(Term::Global("Bool".to_string())),
393 }),
394 };
395 ctx.add_declaration("le", bin_int_bool_type.clone());
396 ctx.add_declaration("lt", bin_int_bool_type.clone());
397 ctx.add_declaration("ge", bin_int_bool_type.clone());
398 ctx.add_declaration("gt", bin_int_bool_type);
399
400 let duration = Term::Global("Duration".to_string());
402 let date = Term::Global("Date".to_string());
403 let moment = Term::Global("Moment".to_string());
404 let bool_type = Term::Global("Bool".to_string());
405
406 let bin_duration_type = Term::Pi {
408 param: "_".to_string(),
409 param_type: Box::new(duration.clone()),
410 body_type: Box::new(Term::Pi {
411 param: "_".to_string(),
412 param_type: Box::new(duration.clone()),
413 body_type: Box::new(duration.clone()),
414 }),
415 };
416
417 let duration_int_duration_type = Term::Pi {
419 param: "_".to_string(),
420 param_type: Box::new(duration.clone()),
421 body_type: Box::new(Term::Pi {
422 param: "_".to_string(),
423 param_type: Box::new(int.clone()),
424 body_type: Box::new(duration.clone()),
425 }),
426 };
427
428 ctx.add_declaration("add_duration", bin_duration_type.clone());
430 ctx.add_declaration("sub_duration", bin_duration_type.clone());
431 ctx.add_declaration("mul_duration", duration_int_duration_type.clone());
432 ctx.add_declaration("div_duration", duration_int_duration_type);
433
434 let date_int_date_type = Term::Pi {
436 param: "_".to_string(),
437 param_type: Box::new(date.clone()),
438 body_type: Box::new(Term::Pi {
439 param: "_".to_string(),
440 param_type: Box::new(int.clone()),
441 body_type: Box::new(date.clone()),
442 }),
443 };
444 ctx.add_declaration("date_add_days", date_int_date_type);
445
446 let date_date_int_type = Term::Pi {
448 param: "_".to_string(),
449 param_type: Box::new(date.clone()),
450 body_type: Box::new(Term::Pi {
451 param: "_".to_string(),
452 param_type: Box::new(date.clone()),
453 body_type: Box::new(int.clone()),
454 }),
455 };
456 ctx.add_declaration("date_sub_date", date_date_int_type);
457
458 let moment_duration_moment_type = Term::Pi {
460 param: "_".to_string(),
461 param_type: Box::new(moment.clone()),
462 body_type: Box::new(Term::Pi {
463 param: "_".to_string(),
464 param_type: Box::new(duration.clone()),
465 body_type: Box::new(moment.clone()),
466 }),
467 };
468 ctx.add_declaration("moment_add_duration", moment_duration_moment_type);
469
470 let moment_moment_duration_type = Term::Pi {
472 param: "_".to_string(),
473 param_type: Box::new(moment.clone()),
474 body_type: Box::new(Term::Pi {
475 param: "_".to_string(),
476 param_type: Box::new(moment.clone()),
477 body_type: Box::new(duration.clone()),
478 }),
479 };
480 ctx.add_declaration("moment_sub_moment", moment_moment_duration_type);
481
482 let date_date_bool_type = Term::Pi {
484 param: "_".to_string(),
485 param_type: Box::new(date.clone()),
486 body_type: Box::new(Term::Pi {
487 param: "_".to_string(),
488 param_type: Box::new(date),
489 body_type: Box::new(bool_type.clone()),
490 }),
491 };
492 ctx.add_declaration("date_lt", date_date_bool_type);
493
494 let moment_moment_bool_type = Term::Pi {
495 param: "_".to_string(),
496 param_type: Box::new(moment.clone()),
497 body_type: Box::new(Term::Pi {
498 param: "_".to_string(),
499 param_type: Box::new(moment),
500 body_type: Box::new(bool_type.clone()),
501 }),
502 };
503 ctx.add_declaration("moment_lt", moment_moment_bool_type);
504
505 let duration_duration_bool_type = Term::Pi {
506 param: "_".to_string(),
507 param_type: Box::new(duration.clone()),
508 body_type: Box::new(Term::Pi {
509 param: "_".to_string(),
510 param_type: Box::new(duration),
511 body_type: Box::new(bool_type),
512 }),
513 };
514 ctx.add_declaration("duration_lt", duration_duration_bool_type);
515 }
516
517 fn register_entity(ctx: &mut Context) {
523 ctx.add_inductive("Entity", Term::Sort(Universe::Type(0)));
524 }
525
526 fn register_nat(ctx: &mut Context) {
530 let nat = Term::Global("Nat".to_string());
531
532 ctx.add_inductive("Nat", Term::Sort(Universe::Type(0)));
534
535 ctx.add_constructor("Zero", "Nat", nat.clone());
537
538 ctx.add_constructor(
540 "Succ",
541 "Nat",
542 Term::Pi {
543 param: "_".to_string(),
544 param_type: Box::new(nat.clone()),
545 body_type: Box::new(nat),
546 },
547 );
548 }
549
550 fn register_monolist(ctx: &mut Context) {
565 let list = Term::Global("EList".to_string());
566 let entity = Term::Global("Entity".to_string());
567
568 ctx.add_inductive("EList", Term::Sort(Universe::Type(0)));
570
571 ctx.add_constructor("ENil", "EList", list.clone());
573
574 ctx.add_constructor(
576 "ECons",
577 "EList",
578 Term::Pi {
579 param: "_".to_string(),
580 param_type: Box::new(entity),
581 body_type: Box::new(Term::Pi {
582 param: "_".to_string(),
583 param_type: Box::new(list.clone()),
584 body_type: Box::new(list),
585 }),
586 },
587 );
588 }
589
590 fn register_bool(ctx: &mut Context) {
594 let bool_type = Term::Global("Bool".to_string());
595
596 ctx.add_inductive("Bool", Term::Sort(Universe::Type(0)));
598
599 ctx.add_constructor("true", "Bool", bool_type.clone());
601
602 ctx.add_constructor("false", "Bool", bool_type);
604 }
605
606 fn register_tlist(ctx: &mut Context) {
610 let type0 = Term::Sort(Universe::Type(0));
611 let a = Term::Var("A".to_string());
612
613 let tlist_type = Term::Pi {
615 param: "A".to_string(),
616 param_type: Box::new(type0.clone()),
617 body_type: Box::new(type0.clone()),
618 };
619 ctx.add_inductive("TList", tlist_type);
620
621 let tlist_a = Term::App(
623 Box::new(Term::Global("TList".to_string())),
624 Box::new(a.clone()),
625 );
626
627 let tnil_type = Term::Pi {
629 param: "A".to_string(),
630 param_type: Box::new(type0.clone()),
631 body_type: Box::new(tlist_a.clone()),
632 };
633 ctx.add_constructor("TNil", "TList", tnil_type);
634
635 let tcons_type = Term::Pi {
637 param: "A".to_string(),
638 param_type: Box::new(type0),
639 body_type: Box::new(Term::Pi {
640 param: "_".to_string(),
641 param_type: Box::new(a.clone()),
642 body_type: Box::new(Term::Pi {
643 param: "_".to_string(),
644 param_type: Box::new(tlist_a.clone()),
645 body_type: Box::new(tlist_a),
646 }),
647 }),
648 };
649 ctx.add_constructor("TCons", "TList", tcons_type);
650
651 Self::register_tactic_list_helpers(ctx);
653 }
654
655 fn register_tactic_list_helpers(ctx: &mut Context) {
661 let syntax = Term::Global("Syntax".to_string());
662 let derivation = Term::Global("Derivation".to_string());
663
664 let tactic_type = Term::Pi {
666 param: "_".to_string(),
667 param_type: Box::new(syntax.clone()),
668 body_type: Box::new(derivation.clone()),
669 };
670
671 let ttactics = Term::App(
673 Box::new(Term::Global("TList".to_string())),
674 Box::new(tactic_type.clone()),
675 );
676
677 ctx.add_definition("TTactics".to_string(), Term::Sort(Universe::Type(0)), ttactics.clone());
679
680 let tac_nil_body = Term::App(
682 Box::new(Term::Global("TNil".to_string())),
683 Box::new(tactic_type.clone()),
684 );
685 ctx.add_definition("TacNil".to_string(), ttactics.clone(), tac_nil_body);
686
687 let tac_cons_type = Term::Pi {
689 param: "t".to_string(),
690 param_type: Box::new(tactic_type.clone()),
691 body_type: Box::new(Term::Pi {
692 param: "ts".to_string(),
693 param_type: Box::new(ttactics.clone()),
694 body_type: Box::new(ttactics.clone()),
695 }),
696 };
697
698 let tac_cons_body = Term::Lambda {
700 param: "t".to_string(),
701 param_type: Box::new(tactic_type.clone()),
702 body: Box::new(Term::Lambda {
703 param: "ts".to_string(),
704 param_type: Box::new(ttactics.clone()),
705 body: Box::new(Term::App(
706 Box::new(Term::App(
707 Box::new(Term::App(
708 Box::new(Term::Global("TCons".to_string())),
709 Box::new(tactic_type),
710 )),
711 Box::new(Term::Var("t".to_string())),
712 )),
713 Box::new(Term::Var("ts".to_string())),
714 )),
715 }),
716 };
717 ctx.add_definition("TacCons".to_string(), tac_cons_type, tac_cons_body);
718 }
719
720 fn register_true(ctx: &mut Context) {
723 ctx.add_inductive("True", Term::Sort(Universe::Prop));
724 ctx.add_constructor("I", "True", Term::Global("True".to_string()));
725 }
726
727 fn register_false(ctx: &mut Context) {
730 ctx.add_inductive("False", Term::Sort(Universe::Prop));
731 }
732
733 fn register_not(ctx: &mut Context) {
736 let not_type = Term::Pi {
738 param: "P".to_string(),
739 param_type: Box::new(Term::Sort(Universe::Prop)),
740 body_type: Box::new(Term::Sort(Universe::Prop)),
741 };
742
743 let not_body = Term::Lambda {
745 param: "P".to_string(),
746 param_type: Box::new(Term::Sort(Universe::Prop)),
747 body: Box::new(Term::Pi {
748 param: "_".to_string(),
749 param_type: Box::new(Term::Var("P".to_string())),
750 body_type: Box::new(Term::Global("False".to_string())),
751 }),
752 };
753
754 ctx.add_definition("Not".to_string(), not_type, not_body);
755 }
756
757 fn register_decidable(ctx: &mut Context) {
762 let prop = || Term::Sort(Universe::Prop);
763 let type0 = || Term::Sort(Universe::Type(0));
764 let g = |s: &str| Term::Global(s.to_string());
765 let v = |s: &str| Term::Var(s.to_string());
766 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
767 let lm = |p: &str, t: Term, b: Term| Term::Lambda {
768 param: p.to_string(),
769 param_type: Box::new(t),
770 body: Box::new(b),
771 };
772 let pi = |p: &str, t: Term, b: Term| Term::Pi {
773 param: p.to_string(),
774 param_type: Box::new(t),
775 body_type: Box::new(b),
776 };
777 let dec = |p: Term| ap(g("Decidable"), p);
778 let not = |p: Term| ap(g("Not"), p);
779
780 ctx.add_indexed_inductive("Decidable", pi("p", prop(), type0()), 1);
782 ctx.add_constructor("isTrue", "Decidable", pi("p", prop(), pi("_", v("p"), dec(v("p")))));
784 ctx.add_constructor(
786 "isFalse",
787 "Decidable",
788 pi("p", prop(), pi("_", not(v("p")), dec(v("p")))),
789 );
790
791 let (rec_ty, rec_body) = crate::recursor::derive_recursor(ctx, "Decidable")
793 .expect("Decidable's eliminator must derive");
794 ctx.add_definition("Decidable_rec".to_string(), rec_ty, rec_body);
795
796 let decide_ty = pi("p", prop(), pi("_", dec(v("p")), g("Bool")));
799 let decide_body = lm(
800 "p",
801 prop(),
802 lm(
803 "inst",
804 dec(v("p")),
805 ap(
806 ap(
807 ap(
808 ap(ap(g("Decidable_rec"), v("p")), lm("_", dec(v("p")), g("Bool"))),
809 lm("_", v("p"), g("true")),
810 ),
811 lm("_", not(v("p")), g("false")),
812 ),
813 v("inst"),
814 ),
815 ),
816 );
817 ctx.add_definition("decide".to_string(), decide_ty, decide_body);
818 }
819
820 fn register_of_decide(ctx: &mut Context) {
825 let prop = || Term::Sort(Universe::Prop);
826 let g = |s: &str| Term::Global(s.to_string());
827 let v = |s: &str| Term::Var(s.to_string());
828 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
829 let lm = |p: &str, t: Term, b: Term| Term::Lambda {
830 param: p.to_string(),
831 param_type: Box::new(t),
832 body: Box::new(b),
833 };
834 let pi = |p: &str, t: Term, b: Term| Term::Pi {
835 param: p.to_string(),
836 param_type: Box::new(t),
837 body_type: Box::new(b),
838 };
839 let dec = |p: Term| ap(g("Decidable"), p);
840 let not = |p: Term| ap(g("Not"), p);
841 let eqb = |x: Term, y: Term| ap(ap(ap(g("Eq"), g("Bool")), x), y);
843 let decide = |p: Term, inst: Term| ap(ap(g("decide"), p), inst);
845 let is_true = |p: Term, h: Term| ap(ap(g("isTrue"), p), h);
846 let is_false = |p: Term, h: Term| ap(ap(g("isFalse"), p), h);
847
848 let ty = pi(
850 "p",
851 prop(),
852 pi(
853 "inst",
854 dec(v("p")),
855 pi("_", eqb(decide(v("p"), v("inst")), g("true")), v("p")),
856 ),
857 );
858
859 let motive = lm(
861 "inst",
862 dec(v("p")),
863 pi("_", eqb(decide(v("p"), v("inst")), g("true")), v("p")),
864 );
865 let f_istrue = lm(
867 "hp",
868 v("p"),
869 lm(
870 "_",
871 eqb(decide(v("p"), is_true(v("p"), v("hp"))), g("true")),
872 v("hp"),
873 ),
874 );
875 let discr = Term::Match {
880 discriminant: Box::new(v("b")),
881 motive: Box::new(lm("_", g("Bool"), prop())),
882 cases: vec![v("p"), g("True")], };
884 let bool_motive = lm("b", g("Bool"), lm("_", eqb(g("false"), v("b")), discr));
885 let noconf = ap(
887 ap(
888 ap(ap(ap(ap(g("Eq_rec_dep"), g("Bool")), g("false")), bool_motive), g("I")),
889 g("true"),
890 ),
891 v("h"),
892 );
893 let f_isfalse = lm(
894 "hnp",
895 not(v("p")),
896 lm(
897 "h",
898 eqb(decide(v("p"), is_false(v("p"), v("hnp"))), g("true")),
899 noconf,
900 ),
901 );
902
903 let rec_app = ap(
905 ap(
906 ap(ap(ap(ap(g("Decidable_rec"), v("p")), motive), f_istrue), f_isfalse),
907 v("inst"),
908 ),
909 v("h"),
910 );
911 let body = lm(
912 "p",
913 prop(),
914 lm(
915 "inst",
916 dec(v("p")),
917 lm("h", eqb(decide(v("p"), v("inst")), g("true")), rec_app),
918 ),
919 );
920 ctx.add_definition("of_decide_eq_true".to_string(), ty, body);
921 }
922
923 fn register_dec_eq_bool(ctx: &mut Context) {
927 let prop = || Term::Sort(Universe::Prop);
928 let g = |s: &str| Term::Global(s.to_string());
929 let v = |s: &str| Term::Var(s.to_string());
930 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
931 let lm = |p: &str, t: Term, b: Term| Term::Lambda {
932 param: p.to_string(),
933 param_type: Box::new(t),
934 body: Box::new(b),
935 };
936 let eqb = |x: Term, y: Term| ap(ap(ap(g("Eq"), g("Bool")), x), y);
937 let dec = |p: Term| ap(g("Decidable"), p);
938 let is_true = |p: Term, h: Term| ap(ap(g("isTrue"), p), h);
939 let is_false = |p: Term, h: Term| ap(ap(g("isFalse"), p), h);
940 let refl = |x: Term| ap(ap(g("refl"), g("Bool")), x);
941 let bool_match = |t_case: Term, f_case: Term| Term::Match {
943 discriminant: Box::new(v("b")),
944 motive: Box::new(lm("_", g("Bool"), prop())),
945 cases: vec![t_case, f_case],
946 };
947
948 let tf_discr = bool_match(g("True"), g("False"));
950 let tf_motive = lm("b", g("Bool"), lm("_", eqb(g("true"), v("b")), tf_discr));
951 let bool_tf_ne = lm(
952 "h",
953 eqb(g("true"), g("false")),
954 ap(
955 ap(ap(ap(ap(ap(g("Eq_rec_dep"), g("Bool")), g("true")), tf_motive), g("I")), g("false")),
956 v("h"),
957 ),
958 );
959 let ft_discr = bool_match(g("False"), g("True"));
961 let ft_motive = lm("b", g("Bool"), lm("_", eqb(g("false"), v("b")), ft_discr));
962 let bool_ft_ne = lm(
963 "h",
964 eqb(g("false"), g("true")),
965 ap(
966 ap(ap(ap(ap(ap(g("Eq_rec_dep"), g("Bool")), g("false")), ft_motive), g("I")), g("true")),
967 v("h"),
968 ),
969 );
970
971 let de_ty = Term::Pi {
973 param: "a".to_string(),
974 param_type: Box::new(g("Bool")),
975 body_type: Box::new(Term::Pi {
976 param: "b".to_string(),
977 param_type: Box::new(g("Bool")),
978 body_type: Box::new(dec(eqb(v("a"), v("b")))),
979 }),
980 };
981 let inner = |af: Term, both_same: Term, ne_proof: Term, same_first: bool| {
983 let motive = lm("b'", g("Bool"), dec(eqb(af.clone(), v("b'"))));
984 let (t_case, f_case) = if same_first {
986 (
988 is_true(eqb(af.clone(), g("true")), both_same),
989 is_false(eqb(af.clone(), g("false")), ne_proof),
990 )
991 } else {
992 (
994 is_false(eqb(af.clone(), g("true")), ne_proof),
995 is_true(eqb(af.clone(), g("false")), both_same),
996 )
997 };
998 Term::Match {
999 discriminant: Box::new(v("b")),
1000 motive: Box::new(motive),
1001 cases: vec![t_case, f_case],
1002 }
1003 };
1004 let a_true = inner(g("true"), refl(g("true")), bool_tf_ne, true);
1005 let a_false = inner(g("false"), refl(g("false")), bool_ft_ne, false);
1006 let outer_motive = lm("a'", g("Bool"), dec(eqb(v("a'"), v("b"))));
1007 let de_body = lm(
1008 "a",
1009 g("Bool"),
1010 lm(
1011 "b",
1012 g("Bool"),
1013 Term::Match {
1014 discriminant: Box::new(v("a")),
1015 motive: Box::new(outer_motive),
1016 cases: vec![a_true, a_false],
1017 },
1018 ),
1019 );
1020 ctx.add_definition("decEqBool".to_string(), de_ty, de_body);
1021 }
1022
1023 fn register_dec_eq_nat(ctx: &mut Context) {
1028 let prop = || Term::Sort(Universe::Prop);
1029 let nat = || Term::Global("Nat".to_string());
1030 let g = |s: &str| Term::Global(s.to_string());
1031 let v = |s: &str| Term::Var(s.to_string());
1032 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
1033 let lm = |p: &str, t: Term, b: Term| Term::Lambda {
1034 param: p.to_string(),
1035 param_type: Box::new(t),
1036 body: Box::new(b),
1037 };
1038 let pi = |p: &str, t: Term, b: Term| Term::Pi {
1039 param: p.to_string(),
1040 param_type: Box::new(t),
1041 body_type: Box::new(b),
1042 };
1043 let succ = |n: Term| ap(g("Succ"), n);
1044 let eqn = |x: Term, y: Term| ap(ap(ap(g("Eq"), nat()), x), y);
1045 let not = |p: Term| ap(g("Not"), p);
1046 let dec = |p: Term| ap(g("Decidable"), p);
1047 let is_true = |p: Term, h: Term| ap(ap(g("isTrue"), p), h);
1048 let is_false = |p: Term, h: Term| ap(ap(g("isFalse"), p), h);
1049 let refln = |x: Term| ap(ap(g("refl"), nat()), x);
1050 let nat_match = |ret: Term, zero_case: Term, succ_case: Term| Term::Match {
1052 discriminant: Box::new(v("k")),
1053 motive: Box::new(lm("_", nat(), ret)),
1054 cases: vec![zero_case, succ_case],
1055 };
1056 let transport = |x: Term, discr_motive: Term, base: Term, y: Term, h: Term| {
1058 ap(ap(ap(ap(ap(ap(g("Eq_rec_dep"), nat()), x), discr_motive), base), y), h)
1059 };
1060
1061 let d_zs = nat_match(prop(), g("True"), lm("_", nat(), g("False")));
1063 let zs_motive = lm("k", nat(), lm("_", eqn(g("Zero"), v("k")), d_zs));
1064 let nat_zs_ne = lm(
1065 "n",
1066 nat(),
1067 lm(
1068 "h",
1069 eqn(g("Zero"), succ(v("n"))),
1070 transport(g("Zero"), zs_motive, g("I"), succ(v("n")), v("h")),
1071 ),
1072 );
1073 ctx.add_definition("nat_zs_ne".to_string(), pi("n", nat(), not(eqn(g("Zero"), succ(v("n"))))), nat_zs_ne);
1074
1075 let d_sz = nat_match(prop(), g("False"), lm("_", nat(), g("True")));
1077 let sz_motive = lm("k", nat(), lm("_", eqn(succ(v("n")), v("k")), d_sz));
1078 let nat_sz_ne = lm(
1079 "n",
1080 nat(),
1081 lm(
1082 "h",
1083 eqn(succ(v("n")), g("Zero")),
1084 transport(succ(v("n")), sz_motive, g("I"), g("Zero"), v("h")),
1085 ),
1086 );
1087 ctx.add_definition("nat_sz_ne".to_string(), pi("n", nat(), not(eqn(succ(v("n")), g("Zero")))), nat_sz_ne);
1088
1089 let sc_motive = lm("b'", nat(), lm("_", eqn(v("a"), v("b'")), eqn(succ(v("a")), succ(v("b'")))));
1091 let succ_cong_body = lm(
1092 "a",
1093 nat(),
1094 lm(
1095 "b",
1096 nat(),
1097 lm(
1098 "h",
1099 eqn(v("a"), v("b")),
1100 ap(ap(ap(ap(ap(ap(g("Eq_rec_dep"), nat()), v("a")), sc_motive), refln(succ(v("a")))), v("b")), v("h")),
1101 ),
1102 ),
1103 );
1104 let succ_cong_ty = pi("a", nat(), pi("b", nat(), pi("_", eqn(v("a"), v("b")), eqn(succ(v("a")), succ(v("b"))))));
1105 ctx.add_definition("succ_cong".to_string(), succ_cong_ty, succ_cong_body);
1106
1107 let pred_y = Term::Match {
1111 discriminant: Box::new(v("y'")),
1112 motive: Box::new(lm("_", nat(), nat())),
1113 cases: vec![g("Zero"), lm("p", nat(), v("p"))],
1114 };
1115 let si_motive = lm("y'", nat(), lm("_", eqn(succ(v("a")), v("y'")), eqn(v("a"), pred_y)));
1116 let succ_inj_body = lm(
1117 "a",
1118 nat(),
1119 lm(
1120 "b",
1121 nat(),
1122 lm(
1123 "h",
1124 eqn(succ(v("a")), succ(v("b"))),
1125 ap(ap(ap(ap(ap(ap(g("Eq_rec_dep"), nat()), succ(v("a"))), si_motive), refln(v("a"))), succ(v("b"))), v("h")),
1126 ),
1127 ),
1128 );
1129 let succ_inj_ty = pi("a", nat(), pi("b", nat(), pi("_", eqn(succ(v("a")), succ(v("b"))), eqn(v("a"), v("b")))));
1130 ctx.add_definition("succ_inj".to_string(), succ_inj_ty, succ_inj_body);
1131
1132 let rec_call = ap(ap(v("rec"), v("a'")), v("b'"));
1135 let true_case = lm(
1136 "hp",
1137 eqn(v("a'"), v("b'")),
1138 is_true(eqn(succ(v("a'")), succ(v("b'"))), ap(ap(ap(g("succ_cong"), v("a'")), v("b'")), v("hp"))),
1139 );
1140 let false_case = lm(
1141 "hnp",
1142 not(eqn(v("a'"), v("b'"))),
1143 is_false(
1144 eqn(succ(v("a'")), succ(v("b'"))),
1145 lm(
1146 "hs",
1147 eqn(succ(v("a'")), succ(v("b'"))),
1148 ap(v("hnp"), ap(ap(ap(g("succ_inj"), v("a'")), v("b'")), v("hs"))),
1149 ),
1150 ),
1151 );
1152 let inner_rec_match = Term::Match {
1153 discriminant: Box::new(rec_call),
1154 motive: Box::new(lm("_", dec(eqn(v("a'"), v("b'"))), dec(eqn(succ(v("a'")), succ(v("b'")))))),
1155 cases: vec![true_case, false_case],
1156 };
1157 let succ_b_match = Term::Match {
1159 discriminant: Box::new(v("b")),
1160 motive: Box::new(lm("b'", nat(), dec(eqn(succ(v("a'")), v("b'"))))),
1161 cases: vec![
1162 is_false(eqn(succ(v("a'")), g("Zero")), ap(g("nat_sz_ne"), v("a'"))),
1163 lm("b'", nat(), inner_rec_match),
1164 ],
1165 };
1166 let zero_b_match = Term::Match {
1168 discriminant: Box::new(v("b")),
1169 motive: Box::new(lm("b'", nat(), dec(eqn(g("Zero"), v("b'"))))),
1170 cases: vec![
1171 is_true(eqn(g("Zero"), g("Zero")), refln(g("Zero"))),
1172 lm("b'", nat(), is_false(eqn(g("Zero"), succ(v("b'"))), ap(g("nat_zs_ne"), v("b'")))),
1173 ],
1174 };
1175 let a_match = Term::Match {
1177 discriminant: Box::new(v("a")),
1178 motive: Box::new(lm("a'", nat(), dec(eqn(v("a'"), v("b"))))),
1179 cases: vec![zero_b_match, lm("a'", nat(), succ_b_match)],
1180 };
1181 let deceqnat_body = Term::Fix {
1182 name: "rec".to_string(),
1183 body: Box::new(lm("a", nat(), lm("b", nat(), a_match))),
1184 };
1185 let deceqnat_ty = pi("a", nat(), pi("b", nat(), dec(eqn(v("a"), v("b")))));
1186 ctx.add_definition("decEqNat".to_string(), deceqnat_ty, deceqnat_body);
1187 }
1188
1189 fn register_native_decide(ctx: &mut Context) {
1196 let g = |s: &str| Term::Global(s.to_string());
1197 let v = |s: &str| Term::Var(s.to_string());
1198 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
1199 let pi = |p: &str, t: Term, b: Term| Term::Pi {
1200 param: p.to_string(),
1201 param_type: Box::new(t),
1202 body_type: Box::new(b),
1203 };
1204 let eqb = |x: Term, y: Term| ap(ap(ap(g("Eq"), g("Bool")), x), y);
1205 ctx.add_declaration("reduceBool", pi("_", g("Bool"), g("Bool")));
1207 ctx.add_declaration(
1209 "ofReduceBool",
1210 pi(
1211 "a",
1212 g("Bool"),
1213 pi(
1214 "b",
1215 g("Bool"),
1216 pi("_", eqb(ap(g("reduceBool"), v("a")), v("b")), eqb(v("a"), v("b"))),
1217 ),
1218 ),
1219 );
1220 }
1221
1222 fn register_quot(ctx: &mut Context) {
1231 let type0 = || Term::Sort(Universe::Type(0));
1232 let prop = || Term::Sort(Universe::Prop);
1233 let g = |s: &str| Term::Global(s.to_string());
1234 let v = |s: &str| Term::Var(s.to_string());
1235 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
1236 let pi = |p: &str, t: Term, b: Term| Term::Pi {
1237 param: p.to_string(),
1238 param_type: Box::new(t),
1239 body_type: Box::new(b),
1240 };
1241 let arrow = |t: Term, b: Term| pi("_", t, b);
1242 let rel = || arrow(v("A"), arrow(v("A"), prop()));
1244 let quot = |a: Term, r: Term| ap(ap(g("Quot"), a), r);
1245 let mk = |a: Term, r: Term, x: Term| ap(ap(ap(g("Quot_mk"), a), r), x);
1246 let eq3 = |t: Term, x: Term, y: Term| ap(ap(ap(g("Eq"), t), x), y);
1247
1248 ctx.add_declaration("Quot", pi("A", type0(), arrow(rel(), type0())));
1250 ctx.add_declaration(
1252 "Quot_mk",
1253 pi("A", type0(), pi("r", rel(), arrow(v("A"), quot(v("A"), v("r"))))),
1254 );
1255 let resp = pi(
1258 "a",
1259 v("A"),
1260 pi(
1261 "b",
1262 v("A"),
1263 arrow(
1264 ap(ap(v("r"), v("a")), v("b")),
1265 eq3(v("B"), ap(v("f"), v("a")), ap(v("f"), v("b"))),
1266 ),
1267 ),
1268 );
1269 ctx.add_declaration(
1270 "Quot_lift",
1271 pi(
1272 "A",
1273 type0(),
1274 pi(
1275 "r",
1276 rel(),
1277 pi(
1278 "B",
1279 type0(),
1280 pi(
1281 "f",
1282 arrow(v("A"), v("B")),
1283 pi("h", resp, arrow(quot(v("A"), v("r")), v("B"))),
1284 ),
1285 ),
1286 ),
1287 ),
1288 );
1289 ctx.add_declaration(
1291 "Quot_sound",
1292 pi(
1293 "A",
1294 type0(),
1295 pi(
1296 "r",
1297 rel(),
1298 pi(
1299 "a",
1300 v("A"),
1301 pi(
1302 "b",
1303 v("A"),
1304 arrow(
1305 ap(ap(v("r"), v("a")), v("b")),
1306 eq3(
1307 quot(v("A"), v("r")),
1308 mk(v("A"), v("r"), v("a")),
1309 mk(v("A"), v("r"), v("b")),
1310 ),
1311 ),
1312 ),
1313 ),
1314 ),
1315 ),
1316 );
1317 ctx.add_declaration(
1320 "Quot_ind",
1321 pi(
1322 "A",
1323 type0(),
1324 pi(
1325 "r",
1326 rel(),
1327 pi(
1328 "P",
1329 arrow(quot(v("A"), v("r")), prop()),
1330 arrow(
1331 pi("a", v("A"), ap(v("P"), mk(v("A"), v("r"), v("a")))),
1332 pi("q", quot(v("A"), v("r")), ap(v("P"), v("q"))),
1333 ),
1334 ),
1335 ),
1336 ),
1337 );
1338 }
1339
1340 fn register_acc(ctx: &mut Context) {
1355 fn pi(p: &str, t: Term, b: Term) -> Term {
1356 Term::Pi { param: p.to_string(), param_type: Box::new(t), body_type: Box::new(b) }
1357 }
1358 fn arrow(a: Term, b: Term) -> Term {
1359 pi("_", a, b)
1360 }
1361 fn v(n: &str) -> Term {
1362 Term::Var(n.to_string())
1363 }
1364 fn g(n: &str) -> Term {
1365 Term::Global(n.to_string())
1366 }
1367 fn apps(f: Term, xs: &[Term]) -> Term {
1368 xs.iter().fold(f, |a, x| Term::App(Box::new(a), Box::new(x.clone())))
1369 }
1370 let type0 = || Term::Sort(Universe::Type(0));
1371 let prop = || Term::Sort(Universe::Prop);
1372 let rel = || arrow(v("A"), arrow(v("A"), prop()));
1374 let acc = |x: Term| apps(g("Acc"), &[v("A"), v("R"), x]);
1376
1377 let acc_ty = pi("A", type0(), pi("R", rel(), arrow(v("A"), prop())));
1379 ctx.add_indexed_inductive("Acc", acc_ty, 2);
1380
1381 let intro_ty = pi(
1383 "A",
1384 type0(),
1385 pi(
1386 "R",
1387 rel(),
1388 pi(
1389 "x",
1390 v("A"),
1391 arrow(
1392 pi("y", v("A"), arrow(apps(v("R"), &[v("y"), v("x")]), acc(v("y")))),
1393 acc(v("x")),
1394 ),
1395 ),
1396 ),
1397 );
1398 ctx.add_constructor("Acc_intro", "Acc", intro_ty);
1399
1400 let (rec_ty, rec_body) = crate::recursor::derive_recursor(ctx, "Acc")
1404 .expect("Acc's dependent eliminator must derive");
1405 ctx.add_definition("Acc_rec".to_string(), rec_ty, rec_body);
1406
1407 let wf_ty = pi("A", type0(), arrow(rel(), prop()));
1410 let wf_body = Term::Lambda {
1411 param: "A".to_string(),
1412 param_type: Box::new(type0()),
1413 body: Box::new(Term::Lambda {
1414 param: "R".to_string(),
1415 param_type: Box::new(rel()),
1416 body: Box::new(pi("x", v("A"), acc(v("x")))),
1417 }),
1418 };
1419 ctx.add_definition("WellFounded".to_string(), wf_ty, wf_body);
1420 }
1421
1422 fn register_eq(ctx: &mut Context) {
1423 let eq_type = Term::Pi {
1425 param: "A".to_string(),
1426 param_type: Box::new(Term::Sort(Universe::Type(0))),
1427 body_type: Box::new(Term::Pi {
1428 param: "x".to_string(),
1429 param_type: Box::new(Term::Var("A".to_string())),
1430 body_type: Box::new(Term::Pi {
1431 param: "y".to_string(),
1432 param_type: Box::new(Term::Var("A".to_string())),
1433 body_type: Box::new(Term::Sort(Universe::Prop)),
1434 }),
1435 }),
1436 };
1437 ctx.add_indexed_inductive("Eq", eq_type, 2);
1440
1441 let refl_type = Term::Pi {
1443 param: "A".to_string(),
1444 param_type: Box::new(Term::Sort(Universe::Type(0))),
1445 body_type: Box::new(Term::Pi {
1446 param: "x".to_string(),
1447 param_type: Box::new(Term::Var("A".to_string())),
1448 body_type: Box::new(Term::App(
1449 Box::new(Term::App(
1450 Box::new(Term::App(
1451 Box::new(Term::Global("Eq".to_string())),
1452 Box::new(Term::Var("A".to_string())),
1453 )),
1454 Box::new(Term::Var("x".to_string())),
1455 )),
1456 Box::new(Term::Var("x".to_string())),
1457 )),
1458 }),
1459 };
1460 ctx.add_constructor("refl", "Eq", refl_type);
1461
1462 Self::register_eq_recursor(ctx);
1467
1468 Self::register_eq_rec(ctx);
1471
1472 Self::register_eq_sym(ctx);
1474
1475 Self::register_eq_trans(ctx);
1477 }
1478
1479 fn register_eq_recursor(ctx: &mut Context) {
1482 let (ty, body) = crate::recursor::derive_recursor(ctx, "Eq")
1483 .expect("Eq's dependent eliminator (J) must derive");
1484 ctx.add_definition("Eq_rec_dep".to_string(), ty, body);
1485 }
1486
1487 fn register_eq_rec(ctx: &mut Context) {
1490 let a = Term::Var("A".to_string());
1491 let x = Term::Var("x".to_string());
1492 let y = Term::Var("y".to_string());
1493 let p = Term::Var("P".to_string());
1494
1495 let p_x = Term::App(Box::new(p.clone()), Box::new(x.clone()));
1497
1498 let p_y = Term::App(Box::new(p.clone()), Box::new(y.clone()));
1500
1501 let eq_a_x_y = Term::App(
1503 Box::new(Term::App(
1504 Box::new(Term::App(
1505 Box::new(Term::Global("Eq".to_string())),
1506 Box::new(a.clone()),
1507 )),
1508 Box::new(x.clone()),
1509 )),
1510 Box::new(y.clone()),
1511 );
1512
1513 let p_type = Term::Pi {
1515 param: "_".to_string(),
1516 param_type: Box::new(a.clone()),
1517 body_type: Box::new(Term::Sort(Universe::Prop)),
1518 };
1519
1520 let eq_rec_type = Term::Pi {
1522 param: "A".to_string(),
1523 param_type: Box::new(Term::Sort(Universe::Type(0))),
1524 body_type: Box::new(Term::Pi {
1525 param: "x".to_string(),
1526 param_type: Box::new(a.clone()),
1527 body_type: Box::new(Term::Pi {
1528 param: "P".to_string(),
1529 param_type: Box::new(p_type),
1530 body_type: Box::new(Term::Pi {
1531 param: "_".to_string(),
1532 param_type: Box::new(p_x),
1533 body_type: Box::new(Term::Pi {
1534 param: "y".to_string(),
1535 param_type: Box::new(a.clone()),
1536 body_type: Box::new(Term::Pi {
1537 param: "_".to_string(),
1538 param_type: Box::new(eq_a_x_y),
1539 body_type: Box::new(p_y),
1540 }),
1541 }),
1542 }),
1543 }),
1544 }),
1545 };
1546
1547 let gl = |s: &str| Term::Global(s.to_string());
1550 let vr = |s: &str| Term::Var(s.to_string());
1551 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
1552 let lm = |p: &str, t: Term, b: Term| Term::Lambda {
1553 param: p.to_string(),
1554 param_type: Box::new(t),
1555 body: Box::new(b),
1556 };
1557 let eq3 = |a: Term, x: Term, y: Term| ap(ap(ap(gl("Eq"), a), x), y);
1558 let dep_motive = lm(
1559 "y'",
1560 vr("A"),
1561 lm("_", eq3(vr("A"), vr("x"), vr("y'")), ap(vr("P"), vr("y'"))),
1562 );
1563 let call = ap(
1564 ap(
1565 ap(ap(ap(ap(gl("Eq_rec_dep"), vr("A")), vr("x")), dep_motive), vr("base")),
1566 vr("y"),
1567 ),
1568 vr("h"),
1569 );
1570 let eq_rec_body = lm(
1571 "A",
1572 Term::Sort(Universe::Type(0)),
1573 lm(
1574 "x",
1575 vr("A"),
1576 lm(
1577 "P",
1578 Term::Pi {
1579 param: "_".to_string(),
1580 param_type: Box::new(vr("A")),
1581 body_type: Box::new(Term::Sort(Universe::Prop)),
1582 },
1583 lm(
1584 "base",
1585 ap(vr("P"), vr("x")),
1586 lm("y", vr("A"), lm("h", eq3(vr("A"), vr("x"), vr("y")), call)),
1587 ),
1588 ),
1589 ),
1590 );
1591
1592 ctx.add_definition("Eq_rec".to_string(), eq_rec_type, eq_rec_body);
1593 }
1594
1595 fn register_eq_sym(ctx: &mut Context) {
1598 let a = Term::Var("A".to_string());
1599 let x = Term::Var("x".to_string());
1600 let y = Term::Var("y".to_string());
1601
1602 let eq_a_x_y = Term::App(
1604 Box::new(Term::App(
1605 Box::new(Term::App(
1606 Box::new(Term::Global("Eq".to_string())),
1607 Box::new(a.clone()),
1608 )),
1609 Box::new(x.clone()),
1610 )),
1611 Box::new(y.clone()),
1612 );
1613
1614 let eq_a_y_x = Term::App(
1616 Box::new(Term::App(
1617 Box::new(Term::App(
1618 Box::new(Term::Global("Eq".to_string())),
1619 Box::new(a.clone()),
1620 )),
1621 Box::new(y.clone()),
1622 )),
1623 Box::new(x.clone()),
1624 );
1625
1626 let eq_sym_type = Term::Pi {
1628 param: "A".to_string(),
1629 param_type: Box::new(Term::Sort(Universe::Type(0))),
1630 body_type: Box::new(Term::Pi {
1631 param: "x".to_string(),
1632 param_type: Box::new(a.clone()),
1633 body_type: Box::new(Term::Pi {
1634 param: "y".to_string(),
1635 param_type: Box::new(a),
1636 body_type: Box::new(Term::Pi {
1637 param: "_".to_string(),
1638 param_type: Box::new(eq_a_x_y),
1639 body_type: Box::new(eq_a_y_x),
1640 }),
1641 }),
1642 }),
1643 };
1644
1645 let gl = |s: &str| Term::Global(s.to_string());
1648 let vr = |s: &str| Term::Var(s.to_string());
1649 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
1650 let lm = |p: &str, t: Term, b: Term| Term::Lambda {
1651 param: p.to_string(),
1652 param_type: Box::new(t),
1653 body: Box::new(b),
1654 };
1655 let eq3 = |a: Term, x: Term, y: Term| ap(ap(ap(gl("Eq"), a), x), y);
1656 let motive = lm(
1657 "y'",
1658 vr("A"),
1659 lm("_", eq3(vr("A"), vr("x"), vr("y'")), eq3(vr("A"), vr("y'"), vr("x"))),
1660 );
1661 let refl_a_x = ap(ap(gl("refl"), vr("A")), vr("x"));
1662 let call = ap(
1663 ap(
1664 ap(ap(ap(ap(gl("Eq_rec_dep"), vr("A")), vr("x")), motive), refl_a_x),
1665 vr("y"),
1666 ),
1667 vr("h"),
1668 );
1669 let eq_sym_body = lm(
1670 "A",
1671 Term::Sort(Universe::Type(0)),
1672 lm(
1673 "x",
1674 vr("A"),
1675 lm("y", vr("A"), lm("h", eq3(vr("A"), vr("x"), vr("y")), call)),
1676 ),
1677 );
1678
1679 ctx.add_definition("Eq_sym".to_string(), eq_sym_type, eq_sym_body);
1680 }
1681
1682 fn register_eq_trans(ctx: &mut Context) {
1685 let a = Term::Var("A".to_string());
1686 let x = Term::Var("x".to_string());
1687 let y = Term::Var("y".to_string());
1688 let z = Term::Var("z".to_string());
1689
1690 let eq_a_x_y = Term::App(
1692 Box::new(Term::App(
1693 Box::new(Term::App(
1694 Box::new(Term::Global("Eq".to_string())),
1695 Box::new(a.clone()),
1696 )),
1697 Box::new(x.clone()),
1698 )),
1699 Box::new(y.clone()),
1700 );
1701
1702 let eq_a_y_z = Term::App(
1704 Box::new(Term::App(
1705 Box::new(Term::App(
1706 Box::new(Term::Global("Eq".to_string())),
1707 Box::new(a.clone()),
1708 )),
1709 Box::new(y.clone()),
1710 )),
1711 Box::new(z.clone()),
1712 );
1713
1714 let eq_a_x_z = Term::App(
1716 Box::new(Term::App(
1717 Box::new(Term::App(
1718 Box::new(Term::Global("Eq".to_string())),
1719 Box::new(a.clone()),
1720 )),
1721 Box::new(x.clone()),
1722 )),
1723 Box::new(z.clone()),
1724 );
1725
1726 let eq_trans_type = Term::Pi {
1728 param: "A".to_string(),
1729 param_type: Box::new(Term::Sort(Universe::Type(0))),
1730 body_type: Box::new(Term::Pi {
1731 param: "x".to_string(),
1732 param_type: Box::new(a.clone()),
1733 body_type: Box::new(Term::Pi {
1734 param: "y".to_string(),
1735 param_type: Box::new(a.clone()),
1736 body_type: Box::new(Term::Pi {
1737 param: "z".to_string(),
1738 param_type: Box::new(a),
1739 body_type: Box::new(Term::Pi {
1740 param: "_".to_string(),
1741 param_type: Box::new(eq_a_x_y),
1742 body_type: Box::new(Term::Pi {
1743 param: "_".to_string(),
1744 param_type: Box::new(eq_a_y_z),
1745 body_type: Box::new(eq_a_x_z),
1746 }),
1747 }),
1748 }),
1749 }),
1750 }),
1751 };
1752
1753 let gl = |s: &str| Term::Global(s.to_string());
1757 let vr = |s: &str| Term::Var(s.to_string());
1758 let ap = |f: Term, x: Term| Term::App(Box::new(f), Box::new(x));
1759 let lm = |p: &str, t: Term, b: Term| Term::Lambda {
1760 param: p.to_string(),
1761 param_type: Box::new(t),
1762 body: Box::new(b),
1763 };
1764 let eq3 = |a: Term, x: Term, y: Term| ap(ap(ap(gl("Eq"), a), x), y);
1765 let motive = lm(
1766 "z'",
1767 vr("A"),
1768 lm("_", eq3(vr("A"), vr("y"), vr("z'")), eq3(vr("A"), vr("x"), vr("z'"))),
1769 );
1770 let call = ap(
1771 ap(
1772 ap(ap(ap(ap(gl("Eq_rec_dep"), vr("A")), vr("y")), motive), vr("hxy")),
1773 vr("z"),
1774 ),
1775 vr("hyz"),
1776 );
1777 let eq_trans_body = lm(
1778 "A",
1779 Term::Sort(Universe::Type(0)),
1780 lm(
1781 "x",
1782 vr("A"),
1783 lm(
1784 "y",
1785 vr("A"),
1786 lm(
1787 "z",
1788 vr("A"),
1789 lm(
1790 "hxy",
1791 eq3(vr("A"), vr("x"), vr("y")),
1792 lm("hyz", eq3(vr("A"), vr("y"), vr("z")), call),
1793 ),
1794 ),
1795 ),
1796 ),
1797 );
1798
1799 ctx.add_definition("Eq_trans".to_string(), eq_trans_type, eq_trans_body);
1800 }
1801
1802 fn register_and(ctx: &mut Context) {
1805 let and_type = Term::Pi {
1807 param: "P".to_string(),
1808 param_type: Box::new(Term::Sort(Universe::Prop)),
1809 body_type: Box::new(Term::Pi {
1810 param: "Q".to_string(),
1811 param_type: Box::new(Term::Sort(Universe::Prop)),
1812 body_type: Box::new(Term::Sort(Universe::Prop)),
1813 }),
1814 };
1815 ctx.add_inductive("And", and_type);
1816
1817 let conj_type = Term::Pi {
1819 param: "P".to_string(),
1820 param_type: Box::new(Term::Sort(Universe::Prop)),
1821 body_type: Box::new(Term::Pi {
1822 param: "Q".to_string(),
1823 param_type: Box::new(Term::Sort(Universe::Prop)),
1824 body_type: Box::new(Term::Pi {
1825 param: "p".to_string(),
1826 param_type: Box::new(Term::Var("P".to_string())),
1827 body_type: Box::new(Term::Pi {
1828 param: "q".to_string(),
1829 param_type: Box::new(Term::Var("Q".to_string())),
1830 body_type: Box::new(Term::App(
1831 Box::new(Term::App(
1832 Box::new(Term::Global("And".to_string())),
1833 Box::new(Term::Var("P".to_string())),
1834 )),
1835 Box::new(Term::Var("Q".to_string())),
1836 )),
1837 }),
1838 }),
1839 }),
1840 };
1841 ctx.add_constructor("conj", "And", conj_type);
1842 }
1843
1844 fn register_or(ctx: &mut Context) {
1848 let or_type = Term::Pi {
1850 param: "P".to_string(),
1851 param_type: Box::new(Term::Sort(Universe::Prop)),
1852 body_type: Box::new(Term::Pi {
1853 param: "Q".to_string(),
1854 param_type: Box::new(Term::Sort(Universe::Prop)),
1855 body_type: Box::new(Term::Sort(Universe::Prop)),
1856 }),
1857 };
1858 ctx.add_inductive("Or", or_type);
1859
1860 let left_type = Term::Pi {
1862 param: "P".to_string(),
1863 param_type: Box::new(Term::Sort(Universe::Prop)),
1864 body_type: Box::new(Term::Pi {
1865 param: "Q".to_string(),
1866 param_type: Box::new(Term::Sort(Universe::Prop)),
1867 body_type: Box::new(Term::Pi {
1868 param: "p".to_string(),
1869 param_type: Box::new(Term::Var("P".to_string())),
1870 body_type: Box::new(Term::App(
1871 Box::new(Term::App(
1872 Box::new(Term::Global("Or".to_string())),
1873 Box::new(Term::Var("P".to_string())),
1874 )),
1875 Box::new(Term::Var("Q".to_string())),
1876 )),
1877 }),
1878 }),
1879 };
1880 ctx.add_constructor("left", "Or", left_type);
1881
1882 let right_type = Term::Pi {
1884 param: "P".to_string(),
1885 param_type: Box::new(Term::Sort(Universe::Prop)),
1886 body_type: Box::new(Term::Pi {
1887 param: "Q".to_string(),
1888 param_type: Box::new(Term::Sort(Universe::Prop)),
1889 body_type: Box::new(Term::Pi {
1890 param: "q".to_string(),
1891 param_type: Box::new(Term::Var("Q".to_string())),
1892 body_type: Box::new(Term::App(
1893 Box::new(Term::App(
1894 Box::new(Term::Global("Or".to_string())),
1895 Box::new(Term::Var("P".to_string())),
1896 )),
1897 Box::new(Term::Var("Q".to_string())),
1898 )),
1899 }),
1900 }),
1901 };
1902 ctx.add_constructor("right", "Or", right_type);
1903 }
1904
1905 fn register_ex(ctx: &mut Context) {
1911 let ex_type = Term::Pi {
1913 param: "A".to_string(),
1914 param_type: Box::new(Term::Sort(Universe::Type(0))),
1915 body_type: Box::new(Term::Pi {
1916 param: "P".to_string(),
1917 param_type: Box::new(Term::Pi {
1918 param: "_".to_string(),
1919 param_type: Box::new(Term::Var("A".to_string())),
1920 body_type: Box::new(Term::Sort(Universe::Prop)),
1921 }),
1922 body_type: Box::new(Term::Sort(Universe::Prop)),
1923 }),
1924 };
1925 ctx.add_inductive("Ex", ex_type);
1926
1927 let a = Term::Var("A".to_string());
1935 let p = Term::Var("P".to_string());
1936 let x = Term::Var("x".to_string());
1937
1938 let p_x = Term::App(Box::new(p.clone()), Box::new(x.clone()));
1940
1941 let ex_a_p = Term::App(
1943 Box::new(Term::App(
1944 Box::new(Term::Global("Ex".to_string())),
1945 Box::new(a.clone()),
1946 )),
1947 Box::new(p.clone()),
1948 );
1949
1950 let witness_type = Term::Pi {
1951 param: "A".to_string(),
1952 param_type: Box::new(Term::Sort(Universe::Type(0))),
1953 body_type: Box::new(Term::Pi {
1954 param: "P".to_string(),
1955 param_type: Box::new(Term::Pi {
1956 param: "_".to_string(),
1957 param_type: Box::new(a.clone()),
1958 body_type: Box::new(Term::Sort(Universe::Prop)),
1959 }),
1960 body_type: Box::new(Term::Pi {
1961 param: "x".to_string(),
1962 param_type: Box::new(a),
1963 body_type: Box::new(Term::Pi {
1964 param: "_".to_string(),
1965 param_type: Box::new(p_x),
1966 body_type: Box::new(ex_a_p),
1967 }),
1968 }),
1969 }),
1970 };
1971 ctx.add_constructor("witness", "Ex", witness_type);
1972 }
1973
1974 fn register_reflection(ctx: &mut Context) {
1985 Self::register_univ(ctx);
1986 Self::register_syntax(ctx);
1987 Self::register_syn_size(ctx);
1988 Self::register_syn_max_var(ctx);
1989 Self::register_syn_lift(ctx);
1990 Self::register_syn_subst(ctx);
1991 Self::register_syn_beta(ctx);
1992 Self::register_syn_step(ctx);
1993 Self::register_syn_eval(ctx);
1994 Self::register_syn_quote(ctx);
1995 Self::register_syn_diag(ctx);
1996 Self::register_derivation(ctx);
1997 Self::register_concludes(ctx);
1998 Self::register_try_refl(ctx);
1999 Self::register_try_compute(ctx);
2000 Self::register_try_cong(ctx);
2001 Self::register_tact_fail(ctx);
2002 Self::register_tact_orelse(ctx);
2003 Self::register_tact_try(ctx);
2004 Self::register_tact_repeat(ctx);
2005 Self::register_tact_then(ctx);
2006 Self::register_tact_first(ctx);
2007 Self::register_tact_solve(ctx);
2008 Self::register_try_ring(ctx);
2009 Self::register_try_lia(ctx);
2010 Self::register_try_cc(ctx);
2011 Self::register_try_simp(ctx);
2012 Self::register_try_omega(ctx);
2013 Self::register_try_auto(ctx);
2014 Self::register_try_induction(ctx);
2015 Self::register_induction_helpers(ctx);
2016 Self::register_try_inversion_tactic(ctx);
2017 Self::register_operator_tactics(ctx);
2018 Self::register_hw_tactics(ctx);
2019 }
2020
2021 fn register_univ(ctx: &mut Context) {
2025 let univ = Term::Global("Univ".to_string());
2026 let int = Term::Global("Int".to_string());
2027
2028 ctx.add_inductive("Univ", Term::Sort(Universe::Type(0)));
2030
2031 ctx.add_constructor("UProp", "Univ", univ.clone());
2033
2034 ctx.add_constructor(
2036 "UType",
2037 "Univ",
2038 Term::Pi {
2039 param: "_".to_string(),
2040 param_type: Box::new(int),
2041 body_type: Box::new(univ),
2042 },
2043 );
2044 }
2045
2046 fn register_syntax(ctx: &mut Context) {
2055 let syntax = Term::Global("Syntax".to_string());
2056 let int = Term::Global("Int".to_string());
2057 let univ = Term::Global("Univ".to_string());
2058
2059 ctx.add_inductive("Syntax", Term::Sort(Universe::Type(0)));
2061
2062 ctx.add_constructor(
2064 "SVar",
2065 "Syntax",
2066 Term::Pi {
2067 param: "_".to_string(),
2068 param_type: Box::new(int.clone()),
2069 body_type: Box::new(syntax.clone()),
2070 },
2071 );
2072
2073 ctx.add_constructor(
2075 "SGlobal",
2076 "Syntax",
2077 Term::Pi {
2078 param: "_".to_string(),
2079 param_type: Box::new(int.clone()),
2080 body_type: Box::new(syntax.clone()),
2081 },
2082 );
2083
2084 ctx.add_constructor(
2086 "SSort",
2087 "Syntax",
2088 Term::Pi {
2089 param: "_".to_string(),
2090 param_type: Box::new(univ),
2091 body_type: Box::new(syntax.clone()),
2092 },
2093 );
2094
2095 ctx.add_constructor(
2097 "SApp",
2098 "Syntax",
2099 Term::Pi {
2100 param: "_".to_string(),
2101 param_type: Box::new(syntax.clone()),
2102 body_type: Box::new(Term::Pi {
2103 param: "_".to_string(),
2104 param_type: Box::new(syntax.clone()),
2105 body_type: Box::new(syntax.clone()),
2106 }),
2107 },
2108 );
2109
2110 ctx.add_constructor(
2112 "SLam",
2113 "Syntax",
2114 Term::Pi {
2115 param: "_".to_string(),
2116 param_type: Box::new(syntax.clone()),
2117 body_type: Box::new(Term::Pi {
2118 param: "_".to_string(),
2119 param_type: Box::new(syntax.clone()),
2120 body_type: Box::new(syntax.clone()),
2121 }),
2122 },
2123 );
2124
2125 ctx.add_constructor(
2127 "SPi",
2128 "Syntax",
2129 Term::Pi {
2130 param: "_".to_string(),
2131 param_type: Box::new(syntax.clone()),
2132 body_type: Box::new(Term::Pi {
2133 param: "_".to_string(),
2134 param_type: Box::new(syntax.clone()),
2135 body_type: Box::new(syntax.clone()),
2136 }),
2137 },
2138 );
2139
2140 ctx.add_constructor(
2142 "SLit",
2143 "Syntax",
2144 Term::Pi {
2145 param: "_".to_string(),
2146 param_type: Box::new(int),
2147 body_type: Box::new(syntax.clone()),
2148 },
2149 );
2150
2151 let text = Term::Global("Text".to_string());
2153 ctx.add_constructor(
2154 "SName",
2155 "Syntax",
2156 Term::Pi {
2157 param: "_".to_string(),
2158 param_type: Box::new(text),
2159 body_type: Box::new(syntax),
2160 },
2161 );
2162 }
2163
2164 fn register_syn_size(ctx: &mut Context) {
2169 let syntax = Term::Global("Syntax".to_string());
2170 let int = Term::Global("Int".to_string());
2171
2172 let syn_size_type = Term::Pi {
2174 param: "_".to_string(),
2175 param_type: Box::new(syntax),
2176 body_type: Box::new(int),
2177 };
2178
2179 ctx.add_declaration("syn_size", syn_size_type);
2180 }
2181
2182 fn register_syn_max_var(ctx: &mut Context) {
2188 let syntax = Term::Global("Syntax".to_string());
2189 let int = Term::Global("Int".to_string());
2190
2191 let syn_max_var_type = Term::Pi {
2192 param: "_".to_string(),
2193 param_type: Box::new(syntax),
2194 body_type: Box::new(int),
2195 };
2196
2197 ctx.add_declaration("syn_max_var", syn_max_var_type);
2198 }
2199
2200 fn register_syn_lift(ctx: &mut Context) {
2212 let syntax = Term::Global("Syntax".to_string());
2213 let int = Term::Global("Int".to_string());
2214
2215 let syn_lift_type = Term::Pi {
2217 param: "_".to_string(),
2218 param_type: Box::new(int.clone()),
2219 body_type: Box::new(Term::Pi {
2220 param: "_".to_string(),
2221 param_type: Box::new(int),
2222 body_type: Box::new(Term::Pi {
2223 param: "_".to_string(),
2224 param_type: Box::new(syntax.clone()),
2225 body_type: Box::new(syntax),
2226 }),
2227 }),
2228 };
2229
2230 ctx.add_declaration("syn_lift", syn_lift_type);
2231 }
2232
2233 fn register_syn_subst(ctx: &mut Context) {
2242 let syntax = Term::Global("Syntax".to_string());
2243 let int = Term::Global("Int".to_string());
2244
2245 let syn_subst_type = Term::Pi {
2247 param: "_".to_string(),
2248 param_type: Box::new(syntax.clone()),
2249 body_type: Box::new(Term::Pi {
2250 param: "_".to_string(),
2251 param_type: Box::new(int),
2252 body_type: Box::new(Term::Pi {
2253 param: "_".to_string(),
2254 param_type: Box::new(syntax.clone()),
2255 body_type: Box::new(syntax),
2256 }),
2257 }),
2258 };
2259
2260 ctx.add_declaration("syn_subst", syn_subst_type);
2261 }
2262
2263 fn register_syn_beta(ctx: &mut Context) {
2276 let syntax = Term::Global("Syntax".to_string());
2277
2278 let syn_beta_type = Term::Pi {
2280 param: "_".to_string(),
2281 param_type: Box::new(syntax.clone()),
2282 body_type: Box::new(Term::Pi {
2283 param: "_".to_string(),
2284 param_type: Box::new(syntax.clone()),
2285 body_type: Box::new(syntax),
2286 }),
2287 };
2288
2289 ctx.add_declaration("syn_beta", syn_beta_type);
2290 }
2291
2292 fn register_syn_step(ctx: &mut Context) {
2300 let syntax = Term::Global("Syntax".to_string());
2301
2302 let syn_step_type = Term::Pi {
2304 param: "_".to_string(),
2305 param_type: Box::new(syntax.clone()),
2306 body_type: Box::new(syntax),
2307 };
2308
2309 ctx.add_declaration("syn_step", syn_step_type);
2310 }
2311
2312 fn register_syn_eval(ctx: &mut Context) {
2324 let syntax = Term::Global("Syntax".to_string());
2325 let int = Term::Global("Int".to_string());
2326
2327 let syn_eval_type = Term::Pi {
2329 param: "_".to_string(),
2330 param_type: Box::new(int),
2331 body_type: Box::new(Term::Pi {
2332 param: "_".to_string(),
2333 param_type: Box::new(syntax.clone()),
2334 body_type: Box::new(syntax),
2335 }),
2336 };
2337
2338 ctx.add_declaration("syn_eval", syn_eval_type);
2339 }
2340
2341 fn register_syn_quote(ctx: &mut Context) {
2350 let syntax = Term::Global("Syntax".to_string());
2351
2352 let syn_quote_type = Term::Pi {
2354 param: "_".to_string(),
2355 param_type: Box::new(syntax.clone()),
2356 body_type: Box::new(syntax),
2357 };
2358
2359 ctx.add_declaration("syn_quote", syn_quote_type);
2360 }
2361
2362 fn register_syn_diag(ctx: &mut Context) {
2371 let syntax = Term::Global("Syntax".to_string());
2372
2373 let syn_diag_type = Term::Pi {
2374 param: "_".to_string(),
2375 param_type: Box::new(syntax.clone()),
2376 body_type: Box::new(syntax),
2377 };
2378
2379 ctx.add_declaration("syn_diag", syn_diag_type);
2380 }
2381
2382 fn register_derivation(ctx: &mut Context) {
2393 let syntax = Term::Global("Syntax".to_string());
2394 let derivation = Term::Global("Derivation".to_string());
2395
2396 ctx.add_inductive("Derivation", Term::Sort(Universe::Type(0)));
2398
2399 ctx.add_constructor(
2401 "DAxiom",
2402 "Derivation",
2403 Term::Pi {
2404 param: "_".to_string(),
2405 param_type: Box::new(syntax.clone()),
2406 body_type: Box::new(derivation.clone()),
2407 },
2408 );
2409
2410 ctx.add_constructor(
2412 "DModusPonens",
2413 "Derivation",
2414 Term::Pi {
2415 param: "_".to_string(),
2416 param_type: Box::new(derivation.clone()),
2417 body_type: Box::new(Term::Pi {
2418 param: "_".to_string(),
2419 param_type: Box::new(derivation.clone()),
2420 body_type: Box::new(derivation.clone()),
2421 }),
2422 },
2423 );
2424
2425 ctx.add_constructor(
2427 "DUnivIntro",
2428 "Derivation",
2429 Term::Pi {
2430 param: "_".to_string(),
2431 param_type: Box::new(derivation.clone()),
2432 body_type: Box::new(derivation.clone()),
2433 },
2434 );
2435
2436 ctx.add_constructor(
2438 "DUnivElim",
2439 "Derivation",
2440 Term::Pi {
2441 param: "_".to_string(),
2442 param_type: Box::new(derivation.clone()),
2443 body_type: Box::new(Term::Pi {
2444 param: "_".to_string(),
2445 param_type: Box::new(syntax.clone()),
2446 body_type: Box::new(derivation.clone()),
2447 }),
2448 },
2449 );
2450
2451 ctx.add_constructor(
2454 "DRefl",
2455 "Derivation",
2456 Term::Pi {
2457 param: "_".to_string(),
2458 param_type: Box::new(syntax.clone()),
2459 body_type: Box::new(Term::Pi {
2460 param: "_".to_string(),
2461 param_type: Box::new(syntax.clone()),
2462 body_type: Box::new(derivation.clone()),
2463 }),
2464 },
2465 );
2466
2467 ctx.add_constructor(
2473 "DInduction",
2474 "Derivation",
2475 Term::Pi {
2476 param: "_".to_string(),
2477 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2479 param: "_".to_string(),
2480 param_type: Box::new(derivation.clone()), body_type: Box::new(Term::Pi {
2482 param: "_".to_string(),
2483 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation.clone()),
2485 }),
2486 }),
2487 },
2488 );
2489
2490 ctx.add_constructor(
2494 "DCompute",
2495 "Derivation",
2496 Term::Pi {
2497 param: "_".to_string(),
2498 param_type: Box::new(syntax.clone()),
2499 body_type: Box::new(derivation.clone()),
2500 },
2501 );
2502
2503 ctx.add_constructor(
2509 "DCong",
2510 "Derivation",
2511 Term::Pi {
2512 param: "_".to_string(),
2513 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2515 param: "_".to_string(),
2516 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation.clone()),
2518 }),
2519 },
2520 );
2521
2522 ctx.add_constructor(
2525 "DCase",
2526 "Derivation",
2527 Term::Pi {
2528 param: "_".to_string(),
2529 param_type: Box::new(derivation.clone()), body_type: Box::new(Term::Pi {
2531 param: "_".to_string(),
2532 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation.clone()),
2534 }),
2535 },
2536 );
2537
2538 ctx.add_constructor("DCaseEnd", "Derivation", derivation.clone());
2541
2542 ctx.add_constructor(
2548 "DElim",
2549 "Derivation",
2550 Term::Pi {
2551 param: "_".to_string(),
2552 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2554 param: "_".to_string(),
2555 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2557 param: "_".to_string(),
2558 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation.clone()),
2560 }),
2561 }),
2562 },
2563 );
2564
2565 ctx.add_constructor(
2570 "DInversion",
2571 "Derivation",
2572 Term::Pi {
2573 param: "_".to_string(),
2574 param_type: Box::new(syntax.clone()),
2575 body_type: Box::new(derivation.clone()),
2576 },
2577 );
2578
2579 ctx.add_constructor(
2583 "DRewrite",
2584 "Derivation",
2585 Term::Pi {
2586 param: "_".to_string(),
2587 param_type: Box::new(derivation.clone()), body_type: Box::new(Term::Pi {
2589 param: "_".to_string(),
2590 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2592 param: "_".to_string(),
2593 param_type: Box::new(syntax.clone()), body_type: Box::new(derivation.clone()),
2595 }),
2596 }),
2597 },
2598 );
2599
2600 ctx.add_constructor(
2606 "DDestruct",
2607 "Derivation",
2608 Term::Pi {
2609 param: "_".to_string(),
2610 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2612 param: "_".to_string(),
2613 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2615 param: "_".to_string(),
2616 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation.clone()),
2618 }),
2619 }),
2620 },
2621 );
2622
2623 ctx.add_constructor(
2630 "DApply",
2631 "Derivation",
2632 Term::Pi {
2633 param: "_".to_string(),
2634 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2636 param: "_".to_string(),
2637 param_type: Box::new(derivation.clone()), body_type: Box::new(Term::Pi {
2639 param: "_".to_string(),
2640 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
2642 param: "_".to_string(),
2643 param_type: Box::new(syntax), body_type: Box::new(derivation),
2645 }),
2646 }),
2647 }),
2648 },
2649 );
2650 }
2651
2652 fn register_concludes(ctx: &mut Context) {
2657 let derivation = Term::Global("Derivation".to_string());
2658 let syntax = Term::Global("Syntax".to_string());
2659
2660 let concludes_type = Term::Pi {
2662 param: "_".to_string(),
2663 param_type: Box::new(derivation),
2664 body_type: Box::new(syntax),
2665 };
2666
2667 ctx.add_declaration("concludes", concludes_type);
2668 }
2669
2670 fn register_try_refl(ctx: &mut Context) {
2681 let syntax = Term::Global("Syntax".to_string());
2682 let derivation = Term::Global("Derivation".to_string());
2683
2684 let try_refl_type = Term::Pi {
2686 param: "_".to_string(),
2687 param_type: Box::new(syntax),
2688 body_type: Box::new(derivation),
2689 };
2690
2691 ctx.add_declaration("try_refl", try_refl_type);
2692 }
2693
2694 fn register_try_compute(ctx: &mut Context) {
2701 let syntax = Term::Global("Syntax".to_string());
2702 let derivation = Term::Global("Derivation".to_string());
2703
2704 let try_compute_type = Term::Pi {
2706 param: "_".to_string(),
2707 param_type: Box::new(syntax),
2708 body_type: Box::new(derivation),
2709 };
2710
2711 ctx.add_declaration("try_compute", try_compute_type);
2712 }
2713
2714 fn register_try_cong(ctx: &mut Context) {
2721 let syntax = Term::Global("Syntax".to_string());
2722 let derivation = Term::Global("Derivation".to_string());
2723
2724 let try_cong_type = Term::Pi {
2726 param: "_".to_string(),
2727 param_type: Box::new(syntax), body_type: Box::new(Term::Pi {
2729 param: "_".to_string(),
2730 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation),
2732 }),
2733 };
2734
2735 ctx.add_declaration("try_cong", try_cong_type);
2736 }
2737
2738 fn register_tact_fail(ctx: &mut Context) {
2748 let syntax = Term::Global("Syntax".to_string());
2749 let derivation = Term::Global("Derivation".to_string());
2750
2751 let tact_fail_type = Term::Pi {
2753 param: "_".to_string(),
2754 param_type: Box::new(syntax),
2755 body_type: Box::new(derivation),
2756 };
2757
2758 ctx.add_declaration("tact_fail", tact_fail_type);
2759 }
2760
2761 fn register_tact_orelse(ctx: &mut Context) {
2767 let syntax = Term::Global("Syntax".to_string());
2768 let derivation = Term::Global("Derivation".to_string());
2769
2770 let tactic_type = Term::Pi {
2772 param: "_".to_string(),
2773 param_type: Box::new(syntax.clone()),
2774 body_type: Box::new(derivation.clone()),
2775 };
2776
2777 let tact_orelse_type = Term::Pi {
2779 param: "_".to_string(),
2780 param_type: Box::new(tactic_type.clone()), body_type: Box::new(Term::Pi {
2782 param: "_".to_string(),
2783 param_type: Box::new(tactic_type), body_type: Box::new(Term::Pi {
2785 param: "_".to_string(),
2786 param_type: Box::new(syntax), body_type: Box::new(derivation),
2788 }),
2789 }),
2790 };
2791
2792 ctx.add_declaration("tact_orelse", tact_orelse_type);
2793 }
2794
2795 fn register_tact_try(ctx: &mut Context) {
2801 let syntax = Term::Global("Syntax".to_string());
2802 let derivation = Term::Global("Derivation".to_string());
2803
2804 let tactic_type = Term::Pi {
2806 param: "_".to_string(),
2807 param_type: Box::new(syntax.clone()),
2808 body_type: Box::new(derivation.clone()),
2809 };
2810
2811 let tact_try_type = Term::Pi {
2813 param: "_".to_string(),
2814 param_type: Box::new(tactic_type), body_type: Box::new(Term::Pi {
2816 param: "_".to_string(),
2817 param_type: Box::new(syntax),
2818 body_type: Box::new(derivation),
2819 }),
2820 };
2821
2822 ctx.add_declaration("tact_try", tact_try_type);
2823 }
2824
2825 fn register_tact_repeat(ctx: &mut Context) {
2831 let syntax = Term::Global("Syntax".to_string());
2832 let derivation = Term::Global("Derivation".to_string());
2833
2834 let tactic_type = Term::Pi {
2836 param: "_".to_string(),
2837 param_type: Box::new(syntax.clone()),
2838 body_type: Box::new(derivation.clone()),
2839 };
2840
2841 let tact_repeat_type = Term::Pi {
2843 param: "_".to_string(),
2844 param_type: Box::new(tactic_type), body_type: Box::new(Term::Pi {
2846 param: "_".to_string(),
2847 param_type: Box::new(syntax),
2848 body_type: Box::new(derivation),
2849 }),
2850 };
2851
2852 ctx.add_declaration("tact_repeat", tact_repeat_type);
2853 }
2854
2855 fn register_tact_then(ctx: &mut Context) {
2862 let syntax = Term::Global("Syntax".to_string());
2863 let derivation = Term::Global("Derivation".to_string());
2864
2865 let tactic_type = Term::Pi {
2867 param: "_".to_string(),
2868 param_type: Box::new(syntax.clone()),
2869 body_type: Box::new(derivation.clone()),
2870 };
2871
2872 let tact_then_type = Term::Pi {
2874 param: "_".to_string(),
2875 param_type: Box::new(tactic_type.clone()), body_type: Box::new(Term::Pi {
2877 param: "_".to_string(),
2878 param_type: Box::new(tactic_type), body_type: Box::new(Term::Pi {
2880 param: "_".to_string(),
2881 param_type: Box::new(syntax),
2882 body_type: Box::new(derivation),
2883 }),
2884 }),
2885 };
2886
2887 ctx.add_declaration("tact_then", tact_then_type);
2888 }
2889
2890 fn register_tact_first(ctx: &mut Context) {
2896 let syntax = Term::Global("Syntax".to_string());
2897 let derivation = Term::Global("Derivation".to_string());
2898
2899 let tactic_type = Term::Pi {
2901 param: "_".to_string(),
2902 param_type: Box::new(syntax.clone()),
2903 body_type: Box::new(derivation.clone()),
2904 };
2905
2906 let tactic_list_type = Term::App(
2908 Box::new(Term::Global("TList".to_string())),
2909 Box::new(tactic_type),
2910 );
2911
2912 let tact_first_type = Term::Pi {
2914 param: "_".to_string(),
2915 param_type: Box::new(tactic_list_type), body_type: Box::new(Term::Pi {
2917 param: "_".to_string(),
2918 param_type: Box::new(syntax),
2919 body_type: Box::new(derivation),
2920 }),
2921 };
2922
2923 ctx.add_declaration("tact_first", tact_first_type);
2924 }
2925
2926 fn register_tact_solve(ctx: &mut Context) {
2933 let syntax = Term::Global("Syntax".to_string());
2934 let derivation = Term::Global("Derivation".to_string());
2935
2936 let tactic_type = Term::Pi {
2938 param: "_".to_string(),
2939 param_type: Box::new(syntax.clone()),
2940 body_type: Box::new(derivation.clone()),
2941 };
2942
2943 let tact_solve_type = Term::Pi {
2945 param: "_".to_string(),
2946 param_type: Box::new(tactic_type), body_type: Box::new(Term::Pi {
2948 param: "_".to_string(),
2949 param_type: Box::new(syntax),
2950 body_type: Box::new(derivation),
2951 }),
2952 };
2953
2954 ctx.add_declaration("tact_solve", tact_solve_type);
2955 }
2956
2957 fn register_try_ring(ctx: &mut Context) {
2967 let syntax = Term::Global("Syntax".to_string());
2968 let derivation = Term::Global("Derivation".to_string());
2969
2970 ctx.add_constructor(
2973 "DRingSolve",
2974 "Derivation",
2975 Term::Pi {
2976 param: "_".to_string(),
2977 param_type: Box::new(syntax.clone()),
2978 body_type: Box::new(derivation.clone()),
2979 },
2980 );
2981
2982 let try_ring_type = Term::Pi {
2985 param: "_".to_string(),
2986 param_type: Box::new(syntax),
2987 body_type: Box::new(derivation),
2988 };
2989
2990 ctx.add_declaration("try_ring", try_ring_type);
2991 }
2992
2993 fn register_try_lia(ctx: &mut Context) {
3003 let syntax = Term::Global("Syntax".to_string());
3004 let derivation = Term::Global("Derivation".to_string());
3005
3006 ctx.add_constructor(
3009 "DLiaSolve",
3010 "Derivation",
3011 Term::Pi {
3012 param: "_".to_string(),
3013 param_type: Box::new(syntax.clone()),
3014 body_type: Box::new(derivation.clone()),
3015 },
3016 );
3017
3018 let try_lia_type = Term::Pi {
3021 param: "_".to_string(),
3022 param_type: Box::new(syntax),
3023 body_type: Box::new(derivation),
3024 };
3025
3026 ctx.add_declaration("try_lia", try_lia_type);
3027 }
3028
3029 fn register_try_cc(ctx: &mut Context) {
3036 let syntax = Term::Global("Syntax".to_string());
3037 let derivation = Term::Global("Derivation".to_string());
3038
3039 ctx.add_constructor(
3042 "DccSolve",
3043 "Derivation",
3044 Term::Pi {
3045 param: "_".to_string(),
3046 param_type: Box::new(syntax.clone()),
3047 body_type: Box::new(derivation.clone()),
3048 },
3049 );
3050
3051 let try_cc_type = Term::Pi {
3054 param: "_".to_string(),
3055 param_type: Box::new(syntax),
3056 body_type: Box::new(derivation),
3057 };
3058
3059 ctx.add_declaration("try_cc", try_cc_type);
3060 }
3061
3062 fn register_try_simp(ctx: &mut Context) {
3070 let syntax = Term::Global("Syntax".to_string());
3071 let derivation = Term::Global("Derivation".to_string());
3072
3073 ctx.add_constructor(
3076 "DSimpSolve",
3077 "Derivation",
3078 Term::Pi {
3079 param: "_".to_string(),
3080 param_type: Box::new(syntax.clone()),
3081 body_type: Box::new(derivation.clone()),
3082 },
3083 );
3084
3085 let try_simp_type = Term::Pi {
3088 param: "_".to_string(),
3089 param_type: Box::new(syntax),
3090 body_type: Box::new(derivation),
3091 };
3092
3093 ctx.add_declaration("try_simp", try_simp_type);
3094 }
3095
3096 fn register_try_omega(ctx: &mut Context) {
3105 let syntax = Term::Global("Syntax".to_string());
3106 let derivation = Term::Global("Derivation".to_string());
3107
3108 ctx.add_constructor(
3111 "DOmegaSolve",
3112 "Derivation",
3113 Term::Pi {
3114 param: "_".to_string(),
3115 param_type: Box::new(syntax.clone()),
3116 body_type: Box::new(derivation.clone()),
3117 },
3118 );
3119
3120 let try_omega_type = Term::Pi {
3123 param: "_".to_string(),
3124 param_type: Box::new(syntax),
3125 body_type: Box::new(derivation),
3126 };
3127
3128 ctx.add_declaration("try_omega", try_omega_type);
3129 }
3130
3131 fn register_try_auto(ctx: &mut Context) {
3139 let syntax = Term::Global("Syntax".to_string());
3140 let derivation = Term::Global("Derivation".to_string());
3141
3142 ctx.add_constructor(
3145 "DAutoSolve",
3146 "Derivation",
3147 Term::Pi {
3148 param: "_".to_string(),
3149 param_type: Box::new(syntax.clone()),
3150 body_type: Box::new(derivation.clone()),
3151 },
3152 );
3153
3154 let try_auto_type = Term::Pi {
3157 param: "_".to_string(),
3158 param_type: Box::new(syntax),
3159 body_type: Box::new(derivation),
3160 };
3161
3162 ctx.add_declaration("try_auto", try_auto_type);
3163 }
3164
3165 fn register_try_induction(ctx: &mut Context) {
3175 let syntax = Term::Global("Syntax".to_string());
3176 let derivation = Term::Global("Derivation".to_string());
3177
3178 let try_induction_type = Term::Pi {
3180 param: "_".to_string(),
3181 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
3183 param: "_".to_string(),
3184 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
3186 param: "_".to_string(),
3187 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation),
3189 }),
3190 }),
3191 };
3192
3193 ctx.add_declaration("try_induction", try_induction_type);
3194 }
3195
3196 fn register_induction_helpers(ctx: &mut Context) {
3203 let syntax = Term::Global("Syntax".to_string());
3204 let nat = Term::Global("Nat".to_string());
3205
3206 ctx.add_declaration(
3209 "induction_base_goal",
3210 Term::Pi {
3211 param: "_".to_string(),
3212 param_type: Box::new(syntax.clone()),
3213 body_type: Box::new(Term::Pi {
3214 param: "_".to_string(),
3215 param_type: Box::new(syntax.clone()),
3216 body_type: Box::new(syntax.clone()),
3217 }),
3218 },
3219 );
3220
3221 ctx.add_declaration(
3224 "induction_step_goal",
3225 Term::Pi {
3226 param: "_".to_string(),
3227 param_type: Box::new(syntax.clone()),
3228 body_type: Box::new(Term::Pi {
3229 param: "_".to_string(),
3230 param_type: Box::new(syntax.clone()),
3231 body_type: Box::new(Term::Pi {
3232 param: "_".to_string(),
3233 param_type: Box::new(nat),
3234 body_type: Box::new(syntax.clone()),
3235 }),
3236 }),
3237 },
3238 );
3239
3240 ctx.add_declaration(
3243 "induction_num_cases",
3244 Term::Pi {
3245 param: "_".to_string(),
3246 param_type: Box::new(syntax),
3247 body_type: Box::new(Term::Global("Nat".to_string())),
3248 },
3249 );
3250 }
3251
3252 fn register_try_inversion_tactic(ctx: &mut Context) {
3266 let syntax = Term::Global("Syntax".to_string());
3267 let derivation = Term::Global("Derivation".to_string());
3268
3269 ctx.add_declaration(
3271 "try_inversion",
3272 Term::Pi {
3273 param: "_".to_string(),
3274 param_type: Box::new(syntax),
3275 body_type: Box::new(derivation),
3276 },
3277 );
3278 }
3279
3280 fn register_operator_tactics(ctx: &mut Context) {
3291 let syntax = Term::Global("Syntax".to_string());
3292 let derivation = Term::Global("Derivation".to_string());
3293
3294 ctx.add_declaration(
3297 "try_rewrite",
3298 Term::Pi {
3299 param: "_".to_string(),
3300 param_type: Box::new(derivation.clone()), body_type: Box::new(Term::Pi {
3302 param: "_".to_string(),
3303 param_type: Box::new(syntax.clone()), body_type: Box::new(derivation.clone()),
3305 }),
3306 },
3307 );
3308
3309 ctx.add_declaration(
3312 "try_rewrite_rev",
3313 Term::Pi {
3314 param: "_".to_string(),
3315 param_type: Box::new(derivation.clone()), body_type: Box::new(Term::Pi {
3317 param: "_".to_string(),
3318 param_type: Box::new(syntax.clone()), body_type: Box::new(derivation.clone()),
3320 }),
3321 },
3322 );
3323
3324 ctx.add_declaration(
3327 "try_destruct",
3328 Term::Pi {
3329 param: "_".to_string(),
3330 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
3332 param: "_".to_string(),
3333 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
3335 param: "_".to_string(),
3336 param_type: Box::new(derivation.clone()), body_type: Box::new(derivation.clone()),
3338 }),
3339 }),
3340 },
3341 );
3342
3343 ctx.add_declaration(
3346 "try_apply",
3347 Term::Pi {
3348 param: "_".to_string(),
3349 param_type: Box::new(syntax.clone()), body_type: Box::new(Term::Pi {
3351 param: "_".to_string(),
3352 param_type: Box::new(derivation.clone()), body_type: Box::new(Term::Pi {
3354 param: "_".to_string(),
3355 param_type: Box::new(syntax), body_type: Box::new(derivation),
3357 }),
3358 }),
3359 },
3360 );
3361 }
3362
3363 fn register_hw_tactics(ctx: &mut Context) {
3368 let syntax = Term::Global("Syntax".to_string());
3369 let derivation = Term::Global("Derivation".to_string());
3370
3371 ctx.add_constructor(
3373 "DBitblastSolve",
3374 "Derivation",
3375 Term::Pi {
3376 param: "_".to_string(),
3377 param_type: Box::new(syntax.clone()),
3378 body_type: Box::new(derivation.clone()),
3379 },
3380 );
3381
3382 ctx.add_declaration(
3384 "try_bitblast",
3385 Term::Pi {
3386 param: "_".to_string(),
3387 param_type: Box::new(syntax.clone()),
3388 body_type: Box::new(derivation.clone()),
3389 },
3390 );
3391
3392 ctx.add_constructor(
3394 "DTabulateSolve",
3395 "Derivation",
3396 Term::Pi {
3397 param: "_".to_string(),
3398 param_type: Box::new(syntax.clone()),
3399 body_type: Box::new(derivation.clone()),
3400 },
3401 );
3402
3403 ctx.add_declaration(
3405 "try_tabulate",
3406 Term::Pi {
3407 param: "_".to_string(),
3408 param_type: Box::new(syntax.clone()),
3409 body_type: Box::new(derivation.clone()),
3410 },
3411 );
3412
3413 ctx.add_constructor(
3415 "DHwAutoSolve",
3416 "Derivation",
3417 Term::Pi {
3418 param: "_".to_string(),
3419 param_type: Box::new(syntax.clone()),
3420 body_type: Box::new(derivation.clone()),
3421 },
3422 );
3423
3424 ctx.add_declaration(
3426 "try_hw_auto",
3427 Term::Pi {
3428 param: "_".to_string(),
3429 param_type: Box::new(syntax.clone()),
3430 body_type: Box::new(derivation),
3431 },
3432 );
3433 }
3434
3435 fn register_hardware(ctx: &mut Context) {
3441 Self::register_bit(ctx);
3442 Self::register_hw_unit(ctx);
3443 Self::register_bvec(ctx);
3444 Self::register_gate_ops(ctx);
3445 Self::register_circuit(ctx);
3446 Self::register_bvec_ops(ctx);
3447 }
3448
3449 fn register_bit(ctx: &mut Context) {
3453 let bit = Term::Global("Bit".to_string());
3454 ctx.add_inductive("Bit", Term::Sort(Universe::Type(0)));
3455 ctx.add_constructor("B0", "Bit", bit.clone());
3456 ctx.add_constructor("B1", "Bit", bit);
3457 }
3458
3459 fn register_hw_unit(ctx: &mut Context) {
3462 let unit = Term::Global("Unit".to_string());
3463 ctx.add_inductive("Unit", Term::Sort(Universe::Type(0)));
3464 ctx.add_constructor("Tt", "Unit", unit);
3465 }
3466
3467 fn register_bvec(ctx: &mut Context) {
3471 let type0 = Term::Sort(Universe::Type(0));
3472 let nat = Term::Global("Nat".to_string());
3473 let n = Term::Var("n".to_string());
3474
3475 let bvec_type = Term::Pi {
3477 param: "n".to_string(),
3478 param_type: Box::new(nat.clone()),
3479 body_type: Box::new(type0),
3480 };
3481 ctx.add_inductive("BVec", bvec_type);
3482
3483 let bvec_zero = Term::App(
3485 Box::new(Term::Global("BVec".to_string())),
3486 Box::new(Term::Global("Zero".to_string())),
3487 );
3488 ctx.add_constructor("BVNil", "BVec", bvec_zero);
3489
3490 let bit = Term::Global("Bit".to_string());
3492 let bvec_n = Term::App(
3493 Box::new(Term::Global("BVec".to_string())),
3494 Box::new(n.clone()),
3495 );
3496 let bvec_succ_n = Term::App(
3497 Box::new(Term::Global("BVec".to_string())),
3498 Box::new(Term::App(
3499 Box::new(Term::Global("Succ".to_string())),
3500 Box::new(n.clone()),
3501 )),
3502 );
3503 let bvcons_type = Term::Pi {
3504 param: "_".to_string(),
3505 param_type: Box::new(bit),
3506 body_type: Box::new(Term::Pi {
3507 param: "n".to_string(),
3508 param_type: Box::new(nat),
3509 body_type: Box::new(Term::Pi {
3510 param: "_".to_string(),
3511 param_type: Box::new(bvec_n),
3512 body_type: Box::new(bvec_succ_n),
3513 }),
3514 }),
3515 };
3516 ctx.add_constructor("BVCons", "BVec", bvcons_type);
3517 }
3518
3519 fn register_gate_ops(ctx: &mut Context) {
3527 let bit = Term::Global("Bit".to_string());
3528
3529 let bit2_type = Term::Pi {
3531 param: "_".to_string(),
3532 param_type: Box::new(bit.clone()),
3533 body_type: Box::new(Term::Pi {
3534 param: "_".to_string(),
3535 param_type: Box::new(bit.clone()),
3536 body_type: Box::new(bit.clone()),
3537 }),
3538 };
3539
3540 let bit1_type = Term::Pi {
3542 param: "_".to_string(),
3543 param_type: Box::new(bit.clone()),
3544 body_type: Box::new(bit.clone()),
3545 };
3546
3547 let bit3_type = Term::Pi {
3549 param: "_".to_string(),
3550 param_type: Box::new(bit.clone()),
3551 body_type: Box::new(Term::Pi {
3552 param: "_".to_string(),
3553 param_type: Box::new(bit.clone()),
3554 body_type: Box::new(Term::Pi {
3555 param: "_".to_string(),
3556 param_type: Box::new(bit.clone()),
3557 body_type: Box::new(bit.clone()),
3558 }),
3559 }),
3560 };
3561
3562 let motive = Term::Lambda {
3564 param: "_".to_string(),
3565 param_type: Box::new(bit.clone()),
3566 body: Box::new(bit.clone()),
3567 };
3568
3569 let bit_and_body = Term::Lambda {
3571 param: "a".to_string(),
3572 param_type: Box::new(bit.clone()),
3573 body: Box::new(Term::Lambda {
3574 param: "b".to_string(),
3575 param_type: Box::new(bit.clone()),
3576 body: Box::new(Term::Match {
3577 discriminant: Box::new(Term::Var("a".to_string())),
3578 motive: Box::new(motive.clone()),
3579 cases: vec![
3580 Term::Global("B0".to_string()), Term::Var("b".to_string()), ],
3583 }),
3584 }),
3585 };
3586 ctx.add_definition("bit_and".to_string(), bit2_type.clone(), bit_and_body);
3587
3588 let bit_or_body = Term::Lambda {
3590 param: "a".to_string(),
3591 param_type: Box::new(bit.clone()),
3592 body: Box::new(Term::Lambda {
3593 param: "b".to_string(),
3594 param_type: Box::new(bit.clone()),
3595 body: Box::new(Term::Match {
3596 discriminant: Box::new(Term::Var("a".to_string())),
3597 motive: Box::new(motive.clone()),
3598 cases: vec![
3599 Term::Var("b".to_string()), Term::Global("B1".to_string()), ],
3602 }),
3603 }),
3604 };
3605 ctx.add_definition("bit_or".to_string(), bit2_type.clone(), bit_or_body);
3606
3607 let bit_not_body = Term::Lambda {
3609 param: "a".to_string(),
3610 param_type: Box::new(bit.clone()),
3611 body: Box::new(Term::Match {
3612 discriminant: Box::new(Term::Var("a".to_string())),
3613 motive: Box::new(motive.clone()),
3614 cases: vec![
3615 Term::Global("B1".to_string()), Term::Global("B0".to_string()), ],
3618 }),
3619 };
3620 ctx.add_definition("bit_not".to_string(), bit1_type, bit_not_body);
3621
3622 let bit_xor_body = Term::Lambda {
3627 param: "a".to_string(),
3628 param_type: Box::new(bit.clone()),
3629 body: Box::new(Term::Lambda {
3630 param: "b".to_string(),
3631 param_type: Box::new(bit.clone()),
3632 body: Box::new(Term::Match {
3633 discriminant: Box::new(Term::Var("a".to_string())),
3634 motive: Box::new(motive.clone()),
3635 cases: vec![
3636 Term::Var("b".to_string()),
3638 Term::App(
3640 Box::new(Term::Global("bit_not".to_string())),
3641 Box::new(Term::Var("b".to_string())),
3642 ),
3643 ],
3644 }),
3645 }),
3646 };
3647 ctx.add_definition("bit_xor".to_string(), bit2_type, bit_xor_body);
3648
3649 let bit_mux_body = Term::Lambda {
3652 param: "sel".to_string(),
3653 param_type: Box::new(bit.clone()),
3654 body: Box::new(Term::Lambda {
3655 param: "then_v".to_string(),
3656 param_type: Box::new(bit.clone()),
3657 body: Box::new(Term::Lambda {
3658 param: "else_v".to_string(),
3659 param_type: Box::new(bit.clone()),
3660 body: Box::new(Term::Match {
3661 discriminant: Box::new(Term::Var("sel".to_string())),
3662 motive: Box::new(motive),
3663 cases: vec![
3664 Term::Var("else_v".to_string()), Term::Var("then_v".to_string()), ],
3667 }),
3668 }),
3669 }),
3670 };
3671 ctx.add_definition("bit_mux".to_string(), bit3_type, bit_mux_body);
3672 }
3673
3674 fn register_circuit(ctx: &mut Context) {
3678 let type0 = Term::Sort(Universe::Type(0));
3679 let s = Term::Var("S".to_string());
3680 let i = Term::Var("I".to_string());
3681 let o = Term::Var("O".to_string());
3682
3683 let circuit_type = Term::Pi {
3685 param: "S".to_string(),
3686 param_type: Box::new(type0.clone()),
3687 body_type: Box::new(Term::Pi {
3688 param: "I".to_string(),
3689 param_type: Box::new(type0.clone()),
3690 body_type: Box::new(Term::Pi {
3691 param: "O".to_string(),
3692 param_type: Box::new(type0.clone()),
3693 body_type: Box::new(type0.clone()),
3694 }),
3695 }),
3696 };
3697 ctx.add_inductive("Circuit", circuit_type);
3698
3699 let circuit_s_i_o = Term::App(
3701 Box::new(Term::App(
3702 Box::new(Term::App(
3703 Box::new(Term::Global("Circuit".to_string())),
3704 Box::new(s.clone()),
3705 )),
3706 Box::new(i.clone()),
3707 )),
3708 Box::new(o.clone()),
3709 );
3710
3711 let trans_type = Term::Pi {
3713 param: "_".to_string(),
3714 param_type: Box::new(s.clone()),
3715 body_type: Box::new(Term::Pi {
3716 param: "_".to_string(),
3717 param_type: Box::new(i.clone()),
3718 body_type: Box::new(s.clone()),
3719 }),
3720 };
3721
3722 let out_type = Term::Pi {
3724 param: "_".to_string(),
3725 param_type: Box::new(s.clone()),
3726 body_type: Box::new(Term::Pi {
3727 param: "_".to_string(),
3728 param_type: Box::new(i.clone()),
3729 body_type: Box::new(o.clone()),
3730 }),
3731 };
3732
3733 let mkcircuit_type = Term::Pi {
3736 param: "S".to_string(),
3737 param_type: Box::new(type0.clone()),
3738 body_type: Box::new(Term::Pi {
3739 param: "I".to_string(),
3740 param_type: Box::new(type0.clone()),
3741 body_type: Box::new(Term::Pi {
3742 param: "O".to_string(),
3743 param_type: Box::new(type0),
3744 body_type: Box::new(Term::Pi {
3745 param: "_".to_string(),
3746 param_type: Box::new(trans_type),
3747 body_type: Box::new(Term::Pi {
3748 param: "_".to_string(),
3749 param_type: Box::new(out_type),
3750 body_type: Box::new(Term::Pi {
3751 param: "_".to_string(),
3752 param_type: Box::new(s),
3753 body_type: Box::new(circuit_s_i_o),
3754 }),
3755 }),
3756 }),
3757 }),
3758 }),
3759 };
3760 ctx.add_constructor("MkCircuit", "Circuit", mkcircuit_type);
3761 }
3762
3763 fn register_bvec_ops(ctx: &mut Context) {
3766 let nat = Term::Global("Nat".to_string());
3767 let n = Term::Var("n".to_string());
3768 let bvec_n = Term::App(
3769 Box::new(Term::Global("BVec".to_string())),
3770 Box::new(n.clone()),
3771 );
3772
3773 let bv_binop_type = Term::Pi {
3775 param: "n".to_string(),
3776 param_type: Box::new(nat.clone()),
3777 body_type: Box::new(Term::Pi {
3778 param: "_".to_string(),
3779 param_type: Box::new(bvec_n.clone()),
3780 body_type: Box::new(Term::Pi {
3781 param: "_".to_string(),
3782 param_type: Box::new(bvec_n.clone()),
3783 body_type: Box::new(bvec_n.clone()),
3784 }),
3785 }),
3786 };
3787
3788 let bv_unop_type = Term::Pi {
3790 param: "n".to_string(),
3791 param_type: Box::new(nat.clone()),
3792 body_type: Box::new(Term::Pi {
3793 param: "_".to_string(),
3794 param_type: Box::new(bvec_n.clone()),
3795 body_type: Box::new(bvec_n.clone()),
3796 }),
3797 };
3798
3799 let bvec_of = |m: Term| -> Term {
3801 Term::App(Box::new(Term::Global("BVec".to_string())), Box::new(m))
3802 };
3803
3804 let motive_n = Term::Lambda {
3807 param: "_".to_string(),
3808 param_type: Box::new(bvec_n.clone()),
3809 body: Box::new(bvec_n.clone()),
3810 };
3811
3812 let bit = Term::Global("Bit".to_string());
3822
3823 let bv_and_body = Self::make_bvec_binop_fix(
3824 "bv_and_rec", "bit_and", &nat, &bvec_n, &bit, &motive_n,
3825 );
3826 ctx.add_definition("bv_and".to_string(), bv_binop_type.clone(), bv_and_body);
3827
3828 let bv_or_body = Self::make_bvec_binop_fix(
3830 "bv_or_rec", "bit_or", &nat, &bvec_n, &bit, &motive_n,
3831 );
3832 ctx.add_definition("bv_or".to_string(), bv_binop_type.clone(), bv_or_body);
3833
3834 let bv_xor_body = Self::make_bvec_binop_fix(
3836 "bv_xor_rec", "bit_xor", &nat, &bvec_n, &bit, &motive_n,
3837 );
3838 ctx.add_definition("bv_xor".to_string(), bv_binop_type, bv_xor_body);
3839
3840 let bv_not_body = Self::make_bvec_unop_fix(
3847 "bv_not_rec", "bit_not", &nat, &bvec_n, &bit, &motive_n,
3848 );
3849 ctx.add_definition("bv_not".to_string(), bv_unop_type, bv_not_body);
3850 }
3851
3852 fn make_bvec_binop_fix(
3856 rec_name: &str,
3857 bit_op: &str,
3858 nat: &Term,
3859 bvec_n: &Term,
3860 bit: &Term,
3861 motive: &Term,
3862 ) -> Term {
3863 let m_var = Term::Var("m".to_string());
3864 let bvec_m = Term::App(Box::new(Term::Global("BVec".to_string())), Box::new(m_var.clone()));
3865 let motive_m = Term::Lambda {
3866 param: "_".to_string(),
3867 param_type: Box::new(bvec_m.clone()),
3868 body: Box::new(bvec_m.clone()),
3869 };
3870
3871 let bit_op_applied = Term::App(
3873 Box::new(Term::App(
3874 Box::new(Term::Global(bit_op.to_string())),
3875 Box::new(Term::Var("b1".to_string())),
3876 )),
3877 Box::new(Term::Var("b2".to_string())),
3878 );
3879 let rec_call = Term::App(
3880 Box::new(Term::App(
3881 Box::new(Term::App(
3882 Box::new(Term::Var(rec_name.to_string())),
3883 Box::new(m_var.clone()),
3884 )),
3885 Box::new(Term::Var("tail1".to_string())),
3886 )),
3887 Box::new(Term::Var("tail2".to_string())),
3888 );
3889 let bvcons_result = Term::App(
3890 Box::new(Term::App(
3891 Box::new(Term::App(
3892 Box::new(Term::Global("BVCons".to_string())),
3893 Box::new(bit_op_applied),
3894 )),
3895 Box::new(m_var.clone()),
3896 )),
3897 Box::new(rec_call),
3898 );
3899
3900 let inner_bvcons_case = Term::Lambda {
3902 param: "b2".to_string(),
3903 param_type: Box::new(bit.clone()),
3904 body: Box::new(Term::Lambda {
3905 param: "_m2".to_string(),
3906 param_type: Box::new(nat.clone()),
3907 body: Box::new(Term::Lambda {
3908 param: "tail2".to_string(),
3909 param_type: Box::new(bvec_m.clone()),
3910 body: Box::new(bvcons_result),
3911 }),
3912 }),
3913 };
3914
3915 let inner_match = Term::Match {
3916 discriminant: Box::new(Term::Var("v2".to_string())),
3917 motive: Box::new(motive_m.clone()),
3918 cases: vec![
3919 Term::Global("BVNil".to_string()), inner_bvcons_case, ],
3922 };
3923
3924 let outer_bvcons_case = Term::Lambda {
3926 param: "b1".to_string(),
3927 param_type: Box::new(bit.clone()),
3928 body: Box::new(Term::Lambda {
3929 param: "m".to_string(),
3930 param_type: Box::new(nat.clone()),
3931 body: Box::new(Term::Lambda {
3932 param: "tail1".to_string(),
3933 param_type: Box::new(bvec_m.clone()),
3934 body: Box::new(inner_match),
3935 }),
3936 }),
3937 };
3938
3939 let outer_match = Term::Match {
3941 discriminant: Box::new(Term::Var("v1".to_string())),
3942 motive: Box::new(motive.clone()),
3943 cases: vec![
3944 Term::Global("BVNil".to_string()), outer_bvcons_case, ],
3947 };
3948
3949 Term::Fix {
3951 name: rec_name.to_string(),
3952 body: Box::new(Term::Lambda {
3953 param: "n".to_string(),
3954 param_type: Box::new(nat.clone()),
3955 body: Box::new(Term::Lambda {
3956 param: "v1".to_string(),
3957 param_type: Box::new(bvec_n.clone()),
3958 body: Box::new(Term::Lambda {
3959 param: "v2".to_string(),
3960 param_type: Box::new(bvec_n.clone()),
3961 body: Box::new(outer_match),
3962 }),
3963 }),
3964 }),
3965 }
3966 }
3967
3968 fn make_bvec_unop_fix(
3972 rec_name: &str,
3973 bit_op: &str,
3974 nat: &Term,
3975 bvec_n: &Term,
3976 bit: &Term,
3977 motive: &Term,
3978 ) -> Term {
3979 let m_var = Term::Var("m".to_string());
3980 let bvec_m = Term::App(Box::new(Term::Global("BVec".to_string())), Box::new(m_var.clone()));
3981
3982 let bit_op_applied = Term::App(
3984 Box::new(Term::Global(bit_op.to_string())),
3985 Box::new(Term::Var("b".to_string())),
3986 );
3987 let rec_call = Term::App(
3988 Box::new(Term::App(
3989 Box::new(Term::Var(rec_name.to_string())),
3990 Box::new(m_var.clone()),
3991 )),
3992 Box::new(Term::Var("tail".to_string())),
3993 );
3994 let bvcons_result = Term::App(
3995 Box::new(Term::App(
3996 Box::new(Term::App(
3997 Box::new(Term::Global("BVCons".to_string())),
3998 Box::new(bit_op_applied),
3999 )),
4000 Box::new(m_var.clone()),
4001 )),
4002 Box::new(rec_call),
4003 );
4004
4005 let bvcons_case = Term::Lambda {
4007 param: "b".to_string(),
4008 param_type: Box::new(bit.clone()),
4009 body: Box::new(Term::Lambda {
4010 param: "m".to_string(),
4011 param_type: Box::new(nat.clone()),
4012 body: Box::new(Term::Lambda {
4013 param: "tail".to_string(),
4014 param_type: Box::new(bvec_m),
4015 body: Box::new(bvcons_result),
4016 }),
4017 }),
4018 };
4019
4020 let match_expr = Term::Match {
4022 discriminant: Box::new(Term::Var("v".to_string())),
4023 motive: Box::new(motive.clone()),
4024 cases: vec![
4025 Term::Global("BVNil".to_string()), bvcons_case, ],
4028 };
4029
4030 Term::Fix {
4032 name: rec_name.to_string(),
4033 body: Box::new(Term::Lambda {
4034 param: "n".to_string(),
4035 param_type: Box::new(nat.clone()),
4036 body: Box::new(Term::Lambda {
4037 param: "v".to_string(),
4038 param_type: Box::new(bvec_n.clone()),
4039 body: Box::new(match_expr),
4040 }),
4041 }),
4042 }
4043 }
4044}