use cvc5_sys::*;
use std::cell::RefCell;
use std::ffi::CString;
use std::rc::Rc;
use crate::{DatatypeConstructorDecl, DatatypeDecl, Op, Sort, Statistics, Term};
#[derive(Clone)]
pub struct TermManager {
pub(crate) inner: Rc<RefCell<*mut Cvc5TermManager>>,
}
impl TermManager {
pub fn new() -> Self {
Self {
inner: Rc::new(RefCell::new(unsafe { cvc5_term_manager_new() })),
}
}
pub(crate) fn ptr(&self) -> *mut Cvc5TermManager {
*self.inner.borrow()
}
pub(crate) fn ptr_mut(&self) -> *mut Cvc5TermManager {
*self.inner.borrow_mut()
}
pub fn boolean_sort(&self) -> Sort {
Sort::from_raw(unsafe { cvc5_get_boolean_sort(self.ptr()) })
}
pub fn integer_sort(&self) -> Sort {
Sort::from_raw(unsafe { cvc5_get_integer_sort(self.ptr()) })
}
pub fn real_sort(&self) -> Sort {
Sort::from_raw(unsafe { cvc5_get_real_sort(self.ptr()) })
}
pub fn string_sort(&self) -> Sort {
Sort::from_raw(unsafe { cvc5_get_string_sort(self.ptr()) })
}
pub fn regexp_sort(&self) -> Sort {
Sort::from_raw(unsafe { cvc5_get_regexp_sort(self.ptr()) })
}
pub fn rm_sort(&self) -> Sort {
Sort::from_raw(unsafe { cvc5_get_rm_sort(self.ptr()) })
}
pub fn mk_array_sort(&self, index: Sort, elem: Sort) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_array_sort(self.ptr_mut(), index.inner, elem.inner) })
}
pub fn mk_bv_sort(&self, size: u32) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_bv_sort(self.ptr_mut(), size) })
}
pub fn mk_fp_sort(&self, exp: u32, sig: u32) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_fp_sort(self.ptr_mut(), exp, sig) })
}
pub fn mk_ff_sort(&self, size: &str, base: u32) -> Sort {
let c = CString::new(size).unwrap();
Sort::from_raw(unsafe { cvc5_mk_ff_sort(self.ptr_mut(), c.as_ptr(), base) })
}
pub fn mk_dt_sort(&self, decl: &DatatypeDecl) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_dt_sort(self.ptr_mut(), decl.inner) })
}
pub fn mk_dt_sorts(&self, decls: &[DatatypeDecl]) -> Vec<Sort> {
let raw: Vec<Cvc5DatatypeDecl> = decls.iter().map(|d| d.inner).collect();
let ptr = unsafe { cvc5_mk_dt_sorts(self.ptr_mut(), raw.len(), raw.as_ptr()) };
(0..decls.len())
.map(|i| Sort::from_raw(unsafe { *ptr.add(i) }))
.collect()
}
pub fn mk_fun_sort(&self, domain: &[Sort], codomain: Sort) -> Sort {
let raw: Vec<Cvc5Sort> = domain.iter().map(|s| s.inner).collect();
Sort::from_raw(unsafe {
cvc5_mk_fun_sort(self.ptr_mut(), raw.len(), raw.as_ptr(), codomain.inner)
})
}
pub fn mk_param_sort(&self, symbol: &str) -> Sort {
let c = CString::new(symbol).unwrap();
Sort::from_raw(unsafe { cvc5_mk_param_sort(self.ptr_mut(), c.as_ptr()) })
}
pub fn mk_predicate_sort(&self, sorts: &[Sort]) -> Sort {
let raw: Vec<Cvc5Sort> = sorts.iter().map(|s| s.inner).collect();
Sort::from_raw(unsafe { cvc5_mk_predicate_sort(self.ptr_mut(), raw.len(), raw.as_ptr()) })
}
pub fn mk_record_sort(&self, names: &[&str], sorts: &[Sort]) -> Sort {
let cnames: Vec<CString> = names.iter().map(|n| CString::new(*n).unwrap()).collect();
let mut ptrs: Vec<*const std::ffi::c_char> = cnames.iter().map(|c| c.as_ptr()).collect();
let raw: Vec<Cvc5Sort> = sorts.iter().map(|s| s.inner).collect();
Sort::from_raw(unsafe {
cvc5_mk_record_sort(self.ptr_mut(), raw.len(), ptrs.as_mut_ptr(), raw.as_ptr())
})
}
pub fn mk_set_sort(&self, elem: Sort) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_set_sort(self.ptr_mut(), elem.inner) })
}
pub fn mk_bag_sort(&self, elem: Sort) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_bag_sort(self.ptr_mut(), elem.inner) })
}
pub fn mk_sequence_sort(&self, elem: Sort) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_sequence_sort(self.ptr_mut(), elem.inner) })
}
pub fn mk_abstract_sort(&self, k: Cvc5SortKind) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_abstract_sort(self.ptr_mut(), k) })
}
pub fn mk_uninterpreted_sort(&self, name: &str) -> Sort {
let c = CString::new(name).unwrap();
Sort::from_raw(unsafe { cvc5_mk_uninterpreted_sort(self.ptr_mut(), c.as_ptr()) })
}
pub fn mk_anonymous_uninterpreted_sort(&self) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_uninterpreted_sort(self.ptr_mut(), std::ptr::null()) })
}
pub fn mk_unresolved_dt_sort(&self, symbol: &str, arity: usize) -> Sort {
let c = CString::new(symbol).unwrap();
Sort::from_raw(unsafe { cvc5_mk_unresolved_dt_sort(self.ptr_mut(), c.as_ptr(), arity) })
}
pub fn mk_uninterpreted_sort_constructor_sort(&self, arity: usize, symbol: &str) -> Sort {
let c = CString::new(symbol).unwrap();
Sort::from_raw(unsafe {
cvc5_mk_uninterpreted_sort_constructor_sort(self.ptr_mut(), arity, c.as_ptr())
})
}
pub fn mk_anonymous_uninterpreted_sort_constructor_sort(&self, arity: usize) -> Sort {
Sort::from_raw(unsafe {
cvc5_mk_uninterpreted_sort_constructor_sort(self.ptr_mut(), arity, std::ptr::null())
})
}
pub fn mk_tuple_sort(&self, sorts: &[Sort]) -> Sort {
let raw: Vec<Cvc5Sort> = sorts.iter().map(|s| s.inner).collect();
Sort::from_raw(unsafe { cvc5_mk_tuple_sort(self.ptr_mut(), raw.len(), raw.as_ptr()) })
}
pub fn mk_nullable_sort(&self, sort: Sort) -> Sort {
Sort::from_raw(unsafe { cvc5_mk_nullable_sort(self.ptr_mut(), sort.inner) })
}
pub fn mk_op(&self, kind: Cvc5Kind, indices: &[u32]) -> Op {
Op::from_raw(unsafe { cvc5_mk_op(self.ptr_mut(), kind, indices.len(), indices.as_ptr()) })
}
pub fn mk_op_from_str(&self, kind: Cvc5Kind, arg: &str) -> Op {
let c = CString::new(arg).unwrap();
Op::from_raw(unsafe { cvc5_mk_op_from_str(self.ptr_mut(), kind, c.as_ptr()) })
}
pub fn mk_term(&self, kind: Cvc5Kind, children: &[Term]) -> Term {
let raw: Vec<Cvc5Term> = children.iter().map(|t| t.inner).collect();
Term::from_raw(unsafe { cvc5_mk_term(self.ptr_mut(), kind, raw.len(), raw.as_ptr()) })
}
pub fn mk_term_from_op(&self, op: Op, children: &[Term]) -> Term {
let raw: Vec<Cvc5Term> = children.iter().map(|t| t.inner).collect();
Term::from_raw(unsafe {
cvc5_mk_term_from_op(self.ptr_mut(), op.inner, raw.len(), raw.as_ptr())
})
}
pub fn mk_tuple(&self, terms: &[Term]) -> Term {
let raw: Vec<Cvc5Term> = terms.iter().map(|t| t.inner).collect();
Term::from_raw(unsafe { cvc5_mk_tuple(self.ptr_mut(), raw.len(), raw.as_ptr()) })
}
pub fn mk_nullable_some(&self, term: Term) -> Term {
Term::from_raw(unsafe { cvc5_mk_nullable_some(self.ptr_mut(), term.inner) })
}
pub fn mk_nullable_val(&self, term: Term) -> Term {
Term::from_raw(unsafe { cvc5_mk_nullable_val(self.ptr_mut(), term.inner) })
}
pub fn mk_nullable_is_null(&self, term: Term) -> Term {
Term::from_raw(unsafe { cvc5_mk_nullable_is_null(self.ptr_mut(), term.inner) })
}
pub fn mk_nullable_is_some(&self, term: Term) -> Term {
Term::from_raw(unsafe { cvc5_mk_nullable_is_some(self.ptr_mut(), term.inner) })
}
pub fn mk_nullable_null(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_nullable_null(self.ptr_mut(), sort.inner) })
}
pub fn mk_nullable_lift(&self, kind: Cvc5Kind, args: &[Term]) -> Term {
let raw: Vec<Cvc5Term> = args.iter().map(|t| t.inner).collect();
Term::from_raw(unsafe {
cvc5_mk_nullable_lift(self.ptr_mut(), kind, raw.len(), raw.as_ptr())
})
}
pub fn mk_skolem(&self, id: Cvc5SkolemId, indices: &[Term]) -> Term {
let raw: Vec<Cvc5Term> = indices.iter().map(|t| t.inner).collect();
Term::from_raw(unsafe { cvc5_mk_skolem(self.ptr_mut(), id, raw.len(), raw.as_ptr()) })
}
pub fn get_num_idxs_for_skolem_id(&self, id: Cvc5SkolemId) -> usize {
unsafe { cvc5_get_num_idxs_for_skolem_id(self.ptr(), id) }
}
pub fn mk_true(&self) -> Term {
Term::from_raw(unsafe { cvc5_mk_true(self.ptr_mut()) })
}
pub fn mk_false(&self) -> Term {
Term::from_raw(unsafe { cvc5_mk_false(self.ptr_mut()) })
}
pub fn mk_boolean(&self, val: bool) -> Term {
Term::from_raw(unsafe { cvc5_mk_boolean(self.ptr_mut(), val) })
}
pub fn mk_pi(&self) -> Term {
Term::from_raw(unsafe { cvc5_mk_pi(self.ptr_mut()) })
}
pub fn mk_integer(&self, val: i64) -> Term {
Term::from_raw(unsafe { cvc5_mk_integer_int64(self.ptr_mut(), val) })
}
pub fn mk_integer_from_str(&self, s: &str) -> Term {
let c = CString::new(s).unwrap();
Term::from_raw(unsafe { cvc5_mk_integer(self.ptr_mut(), c.as_ptr()) })
}
pub fn mk_real(&self, val: i64) -> Term {
Term::from_raw(unsafe { cvc5_mk_real_int64(self.ptr_mut(), val) })
}
pub fn mk_real_from_str(&self, s: &str) -> Term {
let c = CString::new(s).unwrap();
Term::from_raw(unsafe { cvc5_mk_real(self.ptr_mut(), c.as_ptr()) })
}
pub fn mk_real_from_rational(&self, num: i64, den: i64) -> Term {
Term::from_raw(unsafe { cvc5_mk_real_num_den(self.ptr_mut(), num, den) })
}
pub fn mk_regexp_all(&self) -> Term {
Term::from_raw(unsafe { cvc5_mk_regexp_all(self.ptr_mut()) })
}
pub fn mk_regexp_allchar(&self) -> Term {
Term::from_raw(unsafe { cvc5_mk_regexp_allchar(self.ptr_mut()) })
}
pub fn mk_regexp_none(&self) -> Term {
Term::from_raw(unsafe { cvc5_mk_regexp_none(self.ptr_mut()) })
}
pub fn mk_empty_set(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_empty_set(self.ptr_mut(), sort.inner) })
}
pub fn mk_empty_bag(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_empty_bag(self.ptr_mut(), sort.inner) })
}
pub fn mk_sep_emp(&self) -> Term {
Term::from_raw(unsafe { cvc5_mk_sep_emp(self.ptr_mut()) })
}
pub fn mk_sep_nil(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_sep_nil(self.ptr_mut(), sort.inner) })
}
pub fn mk_string(&self, s: &str, use_esc_seq: bool) -> Term {
let c = CString::new(s).unwrap();
Term::from_raw(unsafe { cvc5_mk_string(self.ptr_mut(), c.as_ptr(), use_esc_seq) })
}
pub fn mk_empty_sequence(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_empty_sequence(self.ptr_mut(), sort.inner) })
}
pub fn mk_universe_set(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_universe_set(self.ptr_mut(), sort.inner) })
}
pub fn mk_bv(&self, size: u32, val: u64) -> Term {
Term::from_raw(unsafe { cvc5_mk_bv_uint64(self.ptr_mut(), size, val) })
}
pub fn mk_bv_from_str(&self, size: u32, s: &str, base: u32) -> Term {
let c = CString::new(s).unwrap();
Term::from_raw(unsafe { cvc5_mk_bv(self.ptr_mut(), size, c.as_ptr(), base) })
}
pub fn mk_ff_elem(&self, value: &str, sort: Sort, base: u32) -> Term {
let c = CString::new(value).unwrap();
Term::from_raw(unsafe { cvc5_mk_ff_elem(self.ptr_mut(), c.as_ptr(), sort.inner, base) })
}
pub fn mk_const_array(&self, sort: Sort, val: Term) -> Term {
Term::from_raw(unsafe { cvc5_mk_const_array(self.ptr_mut(), sort.inner, val.inner) })
}
pub fn mk_fp_pos_inf(&self, exp: u32, sig: u32) -> Term {
Term::from_raw(unsafe { cvc5_mk_fp_pos_inf(self.ptr_mut(), exp, sig) })
}
pub fn mk_fp_neg_inf(&self, exp: u32, sig: u32) -> Term {
Term::from_raw(unsafe { cvc5_mk_fp_neg_inf(self.ptr_mut(), exp, sig) })
}
pub fn mk_fp_nan(&self, exp: u32, sig: u32) -> Term {
Term::from_raw(unsafe { cvc5_mk_fp_nan(self.ptr_mut(), exp, sig) })
}
pub fn mk_fp_pos_zero(&self, exp: u32, sig: u32) -> Term {
Term::from_raw(unsafe { cvc5_mk_fp_pos_zero(self.ptr_mut(), exp, sig) })
}
pub fn mk_fp_neg_zero(&self, exp: u32, sig: u32) -> Term {
Term::from_raw(unsafe { cvc5_mk_fp_neg_zero(self.ptr_mut(), exp, sig) })
}
pub fn mk_rm(&self, rm: Cvc5RoundingMode) -> Term {
Term::from_raw(unsafe { cvc5_mk_rm(self.ptr_mut(), rm) })
}
pub fn mk_fp(&self, exp: u32, sig: u32, val: Term) -> Term {
Term::from_raw(unsafe { cvc5_mk_fp(self.ptr_mut(), exp, sig, val.inner) })
}
pub fn mk_fp_from_ieee(&self, sign: Term, exp: Term, sig: Term) -> Term {
Term::from_raw(unsafe {
cvc5_mk_fp_from_ieee(self.ptr_mut(), sign.inner, exp.inner, sig.inner)
})
}
pub fn mk_cardinality_constraint(&self, sort: Sort, upper_bound: u32) -> Term {
Term::from_raw(unsafe {
cvc5_mk_cardinality_constraint(self.ptr_mut(), sort.inner, upper_bound)
})
}
pub fn mk_const(&self, sort: Sort, name: &str) -> Term {
let c = CString::new(name).unwrap();
Term::from_raw(unsafe { cvc5_mk_const(self.ptr_mut(), sort.inner, c.as_ptr()) })
}
pub fn mk_anonymous_const(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_const(self.ptr_mut(), sort.inner, std::ptr::null()) })
}
pub fn mk_var(&self, sort: Sort, name: &str) -> Term {
let c = CString::new(name).unwrap();
Term::from_raw(unsafe { cvc5_mk_var(self.ptr_mut(), sort.inner, c.as_ptr()) })
}
pub fn mk_anonymous_var(&self, sort: Sort) -> Term {
Term::from_raw(unsafe { cvc5_mk_var(self.ptr_mut(), sort.inner, std::ptr::null()) })
}
pub fn mk_dt_cons_decl(&self, name: &str) -> DatatypeConstructorDecl {
let c = CString::new(name).unwrap();
DatatypeConstructorDecl::from_raw(unsafe {
cvc5_mk_dt_cons_decl(self.ptr_mut(), c.as_ptr())
})
}
pub fn mk_dt_decl(&self, name: &str, is_codt: bool) -> DatatypeDecl {
let c = CString::new(name).unwrap();
DatatypeDecl::from_raw(unsafe { cvc5_mk_dt_decl(self.ptr_mut(), c.as_ptr(), is_codt) })
}
pub fn mk_dt_decl_with_params(
&self,
name: &str,
params: &[Sort],
is_codt: bool,
) -> DatatypeDecl {
let c = CString::new(name).unwrap();
let raw: Vec<Cvc5Sort> = params.iter().map(|s| s.inner).collect();
DatatypeDecl::from_raw(unsafe {
cvc5_mk_dt_decl_with_params(
self.ptr_mut(),
c.as_ptr(),
raw.len(),
raw.as_ptr(),
is_codt,
)
})
}
pub fn mk_string_from_wchar(&self, s: &[wchar_t]) -> Term {
Term::from_raw(unsafe { cvc5_mk_string_from_wchar(self.ptr_mut(), s.as_ptr()) })
}
pub fn mk_string_from_char32(&self, s: &[char32_t]) -> Term {
Term::from_raw(unsafe { cvc5_mk_string_from_char32(self.ptr_mut(), s.as_ptr()) })
}
pub fn get_statistics(&self) -> Statistics {
Statistics::from_raw(unsafe { cvc5_term_manager_get_statistics(self.ptr()) })
}
pub fn print_stats_safe(&self, fd: i32) {
unsafe { cvc5_term_manager_print_stats_safe(self.ptr(), fd) }
}
}
impl Default for TermManager {
fn default() -> Self {
Self::new()
}
}
impl Drop for TermManager {
fn drop(&mut self) {
if Rc::strong_count(&self.inner) == 1 {
unsafe { cvc5_term_manager_delete(self.ptr()) }
}
}
}