use crate::ast::{Array, Ast, BV, Bool, Char, Datatype, Float, Int, Real, Seq, Set};
use crate::{Context, Sort, Symbol, ast};
use std::ffi::CString;
use z3_sys::*;
pub struct Dynamic {
pub(crate) ctx: Context,
pub(crate) z3_ast: Z3_ast,
}
impl Dynamic {
pub fn from_ast(ast: &dyn Ast) -> Self {
unsafe { Self::wrap(ast.get_ctx(), ast.get_z3_ast()) }
}
pub fn new_const<S: Into<Symbol>>(name: S, sort: &Sort) -> Self {
let ctx = &Context::thread_local();
unsafe {
Self::wrap(
ctx,
Z3_mk_const(ctx.z3_ctx.0, name.into().as_z3_symbol(), sort.z3_sort).unwrap(),
)
}
}
pub fn fresh_const(prefix: &str, sort: &Sort) -> Self {
let ctx = sort.ctx.clone();
unsafe {
Self::wrap(&ctx, {
let pp = CString::new(prefix).unwrap();
let p = pp.as_ptr();
Z3_mk_fresh_const(ctx.z3_ctx.0, p, sort.z3_sort).unwrap()
})
}
}
pub fn sort_kind(&self) -> SortKind {
unsafe {
Z3_get_sort_kind(
self.ctx.z3_ctx.0,
Z3_get_sort(self.ctx.z3_ctx.0, self.z3_ast).unwrap(),
)
}
}
pub fn as_bool(&self) -> Option<Bool> {
match self.sort_kind() {
SortKind::Bool => Some(unsafe { Bool::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
pub fn as_int(&self) -> Option<Int> {
match self.sort_kind() {
SortKind::Int => Some(unsafe { Int::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
pub fn as_real(&self) -> Option<Real> {
match self.sort_kind() {
SortKind::Real => Some(unsafe { Real::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
pub fn as_float(&self) -> Option<Float> {
match self.sort_kind() {
SortKind::FloatingPoint => Some(unsafe { Float::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
pub fn as_char(&self) -> Option<Char> {
unsafe {
if Z3_is_char_sort(
self.ctx.z3_ctx.0,
Z3_get_sort(self.ctx.z3_ctx.0, self.z3_ast)?,
) {
Some(Char::wrap(&self.ctx, self.z3_ast))
} else {
None
}
}
}
pub fn as_string(&self) -> Option<ast::String> {
unsafe {
if Z3_is_string_sort(
self.ctx.z3_ctx.0,
Z3_get_sort(self.ctx.z3_ctx.0, self.z3_ast)?,
) {
Some(ast::String::wrap(&self.ctx, self.z3_ast))
} else {
None
}
}
}
pub fn as_bv(&self) -> Option<BV> {
match self.sort_kind() {
SortKind::Bv => Some(unsafe { BV::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
pub fn as_array(&self) -> Option<Array> {
match self.sort_kind() {
SortKind::Array => Some(unsafe { Array::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
pub fn as_set(&self) -> Option<Set> {
unsafe {
match self.sort_kind() {
SortKind::Array => {
match Z3_get_sort_kind(
self.ctx.z3_ctx.0,
Z3_get_array_sort_range(
self.ctx.z3_ctx.0,
Z3_get_sort(self.ctx.z3_ctx.0, self.z3_ast)?,
)?,
) {
SortKind::Bool => Some(Set::wrap(&self.ctx, self.z3_ast)),
_ => None,
}
}
_ => None,
}
}
}
pub fn as_seq(&self) -> Option<Seq> {
match self.sort_kind() {
SortKind::Seq => Some(unsafe { Seq::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
pub fn as_datatype(&self) -> Option<Datatype> {
match self.sort_kind() {
SortKind::Datatype => Some(unsafe { Datatype::wrap(&self.ctx, self.z3_ast) }),
_ => None,
}
}
}