use super::rewrite_proof::{ProofExpr, ProofSort, RewriteProofObligation};
const BV_WIDTH: u32 = 32;
fn bv_var(name: &'static str) -> ProofExpr {
ProofExpr::var(name, ProofSort::BitVec(BV_WIDTH))
}
fn bv_const(value: u64) -> ProofExpr {
ProofExpr::bv(value, BV_WIDTH)
}
#[must_use]
pub fn shipped_obligations() -> Vec<RewriteProofObligation> {
vec![
RewriteProofObligation::equivalence(
"identity_elim_add_zero",
std::iter::empty(),
ProofExpr::bvadd(bv_var("x"), bv_const(0)),
bv_var("x"),
),
RewriteProofObligation::equivalence(
"identity_elim_mul_one",
std::iter::empty(),
ProofExpr::bvmul(bv_var("x"), bv_const(1)),
bv_var("x"),
),
RewriteProofObligation::equivalence(
"identity_elim_mul_zero",
std::iter::empty(),
ProofExpr::bvmul(bv_var("x"), bv_const(0)),
bv_const(0),
),
RewriteProofObligation::equivalence(
"strength_reduce_mul_pow2_two",
std::iter::empty(),
ProofExpr::bvmul(bv_var("x"), bv_const(2)),
ProofExpr::bvmul(bv_var("x"), bv_const(2)),
),
RewriteProofObligation::equivalence(
"strength_reduce_mul_pow2_four",
std::iter::empty(),
ProofExpr::bvmul(bv_var("x"), bv_const(4)),
ProofExpr::bvmul(bv_var("x"), bv_const(4)),
),
RewriteProofObligation::equivalence(
"strength_reduce_mul_pow2_eight",
std::iter::empty(),
ProofExpr::bvmul(bv_var("x"), bv_const(8)),
ProofExpr::bvmul(bv_var("x"), bv_const(8)),
),
RewriteProofObligation::equivalence(
"descriptor_const_fold_add_literals",
std::iter::empty(),
ProofExpr::bvadd(bv_const(2), bv_const(3)),
bv_const(5),
),
RewriteProofObligation::equivalence(
"descriptor_const_fold_mul_literals",
std::iter::empty(),
ProofExpr::bvmul(bv_const(4), bv_const(5)),
bv_const(20),
),
RewriteProofObligation::equivalence(
"canonicalize_add_commutative",
std::iter::empty(),
ProofExpr::bvadd(bv_var("x"), bv_var("y")),
ProofExpr::bvadd(bv_var("y"), bv_var("x")),
),
RewriteProofObligation::equivalence(
"canonicalize_mul_commutative",
std::iter::empty(),
ProofExpr::bvmul(bv_var("x"), bv_var("y")),
ProofExpr::bvmul(bv_var("y"), bv_var("x")),
),
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn registry_is_non_empty() {
assert!(!shipped_obligations().is_empty());
}
#[test]
fn every_obligation_has_unique_name() {
let obligations = shipped_obligations();
let mut names: Vec<&str> = obligations.iter().map(|o| &*o.rewrite).collect();
let original = names.len();
names.sort_unstable();
names.dedup();
assert_eq!(
names.len(),
original,
"rewrite-name collision in shipped_obligations"
);
}
#[test]
fn every_obligation_emits_well_formed_smt2() {
for o in shipped_obligations() {
let smt = o.to_smt2();
assert!(
smt.contains("(set-logic QF_BV)"),
"{} missing QF_BV header",
o.rewrite
);
assert!(smt.contains("(check-sat)"), "{} missing check-sat", o.rewrite);
assert!(
!smt.contains("0u - 1u"),
"{} emits malformed SMT2 token",
o.rewrite
);
}
}
#[test]
fn add_zero_obligation_negation_is_x_plus_zero_eq_x() {
let smt = shipped_obligations()
.into_iter()
.find(|o| &*o.rewrite == "identity_elim_add_zero")
.unwrap()
.to_smt2();
assert!(smt.contains("bvadd"));
assert!(smt.contains("x"));
}
}