Skip to content

Commit e72eacf

Browse files
Pull array_pool class out of constraint generator
Pull out this part of constraint generator to decrease the size of the class, make unit test easier and the code more modular and reusable.
1 parent 42971da commit e72eacf

File tree

3 files changed

+104
-53
lines changed

3 files changed

+104
-53
lines changed

src/solvers/refinement/string_constraint_generator.h

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,51 @@ class symbol_generatort final
3838
unsigned symbol_count = 0;
3939
};
4040

41+
/// Correspondance between arrays and pointers string representations
42+
class array_poolt final
43+
{
44+
public:
45+
explicit array_poolt(symbol_generatort &symbol_generator)
46+
: fresh_symbol(symbol_generator)
47+
{
48+
}
49+
50+
const std::unordered_map<exprt, array_string_exprt, irep_hash> &
51+
get_arrays_of_pointers() const
52+
{
53+
return arrays_of_pointers;
54+
}
55+
56+
exprt get_length(const array_string_exprt &s) const;
57+
58+
void insert(const exprt &pointer_expr, array_string_exprt &array);
59+
60+
array_string_exprt find(const exprt &pointer, const exprt &length);
61+
62+
array_string_exprt find(const refined_string_exprt &str);
63+
64+
/// Converts a struct containing a length and pointer to an array.
65+
/// This allows to get a string expression from arguments of a string
66+
/// builtion function, because string arguments in these function calls
67+
/// are given as a struct containing a length and pointer to an array.
68+
array_string_exprt of_argument(const exprt &arg);
69+
70+
private:
71+
// associate arrays to char pointers
72+
std::unordered_map<exprt, array_string_exprt, irep_hash> arrays_of_pointers;
73+
74+
// associate length to arrays of infinite size
75+
std::unordered_map<array_string_exprt, symbol_exprt, irep_hash>
76+
length_of_array;
77+
78+
// generates fresh symbols
79+
symbol_generatort &fresh_symbol;
80+
81+
array_string_exprt make_char_array_for_char_pointer(
82+
const exprt &char_pointer,
83+
const typet &char_array_type);
84+
};
85+
4186
class string_constraint_generatort final
4287
{
4388
public:
@@ -85,15 +130,12 @@ class string_constraint_generatort final
85130

86131
symbol_generatort fresh_symbol;
87132

88-
const std::map<exprt, array_string_exprt> &get_arrays_of_pointers() const
89-
{
90-
return arrays_of_pointers_;
91-
}
92133
symbol_exprt fresh_univ_index(const irep_idt &prefix, const typet &type);
93134

94-
exprt get_length_of_string_array(const array_string_exprt &s) const;
95135
symbol_exprt fresh_exist_index(const irep_idt &prefix, const typet &type);
96136

137+
array_poolt array_pool;
138+
97139
// Type used by primitives to signal errors
98140
const signedbv_typet get_return_code_type()
99141
{
@@ -107,9 +149,6 @@ class string_constraint_generatort final
107149
array_string_exprt get_string_expr(const exprt &expr);
108150
plus_exprt plus_exprt_with_overflow_check(const exprt &op1, const exprt &op2);
109151

110-
array_string_exprt associate_char_array_to_char_pointer(
111-
const exprt &char_pointer,
112-
const typet &char_array_type);
113152

114153
static constant_exprt constant_char(int i, const typet &char_type);
115154

@@ -371,12 +410,6 @@ class string_constraint_generatort final
371410

372411
// Pool used for the intern method
373412
std::map<array_string_exprt, symbol_exprt> intern_of_string;
374-
375-
// associate arrays to char pointers
376-
std::map<exprt, array_string_exprt> arrays_of_pointers_;
377-
378-
// associate length to arrays of infinite size
379-
std::map<array_string_exprt, symbol_exprt> length_of_array_;
380413
};
381414

382415
exprt is_digit_with_radix(

src/solvers/refinement/string_constraint_generator_main.cpp

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ Author: Romain Brenguier, [email protected]
3131
string_constraint_generatort::string_constraint_generatort(
3232
const string_constraint_generatort::infot &info,
3333
const namespacet &ns)
34-
: max_string_length(info.string_max_length),
35-
ns(ns)
34+
: array_pool(fresh_symbol), max_string_length(info.string_max_length), ns(ns)
3635
{
3736
}
3837

@@ -157,13 +156,12 @@ plus_exprt string_constraint_generatort::plus_exprt_with_overflow_check(
157156
/// Associate an actual finite length to infinite arrays
158157
/// \param s: array expression representing a string
159158
/// \return expression for the length of `s`
160-
exprt string_constraint_generatort::get_length_of_string_array(
161-
const array_string_exprt &s) const
159+
exprt array_poolt::get_length(const array_string_exprt &s) const
162160
{
163161
if(s.length() == infinity_exprt(s.length().type()))
164162
{
165-
auto it = length_of_array_.find(s);
166-
if(it != length_of_array_.end())
163+
auto it = length_of_array.find(s);
164+
if(it != length_of_array.end())
167165
return it->second;
168166
}
169167
return s.length();
@@ -185,10 +183,9 @@ array_string_exprt string_constraint_generatort::fresh_string(
185183
return str;
186184
}
187185

188-
// Associate a char array to a char pointer. The size of the char array is a
186+
// Make a new char array for a char pointer. The size of the char array is a
189187
// variable with no constraint.
190-
array_string_exprt
191-
string_constraint_generatort::associate_char_array_to_char_pointer(
188+
array_string_exprt array_poolt::make_char_array_for_char_pointer(
192189
const exprt &char_pointer,
193190
const typet &char_array_type)
194191
{
@@ -214,10 +211,10 @@ string_constraint_generatort::associate_char_array_to_char_pointer(
214211
else if(char_pointer.id() == ID_if)
215212
{
216213
const if_exprt &if_expr = to_if_expr(char_pointer);
217-
const array_string_exprt t = associate_char_array_to_char_pointer(
218-
if_expr.true_case(), char_array_type);
219-
const array_string_exprt f = associate_char_array_to_char_pointer(
220-
if_expr.false_case(), char_array_type);
214+
const array_string_exprt t =
215+
make_char_array_for_char_pointer(if_expr.true_case(), char_array_type);
216+
const array_string_exprt f =
217+
make_char_array_for_char_pointer(if_expr.false_case(), char_array_type);
221218
array_typet array_type(
222219
char_array_type.subtype(),
223220
if_exprt(
@@ -247,15 +244,32 @@ string_constraint_generatort::associate_char_array_to_char_pointer(
247244
array_string_exprt array_sym =
248245
to_array_string_expr(fresh_symbol(symbol_name, char_array_type));
249246
auto insert_result =
250-
arrays_of_pointers_.insert(std::make_pair(char_pointer, array_sym));
247+
arrays_of_pointers.insert(std::make_pair(char_pointer, array_sym));
251248
array_string_exprt result = to_array_string_expr(insert_result.first->second);
252249
return result;
253250
}
254251

252+
void array_poolt::insert(
253+
const exprt &pointer_expr,
254+
array_string_exprt &array_expr)
255+
{
256+
const exprt &length = array_expr.length();
257+
if(length == infinity_exprt(length.type()))
258+
{
259+
auto pair = length_of_array.insert(
260+
std::make_pair(array_expr, fresh_symbol("string_length", length.type())));
261+
array_expr.length() = pair.first->second;
262+
}
263+
264+
const auto it_bool =
265+
arrays_of_pointers.insert(std::make_pair(pointer_expr, array_expr));
266+
INVARIANT(
267+
it_bool.second, "should not associate two arrays to the same pointer");
268+
}
269+
255270
/// Associate a char array to a char pointer.
256-
/// Insert in `arrays_of_pointers_` a binding from `ptr` to `arr`.
257-
/// If the length of `arr` is infinite, we create a new integer symbol and add
258-
/// a binding from `arr` to this length in `length_of_array_`.
271+
/// Insert in `array_pool` a binding from `ptr` to `arr`. If the length of `arr`
272+
/// is infinite, a new integer symbol is created and stored in `array_pool`.
259273
/// This also adds the default axioms for `arr`.
260274
/// \param f: a function application with argument a character array `arr` and
261275
/// a character pointer `ptr`.
@@ -271,21 +285,7 @@ exprt string_constraint_generatort::associate_array_to_pointer(
271285
: f.arguments()[0]);
272286

273287
const exprt &pointer_expr = f.arguments()[1];
274-
275-
const auto &length = array_expr.length();
276-
if(length == infinity_exprt(length.type()))
277-
{
278-
auto pair = length_of_array_.insert(
279-
std::make_pair(array_expr, fresh_symbol("string_length", length.type())));
280-
array_expr.length() = pair.first->second;
281-
}
282-
283-
/// \todo We should use a function for inserting the correspondance
284-
/// between array and pointers.
285-
const auto it_bool =
286-
arrays_of_pointers_.insert(std::make_pair(pointer_expr, array_expr));
287-
INVARIANT(
288-
it_bool.second, "should not associate two arrays to the same pointer");
288+
array_pool.insert(pointer_expr, array_expr);
289289
add_default_axioms(to_array_string_expr(array_expr));
290290
return from_integer(0, f.type());
291291
}
@@ -302,7 +302,7 @@ exprt string_constraint_generatort::associate_length_to_array(
302302
array_string_exprt array_expr = to_array_string_expr(f.arguments()[0]);
303303
const exprt &new_length = f.arguments()[1];
304304

305-
const auto &length = get_length_of_string_array(array_expr);
305+
const auto &length = array_pool.get_length(array_expr);
306306
lemmas.push_back(equal_exprt(length, new_length));
307307
return from_integer(0, f.type());
308308
}
@@ -400,19 +400,36 @@ exprt string_constraint_generatort::add_axioms_for_constrain_characters(
400400
return from_integer(0, get_return_code_type());
401401
}
402402

403+
/// Creates a new array if the pointer is not pointing to an array
404+
/// \todo This should be replaced by make_char_array_for_char_pointer
405+
array_string_exprt array_poolt::find(const exprt &pointer, const exprt &length)
406+
{
407+
const array_typet array_type(pointer.type().subtype(), length);
408+
return make_char_array_for_char_pointer(pointer, array_type);
409+
}
410+
403411
/// Adds creates a new array if it does not already exists
404412
/// \todo This should be replaced by associate_char_array_to_char_pointer
405413
array_string_exprt string_constraint_generatort::char_array_of_pointer(
406414
const exprt &pointer,
407415
const exprt &length)
408416
{
409-
const array_typet array_type(pointer.type().subtype(), length);
410-
const array_string_exprt array =
411-
associate_char_array_to_char_pointer(pointer, array_type);
417+
const array_string_exprt array = array_pool.find(pointer, length);
412418
add_default_axioms(array);
413419
return array;
414420
}
415421

422+
array_string_exprt array_poolt::find(const refined_string_exprt &str)
423+
{
424+
return find(str.content(), str.length());
425+
}
426+
427+
array_string_exprt array_poolt::of_argument(const exprt &arg)
428+
{
429+
const auto string_argument = expr_checked_cast<struct_exprt>(arg);
430+
return find(string_argument.op1(), string_argument.op0());
431+
}
432+
416433
/// strings contained in this call are converted to objects of type
417434
/// `string_exprt`, through adding axioms. Axioms are then added to enforce that
418435
/// the result corresponds to the function application.

src/solvers/refinement/string_refinement.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,8 @@ decision_proceduret::resultt string_refinementt::dec_solve()
801801

802802
#ifdef DEBUG
803803
debug() << "dec_solve: arrays_of_pointers:" << eom;
804-
for(auto pair : generator.get_arrays_of_pointers())
804+
for(auto pair :
805+
generator.array_pointer_correspondance.get_arrays_of_pointers())
805806
{
806807
debug() << " * " << format(pair.first) << "\t--> " << format(pair.second)
807808
<< " : " << format(pair.second.type()) << eom;
@@ -1193,7 +1194,7 @@ void debug_model(
11931194
static const std::string indent(" ");
11941195

11951196
stream << "debug_model:" << '\n';
1196-
for(const auto &pointer_array : generator.get_arrays_of_pointers())
1197+
for(const auto &pointer_array : generator.array_pool.get_arrays_of_pointers())
11971198
{
11981199
const auto arr = pointer_array.second;
11991200
const exprt model = get_char_array_and_concretize(
@@ -2418,7 +2419,7 @@ exprt string_refinementt::get(const exprt &expr) const
24182419
if(is_char_array_type(ecopy.type(), ns))
24192420
{
24202421
array_string_exprt &arr = to_array_string_expr(ecopy);
2421-
arr.length() = generator.get_length_of_string_array(arr);
2422+
arr.length() = generator.array_pool.get_length(arr);
24222423
const auto arr_model_opt =
24232424
get_array(super_get, ns, generator.max_string_length, debug(), arr);
24242425
// \todo Refactor with get array in model

0 commit comments

Comments
 (0)