@@ -21,10 +21,27 @@ Author: Alberto Griggio, alberto.griggio@gmail.com
21
21
#include < langapi/language_util.h>
22
22
#include < java_bytecode/java_types.h>
23
23
24
+ /* ******************************************************************\
25
+
26
+ Constructor: string_refinementt
27
+
28
+ Inputs: a namespace, a decision procedure, a bound on the number
29
+ of refinements and a boolean flag `concretize_result`
30
+
31
+ Purpose: refinement_bound is a bound on the number of refinement allowed.
32
+ if `concretize_result` is set to true, at the end of the decision
33
+ procedure, the solver try to find a concrete value for each
34
+ character
35
+
36
+ \*******************************************************************/
37
+
24
38
string_refinementt::string_refinementt (
25
- const namespacet &_ns, propt &_prop, unsigned refinement_bound):
39
+ const namespacet &_ns,
40
+ propt &_prop,
41
+ unsigned refinement_bound):
26
42
supert(_ns, _prop),
27
43
use_counter_example(false ),
44
+ do_concretizing(false ),
28
45
initial_loop_bound(refinement_bound)
29
46
{ }
30
47
@@ -194,7 +211,7 @@ exprt string_refinementt::substitute_function_applications(exprt expr)
194
211
return expr;
195
212
}
196
213
197
- bool string_refinementt::is_char_array (const typet &type)
214
+ bool string_refinementt::is_char_array (const typet &type) const
198
215
{
199
216
if (type.id ()==ID_symbol)
200
217
return is_char_array (ns.follow (type));
@@ -220,7 +237,12 @@ bool string_refinementt::add_axioms_for_string_assigns(const exprt &lhs,
220
237
if (is_char_array (rhs.type ()))
221
238
{
222
239
set_char_array_equality (lhs, rhs);
223
- add_symbol_to_symbol_map (lhs, rhs);
240
+ if (rhs.id () != ID_nondet_symbol)
241
+ add_symbol_to_symbol_map (lhs, rhs);
242
+ else
243
+ add_symbol_to_symbol_map (
244
+ lhs, generator.fresh_symbol (" nondet_array" , lhs.type ()));
245
+
224
246
return false ;
225
247
}
226
248
if (refined_string_typet::is_refined_string_type (rhs.type ()))
@@ -235,6 +257,46 @@ bool string_refinementt::add_axioms_for_string_assigns(const exprt &lhs,
235
257
236
258
/* ******************************************************************\
237
259
260
+ Function: string_refinementt::concretize_results
261
+
262
+ Purpose: For each string whose length has been solved, add constants
263
+ to the index set to force the solver to pick concrete values
264
+ for each character
265
+
266
+ \*******************************************************************/
267
+
268
+ void string_refinementt::concretize_results ()
269
+ {
270
+ for (const auto & it : symbol_resolve)
271
+ {
272
+ if (refined_string_typet::is_refined_string_type (it.second .type ()))
273
+ {
274
+ string_exprt str=to_string_expr (it.second );
275
+ exprt length=current_model[str.length ()];
276
+ mp_integer found_length;
277
+ if (!to_integer (length, found_length))
278
+ {
279
+ assert (found_length.is_long () && found_length >= 0 );
280
+ size_t concretize_limit=found_length.to_long ();
281
+ concretize_limit=concretize_limit>MAX_CONCRETE_STRING_SIZE?
282
+ MAX_CONCRETE_STRING_SIZE:concretize_limit;
283
+ exprt content_expr=str.content ();
284
+ replace_expr (current_model, content_expr);
285
+ for (size_t i=0 ; i<concretize_limit; ++i)
286
+ {
287
+ auto i_expr=from_integer (i, str.length ().type ());
288
+ debug () << " Concretizing " << from_expr (content_expr)
289
+ << " / " << i << eom;
290
+ current_index_set[str.content ()].insert (i_expr);
291
+ }
292
+ }
293
+ }
294
+ }
295
+ add_instantiations ();
296
+ }
297
+
298
+ /* ******************************************************************\
299
+
238
300
Function: string_refinementt::set_to
239
301
240
302
Inputs: an expression and the value to set it to
@@ -397,7 +459,13 @@ decision_proceduret::resultt string_refinementt::dec_solve()
397
459
if (current_index_set.empty ())
398
460
{
399
461
debug () << " current index set is empty" << eom;
400
- return D_SATISFIABLE;
462
+ if (do_concretizing)
463
+ {
464
+ concretize_results ();
465
+ do_concretizing=false ;
466
+ }
467
+ else
468
+ return D_SATISFIABLE;
401
469
}
402
470
403
471
display_index_set ();
@@ -488,7 +556,7 @@ Function: string_refinementt::get_array
488
556
489
557
exprt string_refinementt::get_array (const exprt &arr, const exprt &size)
490
558
{
491
- exprt arr_val=get (arr);
559
+ exprt arr_val=get_array (arr);
492
560
exprt size_val=get (size);
493
561
typet char_type=arr.type ().subtype ();
494
562
typet index_type=size.type ();
@@ -566,6 +634,32 @@ exprt string_refinementt::get_array(const exprt &arr, const exprt &size)
566
634
return ret;
567
635
}
568
636
637
+
638
+ /* ******************************************************************\
639
+
640
+ Function: string_refinementt::get_array
641
+
642
+ Inputs: an expression representing an array
643
+
644
+ Outputs: an expression
645
+
646
+ Purpose: get a model of an array of unknown size and infer the size if
647
+ possible
648
+
649
+ \*******************************************************************/
650
+
651
+ exprt string_refinementt::get_array (const exprt &arr)
652
+ {
653
+ exprt arr_model=supert::get (arr);
654
+ if (arr_model.id ()==ID_array)
655
+ {
656
+ array_typet &arr_type=to_array_type (arr_model.type ());
657
+ arr_type.size ()=from_integer (
658
+ arr_model.operands ().size (), arr_type.size ().type ());
659
+ }
660
+ return arr_model;
661
+ }
662
+
569
663
/* ******************************************************************\
570
664
571
665
Function: string_refinementt::string_of_array
@@ -616,56 +710,64 @@ std::string string_refinementt::string_of_array(const array_exprt &arr)
616
710
617
711
Function: string_refinementt::fill_model
618
712
619
- Outputs: a replace map
620
-
621
- Purpose: maps the variable created by the solver to constant expressions
622
- given by the current model
713
+ Purpose: Fill in `current_model` by mapping the variables created by
714
+ the solver to constant expressions given by the current model
623
715
624
716
\*******************************************************************/
625
717
626
- replace_mapt string_refinementt::fill_model ()
718
+ void string_refinementt::fill_model ()
627
719
{
628
- replace_mapt fmodel;
629
-
630
720
for (auto it : symbol_resolve)
631
721
{
632
722
if (refined_string_typet::is_refined_string_type (it.second .type ()))
633
723
{
634
724
string_exprt refined=to_string_expr (it.second );
725
+ // TODO: check whith this is necessary:
635
726
replace_expr (symbol_resolve, refined);
636
727
const exprt &econtent=refined.content ();
637
728
const exprt &elength=refined.length ();
638
729
639
- exprt len=get (elength);
730
+ exprt len=supert:: get (elength);
640
731
exprt arr=get_array (econtent, len);
641
732
642
- fmodel[elength]=len;
643
- fmodel[econtent]=arr;
644
-
733
+ current_model[elength]=len;
734
+ current_model[econtent]=arr;
645
735
debug () << from_expr (to_symbol_expr (it.first )) << " ="
646
736
<< from_expr (refined);
737
+
647
738
if (arr.id ()==ID_array)
648
739
debug () << " = \" " << string_of_array (to_array_expr (arr))
649
740
<< " \" (size:" << from_expr (len) << " )" << eom;
650
741
else
651
742
debug () << " = " << from_expr (arr) << " " << eom;
652
743
}
744
+ else
745
+ {
746
+ assert (is_char_array (it.second .type ()));
747
+ exprt arr=it.second ;
748
+ replace_expr (symbol_resolve, arr);
749
+ replace_expr (current_model, arr);
750
+ exprt arr_model=get_array (arr);
751
+ current_model[it.first ]=arr_model;
752
+
753
+ debug () << from_expr (to_symbol_expr (it.first )) << " ="
754
+ << from_expr (arr) << " = " << from_expr (arr_model) << " " << eom;
755
+ }
653
756
}
654
757
655
758
for (auto it : generator.boolean_symbols )
656
759
{
657
760
debug () << " " << it.get_identifier () << " := "
658
- << from_expr (get (it)) << eom;
659
- fmodel [it]=get (it);
761
+ << from_expr (supert:: get (it)) << eom;
762
+ current_model [it]=supert:: get (it);
660
763
}
661
764
662
765
for (auto it : generator.index_symbols )
663
766
{
664
- debug () << " " << it.get_identifier () << " := "
665
- << from_expr (get (it)) << eom;
666
- fmodel [it]=get (it);
767
+ debug () << " " << it.get_identifier () << " := "
768
+ << from_expr (supert:: get (it)) << eom;
769
+ current_model [it]=supert:: get (it);
667
770
}
668
- return fmodel;
669
771
}
670
772
671
773
/* ******************************************************************\
@@ -730,7 +832,7 @@ bool string_refinementt::check_axioms()
730
832
<< " ===========================================" << eom;
731
833
debug () << " string_refinementt::check_axioms: build the"
732
834
<< " interpretation from the model of the prop_solver" << eom;
733
- replace_mapt fmodel= fill_model ();
835
+ fill_model ();
734
836
735
837
// Maps from indexes of violated universal axiom to a witness of violation
736
838
std::map<size_t , exprt> violated;
@@ -746,10 +848,10 @@ bool string_refinementt::check_axioms()
746
848
exprt prem=axiom.premise ();
747
849
exprt body=axiom.body ();
748
850
749
- replace_expr (fmodel , bound_inf);
750
- replace_expr (fmodel , bound_sup);
751
- replace_expr (fmodel , prem);
752
- replace_expr (fmodel , body);
851
+ replace_expr (current_model , bound_inf);
852
+ replace_expr (current_model , bound_sup);
853
+ replace_expr (current_model , prem);
854
+ replace_expr (current_model , body);
753
855
string_constraintt axiom_in_model (
754
856
univ_var, bound_inf, bound_sup, prem, body);
755
857
@@ -1320,3 +1422,23 @@ void string_refinementt::instantiate_not_contains(
1320
1422
new_lemmas.push_back (witness_bounds);
1321
1423
}
1322
1424
}
1425
+
1426
+ /* ******************************************************************\
1427
+
1428
+ Function: string_refinementt::get
1429
+
1430
+ Inputs: an expression
1431
+
1432
+ Outputs: an expression
1433
+
1434
+ Purpose: evaluation of the expression in the current model
1435
+
1436
+ \*******************************************************************/
1437
+
1438
+ exprt string_refinementt::get (const exprt &expr) const
1439
+ {
1440
+ exprt ecopy (expr);
1441
+ replace_expr (symbol_resolve, ecopy);
1442
+ replace_expr (current_model, ecopy);
1443
+ return supert::get (ecopy);
1444
+ }
0 commit comments