Skip to content

Commit 71990ad

Browse files
romainbrenguiertautschnig
authored andcommitted
Add an add_axioms_for_concat_substr function
Implements the concatenation of a substring of the second argument. This will make the encoding of StringBuilder.append(CharSequence s, int start, int end) more efficient. Part of test-gen/#256
1 parent 9546c19 commit 71990ad

File tree

2 files changed

+60
-23
lines changed

2 files changed

+60
-23
lines changed

src/solvers/refinement/string_constraint_generator.h

+5
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ class string_constraint_generatort
145145
string_exprt add_axioms_for_copy(const function_application_exprt &f);
146146
string_exprt add_axioms_for_concat(
147147
const string_exprt &s1, const string_exprt &s2);
148+
string_exprt add_axioms_for_concat_substr(
149+
const string_exprt &s1,
150+
const string_exprt &s2,
151+
const exprt &start_index,
152+
const exprt &end_index);
148153
string_exprt add_axioms_for_concat(const function_application_exprt &f);
149154
string_exprt add_axioms_for_concat_int(const function_application_exprt &f);
150155
string_exprt add_axioms_for_concat_long(const function_application_exprt &f);

src/solvers/refinement/string_constraint_generator_concat.cpp

+55-23
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,85 @@ Author: Romain Brenguier, [email protected]
1414
#include <solvers/refinement/string_constraint_generator.h>
1515

1616
/// add axioms to say that the returned string expression is equal to the
17-
/// concatenation of the two string expressions given as input
18-
/// \par parameters: two string expressions
17+
/// concatenation of s1 with the substring of s2 starting at index start_index
18+
/// and ending at index end_index. If start_index >= end_index, the value
19+
/// returned is s1. If end_index > |s2| and/or start_index < 0, the appended
20+
/// string will be of length end_index - start_index and padded with non-
21+
/// deterministic values.
22+
/// \param s1: string expression
23+
/// \param s2: string expression
24+
/// \param start_index: expression representing an integer
25+
/// \param end_index: expression representing an integer
1926
/// \return a new string expression
20-
string_exprt string_constraint_generatort::add_axioms_for_concat(
21-
const string_exprt &s1, const string_exprt &s2)
27+
string_exprt string_constraint_generatort::add_axioms_for_concat_substr(
28+
const string_exprt &s1,
29+
const string_exprt &s2,
30+
const exprt &start_index,
31+
const exprt &end_index)
2232
{
2333
const refined_string_typet &ref_type=to_refined_string_type(s1.type());
2434
string_exprt res=fresh_string(ref_type);
2535

2636
// We add axioms:
27-
// a1 : |res|=|s1|+|s2|
28-
// a2 : |s1| <= |res| (to avoid overflow with very long strings)
29-
// a3 : |s2| <= |res| (to avoid overflow with very long strings)
30-
// a4 : forall i<|s1|. res[i]=s1[i]
31-
// a5 : forall i<|s2|. res[i+|s1|]=s2[i]
32-
33-
equal_exprt a1(
34-
res.length(), plus_exprt_with_overflow_check(s1.length(), s2.length()));
37+
// a1 : end_index > start_index => |res|=|s1|+ end_index - start_index
38+
// a2 : end_index <= start_index => res = s1
39+
// a3 : forall i<|s1|. res[i]=s1[i]
40+
// a4 : forall i< end_index - start_index. res[i+|s1|]=s2[start_index+i]
41+
42+
binary_relation_exprt prem(end_index, ID_gt, start_index);
43+
44+
exprt res_length=plus_exprt_with_overflow_check(
45+
s1.length(), minus_exprt(end_index, start_index));
46+
implies_exprt a1(prem, equal_exprt(res.length(), res_length));
3547
axioms.push_back(a1);
36-
axioms.push_back(s1.axiom_for_is_shorter_than(res));
37-
axioms.push_back(s2.axiom_for_is_shorter_than(res));
48+
49+
implies_exprt a2(not_exprt(prem), equal_exprt(res.length(), s1.length()));
50+
axioms.push_back(a2);
3851

3952
symbol_exprt idx=fresh_univ_index("QA_index_concat", res.length().type());
40-
string_constraintt a4(idx, s1.length(), equal_exprt(s1[idx], res[idx]));
41-
axioms.push_back(a4);
53+
string_constraintt a3(idx, s1.length(), equal_exprt(s1[idx], res[idx]));
54+
axioms.push_back(a3);
4255

4356
symbol_exprt idx2=fresh_univ_index("QA_index_concat2", res.length().type());
44-
equal_exprt res_eq(s2[idx2], res[plus_exprt(idx2, s1.length())]);
45-
string_constraintt a5(idx2, s2.length(), res_eq);
46-
axioms.push_back(a5);
57+
equal_exprt res_eq(
58+
res[plus_exprt(idx2, s1.length())], s2[plus_exprt(start_index, idx2)]);
59+
string_constraintt a4(idx2, minus_exprt(end_index, start_index), res_eq);
60+
axioms.push_back(a4);
4761

4862
return res;
4963
}
5064

5165
/// add axioms to say that the returned string expression is equal to the
52-
/// concatenation of the two string arguments of the function application
66+
/// concatenation of the two string expressions given as input
67+
/// \par parameters: two string expressions
68+
/// \return a new string expression
69+
string_exprt string_constraint_generatort::add_axioms_for_concat(
70+
const string_exprt &s1, const string_exprt &s2)
71+
{
72+
exprt index_zero=from_integer(0, s2.length().type());
73+
return add_axioms_for_concat_substr(s1, s2, index_zero, s2.length());
74+
}
75+
76+
/// add axioms to say that the returned string expression is equal to the
77+
/// concatenation of the two string arguments of the function application. In
78+
/// case 4 arguments instead of 2 are given the last two arguments are
79+
/// intepreted as a start index and last index from which we extract a substring
80+
/// of the second argument: this is similar to the Java
81+
/// StringBuiledr.append(CharSequence s, int start, int end) method.
5382
/// \par parameters: function application with two arguments which are strings
5483
/// \return a new string expression
5584
string_exprt string_constraint_generatort::add_axioms_for_concat(
5685
const function_application_exprt &f)
5786
{
5887
const function_application_exprt::argumentst &args=f.arguments();
59-
assert(args.size()==2);
60-
88+
assert(args.size()>=2);
6189
string_exprt s1=get_string_expr(args[0]);
6290
string_exprt s2=get_string_expr(args[1]);
63-
91+
if(args.size()!=2)
92+
{
93+
assert(args.size()==4);
94+
return add_axioms_for_concat_substr(s1, s2, args[2], args[3]);
95+
}
6496
return add_axioms_for_concat(s1, s2);
6597
}
6698

0 commit comments

Comments
 (0)