@@ -7,27 +7,43 @@ use std::{
77} ;
88
99use num:: { BigInt , BigRational } ;
10+
11+ use smtlib_lowlevel:: {
12+ ast:: {
13+ FunctionDef , GetModelResponse , Identifier , ModelResponse , QualIdentifier , SpecConstant ,
14+ Term ,
15+ } ,
16+ lexicon:: { Decimal , Symbol } ,
17+ } ;
18+
1019use thiserror:: Error ;
20+
1121use z3:: {
1222 ast:: { Ast , Bool , Dynamic , Int , Real } ,
1323 FuncDecl , FuncInterp , Model ,
1424} ;
1525
26+ #[ derive( Debug ) ]
27+ pub enum ModelSource < ' ctx > {
28+ Z3Model ( Model < ' ctx > ) ,
29+ SwineModel ( GetModelResponse < ' ctx > ) ,
30+ }
31+
1632/// A [`z3::Model`] which keeps track of the accessed constants. This is useful
1733/// to later print those constants which were not accessed by any of the
1834/// [`SmtEval`] implementations (e.g. stuff generated by Z3 we don't know
1935/// about). This way, we can print the whole model and pretty-print everything
2036/// we know, and then print the rest of the assignments in the model as well.
2137#[ derive( Debug ) ]
2238pub struct InstrumentedModel < ' ctx > {
23- model : Model < ' ctx > ,
39+ model : ModelSource < ' ctx > ,
2440 // TODO: turn this into a HashSet of FuncDecls when the type implements Hash
2541 accessed_decls : RefCell < im_rc:: HashSet < String > > ,
2642 accessed_exprs : RefCell < im_rc:: HashSet < Dynamic < ' ctx > > > ,
2743}
2844
2945impl < ' ctx > InstrumentedModel < ' ctx > {
30- pub fn new ( model : Model < ' ctx > ) -> Self {
46+ pub fn new ( model : ModelSource < ' ctx > ) -> Self {
3147 InstrumentedModel {
3248 model,
3349 accessed_decls : Default :: default ( ) ,
@@ -57,14 +73,129 @@ impl<'ctx> InstrumentedModel<'ctx> {
5773 /// the model.
5874 pub fn eval < T : Ast < ' ctx > > ( & self , ast : & T , model_completion : bool ) -> Option < T > {
5975 self . add_children_accessed ( Dynamic :: from_ast ( ast) ) ;
60- let res = self . model . eval ( ast, model_completion) ?;
61- Some ( res)
76+ match & self . model {
77+ ModelSource :: Z3Model ( model) => {
78+ let res = model. eval ( ast, model_completion) ?;
79+ Some ( res)
80+ }
81+ ModelSource :: SwineModel ( _) => todo ! ( ) ,
82+ }
83+ }
84+
85+ pub fn eval_ast_bool ( & self , ast : & Bool < ' ctx > ) -> Option < Bool < ' ctx > > {
86+ let name = ast. decl ( ) . name ( ) ;
87+
88+ if let ModelSource :: SwineModel ( s_model) = & self . model {
89+ match Self :: find_fun_def ( s_model, & name) {
90+ Some ( fun_def) => match fun_def. 3 {
91+ Term :: Identifier ( QualIdentifier :: Identifier ( Identifier :: Simple ( Symbol (
92+ "true" ,
93+ ) ) ) ) => Some ( Bool :: from_bool ( ast. get_ctx ( ) , true ) ) ,
94+ Term :: Identifier ( QualIdentifier :: Identifier ( Identifier :: Simple ( Symbol (
95+ "false" ,
96+ ) ) ) ) => Some ( Bool :: from_bool ( ast. get_ctx ( ) , false ) ) ,
97+ _ => None ,
98+ } ,
99+ None => None ,
100+ }
101+ } else {
102+ None
103+ }
104+ }
105+
106+ pub fn eval_ast_int ( & self , ast : & Int < ' ctx > ) -> Option < Int < ' ctx > > {
107+ let name = ast. decl ( ) . name ( ) ;
108+
109+ if let ModelSource :: SwineModel ( s_model) = & self . model {
110+ match Self :: find_fun_def ( s_model, & name) {
111+ Some ( fun_def) => match fun_def. 3 {
112+ Term :: SpecConstant ( SpecConstant :: Numeral ( numeral) ) => {
113+ if let Ok ( n) = numeral. into_u128 ( ) {
114+ let n_str = n. to_string ( ) ;
115+ Int :: from_str ( ast. get_ctx ( ) , & n_str)
116+ } else {
117+ None
118+ }
119+ }
120+ _ => None ,
121+ } ,
122+ None => None ,
123+ }
124+ } else {
125+ None
126+ }
127+ }
128+
129+ pub fn eval_ast_real ( & self , ast : & Real < ' ctx > ) -> Option < Real < ' ctx > > {
130+ let name = ast. decl ( ) . name ( ) ;
131+
132+ if let ModelSource :: SwineModel ( s_model) = & self . model {
133+ match Self :: find_fun_def ( s_model, & name) {
134+ Some ( fun_def) => match fun_def. 3 {
135+ Term :: SpecConstant ( SpecConstant :: Decimal ( Decimal ( d_str) ) ) => {
136+ if let Some ( ( num, den) ) = Self :: from_str_to_num_den ( d_str) {
137+ Real :: from_real_str ( ast. get_ctx ( ) , & num, & den)
138+ } else {
139+ None
140+ }
141+ }
142+ _ => None ,
143+ } ,
144+ None => None ,
145+ }
146+ } else {
147+ None
148+ }
149+ }
150+
151+ /// Convert a decimal string `d_str` into a pair of a numerator (`num`) and
152+ /// a denominator (`den`) in the form of '[numeral]' strings such that:
153+ /// d_str = num / den
154+ pub fn from_str_to_num_den ( d_str : & str ) -> Option < ( String , String ) > {
155+ if d_str. is_empty ( ) {
156+ return None ;
157+ }
158+
159+ if let Some ( pos) = d_str. find ( '.' ) {
160+ let den = "1" . to_string ( ) + & "0" . repeat ( d_str. len ( ) - pos - 1 ) ;
161+
162+ let mut num = d_str. to_string ( ) ;
163+ num. remove ( pos) ;
164+ num. trim_start_matches ( '0' ) ;
165+
166+ if num. is_empty ( ) {
167+ num = "0" . to_string ( ) ;
168+ }
169+
170+ Some ( ( num, den) )
171+ } else {
172+ Some ( ( d_str. to_string ( ) , "1" . to_string ( ) ) )
173+ }
174+ }
175+
176+ /// Find a `FunctionDef` object defined for a given symbol `symbol` within the `model_res`.
177+ pub fn find_fun_def (
178+ model_res : & GetModelResponse < ' ctx > ,
179+ symbol : & str ,
180+ ) -> Option < & ' ctx FunctionDef < ' ctx > > {
181+ model_res. 0 . iter ( ) . find_map ( |m_res| {
182+ if let ModelResponse :: DefineFun ( fun_def) = m_res {
183+ if fun_def. 0 . 0 == symbol {
184+ Some ( fun_def)
185+ } else {
186+ None
187+ }
188+ } else {
189+ None
190+ }
191+ } )
62192 }
63193
64194 /// Get the function interpretation for this `f`.
65195 pub fn get_func_interp ( & self , f : & FuncDecl < ' ctx > ) -> Option < FuncInterp < ' ctx > > {
66196 self . accessed_decls . borrow_mut ( ) . insert ( f. name ( ) ) ;
67- self . model . get_func_interp ( f)
197+ todo ! ( )
198+ // self.model.get_func_interp(f)
68199 }
69200
70201 /// Add this ast node and all its children to the accessed set.
@@ -89,9 +220,12 @@ impl<'ctx> InstrumentedModel<'ctx> {
89220 /// Iterate over all function declarations that were not accessed using
90221 /// `eval` so far.
91222 pub fn iter_unaccessed ( & self ) -> impl Iterator < Item = FuncDecl < ' ctx > > + ' _ {
223+ todo ! ( )
224+ /*
92225 self.model
93226 .iter()
94227 .filter(|decl| !self.accessed_decls.borrow().contains(&decl.name()))
228+ */
95229 }
96230
97231 /// Reset the internally tracked accessed declarations and expressions.
@@ -101,15 +235,17 @@ impl<'ctx> InstrumentedModel<'ctx> {
101235 }
102236
103237 pub fn into_model ( self ) -> Model < ' ctx > {
104- self . model
238+ todo ! ( )
239+ // self.model
105240 }
106241}
107242
108243/// The [`Display`] implementation simply defers to the underlying
109244/// [`z3::Model`]'s implementation.
110245impl Display for InstrumentedModel < ' _ > {
111246 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
112- f. write_fmt ( format_args ! ( "{}" , & self . model) )
247+ todo ! ( )
248+ // f.write_fmt(format_args!("{}", &self.model))
113249 }
114250}
115251
0 commit comments