|
14 | 14 | #include <solvers/refinement/string_constraint_generator.h>
|
15 | 15 |
|
16 | 16 | /// 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 |
19 | 26 | /// \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) |
22 | 32 | {
|
23 | 33 | const refined_string_typet &ref_type=to_refined_string_type(s1.type());
|
24 | 34 | string_exprt res=fresh_string(ref_type);
|
25 | 35 |
|
26 | 36 | // 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)); |
35 | 47 | 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); |
38 | 51 |
|
39 | 52 | 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); |
42 | 55 |
|
43 | 56 | 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); |
47 | 61 |
|
48 | 62 | return res;
|
49 | 63 | }
|
50 | 64 |
|
51 | 65 | /// 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. |
53 | 82 | /// \par parameters: function application with two arguments which are strings
|
54 | 83 | /// \return a new string expression
|
55 | 84 | string_exprt string_constraint_generatort::add_axioms_for_concat(
|
56 | 85 | const function_application_exprt &f)
|
57 | 86 | {
|
58 | 87 | const function_application_exprt::argumentst &args=f.arguments();
|
59 |
| - assert(args.size()==2); |
60 |
| - |
| 88 | + assert(args.size()>=2); |
61 | 89 | string_exprt s1=get_string_expr(args[0]);
|
62 | 90 | 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 | + } |
64 | 96 | return add_axioms_for_concat(s1, s2);
|
65 | 97 | }
|
66 | 98 |
|
|
0 commit comments