Skip to content

Commit 12f1571

Browse files
author
Joel Allred
authored
Merge pull request #4608 from allredj/clean-up/strings-refactor-binary-relations
Clean-up string solver: refactor binary relations [TG-7439]
2 parents 9d2ca43 + afef09f commit 12f1571

7 files changed

+69
-61
lines changed

src/solvers/strings/string_constraint_generator_code_points.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ std::pair<exprt, string_constraintst> add_axioms_for_code_point(
4141
exprt hex0400 = from_integer(0x0400, type);
4242

4343
binary_relation_exprt small(code_point, ID_lt, hex010000);
44-
implies_exprt a1(small, length_eq(res, 1));
44+
implies_exprt a1(small, equal_to(res.length(), 1));
4545
constraints.existential.push_back(a1);
4646

47-
implies_exprt a2(not_exprt(small), length_eq(res, 2));
47+
implies_exprt a2(not_exprt(small), equal_to(res.length(), 2));
4848
constraints.existential.push_back(a2);
4949

5050
typecast_exprt code_point_as_char(code_point, char_type);

src/solvers/strings/string_constraint_generator_comparison.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ string_constraint_generatort::add_axioms_for_hash_code(
208208
equal_exprt(it.first.length(), str.length()),
209209
and_exprt(
210210
notequal_exprt(str[i], it.first[i]),
211-
and_exprt(length_gt(str, i), is_positive(i))));
211+
and_exprt(greater_than(str.length(), i), is_positive(i))));
212212
hash_constraints.existential.push_back(or_exprt(c1, or_exprt(c2, c3)));
213213
}
214214
return {hash, std::move(hash_constraints)};
@@ -271,12 +271,17 @@ std::pair<exprt, string_constraintst> add_axioms_for_compare_to(
271271
typecast_exprt(s1.length(), return_type),
272272
typecast_exprt(s2.length(), return_type)));
273273
const or_exprt guard1(
274-
and_exprt(length_le(s1, s2.length()), length_gt(s1, x)),
275-
and_exprt(length_ge(s1, s2.length()), length_gt(s2, x)));
274+
and_exprt(
275+
less_than_or_equal_to(s1.length(), s2.length()),
276+
greater_than(s1.length(), x)),
277+
and_exprt(
278+
greater_or_equal_to(s1.length(), s2.length()),
279+
greater_than(s2.length(), x)));
276280
const and_exprt cond1(ret_char_diff, guard1);
277281
const or_exprt guard2(
278-
and_exprt(length_gt(s2, s1.length()), length_eq(s1, x)),
279-
and_exprt(length_gt(s1, s2.length()), length_eq(s2, x)));
282+
and_exprt(greater_than(s2.length(), s1.length()), equal_to(s1.length(), x)),
283+
and_exprt(
284+
greater_than(s1.length(), s2.length()), equal_to(s2.length(), x)));
280285
const and_exprt cond2(ret_length_diff, guard2);
281286

