1#![allow(clippy::items_after_test_module)]
5
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7
8#[allow(dead_code)]
10pub fn app(f: Expr, a: Expr) -> Expr {
11 Expr::App(Box::new(f), Box::new(a))
12}
13#[allow(dead_code)]
15pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
16 app(app(f, a), b)
17}
18#[allow(dead_code)]
20pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
21 app(app2(f, a, b), c)
22}
23#[allow(dead_code)]
25pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
26 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
27}
28#[allow(dead_code)]
30pub fn arrow(a: Expr, b: Expr) -> Expr {
31 pi(BinderInfo::Default, "_", a, b)
32}
33#[allow(dead_code)]
35pub fn cst(s: &str) -> Expr {
36 Expr::Const(Name::str(s), vec![])
37}
38#[allow(dead_code)]
40pub fn prop() -> Expr {
41 Expr::Sort(Level::zero())
42}
43#[allow(dead_code)]
45pub fn type1() -> Expr {
46 Expr::Sort(Level::succ(Level::zero()))
47}
48#[allow(dead_code)]
50pub fn bvar(n: u32) -> Expr {
51 Expr::BVar(n)
52}
53#[allow(dead_code)]
55pub fn nat_ty() -> Expr {
56 cst("Nat")
57}
58#[allow(dead_code)]
60pub fn int_ty() -> Expr {
61 cst("Int")
62}
63#[allow(dead_code)]
65pub fn bool_ty() -> Expr {
66 cst("Bool")
67}
68#[allow(dead_code)]
70pub fn mk_bitvec(n: Expr) -> Expr {
71 app(cst("BitVec"), n)
72}
73#[allow(dead_code)]
75pub fn mk_bitvec_of_nat(n: Expr, val: Expr) -> Expr {
76 app2(cst("BitVec.ofNat"), n, val)
77}
78#[allow(dead_code)]
80pub fn mk_bitvec_zero(n: Expr) -> Expr {
81 app(cst("BitVec.zero"), n)
82}
83#[allow(dead_code)]
85pub fn mk_bitvec_and(a: Expr, b: Expr) -> Expr {
86 app2(cst("BitVec.and"), a, b)
87}
88#[allow(dead_code)]
90pub fn mk_bitvec_or(a: Expr, b: Expr) -> Expr {
91 app2(cst("BitVec.or"), a, b)
92}
93#[allow(dead_code)]
95pub fn mk_bitvec_xor(a: Expr, b: Expr) -> Expr {
96 app2(cst("BitVec.xor"), a, b)
97}
98#[allow(dead_code)]
100pub fn mk_bitvec_add(a: Expr, b: Expr) -> Expr {
101 app2(cst("BitVec.add"), a, b)
102}
103#[allow(dead_code)]
105pub fn mk_bitvec_sub(a: Expr, b: Expr) -> Expr {
106 app2(cst("BitVec.sub"), a, b)
107}
108#[allow(dead_code)]
110pub fn mk_bitvec_mul(a: Expr, b: Expr) -> Expr {
111 app2(cst("BitVec.mul"), a, b)
112}
113#[allow(dead_code)]
115pub fn mk_eq(ty: Expr, a: Expr, b: Expr) -> Expr {
116 app3(cst("Eq"), ty, a, b)
117}
118#[allow(dead_code)]
120pub fn mk_bv_eq(n: Expr, a: Expr, b: Expr) -> Expr {
121 mk_eq(mk_bitvec(n), a, b)
122}
123#[allow(dead_code)]
125pub fn mk_iff(a: Expr, b: Expr) -> Expr {
126 app2(cst("Iff"), a, b)
127}
128#[allow(dead_code)]
130pub fn mk_nat_eq(a: Expr, b: Expr) -> Expr {
131 mk_eq(nat_ty(), a, b)
132}
133#[allow(dead_code)]
134pub fn add_axiom(
135 env: &mut Environment,
136 name: &str,
137 univ_params: Vec<Name>,
138 ty: Expr,
139) -> Result<(), String> {
140 env.add(Declaration::Axiom {
141 name: Name::str(name),
142 univ_params,
143 ty,
144 })
145 .map_err(|e| e.to_string())
146}
147#[allow(dead_code)]
149pub fn bitvec_binop_ty() -> Expr {
150 pi(
151 BinderInfo::Implicit,
152 "n",
153 nat_ty(),
154 arrow(
155 mk_bitvec(bvar(0)),
156 arrow(mk_bitvec(bvar(1)), mk_bitvec(bvar(2))),
157 ),
158 )
159}
160#[allow(dead_code)]
162pub fn bitvec_unop_ty() -> Expr {
163 pi(
164 BinderInfo::Implicit,
165 "n",
166 nat_ty(),
167 arrow(mk_bitvec(bvar(0)), mk_bitvec(bvar(1))),
168 )
169}
170#[allow(dead_code)]
172pub fn bitvec_shift_ty() -> Expr {
173 pi(
174 BinderInfo::Implicit,
175 "n",
176 nat_ty(),
177 arrow(mk_bitvec(bvar(0)), arrow(nat_ty(), mk_bitvec(bvar(1)))),
178 )
179}
180#[allow(dead_code)]
182pub fn bitvec_cmp_ty() -> Expr {
183 pi(
184 BinderInfo::Implicit,
185 "n",
186 nat_ty(),
187 arrow(mk_bitvec(bvar(0)), arrow(mk_bitvec(bvar(1)), bool_ty())),
188 )
189}
190#[allow(dead_code)]
192pub fn bitvec_getbit_ty() -> Expr {
193 pi(
194 BinderInfo::Implicit,
195 "n",
196 nat_ty(),
197 arrow(mk_bitvec(bvar(0)), arrow(nat_ty(), bool_ty())),
198 )
199}
200#[allow(clippy::too_many_lines)]
205pub fn build_bitvec_env(env: &mut Environment) -> Result<(), String> {
206 add_axiom(env, "BitVec", vec![], arrow(nat_ty(), type1()))?;
207 let of_nat_ty = pi(
208 BinderInfo::Default,
209 "n",
210 nat_ty(),
211 arrow(nat_ty(), mk_bitvec(bvar(0))),
212 );
213 add_axiom(env, "BitVec.ofNat", vec![], of_nat_ty)?;
214 let to_nat_ty = pi(
215 BinderInfo::Implicit,
216 "n",
217 nat_ty(),
218 arrow(mk_bitvec(bvar(0)), nat_ty()),
219 );
220 add_axiom(env, "BitVec.toNat", vec![], to_nat_ty)?;
221 let of_bool_ty = arrow(bool_ty(), mk_bitvec(app(cst("Nat.succ"), cst("Nat.zero"))));
222 add_axiom(env, "BitVec.ofBool", vec![], of_bool_ty)?;
223 let zero_ty = pi(BinderInfo::Default, "n", nat_ty(), mk_bitvec(bvar(0)));
224 add_axiom(env, "BitVec.zero", vec![], zero_ty)?;
225 let all_ones_ty = pi(BinderInfo::Default, "n", nat_ty(), mk_bitvec(bvar(0)));
226 add_axiom(env, "BitVec.allOnes", vec![], all_ones_ty)?;
227 add_axiom(env, "BitVec.and", vec![], bitvec_binop_ty())?;
228 add_axiom(env, "BitVec.or", vec![], bitvec_binop_ty())?;
229 add_axiom(env, "BitVec.xor", vec![], bitvec_binop_ty())?;
230 add_axiom(env, "BitVec.not", vec![], bitvec_unop_ty())?;
231 add_axiom(env, "BitVec.shiftLeft", vec![], bitvec_shift_ty())?;
232 add_axiom(env, "BitVec.shiftRight", vec![], bitvec_shift_ty())?;
233 add_axiom(env, "BitVec.add", vec![], bitvec_binop_ty())?;
234 add_axiom(env, "BitVec.sub", vec![], bitvec_binop_ty())?;
235 add_axiom(env, "BitVec.mul", vec![], bitvec_binop_ty())?;
236 add_axiom(env, "BitVec.neg", vec![], bitvec_unop_ty())?;
237 add_axiom(env, "BitVec.udiv", vec![], bitvec_binop_ty())?;
238 add_axiom(env, "BitVec.umod", vec![], bitvec_binop_ty())?;
239 add_axiom(env, "BitVec.sdiv", vec![], bitvec_binop_ty())?;
240 add_axiom(env, "BitVec.smod", vec![], bitvec_binop_ty())?;
241 add_axiom(env, "BitVec.ult", vec![], bitvec_cmp_ty())?;
242 add_axiom(env, "BitVec.ule", vec![], bitvec_cmp_ty())?;
243 add_axiom(env, "BitVec.slt", vec![], bitvec_cmp_ty())?;
244 add_axiom(env, "BitVec.sle", vec![], bitvec_cmp_ty())?;
245 add_axiom(env, "BitVec.beq", vec![], bitvec_cmp_ty())?;
246 add_axiom(env, "BitVec.getLsb", vec![], bitvec_getbit_ty())?;
247 add_axiom(env, "BitVec.getMsb", vec![], bitvec_getbit_ty())?;
248 let set_width_ty = pi(
249 BinderInfo::Implicit,
250 "n",
251 nat_ty(),
252 pi(
253 BinderInfo::Default,
254 "m",
255 nat_ty(),
256 arrow(mk_bitvec(bvar(1)), mk_bitvec(bvar(0))),
257 ),
258 );
259 add_axiom(env, "BitVec.setWidth", vec![], set_width_ty)?;
260 let append_ty = pi(
261 BinderInfo::Implicit,
262 "n",
263 nat_ty(),
264 pi(
265 BinderInfo::Implicit,
266 "m",
267 nat_ty(),
268 arrow(
269 mk_bitvec(bvar(1)),
270 arrow(
271 mk_bitvec(bvar(1)),
272 mk_bitvec(app2(cst("Nat.add"), bvar(3), bvar(2))),
273 ),
274 ),
275 ),
276 );
277 add_axiom(env, "BitVec.append", vec![], append_ty)?;
278 let extract_lsb_ty = pi(
279 BinderInfo::Implicit,
280 "n",
281 nat_ty(),
282 pi(
283 BinderInfo::Default,
284 "hi",
285 nat_ty(),
286 pi(
287 BinderInfo::Default,
288 "lo",
289 nat_ty(),
290 arrow(
291 mk_bitvec(bvar(2)),
292 mk_bitvec(app2(
293 cst("Nat.add"),
294 app2(cst("Nat.sub"), bvar(2), bvar(1)),
295 app(cst("Nat.succ"), cst("Nat.zero")),
296 )),
297 ),
298 ),
299 ),
300 );
301 add_axiom(env, "BitVec.extractLsb", vec![], extract_lsb_ty)?;
302 let replicate_ty = pi(
303 BinderInfo::Implicit,
304 "n",
305 nat_ty(),
306 pi(
307 BinderInfo::Default,
308 "k",
309 nat_ty(),
310 arrow(
311 mk_bitvec(bvar(1)),
312 mk_bitvec(app2(cst("Nat.mul"), bvar(1), bvar(2))),
313 ),
314 ),
315 );
316 add_axiom(env, "BitVec.replicate", vec![], replicate_ty)?;
317 add_axiom(env, "BitVec.rotateLeft", vec![], bitvec_shift_ty())?;
318 add_axiom(env, "BitVec.rotateRight", vec![], bitvec_shift_ty())?;
319 let sign_extend_ty = pi(
320 BinderInfo::Implicit,
321 "n",
322 nat_ty(),
323 pi(
324 BinderInfo::Default,
325 "m",
326 nat_ty(),
327 arrow(mk_bitvec(bvar(1)), mk_bitvec(bvar(0))),
328 ),
329 );
330 add_axiom(env, "BitVec.signExtend", vec![], sign_extend_ty)?;
331 let to_int_ty = pi(
332 BinderInfo::Implicit,
333 "n",
334 nat_ty(),
335 arrow(mk_bitvec(bvar(0)), int_ty()),
336 );
337 add_axiom(env, "BitVec.toInt", vec![], to_int_ty)?;
338 let of_int_ty = pi(
339 BinderInfo::Default,
340 "n",
341 nat_ty(),
342 arrow(int_ty(), mk_bitvec(bvar(0))),
343 );
344 add_axiom(env, "BitVec.ofInt", vec![], of_int_ty)?;
345 let add_comm_ty = pi(
346 BinderInfo::Implicit,
347 "n",
348 nat_ty(),
349 pi(
350 BinderInfo::Default,
351 "a",
352 mk_bitvec(bvar(0)),
353 pi(
354 BinderInfo::Default,
355 "b",
356 mk_bitvec(bvar(1)),
357 mk_bv_eq(
358 bvar(2),
359 app2(cst("BitVec.add"), bvar(1), bvar(0)),
360 app2(cst("BitVec.add"), bvar(0), bvar(1)),
361 ),
362 ),
363 ),
364 );
365 add_axiom(env, "BitVec.add_comm", vec![], add_comm_ty)?;
366 let add_assoc_ty = pi(
367 BinderInfo::Implicit,
368 "n",
369 nat_ty(),
370 pi(
371 BinderInfo::Default,
372 "a",
373 mk_bitvec(bvar(0)),
374 pi(
375 BinderInfo::Default,
376 "b",
377 mk_bitvec(bvar(1)),
378 pi(
379 BinderInfo::Default,
380 "c",
381 mk_bitvec(bvar(2)),
382 mk_bv_eq(
383 bvar(3),
384 app2(
385 cst("BitVec.add"),
386 app2(cst("BitVec.add"), bvar(2), bvar(1)),
387 bvar(0),
388 ),
389 app2(
390 cst("BitVec.add"),
391 bvar(2),
392 app2(cst("BitVec.add"), bvar(1), bvar(0)),
393 ),
394 ),
395 ),
396 ),
397 ),
398 );
399 add_axiom(env, "BitVec.add_assoc", vec![], add_assoc_ty)?;
400 let add_zero_ty = pi(
401 BinderInfo::Implicit,
402 "n",
403 nat_ty(),
404 pi(
405 BinderInfo::Default,
406 "a",
407 mk_bitvec(bvar(0)),
408 mk_bv_eq(
409 bvar(1),
410 app2(cst("BitVec.add"), bvar(0), app(cst("BitVec.zero"), bvar(1))),
411 bvar(0),
412 ),
413 ),
414 );
415 add_axiom(env, "BitVec.add_zero", vec![], add_zero_ty)?;
416 let zero_add_ty = pi(
417 BinderInfo::Implicit,
418 "n",
419 nat_ty(),
420 pi(
421 BinderInfo::Default,
422 "a",
423 mk_bitvec(bvar(0)),
424 mk_bv_eq(
425 bvar(1),
426 app2(cst("BitVec.add"), app(cst("BitVec.zero"), bvar(1)), bvar(0)),
427 bvar(0),
428 ),
429 ),
430 );
431 add_axiom(env, "BitVec.zero_add", vec![], zero_add_ty)?;
432 let and_comm_ty = pi(
433 BinderInfo::Implicit,
434 "n",
435 nat_ty(),
436 pi(
437 BinderInfo::Default,
438 "a",
439 mk_bitvec(bvar(0)),
440 pi(
441 BinderInfo::Default,
442 "b",
443 mk_bitvec(bvar(1)),
444 mk_bv_eq(
445 bvar(2),
446 app2(cst("BitVec.and"), bvar(1), bvar(0)),
447 app2(cst("BitVec.and"), bvar(0), bvar(1)),
448 ),
449 ),
450 ),
451 );
452 add_axiom(env, "BitVec.and_comm", vec![], and_comm_ty)?;
453 let and_assoc_ty = pi(
454 BinderInfo::Implicit,
455 "n",
456 nat_ty(),
457 pi(
458 BinderInfo::Default,
459 "a",
460 mk_bitvec(bvar(0)),
461 pi(
462 BinderInfo::Default,
463 "b",
464 mk_bitvec(bvar(1)),
465 pi(
466 BinderInfo::Default,
467 "c",
468 mk_bitvec(bvar(2)),
469 mk_bv_eq(
470 bvar(3),
471 app2(
472 cst("BitVec.and"),
473 app2(cst("BitVec.and"), bvar(2), bvar(1)),
474 bvar(0),
475 ),
476 app2(
477 cst("BitVec.and"),
478 bvar(2),
479 app2(cst("BitVec.and"), bvar(1), bvar(0)),
480 ),
481 ),
482 ),
483 ),
484 ),
485 );
486 add_axiom(env, "BitVec.and_assoc", vec![], and_assoc_ty)?;
487 let or_comm_ty = pi(
488 BinderInfo::Implicit,
489 "n",
490 nat_ty(),
491 pi(
492 BinderInfo::Default,
493 "a",
494 mk_bitvec(bvar(0)),
495 pi(
496 BinderInfo::Default,
497 "b",
498 mk_bitvec(bvar(1)),
499 mk_bv_eq(
500 bvar(2),
501 app2(cst("BitVec.or"), bvar(1), bvar(0)),
502 app2(cst("BitVec.or"), bvar(0), bvar(1)),
503 ),
504 ),
505 ),
506 );
507 add_axiom(env, "BitVec.or_comm", vec![], or_comm_ty)?;
508 let or_assoc_ty = pi(
509 BinderInfo::Implicit,
510 "n",
511 nat_ty(),
512 pi(
513 BinderInfo::Default,
514 "a",
515 mk_bitvec(bvar(0)),
516 pi(
517 BinderInfo::Default,
518 "b",
519 mk_bitvec(bvar(1)),
520 pi(
521 BinderInfo::Default,
522 "c",
523 mk_bitvec(bvar(2)),
524 mk_bv_eq(
525 bvar(3),
526 app2(
527 cst("BitVec.or"),
528 app2(cst("BitVec.or"), bvar(2), bvar(1)),
529 bvar(0),
530 ),
531 app2(
532 cst("BitVec.or"),
533 bvar(2),
534 app2(cst("BitVec.or"), bvar(1), bvar(0)),
535 ),
536 ),
537 ),
538 ),
539 ),
540 );
541 add_axiom(env, "BitVec.or_assoc", vec![], or_assoc_ty)?;
542 let xor_self_ty = pi(
543 BinderInfo::Implicit,
544 "n",
545 nat_ty(),
546 pi(
547 BinderInfo::Default,
548 "a",
549 mk_bitvec(bvar(0)),
550 mk_bv_eq(
551 bvar(1),
552 app2(cst("BitVec.xor"), bvar(0), bvar(0)),
553 app(cst("BitVec.zero"), bvar(1)),
554 ),
555 ),
556 );
557 add_axiom(env, "BitVec.xor_self", vec![], xor_self_ty)?;
558 let and_self_ty = pi(
559 BinderInfo::Implicit,
560 "n",
561 nat_ty(),
562 pi(
563 BinderInfo::Default,
564 "a",
565 mk_bitvec(bvar(0)),
566 mk_bv_eq(bvar(1), app2(cst("BitVec.and"), bvar(0), bvar(0)), bvar(0)),
567 ),
568 );
569 add_axiom(env, "BitVec.and_self", vec![], and_self_ty)?;
570 let or_self_ty = pi(
571 BinderInfo::Implicit,
572 "n",
573 nat_ty(),
574 pi(
575 BinderInfo::Default,
576 "a",
577 mk_bitvec(bvar(0)),
578 mk_bv_eq(bvar(1), app2(cst("BitVec.or"), bvar(0), bvar(0)), bvar(0)),
579 ),
580 );
581 add_axiom(env, "BitVec.or_self", vec![], or_self_ty)?;
582 let not_not_ty = pi(
583 BinderInfo::Implicit,
584 "n",
585 nat_ty(),
586 pi(
587 BinderInfo::Default,
588 "a",
589 mk_bitvec(bvar(0)),
590 mk_bv_eq(
591 bvar(1),
592 app(cst("BitVec.not"), app(cst("BitVec.not"), bvar(0))),
593 bvar(0),
594 ),
595 ),
596 );
597 add_axiom(env, "BitVec.not_not", vec![], not_not_ty)?;
598 let demorgan_and_ty = pi(
599 BinderInfo::Implicit,
600 "n",
601 nat_ty(),
602 pi(
603 BinderInfo::Default,
604 "a",
605 mk_bitvec(bvar(0)),
606 pi(
607 BinderInfo::Default,
608 "b",
609 mk_bitvec(bvar(1)),
610 mk_bv_eq(
611 bvar(2),
612 app(cst("BitVec.not"), app2(cst("BitVec.and"), bvar(1), bvar(0))),
613 app2(
614 cst("BitVec.or"),
615 app(cst("BitVec.not"), bvar(1)),
616 app(cst("BitVec.not"), bvar(0)),
617 ),
618 ),
619 ),
620 ),
621 );
622 add_axiom(env, "BitVec.demorgan_and", vec![], demorgan_and_ty)?;
623 let demorgan_or_ty = pi(
624 BinderInfo::Implicit,
625 "n",
626 nat_ty(),
627 pi(
628 BinderInfo::Default,
629 "a",
630 mk_bitvec(bvar(0)),
631 pi(
632 BinderInfo::Default,
633 "b",
634 mk_bitvec(bvar(1)),
635 mk_bv_eq(
636 bvar(2),
637 app(cst("BitVec.not"), app2(cst("BitVec.or"), bvar(1), bvar(0))),
638 app2(
639 cst("BitVec.and"),
640 app(cst("BitVec.not"), bvar(1)),
641 app(cst("BitVec.not"), bvar(0)),
642 ),
643 ),
644 ),
645 ),
646 );
647 add_axiom(env, "BitVec.demorgan_or", vec![], demorgan_or_ty)?;
648 let to_nat_of_nat_ty = pi(
649 BinderInfo::Default,
650 "n",
651 nat_ty(),
652 pi(
653 BinderInfo::Default,
654 "val",
655 nat_ty(),
656 mk_nat_eq(
657 app(
658 cst("BitVec.toNat"),
659 app2(cst("BitVec.ofNat"), bvar(1), bvar(0)),
660 ),
661 app2(
662 cst("Nat.mod"),
663 bvar(0),
664 app2(
665 cst("Nat.pow"),
666 app(cst("Nat.succ"), app(cst("Nat.succ"), cst("Nat.zero"))),
667 bvar(1),
668 ),
669 ),
670 ),
671 ),
672 );
673 add_axiom(env, "BitVec.toNat_ofNat", vec![], to_nat_of_nat_ty)?;
674 let of_nat_to_nat_ty = pi(
675 BinderInfo::Implicit,
676 "n",
677 nat_ty(),
678 pi(
679 BinderInfo::Default,
680 "v",
681 mk_bitvec(bvar(0)),
682 mk_bv_eq(
683 bvar(1),
684 app2(
685 cst("BitVec.ofNat"),
686 bvar(1),
687 app(cst("BitVec.toNat"), bvar(0)),
688 ),
689 bvar(0),
690 ),
691 ),
692 );
693 add_axiom(env, "BitVec.ofNat_toNat", vec![], of_nat_to_nat_ty)?;
694 Ok(())
695}
696#[cfg(test)]
697mod tests {
698 use super::*;
699 fn setup_env() -> Environment {
701 let mut env = Environment::new();
702 env.add(Declaration::Axiom {
703 name: Name::str("Nat"),
704 univ_params: vec![],
705 ty: type1(),
706 })
707 .expect("operation should succeed");
708 for name in &[
709 "Nat.zero", "Nat.succ", "Nat.add", "Nat.mul", "Nat.sub", "Nat.mod", "Nat.pow",
710 ] {
711 env.add(Declaration::Axiom {
712 name: Name::str(*name),
713 univ_params: vec![],
714 ty: nat_ty(),
715 })
716 .expect("operation should succeed");
717 }
718 env.add(Declaration::Axiom {
719 name: Name::str("Int"),
720 univ_params: vec![],
721 ty: type1(),
722 })
723 .expect("operation should succeed");
724 env.add(Declaration::Axiom {
725 name: Name::str("Bool"),
726 univ_params: vec![],
727 ty: type1(),
728 })
729 .expect("operation should succeed");
730 for name in &["true", "false"] {
731 env.add(Declaration::Axiom {
732 name: Name::str(*name),
733 univ_params: vec![],
734 ty: bool_ty(),
735 })
736 .expect("operation should succeed");
737 }
738 env.add(Declaration::Axiom {
739 name: Name::str("Eq"),
740 univ_params: vec![],
741 ty: prop(),
742 })
743 .expect("operation should succeed");
744 env.add(Declaration::Axiom {
745 name: Name::str("Iff"),
746 univ_params: vec![],
747 ty: prop(),
748 })
749 .expect("operation should succeed");
750 env
751 }
752 fn full_env() -> Environment {
754 let mut env = setup_env();
755 build_bitvec_env(&mut env).expect("build_bitvec_env should succeed");
756 env
757 }
758 #[test]
759 fn test_build_bitvec_env_succeeds() {
760 let _ = full_env();
761 }
762 #[test]
763 fn test_bitvec_type_present() {
764 let env = full_env();
765 assert!(env.contains(&Name::str("BitVec")));
766 }
767 #[test]
768 fn test_bitvec_constructors_present() {
769 let env = full_env();
770 let names = [
771 "BitVec.ofNat",
772 "BitVec.toNat",
773 "BitVec.ofBool",
774 "BitVec.zero",
775 "BitVec.allOnes",
776 ];
777 for name in &names {
778 assert!(
779 env.contains(&Name::str(*name)),
780 "missing constructor: {}",
781 name
782 );
783 }
784 }
785 #[test]
786 fn test_bitvec_bitwise_ops_present() {
787 let env = full_env();
788 let names = [
789 "BitVec.and",
790 "BitVec.or",
791 "BitVec.xor",
792 "BitVec.not",
793 "BitVec.shiftLeft",
794 "BitVec.shiftRight",
795 ];
796 for name in &names {
797 assert!(
798 env.contains(&Name::str(*name)),
799 "missing bitwise op: {}",
800 name
801 );
802 }
803 }
804 #[test]
805 fn test_bitvec_arithmetic_ops_present() {
806 let env = full_env();
807 let names = [
808 "BitVec.add",
809 "BitVec.sub",
810 "BitVec.mul",
811 "BitVec.neg",
812 "BitVec.udiv",
813 "BitVec.umod",
814 "BitVec.sdiv",
815 "BitVec.smod",
816 ];
817 for name in &names {
818 assert!(
819 env.contains(&Name::str(*name)),
820 "missing arith op: {}",
821 name
822 );
823 }
824 }
825 #[test]
826 fn test_bitvec_comparison_ops_present() {
827 let env = full_env();
828 let names = [
829 "BitVec.ult",
830 "BitVec.ule",
831 "BitVec.slt",
832 "BitVec.sle",
833 "BitVec.beq",
834 ];
835 for name in &names {
836 assert!(
837 env.contains(&Name::str(*name)),
838 "missing comparison: {}",
839 name
840 );
841 }
842 }
843 #[test]
844 fn test_bitvec_bit_ops_present() {
845 let env = full_env();
846 let names = [
847 "BitVec.getLsb",
848 "BitVec.getMsb",
849 "BitVec.setWidth",
850 "BitVec.append",
851 "BitVec.extractLsb",
852 "BitVec.replicate",
853 "BitVec.rotateLeft",
854 "BitVec.rotateRight",
855 "BitVec.signExtend",
856 ];
857 for name in &names {
858 assert!(env.contains(&Name::str(*name)), "missing bit op: {}", name);
859 }
860 }
861 #[test]
862 fn test_bitvec_conversion_present() {
863 let env = full_env();
864 let names = ["BitVec.toInt", "BitVec.ofInt"];
865 for name in &names {
866 assert!(
867 env.contains(&Name::str(*name)),
868 "missing conversion: {}",
869 name
870 );
871 }
872 }
873 #[test]
874 fn test_bitvec_theorems_present() {
875 let env = full_env();
876 let names = [
877 "BitVec.add_comm",
878 "BitVec.add_assoc",
879 "BitVec.add_zero",
880 "BitVec.zero_add",
881 "BitVec.and_comm",
882 "BitVec.and_assoc",
883 "BitVec.or_comm",
884 "BitVec.or_assoc",
885 "BitVec.xor_self",
886 "BitVec.and_self",
887 "BitVec.or_self",
888 "BitVec.not_not",
889 "BitVec.demorgan_and",
890 "BitVec.demorgan_or",
891 "BitVec.toNat_ofNat",
892 "BitVec.ofNat_toNat",
893 ];
894 for name in &names {
895 assert!(env.contains(&Name::str(*name)), "missing theorem: {}", name);
896 }
897 }
898 #[test]
899 fn test_bitvec_type_is_arrow() {
900 let env = full_env();
901 let decl = env
902 .get(&Name::str("BitVec"))
903 .expect("declaration 'BitVec' should exist in env");
904 let ty = decl.ty();
905 assert!(ty.is_pi());
906 }
907 #[test]
908 fn test_bitvec_of_nat_type_is_pi() {
909 let env = full_env();
910 let decl = env
911 .get(&Name::str("BitVec.ofNat"))
912 .expect("declaration 'BitVec.ofNat' should exist in env");
913 let ty = decl.ty();
914 assert!(ty.is_pi());
915 }
916 #[test]
917 fn test_bitvec_and_type_is_pi() {
918 let env = full_env();
919 let decl = env
920 .get(&Name::str("BitVec.and"))
921 .expect("declaration 'BitVec.and' should exist in env");
922 let ty = decl.ty();
923 assert!(ty.is_pi());
924 if let Expr::Pi(bi, _, dom, _) = ty {
925 assert_eq!(*bi, BinderInfo::Implicit);
926 assert_eq!(**dom, nat_ty());
927 }
928 }
929 #[test]
930 fn test_bitvec_add_type_is_pi() {
931 let env = full_env();
932 let decl = env
933 .get(&Name::str("BitVec.add"))
934 .expect("declaration 'BitVec.add' should exist in env");
935 let ty = decl.ty();
936 assert!(ty.is_pi());
937 }
938 #[test]
939 fn test_bitvec_ult_type_is_pi() {
940 let env = full_env();
941 let decl = env
942 .get(&Name::str("BitVec.ult"))
943 .expect("declaration 'BitVec.ult' should exist in env");
944 let ty = decl.ty();
945 assert!(ty.is_pi());
946 }
947 #[test]
948 fn test_bitvec_get_lsb_type_is_pi() {
949 let env = full_env();
950 let decl = env
951 .get(&Name::str("BitVec.getLsb"))
952 .expect("declaration 'BitVec.getLsb' should exist in env");
953 let ty = decl.ty();
954 assert!(ty.is_pi());
955 }
956 #[test]
957 fn test_bitvec_to_int_type_is_pi() {
958 let env = full_env();
959 let decl = env
960 .get(&Name::str("BitVec.toInt"))
961 .expect("declaration 'BitVec.toInt' should exist in env");
962 let ty = decl.ty();
963 assert!(ty.is_pi());
964 }
965 #[test]
966 fn test_bitvec_add_comm_type_is_pi() {
967 let env = full_env();
968 let decl = env
969 .get(&Name::str("BitVec.add_comm"))
970 .expect("declaration 'BitVec.add_comm' should exist in env");
971 let ty = decl.ty();
972 assert!(ty.is_pi());
973 }
974 #[test]
975 fn test_bitvec_not_not_type_is_pi() {
976 let env = full_env();
977 let decl = env
978 .get(&Name::str("BitVec.not_not"))
979 .expect("declaration 'BitVec.not_not' should exist in env");
980 let ty = decl.ty();
981 assert!(ty.is_pi());
982 }
983 #[test]
984 fn test_bitvec_append_type_is_pi() {
985 let env = full_env();
986 let decl = env
987 .get(&Name::str("BitVec.append"))
988 .expect("declaration 'BitVec.append' should exist in env");
989 let ty = decl.ty();
990 assert!(ty.is_pi());
991 }
992 #[test]
993 fn test_mk_bitvec_structure() {
994 let e = mk_bitvec(cst("n"));
995 if let Expr::App(f, arg) = &e {
996 assert_eq!(**f, cst("BitVec"));
997 assert_eq!(**arg, cst("n"));
998 } else {
999 panic!("expected App");
1000 }
1001 }
1002 #[test]
1003 fn test_mk_bitvec_of_nat_structure() {
1004 let e = mk_bitvec_of_nat(cst("n"), cst("val"));
1005 assert!(e.is_app());
1006 }
1007 #[test]
1008 fn test_mk_bitvec_zero_structure() {
1009 let e = mk_bitvec_zero(cst("n"));
1010 if let Expr::App(f, arg) = &e {
1011 assert_eq!(**f, cst("BitVec.zero"));
1012 assert_eq!(**arg, cst("n"));
1013 } else {
1014 panic!("expected App");
1015 }
1016 }
1017 #[test]
1018 fn test_mk_bitvec_and_structure() {
1019 let e = mk_bitvec_and(cst("a"), cst("b"));
1020 assert!(e.is_app());
1021 }
1022 #[test]
1023 fn test_mk_bitvec_or_structure() {
1024 let e = mk_bitvec_or(cst("a"), cst("b"));
1025 assert!(e.is_app());
1026 }
1027 #[test]
1028 fn test_mk_bitvec_xor_structure() {
1029 let e = mk_bitvec_xor(cst("a"), cst("b"));
1030 assert!(e.is_app());
1031 }
1032 #[test]
1033 fn test_mk_bitvec_add_structure() {
1034 let e = mk_bitvec_add(cst("a"), cst("b"));
1035 assert!(e.is_app());
1036 }
1037 #[test]
1038 fn test_mk_bitvec_sub_structure() {
1039 let e = mk_bitvec_sub(cst("a"), cst("b"));
1040 assert!(e.is_app());
1041 }
1042 #[test]
1043 fn test_mk_bitvec_mul_structure() {
1044 let e = mk_bitvec_mul(cst("a"), cst("b"));
1045 assert!(e.is_app());
1046 }
1047 #[test]
1048 fn test_total_declaration_count() {
1049 let env = full_env();
1050 let prereq_count = 13;
1051 assert!(
1052 env.len() >= prereq_count + 52,
1053 "expected at least {} declarations, got {}",
1054 prereq_count + 52,
1055 env.len()
1056 );
1057 }
1058 #[test]
1059 fn test_bitvec_set_width_type_structure() {
1060 let env = full_env();
1061 let decl = env
1062 .get(&Name::str("BitVec.setWidth"))
1063 .expect("declaration 'BitVec.setWidth' should exist in env");
1064 let ty = decl.ty();
1065 assert!(ty.is_pi());
1066 if let Expr::Pi(bi, _, dom, _) = ty {
1067 assert_eq!(*bi, BinderInfo::Implicit);
1068 assert_eq!(**dom, nat_ty());
1069 }
1070 }
1071 #[test]
1072 fn test_bitvec_sign_extend_type_structure() {
1073 let env = full_env();
1074 let decl = env
1075 .get(&Name::str("BitVec.signExtend"))
1076 .expect("declaration 'BitVec.signExtend' should exist in env");
1077 let ty = decl.ty();
1078 assert!(ty.is_pi());
1079 }
1080 #[test]
1081 fn test_bitvec_of_bool_type_structure() {
1082 let env = full_env();
1083 let decl = env
1084 .get(&Name::str("BitVec.ofBool"))
1085 .expect("declaration 'BitVec.ofBool' should exist in env");
1086 let ty = decl.ty();
1087 assert!(ty.is_pi());
1088 if let Expr::Pi(_, _, dom, _) = ty {
1089 assert_eq!(**dom, bool_ty());
1090 }
1091 }
1092}
1093#[allow(dead_code)]
1095pub fn bvx_ext_forall_two(body_builder: impl Fn() -> Expr) -> Expr {
1096 pi(
1097 BinderInfo::Implicit,
1098 "n",
1099 nat_ty(),
1100 pi(
1101 BinderInfo::Default,
1102 "a",
1103 mk_bitvec(bvar(0)),
1104 pi(BinderInfo::Default, "b", mk_bitvec(bvar(1)), body_builder()),
1105 ),
1106 )
1107}
1108#[allow(dead_code)]
1110pub fn bvx_ext_forall_one(body_builder: impl Fn() -> Expr) -> Expr {
1111 pi(
1112 BinderInfo::Implicit,
1113 "n",
1114 nat_ty(),
1115 pi(BinderInfo::Default, "a", mk_bitvec(bvar(0)), body_builder()),
1116 )
1117}
1118#[allow(dead_code)]
1120pub fn bvx_ext_forall_three(body_builder: impl Fn() -> Expr) -> Expr {
1121 pi(
1122 BinderInfo::Implicit,
1123 "n",
1124 nat_ty(),
1125 pi(
1126 BinderInfo::Default,
1127 "a",
1128 mk_bitvec(bvar(0)),
1129 pi(
1130 BinderInfo::Default,
1131 "b",
1132 mk_bitvec(bvar(1)),
1133 pi(BinderInfo::Default, "c", mk_bitvec(bvar(2)), body_builder()),
1134 ),
1135 ),
1136 )
1137}
1138#[allow(dead_code)]
1140pub fn bvx_ext_forall_bv_nat(body_builder: impl Fn() -> Expr) -> Expr {
1141 pi(
1142 BinderInfo::Implicit,
1143 "n",
1144 nat_ty(),
1145 pi(
1146 BinderInfo::Default,
1147 "a",
1148 mk_bitvec(bvar(0)),
1149 pi(BinderInfo::Default, "k", nat_ty(), body_builder()),
1150 ),
1151 )
1152}
1153#[allow(dead_code)]
1155pub fn bvx_ext_forall_nat_bv(body_builder: impl Fn() -> Expr) -> Expr {
1156 pi(
1157 BinderInfo::Default,
1158 "n",
1159 nat_ty(),
1160 pi(BinderInfo::Default, "a", mk_bitvec(bvar(0)), body_builder()),
1161 )
1162}
1163#[allow(dead_code)]
1165pub fn bvx_ext_bveq(n_idx: u32, a_idx: u32, b_idx: u32) -> Expr {
1166 mk_bv_eq(bvar(n_idx), bvar(a_idx), bvar(b_idx))
1167}
1168#[allow(dead_code)]
1170pub fn bvx_ext_nateq(lhs: Expr, rhs: Expr) -> Expr {
1171 mk_nat_eq(lhs, rhs)
1172}
1173#[allow(dead_code)]
1175pub fn bvx_ext_arith_shift_right_ty() -> Expr {
1176 bitvec_shift_ty()
1177}
1178#[allow(dead_code)]
1180pub fn bvx_ext_popcount_ty() -> Expr {
1181 pi(
1182 BinderInfo::Implicit,
1183 "n",
1184 nat_ty(),
1185 arrow(mk_bitvec(bvar(0)), nat_ty()),
1186 )
1187}
1188#[allow(dead_code)]
1190pub fn bvx_ext_count_zeros_ty() -> Expr {
1191 pi(
1192 BinderInfo::Implicit,
1193 "n",
1194 nat_ty(),
1195 arrow(mk_bitvec(bvar(0)), nat_ty()),
1196 )
1197}
1198#[allow(dead_code)]
1200pub fn bvx_ext_reverse_ty() -> Expr {
1201 bitvec_unop_ty()
1202}
1203#[allow(dead_code)]
1206pub fn bvx_ext_ext_ty() -> Expr {
1207 bvx_ext_forall_two(|| bvx_ext_bveq(2, 1, 0))
1208}
1209#[allow(dead_code)]
1211pub fn bvx_ext_zero_extend_ty() -> Expr {
1212 pi(
1213 BinderInfo::Implicit,
1214 "n",
1215 nat_ty(),
1216 pi(
1217 BinderInfo::Default,
1218 "m",
1219 nat_ty(),
1220 arrow(mk_bitvec(bvar(1)), mk_bitvec(bvar(0))),
1221 ),
1222 )
1223}
1224#[allow(dead_code)]
1226pub fn bvx_ext_concat_result(n_bvar: u32, m_bvar: u32) -> Expr {
1227 mk_bitvec(app2(cst("Nat.add"), bvar(n_bvar), bvar(m_bvar)))
1228}
1229#[allow(dead_code)]
1231pub fn bvx_ext_fin2n(n: Expr) -> Expr {
1232 app(
1233 cst("Fin"),
1234 app2(
1235 cst("Nat.pow"),
1236 app(cst("Nat.succ"), app(cst("Nat.succ"), cst("Nat.zero"))),
1237 n,
1238 ),
1239 )
1240}
1241#[allow(dead_code)]
1243pub fn bvx_ext_int() -> Expr {
1244 int_ty()
1245}
1246#[allow(dead_code)]
1248pub fn bvx_ext_nat() -> Expr {
1249 nat_ty()
1250}