@@ -8,13 +8,6 @@ use std::{
88
99use  num:: { BigInt ,  BigRational } ; 
1010
11- use  smtlib_lowlevel:: { 
12-     ast:: { 
13-         FunctionDef ,  GetModelResponse ,  Identifier ,  ModelResponse ,  QualIdentifier ,  SpecConstant , 
14-         Term , 
15-     } , 
16-     lexicon:: { Decimal ,  Symbol } , 
17- } ; 
1811
1912use  thiserror:: Error ; 
2013
@@ -23,67 +16,21 @@ use z3::{
2316    FuncDecl ,  FuncInterp ,  Model , 
2417} ; 
2518
26- #[ derive( Debug ) ]  
27- pub  enum  ModelSource < ' ctx >  { 
28-     Z3Model ( Model < ' ctx > ) , 
29-     SwineModel ( GetModelResponse < ' ctx > ) , 
30- } 
31- 
32- /// Convert a decimal string `d_str` into a pair of a numerator (`num`) and  
33- /// a denominator (`den`) in the form of '[numeral]' strings such that:  
34- /// d_str = num / den 
35- fn  from_str_to_num_den ( d_str :  & str )  -> Option < ( BigInt ,  BigInt ) >  { 
36-     if  d_str. is_empty ( )  { 
37-         return  None ; 
38-     } 
39- 
40-     if  d_str. ends_with ( ".0" )  { 
41-         let  num = BigInt :: from_str ( & d_str. replace ( ".0" ,  "" ) ) . ok ( ) ?; 
42-         Some ( ( num,  BigInt :: from ( 1 ) ) ) 
43-     }  else  if  let  Some ( pos)  = d_str. find ( '.' )  { 
44-         let  den = BigInt :: from ( 10 ) . pow ( ( d_str. len ( )  - pos - 1 ) . try_into ( ) . unwrap ( ) ) ; 
45-         let  num = BigInt :: from_str ( & d_str. replace ( "." ,  "" ) ) . ok ( ) ?; 
46- 
47-         Some ( ( num,  den) ) 
48-     }  else  { 
49-         let  num = BigInt :: from_str ( d_str) . ok ( ) ?; 
50-         Some ( ( num,  BigInt :: from ( 1 ) ) ) 
51-     } 
52- } 
53- 
54- /// Find a `FunctionDef` object defined for a given symbol `symbol` within the `model_res`. 
55- fn  find_fun_def < ' ctx > ( 
56-     model_res :  & GetModelResponse < ' ctx > , 
57-     symbol :  & str , 
58- )  -> Option < & ' ctx  FunctionDef < ' ctx > >  { 
59-     model_res. 0 . iter ( ) . find_map ( |m_res| { 
60-         if  let  ModelResponse :: DefineFun ( fun_def)  = m_res { 
61-             if  fun_def. 0 . 0  == symbol { 
62-                 Some ( fun_def) 
63-             }  else  { 
64-                 None 
65-             } 
66-         }  else  { 
67-             None 
68-         } 
69-     } ) 
70- } 
71- 
7219/// A [`z3::Model`] which keeps track of the accessed constants. This is useful 
7320/// to later print those constants which were not accessed by any of the 
7421/// [`SmtEval`] implementations (e.g. stuff generated by Z3 we don't know 
7522/// about). This way, we can print the whole model and pretty-print everything 
7623/// we know, and then print the rest of the assignments in the model as well. 
7724#[ derive( Debug ) ]  
7825pub  struct  InstrumentedModel < ' ctx >  { 
79-     model :  ModelSource < ' ctx > , 
26+     model :  Model < ' ctx > , 
8027    // TODO: turn this into a HashSet of FuncDecls when the type implements Hash 
8128    accessed_decls :  RefCell < im_rc:: HashSet < String > > , 
8229    accessed_exprs :  RefCell < im_rc:: HashSet < Dynamic < ' ctx > > > , 
8330} 
8431
8532impl < ' ctx >  InstrumentedModel < ' ctx >  { 
86-     pub  fn  new ( model :  ModelSource < ' ctx > )  -> Self  { 
33+     pub  fn  new ( model :  Model < ' ctx > )  -> Self  { 
8734        InstrumentedModel  { 
8835            model, 
8936            accessed_decls :  Default :: default ( ) , 
@@ -113,20 +60,14 @@ impl<'ctx> InstrumentedModel<'ctx> {
11360     /// the model. 
11461     pub  fn  eval < T :  Ast < ' ctx > > ( & self ,  ast :  & T ,  model_completion :  bool )  -> Option < T >  { 
11562        self . add_children_accessed ( Dynamic :: from_ast ( ast) ) ; 
116-         match  & self . model  { 
117-             ModelSource :: Z3Model ( model)  => { 
118-                 let  res = model. eval ( ast,  model_completion) ?; 
119-                 Some ( res) 
120-             } 
121-             ModelSource :: SwineModel ( _)  => todo ! ( ) , 
122-         } 
63+         let  res = self . model . eval ( ast,  model_completion) ?; 
64+         Some ( res) 
12365    } 
12466
12567    /// Get the function interpretation for this `f`. 
12668     pub  fn  get_func_interp ( & self ,  f :  & FuncDecl < ' ctx > )  -> Option < FuncInterp < ' ctx > >  { 
12769        self . accessed_decls . borrow_mut ( ) . insert ( f. name ( ) ) ; 
128-         todo ! ( ) 
129-         // self.model.get_func_interp(f) 
70+         self . model . get_func_interp ( f) 
13071    } 
13172
13273    /// Add this ast node and all its children to the accessed set. 
@@ -151,12 +92,9 @@ impl<'ctx> InstrumentedModel<'ctx> {
15192    /// Iterate over all function declarations that were not accessed using 
15293     /// `eval` so far. 
15394     pub  fn  iter_unaccessed ( & self )  -> impl  Iterator < Item  = FuncDecl < ' ctx > >  + ' _  { 
154-         todo ! ( ) 
155-         /* 
15695        self . model 
15796            . iter ( ) 
15897            . filter ( |decl| !self . accessed_decls . borrow ( ) . contains ( & decl. name ( ) ) ) 
159-          */ 
16098    } 
16199
162100    /// Reset the internally tracked accessed declarations and expressions. 
@@ -166,17 +104,15 @@ impl<'ctx> InstrumentedModel<'ctx> {
166104    } 
167105
168106    pub  fn  into_model ( self )  -> Model < ' ctx >  { 
169-         todo ! ( ) 
170-         // self.model 
107+         self . model 
171108    } 
172109} 
173110
174111/// The [`Display`] implementation simply defers to the underlying 
175112/// [`z3::Model`]'s implementation. 
176113impl  Display  for  InstrumentedModel < ' _ >  { 
177114    fn  fmt ( & self ,  f :  & mut  fmt:: Formatter < ' _ > )  -> fmt:: Result  { 
178-         todo ! ( ) 
179-         // f.write_fmt(format_args!("{}", &self.model)) 
115+         f. write_fmt ( format_args ! ( "{}" ,  & self . model) ) 
180116    } 
181117} 
182118
@@ -200,164 +136,64 @@ impl<'ctx> SmtEval<'ctx> for Bool<'ctx> {
200136    type  Value  = bool ; 
201137
202138    fn  eval ( & self ,  model :  & InstrumentedModel < ' ctx > )  -> Result < bool ,  SmtEvalError >  { 
203-         match  model. model  { 
204-             ModelSource :: Z3Model ( _)  => { 
205-                 model
206-                 . eval ( self ,  true ) 
207-                 . ok_or ( SmtEvalError :: EvalError ) ?
208-                 . as_bool ( ) 
209-                 . ok_or ( SmtEvalError :: ParseError ) 
210-             } , 
211-             ModelSource :: SwineModel ( s_model)  => { 
212- 
213-                 let  name:  String  = self . decl ( ) . name ( ) ; 
214- 
215-                 match  find_fun_def ( & s_model,  & name)  { 
216-                     Some ( fun_def)  => match  fun_def. 3  { 
217-                         Term :: Identifier ( QualIdentifier :: Identifier ( Identifier :: Simple ( Symbol ( 
218-                             "true" , 
219-                         ) ) ) )  => Ok ( true ) , 
220-                         Term :: Identifier ( QualIdentifier :: Identifier ( Identifier :: Simple ( Symbol ( 
221-                             "false" , 
222-                         ) ) ) )  => Ok ( false ) , 
223-                         _ => Err ( SmtEvalError :: EvalError ) , 
224-                     } , 
225-                     None  => Err ( SmtEvalError :: EvalError ) , 
226-                 } 
227-             } , 
228-         } 
139+         model
140+             . eval ( self ,  true ) 
141+             . ok_or ( SmtEvalError :: EvalError ) ?
142+             . as_bool ( ) 
143+             . ok_or ( SmtEvalError :: ParseError ) 
229144    } 
230145} 
231146
232147impl < ' ctx >  SmtEval < ' ctx >  for  Int < ' ctx >  { 
233148    type  Value  = BigInt ; 
234149
235150    fn  eval ( & self ,  model :  & InstrumentedModel < ' ctx > )  -> Result < BigInt ,  SmtEvalError >  { 
236-         match  model. model  { 
237-             ModelSource :: Z3Model ( _)  => { 
238-                 // TODO: Z3's as_i64 only returns an i64 value. is there something more complete? 
239-                 let  value = model
240-                     . eval ( self ,  true ) 
241-                     . ok_or ( SmtEvalError :: EvalError ) ?
242-                     . as_i64 ( ) 
243-                     . ok_or ( SmtEvalError :: ParseError ) ?; 
244-                 Ok ( BigInt :: from ( value) ) 
245-             } 
246-             ModelSource :: SwineModel ( s_model)  => { 
247-                 let  name = self . decl ( ) . name ( ) ; 
248-                 match  find_fun_def ( & s_model,  & name)  { 
249-                     Some ( fun_def)  => match  fun_def. 3  { 
250-                         Term :: SpecConstant ( SpecConstant :: Numeral ( numeral) )  => { 
251-                             if  let  Ok ( n)  = numeral. into_u128 ( )  { 
252-                                 Ok ( BigInt :: from ( n) ) 
253-                             }  else  { 
254-                                 Err ( SmtEvalError :: EvalError ) 
255-                             } 
256-                         } 
257-                         _ => Err ( SmtEvalError :: EvalError ) , 
258-                     } , 
259-                     None  => Err ( SmtEvalError :: EvalError ) , 
260-                 } 
261-             } , 
262-         } 
151+         // TODO: Z3's as_i64 only returns an i64 value. is there something more complete? 
152+         let  value = model
153+             . eval ( self ,  true ) 
154+             . ok_or ( SmtEvalError :: EvalError ) ?
155+             . as_i64 ( ) 
156+             . ok_or ( SmtEvalError :: ParseError ) ?; 
157+         Ok ( BigInt :: from ( value) ) 
263158    } 
264159} 
265160
266161impl < ' ctx >  SmtEval < ' ctx >  for  Real < ' ctx >  { 
267162    type  Value  = BigRational ; 
268163
269164    fn  eval ( & self ,  model :  & InstrumentedModel < ' ctx > )  -> Result < Self :: Value ,  SmtEvalError >  { 
270-         match  model. model  { 
271-             ModelSource :: Z3Model ( _)  => { 
272-                 let  res = model
273-                     . eval ( self ,  false )  // TODO 
274-                     . ok_or ( SmtEvalError :: EvalError ) ?; 
275- 
276-                 // The .as_real() method only returns a pair of i64 values. If the 
277-                 // results don't fit in these types, we start some funky string parsing. 
278-                 if  let  Some ( ( num,  den) )  = res. as_real ( )  { 
279-                     Ok ( BigRational :: new ( num. into ( ) ,  den. into ( ) ) ) 
280-                 }  else  { 
281-                     // we parse a string of the form "(/ num.0 denom.0)" 
282-                     let  division_expr = format ! ( "{:?}" ,  res) ; 
283-                     if  !division_expr. starts_with ( "(/ " )  || !division_expr. ends_with ( ".0)" )  { 
284-                         return  Err ( SmtEvalError :: ParseError ) ; 
285-                     } 
286- 
287-                     let  mut  parts = division_expr. split_ascii_whitespace ( ) ; 
165+         let  res = model
166+             . eval ( self ,  false )  // TODO 
167+             . ok_or ( SmtEvalError :: EvalError ) ?; 
168+ 
169+         // The .as_real() method only returns a pair of i64 values. If the 
170+         // results don't fit in these types, we start some funky string parsing. 
171+         if  let  Some ( ( num,  den) )  = res. as_real ( )  { 
172+             Ok ( BigRational :: new ( num. into ( ) ,  den. into ( ) ) ) 
173+         }  else  { 
174+             // we parse a string of the form "(/ num.0 denom.0)" 
175+             let  division_expr = format ! ( "{:?}" ,  res) ; 
176+             if  !division_expr. starts_with ( "(/ " )  || !division_expr. ends_with ( ".0)" )  { 
177+                 return  Err ( SmtEvalError :: ParseError ) ; 
178+             } 
288179
289-                     let  first_part = parts. next ( ) . ok_or ( SmtEvalError :: ParseError ) ?; 
290-                     if  first_part != "(/"  { 
291-                         return  Err ( SmtEvalError :: ParseError ) ; 
292-                     } 
180+             let  mut  parts = division_expr. split_ascii_whitespace ( ) ; 
293181
294-                     let  second_part = parts. next ( ) . ok_or ( SmtEvalError :: ParseError ) ?; 
295-                     let  second_part = second_part. replace ( ".0" ,  "" ) ; 
296-                     let  numerator = BigInt :: from_str ( & second_part) . map_err ( |_| SmtEvalError :: ParseError ) ?; 
182+             let  first_part = parts. next ( ) . ok_or ( SmtEvalError :: ParseError ) ?; 
183+             if  first_part != "(/"  { 
184+                 return  Err ( SmtEvalError :: ParseError ) ; 
185+             } 
297186
298-                     let  third_part = parts. next ( ) . ok_or ( SmtEvalError :: ParseError ) ?; 
299-                     let  third_part = third_part. replace ( ".0)" ,  "" ) ; 
300-                     let  denominator =
301-                         BigInt :: from_str ( & third_part) . map_err ( |_| SmtEvalError :: ParseError ) ?; 
187+             let  second_part = parts. next ( ) . ok_or ( SmtEvalError :: ParseError ) ?; 
188+             let  second_part = second_part. replace ( ".0" ,  "" ) ; 
189+             let  numerator = BigInt :: from_str ( & second_part) . map_err ( |_| SmtEvalError :: ParseError ) ?; 
302190
303-                     Ok ( BigRational :: new ( numerator,  denominator) ) 
304-                 } 
305-             } , 
306-             ModelSource :: SwineModel ( s_model)  => { 
307-                 let  name = self . decl ( ) . name ( ) ; 
191+             let  third_part = parts. next ( ) . ok_or ( SmtEvalError :: ParseError ) ?; 
192+             let  third_part = third_part. replace ( ".0)" ,  "" ) ; 
193+             let  denominator =
194+                 BigInt :: from_str ( & third_part) . map_err ( |_| SmtEvalError :: ParseError ) ?; 
308195
309-                 match  find_fun_def ( & s_model,  & name)  { 
310-                     Some ( fun_def)  => match  fun_def. 3  { 
311-                         Term :: SpecConstant ( SpecConstant :: Decimal ( Decimal ( d_str) ) )  => { 
312-                             let  f = ( * d_str) . parse :: < f64 > ( ) . map_err ( |_| SmtEvalError :: EvalError ) ?; 
313-                             let  res = BigRational :: from_float ( f) . ok_or ( SmtEvalError :: EvalError ) ?; 
314-                             Ok ( res) 
315-                         } 
316-                         Term :: Application ( QualIdentifier :: Identifier ( Identifier :: Simple ( Symbol ( "/" ) ) ) ,  [ t1,  t2] )  => { 
317-                             let  mut  num = BigInt :: from ( 1 ) ; 
318-                             let  mut  den = BigInt :: from ( 1 ) ; 
319-                             match  t1 { 
320-                                 Term :: SpecConstant ( SpecConstant :: Numeral ( numeral) )  => { 
321-                                     let  n = numeral. into_u128 ( ) . map_err ( |_| SmtEvalError :: EvalError ) ?; 
322-                                     num *= BigInt :: from ( n) ; 
323-                                 } , 
324-                                 Term :: SpecConstant ( SpecConstant :: Decimal ( Decimal ( d_str) ) )  => { 
325-                                     if  let  Some ( ( n,  d) )  = from_str_to_num_den ( d_str)  { 
326-                                         num *= n; 
327-                                         den *= d; 
328-                                     }  else  { 
329-                                         return  Err ( SmtEvalError :: EvalError ) ; 
330-                                     } 
331-                                 } , 
332-                                 _ => { 
333-                                     return  Err ( SmtEvalError :: EvalError ) ; 
334-                                 } , 
335-                             } 
336-                             match  t2 { 
337-                                 Term :: SpecConstant ( SpecConstant :: Numeral ( numeral) )  => { 
338-                                     let  n = numeral. into_u128 ( ) . map_err ( |_| SmtEvalError :: EvalError ) ?; 
339-                                     den *= BigInt :: from ( n) ; 
340-                                 } , 
341-                                 Term :: SpecConstant ( SpecConstant :: Decimal ( Decimal ( d_str) ) )  => { 
342-                                     if  let  Some ( ( n,  d) )  = from_str_to_num_den ( d_str)  { 
343-                                         den *= n; 
344-                                         num *= d; 
345-                                     }  else  { 
346-                                         return  Err ( SmtEvalError :: EvalError ) ; 
347-                                     } 
348-                                 } , 
349-                                 _ => { 
350-                                     return  Err ( SmtEvalError :: EvalError ) ; 
351-                                 } , 
352-                             } 
353-                             Ok ( BigRational :: new ( num,  den) ) 
354-                         } 
355-                         _ => Err ( SmtEvalError :: EvalError ) , 
356-                     } , 
357-                     None  => Err ( SmtEvalError :: EvalError ) , 
358-                 } 
359-             } , 
196+             Ok ( BigRational :: new ( numerator,  denominator) ) 
360197        } 
361-         
362198    } 
363199} 
0 commit comments