282287
const implies_exprt a3(

src/solvers/strings/string_constraint_generator_float.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ std::pair<exprt, string_constraintst> add_axioms_for_fractional_part(
278278
// no_trailing_zero: forall j:[2, max_size[. !(|res| = j+1 && res[j] = '0')
279279
// a3 : int_expr = sum_j 10^j (j < |res| ? res[j] - '0' : 0)
280280

281-
const and_exprt a1(length_gt(res, 1), length_le(res, max));
281+
const and_exprt a1(
282+
greater_than(res.length(), 1), less_than_or_equal_to(res.length(), max));
282283
constraints.existential.push_back(a1);
283284

284285
equal_exprt starts_with_dot(res[0], from_integer('.', char_type));

src/solvers/strings/string_constraint_generator_testing.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,12 @@ std::pair<exprt, string_constraintst> add_axioms_for_is_prefix(
6868
const exprt witness = fresh_symbol("witness_not_isprefix", index_type);
6969
const exprt strings_differ_at_witness = and_exprt(
7070
is_positive(witness),
71-
length_gt(prefix, witness),
71+
greater_than(prefix.length(), witness),
7272
notequal_exprt(str[plus_exprt(witness, offset)], prefix[witness]));
7373
const exprt s1_does_not_start_with_s0 = or_exprt(
7474
not_exprt(offset_within_bounds),
75-
not_exprt(length_ge(str, plus_exprt(prefix.length(), offset))),
75+
not_exprt(
76+
greater_or_equal_to(str.length(), plus_exprt(prefix.length(), offset))),
7677
strings_differ_at_witness);
7778
return implies_exprt(not_exprt(isprefix), s1_does_not_start_with_s0);
7879
}());
@@ -138,8 +139,8 @@ std::pair<exprt, string_constraintst> add_axioms_for_is_empty(
138139
symbol_exprt is_empty = fresh_symbol("is_empty");
139140
array_string_exprt s0 = get_string_expr(array_pool, f.arguments()[0]);
140141
string_constraintst constraints;
141-
constraints.existential = {implies_exprt(is_empty, length_eq(s0, 0)),
142-
implies_exprt(length_eq(s0, 0), is_empty)};
142+
constraints.existential = {implies_exprt(is_empty, equal_to(s0.length(), 0)),
143+
implies_exprt(equal_to(s0.length(), 0), is_empty)};
143144
return {typecast_exprt(is_empty, f.type()), std::move(constraints)};
144145
}
145146

@@ -186,7 +187,7 @@ std::pair<exprt, string_constraintst> add_axioms_for_is_suffix(
186187
get_string_expr(array_pool, args[swap_arguments ? 0u : 1u]);
187188
const typet &index_type = s0.length().type();
188189

189-
implies_exprt a1(issuffix, length_ge(s1, s0.length()));
190+
implies_exprt a1(issuffix, greater_or_equal_to(s1.length(), s0.length()));
190191
constraints.existential.push_back(a1);
191192

192193
symbol_exprt qvar = fresh_symbol("QA_suffix", index_type);
@@ -201,11 +202,11 @@ std::pair<exprt, string_constraintst> add_axioms_for_is_suffix(
201202
const plus_exprt shifted(witness, minus_exprt(s1.length(), s0.length()));
202203
or_exprt constr3(
203204
and_exprt(
204-
length_gt(s0, s1.length()),
205+
greater_than(s0.length(), s1.length()),
205206
equal_exprt(witness, from_integer(-1, index_type))),
206207
and_exprt(
207208
notequal_exprt(s0[witness], s1[shifted]),
208-
and_exprt(length_gt(s0, witness), is_positive(witness))));
209+
and_exprt(greater_than(s0.length(), witness), is_positive(witness))));
209210
implies_exprt a3(not_exprt(issuffix), constr3);
210211

211212
constraints.existential.push_back(a3);
@@ -246,7 +247,8 @@ std::pair<exprt, string_constraintst> add_axioms_for_contains(
246247
const symbol_exprt contains = fresh_symbol("contains");
247248
const symbol_exprt startpos = fresh_symbol("startpos_contains", index_type);
248249

249-
const implies_exprt a1(contains, length_ge(s0, s1.length()));
250+
const implies_exprt a1(
251+
contains, greater_or_equal_to(s0.length(), s1.length()));
250252
constraints.existential.push_back(a1);
251253

252254
minus_exprt length_diff(s0.length(), s1.length());
@@ -270,7 +272,8 @@ std::pair<exprt, string_constraintst> add_axioms_for_contains(
270272
const string_not_contains_constraintt a5 = {
271273
from_integer(0, index_type),
272274
plus_exprt(from_integer(1, index_type), length_diff),
273-
and_exprt(not_exprt(contains), length_ge(s0, s1.length())),
275+
and_exprt(
276+
not_exprt(contains), greater_or_equal_to(s0.length(), s1.length())),
274277
from_integer(0, index_type),
275278
s1.length(),
276279
s0,

src/solvers/strings/string_constraint_generator_transformation.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ std::pair<exprt, string_constraintst> add_axioms_for_set_length(
5454
// a2 : forall i< min(|s1|, k) .res[i] = s1[i]
5555
// a3 : forall |s1| <= i < |res|. res[i] = 0
5656

57-
constraints.existential.push_back(length_eq(res, k));
57+
constraints.existential.push_back(equal_to(res.length(), k));
5858

5959
const symbol_exprt idx = fresh_symbol("QA_index_set_length", index_type);
6060
const string_constraintt a2(
@@ -197,18 +197,19 @@ std::pair<exprt, string_constraintst> add_axioms_for_trim(
197197

198198
// Axiom 1.
199199
constraints.existential.push_back(
200-
length_ge(str, plus_exprt(idx, res.length())));
200+
greater_or_equal_to(str.length(), plus_exprt(idx, res.length())));
201201

202202
binary_relation_exprt a2(idx, ID_ge, from_integer(0, index_type));
203203
constraints.existential.push_back(a2);
204204

205-
const exprt a3 = length_ge(str, idx);
205+
const exprt a3 = greater_or_equal_to(str.length(), idx);
206206
constraints.existential.push_back(a3);
207207

208-
const exprt a4 = length_ge(res, from_integer(0, index_type));
208+
const exprt a4 =
209+
greater_or_equal_to(res.length(), from_integer(0, index_type));
209210
constraints.existential.push_back(a4);
210211

211-
const exprt a5 = length_le(res, str.length());
212+
const exprt a5 = less_than_or_equal_to(res.length(), str.length());
212213
constraints.existential.push_back(a5);
213214

214215
symbol_exprt n = fresh_symbol("QA_index_trim", index_type);

src/solvers/strings/string_constraint_generator_valueof.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ add_axioms_from_bool(const array_string_exprt &res, const exprt &b)
9696
// a4 : forall i < |"false"|. !eq => res[i]="false"[i]
9797

9898
std::string str_true = "true";
99-
const implies_exprt a1(eq, length_eq(res, str_true.length()));
99+
const implies_exprt a1(eq, equal_to(res.length(), str_true.length()));
100100
constraints.existential.push_back(a1);
101101

102102
for(std::size_t i = 0; i < str_true.length(); i++)
@@ -107,7 +107,8 @@ add_axioms_from_bool(const array_string_exprt &res, const exprt &b)
107107
}
108108

109109
std::string str_false = "false";
110-
const implies_exprt a3(not_exprt(eq), length_eq(res, str_false.length()));
110+
const implies_exprt a3(
111+
not_exprt(eq), equal_to(res.length(), str_false.length()));
111112
constraints.existential.push_back(a3);
112113

113114
for(std::size_t i = 0; i < str_false.length(); i++)
@@ -229,8 +230,9 @@ add_axioms_from_int_hex(const array_string_exprt &res, const exprt &i)
229230
exprt f_char = from_integer('f', char_type);
230231

231232
size_t max_size = 8;
232-
constraints.existential.push_back(
233-
and_exprt(length_gt(res, 0), length_le(res, max_size)));
233+
constraints.existential.push_back(and_exprt(
234+
greater_than(res.length(), 0),
235+
less_than_or_equal_to(res.length(), max_size)));
234236

235237
for(size_t size = 1; size <= max_size; size++)
236238
{
@@ -253,7 +255,7 @@ add_axioms_from_int_hex(const array_string_exprt &res, const exprt &i)
253255
all_numbers = and_exprt(all_numbers, is_number);
254256
}
255257

256-
const equal_exprt premise = length_eq(res, size);
258+
const equal_exprt premise = equal_to(res.length(), size);
257259
constraints.existential.push_back(
258260
implies_exprt(premise, and_exprt(equal_exprt(i, sum), all_numbers)));
259261

@@ -312,7 +314,7 @@ add_axioms_from_char(const array_string_exprt &res, const exprt &c)
312314
{
313315
string_constraintst constraints;
314316
constraints.existential = {
315-
and_exprt(equal_exprt(res[0], c), length_eq(res, 1))};
317+
and_exprt(equal_exprt(res[0], c), equal_to(res.length(), 1))};
316318
return {from_integer(0, get_return_code_type()), std::move(constraints)};
317319
}
318320

@@ -344,7 +346,8 @@ string_constraintst add_axioms_for_correct_number_format(
344346
is_digit_with_radix(chr, strict_formatting, radix_as_char, radix_ul);
345347

346348
// |str| > 0
347-
const exprt non_empty = length_ge(str, from_integer(1, index_type));
349+
const exprt non_empty =
350+
greater_or_equal_to(str.length(), from_integer(1, index_type));
348351
constraints.existential.push_back(non_empty);
349352

350353
if(strict_formatting)
@@ -364,11 +367,12 @@ string_constraintst add_axioms_for_correct_number_format(
364367
// str[0]='+' or '-' ==> |str| > 1
365368
const implies_exprt contains_digit(
366369
or_exprt(starts_with_minus, starts_with_plus),
367-
length_ge(str, from_integer(2, index_type)));
370+
greater_or_equal_to(str.length(), from_integer(2, index_type)));
368371
constraints.existential.push_back(contains_digit);
369372

370373
// |str| <= max_size
371-
constraints.existential.push_back(length_le(str, max_size));
374+
constraints.existential.push_back(
375+
less_than_or_equal_to(str.length(), max_size));
372376

373377
// forall 1 <= i < |str| . is_digit_with_radix(str[i], radix)
374378
// We unfold the above because we know that it will be used for all i up to
@@ -377,7 +381,7 @@ string_constraintst add_axioms_for_correct_number_format(
377381
{
378382
/// index < length => is_digit_with_radix(str[index], radix)
379383
const implies_exprt character_at_index_is_digit(
380-
length_ge(str, from_integer(index + 1, index_type)),
384+
greater_or_equal_to(str.length(), from_integer(index + 1, index_type)),
381385
is_digit_with_radix(
382386
str[index], strict_formatting, radix_as_char, radix_ul));
383387
constraints.existential.push_back(character_at_index_is_digit);
@@ -389,7 +393,8 @@ string_constraintst add_axioms_for_correct_number_format(
389393

390394
// no_leading_zero : str[0] = '0' => |str| = 1
391395
const implies_exprt no_leading_zero(
392-
equal_exprt(chr, zero_char), length_eq(str, from_integer(1, index_type)));
396+
equal_exprt(chr, zero_char),
397+
equal_to(str.length(), from_integer(1, index_type)));
393398
constraints.existential.push_back(no_leading_zero);
394399

395400
// no_leading_zero_after_minus : str[0]='-' => str[1]!='0'
@@ -435,7 +440,7 @@ string_constraintst add_axioms_for_characters_in_integer_string(
435440
/// add_axioms_for_correct_number_format which say that the string must
436441
/// contain at least one digit, so we don't have to worry about "+" or "-".
437442
constraints.existential.push_back(
438-
implies_exprt(length_eq(str, 1), equal_exprt(input_int, sum)));
443+
implies_exprt(equal_to(str.length(), 1), equal_exprt(input_int, sum)));
439444

440445
for(size_t size = 2; size <= max_string_length; size++)
441446
{
@@ -473,7 +478,7 @@ string_constraintst add_axioms_for_characters_in_integer_string(
473478
}
474479
sum = new_sum;
475480

476-
const equal_exprt premise = length_eq(str, size);
481+
const equal_exprt premise = equal_to(str.length(), size);
477482

478483
if(!digit_constraints.empty())
479484
{

src/util/string_expr.h

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,44 @@ Author: Romain Brenguier, [email protected]
1616
#include "refined_string_type.h"
1717
#include "std_expr.h"
1818

19-
// Comparison on the length of the strings
20-
template <typename T>
21-
binary_relation_exprt length_ge(const T &lhs, const exprt &rhs)
19+
inline binary_relation_exprt greater_or_equal_to(exprt lhs, exprt rhs)
2220
{
23-
PRECONDITION(rhs.type() == lhs.length().type());
24-
return binary_relation_exprt(lhs.length(), ID_ge, rhs);
21+
PRECONDITION(rhs.type() == lhs.type());
22+
return binary_relation_exprt(std::move(lhs), ID_ge, std::move(rhs));
2523
}
2624

27-
template <typename T>
28-
binary_relation_exprt length_gt(const T &lhs, const exprt &rhs)
25+
inline binary_relation_exprt greater_than(exprt lhs, exprt rhs)
2926
{
30-
PRECONDITION(rhs.type() == lhs.length().type());
31-
return binary_relation_exprt(rhs, ID_lt, lhs.length());
27+
PRECONDITION(rhs.type() == lhs.type());
28+
return binary_relation_exprt(std::move(rhs), ID_lt, std::move(lhs));
3229
}
3330

34-
template <typename T>
35-
binary_relation_exprt length_gt(const T &lhs, mp_integer i)
31+
inline binary_relation_exprt greater_than(const exprt &lhs, mp_integer i)
3632
{
37-
return length_gt(lhs, from_integer(i, lhs.length().type()));
33+
return binary_relation_exprt(from_integer(i, lhs.type()), ID_lt, lhs);
3834
}
3935

40-
template <typename T>
41-
binary_relation_exprt length_le(const T &lhs, const exprt &rhs)
36+
inline binary_relation_exprt less_than_or_equal_to(exprt lhs, exprt rhs)
4237
{
43-
PRECONDITION(rhs.type() == lhs.length().type());
44-
return binary_relation_exprt(lhs.length(), ID_le, rhs);
38+
PRECONDITION(rhs.type() == lhs.type());
39+
return binary_relation_exprt(std::move(lhs), ID_le, std::move(rhs));
4540
}
4641

47-
template <typename T>
48-
binary_relation_exprt length_le(const T &lhs, mp_integer i)
42+
inline binary_relation_exprt
43+
less_than_or_equal_to(const exprt &lhs, mp_integer i)
4944
{
50-
return length_le(lhs, from_integer(i, lhs.length().type()));
45+
return binary_relation_exprt(lhs, ID_le, from_integer(i, lhs.type()));
5146
}
5247

53-
template <typename T>
54-
equal_exprt length_eq(const T &lhs, const exprt &rhs)
48+
inline equal_exprt equal_to(exprt lhs, exprt rhs)
5549
{
56-
PRECONDITION(rhs.type() == lhs.length().type());
57-
return equal_exprt(lhs.length(), rhs);
50+
PRECONDITION(rhs.type() == lhs.type());
51+
return equal_exprt(std::move(lhs), std::move(rhs));
5852
}
5953

60-
template <typename T>
61-
equal_exprt length_eq(const T &lhs, mp_integer i)
54+
inline equal_exprt equal_to(const exprt &lhs, mp_integer i)
6255
{
63-
return length_eq(lhs, from_integer(i, lhs.length().type()));
56+
return equal_exprt(lhs, from_integer(i, lhs.type()));
6457
}
6558

6659
// Representation of strings as arrays

0 commit comments

Comments
 (0)