32
32
static bool is_valid_string_constraint (
33
33
messaget::mstreamt &stream,
34
34
const namespacet &ns,
35
- const string_constraintt &expr );
35
+ const string_constraintt &constraint );
36
36
37
37
static optionalt<exprt> find_counter_example (
38
38
const namespacet &ns,
@@ -693,7 +693,7 @@ decision_proceduret::resultt string_refinementt::dec_solve()
693
693
constraints.end (),
694
694
std::back_inserter (axioms.universal ),
695
695
[&](string_constraintt constraint) { // NOLINT
696
- symbol_resolve .replace_expr (constraint );
696
+ constraint .replace_expr (symbol_resolve );
697
697
DATA_INVARIANT (
698
698
is_valid_string_constraint (error (), ns, constraint),
699
699
string_refinement_invariantt (
@@ -1243,34 +1243,22 @@ static exprt negation_of_not_contains_constraint(
1243
1243
1244
1244
// / Debugging function which outputs the different steps an axiom goes through
1245
1245
// / to be checked in check axioms.
1246
+ // / \tparam T: can be either string_constraintt or string_not_contains_constraintt
1247
+ template <typename T>
1246
1248
static void debug_check_axioms_step (
1247
1249
messaget::mstreamt &stream,
1248
1250
const namespacet &ns,
1249
- const exprt &axiom,
1250
- const exprt &axiom_in_model,
1251
+ const T &axiom,
1252
+ const T &axiom_in_model,
1251
1253
const exprt &negaxiom,
1252
1254
const exprt &with_concretized_arrays)
1253
1255
{
1254
1256
static const std::string indent = " " ;
1255
1257
static const std::string indent2 = " " ;
1256
1258
stream << indent2 << " - axiom:\n " << indent2 << indent;
1257
-
1258
- if (axiom.id () == ID_string_constraint)
1259
- stream << to_string (to_string_constraint (axiom));
1260
- else if (axiom.id () == ID_string_not_contains_constraint)
1261
- stream << to_string (to_string_not_contains_constraint (axiom));
1262
- else
1263
- stream << format (axiom);
1259
+ stream << to_string (axiom);
1264
1260
stream << ' \n ' << indent2 << " - axiom_in_model:\n " << indent2 << indent;
1265
-
1266
- if (axiom_in_model.id () == ID_string_constraint)
1267
- stream << to_string (to_string_constraint (axiom_in_model));
1268
- else if (axiom_in_model.id () == ID_string_not_contains_constraint)
1269
- stream << to_string (to_string_not_contains_constraint (axiom_in_model));
1270
- else
1271
- stream << format (axiom_in_model);
1272
-
1273
- stream << ' \n '
1261
+ stream << to_string (axiom_in_model) << ' \n '
1274
1262
<< indent2 << " - negated_axiom:\n "
1275
1263
<< indent2 << indent << format (negaxiom) << ' \n ' ;
1276
1264
stream << indent2 << " - negated_axiom_with_concretized_arrays:\n "
@@ -1327,16 +1315,11 @@ static std::pair<bool, std::vector<exprt>> check_axioms(
1327
1315
for (size_t i=0 ; i<axioms.universal .size (); i++)
1328
1316
{
1329
1317
const string_constraintt &axiom=axioms.universal [i];
1330
- const symbol_exprt &univ_var=axiom.univ_var ();
1331
- const exprt &bound_inf=axiom.lower_bound ();
1332
- const exprt &bound_sup=axiom.upper_bound ();
1333
- const exprt &prem=axiom.premise ();
1334
- INVARIANT (
1335
- prem == true_exprt (), " string constraint premises are not supported" );
1336
- const exprt &body=axiom.body ();
1337
-
1338
1318
const string_constraintt axiom_in_model (
1339
- univ_var, get (bound_inf), get (bound_sup), get (body));
1319
+ axiom.univ_var ,
1320
+ get (axiom.lower_bound ),
1321
+ get (axiom.upper_bound ),
1322
+ get (axiom.body ));
1340
1323
1341
1324
exprt negaxiom = axiom_in_model.negation ();
1342
1325
negaxiom = simplify_expr (negaxiom, ns);
@@ -1347,11 +1330,12 @@ static std::pair<bool, std::vector<exprt>> check_axioms(
1347
1330
debug_check_axioms_step (
1348
1331
stream, ns, axiom, axiom_in_model, negaxiom, with_concretized_arrays);
1349
1332
1350
- if (const auto &witness=
1351
- find_counter_example (ns, ui, with_concretized_arrays, univ_var))
1333
+ if (
1334
+ const auto &witness =
1335
+ find_counter_example (ns, ui, with_concretized_arrays, axiom.univ_var ))
1352
1336
{
1353
- stream << indent2 << " - violated_for: " << univ_var. get_identifier ()
1354
- << " = " << format (*witness) << eom;
1337
+ stream << indent2 << " - violated_for: " << format (axiom. univ_var ) << " = "
1338
+ << format (*witness) << eom;
1355
1339
violated[i]=*witness;
1356
1340
}
1357
1341
else
@@ -1430,13 +1414,13 @@ static std::pair<bool, std::vector<exprt>> check_axioms(
1430
1414
const exprt &val=v.second ;
1431
1415
const string_constraintt &axiom=axioms.universal [v.first ];
1432
1416
1433
- implies_exprt instance (axiom.premise (), axiom. body () );
1434
- replace_expr (axiom.univ_var () , val, instance);
1417
+ exprt instance (axiom.body );
1418
+ replace_expr (axiom.univ_var , val, instance);
1435
1419
// We are not sure the index set contains only positive numbers
1436
1420
and_exprt bounds (
1437
1421
axiom.univ_within_bounds (),
1438
1422
binary_relation_exprt (from_integer (0 , val.type ()), ID_le, val));
1439
- replace_expr (axiom.univ_var () , val, bounds);
1423
+ replace_expr (axiom.univ_var , val, bounds);
1440
1424
const implies_exprt counter (bounds, instance);
1441
1425
lemmas.push_back (counter);
1442
1426
}
@@ -1794,10 +1778,10 @@ static void initial_index_set(
1794
1778
const namespacet &ns,
1795
1779
const string_constraintt &axiom)
1796
1780
{
1797
- const symbol_exprt &qvar= axiom.univ_var () ;
1798
- const auto &bound = axiom.upper_bound () ;
1799
- auto it = axiom.body () .depth_begin ();
1800
- const auto end = axiom.body () .depth_end ();
1781
+ const symbol_exprt &qvar = axiom.univ_var ;
1782
+ const auto &bound = axiom.upper_bound ;
1783
+ auto it = axiom.body .depth_begin ();
1784
+ const auto end = axiom.body .depth_end ();
1801
1785
while (it != end)
1802
1786
{
1803
1787
if (it->id () == ID_index && is_char_type (it->type ()))
@@ -1940,18 +1924,17 @@ static exprt instantiate(
1940
1924
const exprt &str,
1941
1925
const exprt &val)
1942
1926
{
1943
- const optionalt<exprt> idx = find_index (axiom.body () , str, axiom.univ_var () );
1927
+ const optionalt<exprt> idx = find_index (axiom.body , str, axiom.univ_var );
1944
1928
if (!idx.has_value ())
1945
1929
return true_exprt ();
1946
1930
1947
- const exprt r = compute_inverse_function (stream, axiom.univ_var () , val, *idx);
1931
+ const exprt r = compute_inverse_function (stream, axiom.univ_var , val, *idx);
1948
1932
implies_exprt instance (
1949
1933
and_exprt (
1950
- binary_relation_exprt (axiom.univ_var (), ID_ge, axiom.lower_bound ()),
1951
- binary_relation_exprt (axiom.univ_var (), ID_lt, axiom.upper_bound ()),
1952
- axiom.premise ()),
1953
- axiom.body ());
1954
- replace_expr (axiom.univ_var (), r, instance);
1934
+ binary_relation_exprt (axiom.univ_var , ID_ge, axiom.lower_bound ),
1935
+ binary_relation_exprt (axiom.univ_var , ID_lt, axiom.upper_bound )),
1936
+ axiom.body );
1937
+ replace_expr (axiom.univ_var , r, instance);
1955
1938
return instance;
1956
1939
}
1957
1940
@@ -2208,11 +2191,11 @@ is_linear_arithmetic_expr(const exprt &expr, const symbol_exprt &var)
2208
2191
// / \param [in] expr: The string constraint to check
2209
2192
// / \return true if the universal variable only occurs in index expressions,
2210
2193
// / false otherwise.
2211
- static bool universal_only_in_index (const string_constraintt &expr )
2194
+ static bool universal_only_in_index (const string_constraintt &constr )
2212
2195
{
2213
- for (auto it = expr .body () .depth_begin (); it != expr .body () .depth_end ();)
2196
+ for (auto it = constr .body .depth_begin (); it != constr .body .depth_end ();)
2214
2197
{
2215
- if (*it == expr .univ_var () )
2198
+ if (*it == constr .univ_var )
2216
2199
return false ;
2217
2200
if (it->id () == ID_index)
2218
2201
it.next_sibling_or_parent ();
@@ -2226,35 +2209,20 @@ static bool universal_only_in_index(const string_constraintt &expr)
2226
2209
// / \related string_constraintt
2227
2210
// / \param stream: message stream
2228
2211
// / \param ns: namespace
2229
- // / \param [in] expr : the string constraint to check
2212
+ // / \param [in] constraint : the string constraint to check
2230
2213
// / \return whether the constraint satisfies the invariant
2231
2214
static bool is_valid_string_constraint (
2232
2215
messaget::mstreamt &stream,
2233
2216
const namespacet &ns,
2234
- const string_constraintt &expr )
2217
+ const string_constraintt &constraint )
2235
2218
{
2236
2219
const auto eom=messaget::eom;
2237
- // Condition 1: The premise cannot contain any string indices
2238
- const array_index_mapt premise_indices=gather_indices (expr.premise ());
2239
- if (!premise_indices.empty ())
2240
- {
2241
- stream << " Premise has indices: " << format (expr) << " , map: {" ;
2242
- for (const auto &pair : premise_indices)
2243
- {
2244
- stream << format (pair.first ) << " : {" ;
2245
- for (const auto &i : pair.second )
2246
- stream << format (i) << " , " ;
2247
- }
2248
- stream << " }}" << eom;
2249
- return false ;
2250
- }
2251
-
2252
- const array_index_mapt body_indices=gather_indices (expr.body ());
2220
+ const array_index_mapt body_indices = gather_indices (constraint.body );
2253
2221
// Must validate for each string. Note that we have an invariant that the
2254
2222
// second value in the pair is non-empty.
2255
2223
for (const auto &pair : body_indices)
2256
2224
{
2257
- // Condition 2 : All indices of the same string must be the of the same form
2225
+ // Condition 1 : All indices of the same string must be the of the same form
2258
2226
const exprt rep=pair.second .back ();
2259
2227
for (size_t j=0 ; j<pair.second .size ()-1 ; j++)
2260
2228
{
@@ -2263,25 +2231,26 @@ static bool is_valid_string_constraint(
2263
2231
const exprt result=simplify_expr (equals, ns);
2264
2232
if (result.is_false ())
2265
2233
{
2266
- stream << " Indices not equal: " << format (expr )
2234
+ stream << " Indices not equal: " << to_string (constraint )
2267
2235
<< " , str: " << format (pair.first ) << eom;
2268
2236
return false ;
2269
2237
}
2270
2238
}
2271
2239
2272
- // Condition 3 : f must be linear in the quantified variable
2273
- if (!is_linear_arithmetic_expr (rep, expr .univ_var () ))
2240
+ // Condition 2 : f must be linear in the quantified variable
2241
+ if (!is_linear_arithmetic_expr (rep, constraint .univ_var ))
2274
2242
{
2275
- stream << " f is not linear: " << format (expr )
2243
+ stream << " f is not linear: " << to_string (constraint )
2276
2244
<< " , str: " << format (pair.first ) << eom;
2277
2245
return false ;
2278
2246
}
2279
2247
2280
- // Condition 4 : the quantified variable can only occur in indices in the
2248
+ // Condition 3 : the quantified variable can only occur in indices in the
2281
2249
// body
2282
- if (!universal_only_in_index (expr ))
2250
+ if (!universal_only_in_index (constraint ))
2283
2251
{
2284
- stream << " Universal variable outside of index:" << format (expr) << eom;
2252
+ stream << " Universal variable outside of index:" << to_string (constraint)
2253
+ << eom;
2285
2254
return false ;
2286
2255
}
2287
2256
}
0 commit comments