1use crate::ast::{Array, Ast, BV, Bool, Datatype, Float, Int, Real, Seq, Set};
2use crate::{Context, Sort, Symbol, ast};
3use std::ffi::CString;
4use z3_sys::*;
5
6pub struct Dynamic {
8 pub(crate) ctx: Context,
9 pub(crate) z3_ast: Z3_ast,
10}
11
12impl Dynamic {
13 pub fn from_ast(ast: &dyn Ast) -> Self {
14 unsafe { Self::wrap(ast.get_ctx(), ast.get_z3_ast()) }
15 }
16
17 pub fn new_const<S: Into<Symbol>>(name: S, sort: &Sort) -> Self {
18 let ctx = &Context::thread_local();
19 unsafe {
20 Self::wrap(
21 ctx,
22 Z3_mk_const(ctx.z3_ctx.0, name.into().as_z3_symbol(), sort.z3_sort).unwrap(),
23 )
24 }
25 }
26
27 pub fn fresh_const(prefix: &str, sort: &Sort) -> Self {
28 let ctx = sort.ctx.clone();
29 unsafe {
30 Self::wrap(&ctx, {
31 let pp = CString::new(prefix).unwrap();
32 let p = pp.as_ptr();
33 Z3_mk_fresh_const(ctx.z3_ctx.0, p, sort.z3_sort).unwrap()
34 })
35 }
36 }
37
38 pub fn sort_kind(&self) -> SortKind {
39 unsafe {
40 Z3_get_sort_kind(
41 self.ctx.z3_ctx.0,
42 Z3_get_sort(self.ctx.z3_ctx.0, self.z3_ast).unwrap(),
43 )
44 }
45 }
46
47 pub fn as_bool(&self) -> Option<Bool> {
49 match self.sort_kind() {
50 SortKind::Bool => Some(unsafe { Bool::wrap(&self.ctx, self.z3_ast) }),
51 _ => None,
52 }
53 }
54
55 pub fn as_int(&self) -> Option<Int> {
57 match self.sort_kind() {
58 SortKind::Int => Some(unsafe { Int::wrap(&self.ctx, self.z3_ast) }),
59 _ => None,
60 }
61 }
62
63 pub fn as_real(&self) -> Option<Real> {
65 match self.sort_kind() {
66 SortKind::Real => Some(unsafe { Real::wrap(&self.ctx, self.z3_ast) }),
67 _ => None,
68 }
69 }
70
71 pub fn as_float(&self) -> Option<Float> {
73 match self.sort_kind() {
74 SortKind::FloatingPoint => Some(unsafe { Float::wrap(&self.ctx, self.z3_ast) }),
75 _ => None,
76 }
77 }
78
79 pub fn as_string(&self) -> Option<ast::String> {
81 unsafe {
82 if Z3_is_string_sort(
83 self.ctx.z3_ctx.0,
84 Z3_get_sort(self.ctx.z3_ctx.0, self.z3_ast)?,
85 ) {
86 Some(ast::String::wrap(&self.ctx, self.z3_ast))
87 } else {
88 None
89 }
90 }
91 }
92
93 pub fn as_bv(&self) -> Option<BV> {
95 match self.sort_kind() {
96 SortKind::BV => Some(unsafe { BV::wrap(&self.ctx, self.z3_ast) }),
97 _ => None,
98 }
99 }
100
101 pub fn as_array(&self) -> Option<Array> {
103 match self.sort_kind() {
104 SortKind::Array => Some(unsafe { Array::wrap(&self.ctx, self.z3_ast) }),
105 _ => None,
106 }
107 }
108
109 pub fn as_set(&self) -> Option<Set> {
111 unsafe {
112 match self.sort_kind() {
113 SortKind::Array => {
114 match Z3_get_sort_kind(
115 self.ctx.z3_ctx.0,
116 Z3_get_array_sort_range(
117 self.ctx.z3_ctx.0,
118 Z3_get_sort(self.ctx.z3_ctx.0, self.z3_ast)?,
119 )?,
120 ) {
121 SortKind::Bool => Some(Set::wrap(&self.ctx, self.z3_ast)),
122 _ => None,
123 }
124 }
125 _ => None,
126 }
127 }
128 }
129
130 pub fn as_seq(&self) -> Option<Seq> {
132 match self.sort_kind() {
133 SortKind::Seq => Some(unsafe { Seq::wrap(&self.ctx, self.z3_ast) }),
134 _ => None,
135 }
136 }
137
138 pub fn as_datatype(&self) -> Option<Datatype> {
140 match self.sort_kind() {
141 SortKind::Datatype => Some(unsafe { Datatype::wrap(&self.ctx, self.z3_ast) }),
142 _ => None,
143 }
144 }
145}