@@ -117,28 +117,71 @@ void string_refinementt::add_instantiations()
117
117
}
118
118
}
119
119
120
+ // / List the simple expressions on which the expression depends in the
121
+ // / `symbol_resolve` map. A simple expression is either a symbol or a
122
+ // / constant array
123
+ // / \param expr: an expression
124
+ static void depends_in_symbol_map (const exprt &expr, std::vector<exprt> &accu)
125
+ {
126
+ if (expr.id ()==ID_if)
127
+ {
128
+ if_exprt if_expr=to_if_expr (expr);
129
+ depends_in_symbol_map (if_expr.true_case (), accu);
130
+ depends_in_symbol_map (if_expr.false_case (), accu);
131
+ }
132
+ else if (expr.id ()==ID_struct)
133
+ {
134
+ string_exprt str=to_string_expr (expr);
135
+ depends_in_symbol_map (str.content (), accu);
136
+ }
137
+ else
138
+ {
139
+ INVARIANT (
140
+ expr.id ()==ID_symbol || expr.id ()==ID_array || expr.id ()==ID_array_of,
141
+ " leaf in symbol resolve should be a symbol or a constant array" );
142
+ accu.push_back (expr);
143
+ }
144
+ }
145
+
120
146
// / keeps a map of symbols to expressions, such as none of the mapped values
121
147
// / exist as a key
122
148
// / \param lhs: a symbol expression
123
- // / \param rhs: an expression to map it to
149
+ // / \param rhs: an expression to map it to, which should be either a symbol
150
+ // / a string_exprt, an array_exprt, an array_of_exprt or an
151
+ // / if_exprt with branches of the previous kind
124
152
void string_refinementt::add_symbol_to_symbol_map (
125
153
const exprt &lhs, const exprt &rhs)
126
154
{
127
155
PRECONDITION (lhs.id ()==ID_symbol);
156
+ PRECONDITION (rhs.id ()==ID_symbol ||
157
+ rhs.id ()==ID_array ||
158
+ rhs.id ()==ID_array_of ||
159
+ rhs.id ()==ID_if ||
160
+ (rhs.id ()==ID_struct &&
161
+ refined_string_typet::is_refined_string_type (rhs.type ())));
128
162
129
163
// We insert the mapped value of the rhs, if it exists.
130
164
auto it=symbol_resolve.find (rhs);
131
165
const exprt &new_rhs=it!=symbol_resolve.end ()?it->second :rhs;
132
-
133
166
symbol_resolve[lhs]=new_rhs;
134
- reverse_symbol_resolve[new_rhs].push_back (lhs);
135
167
136
- const std::list<exprt> &symbols_to_update_with_new_rhs (
137
- reverse_symbol_resolve[lhs]);
138
- for (exprt item : symbols_to_update_with_new_rhs)
168
+ // List the leaves of new_rhs
169
+ std::vector<exprt> leaves;
170
+ depends_in_symbol_map (new_rhs, leaves);
171
+
172
+ const auto &symbols_to_update_with_new_rhs=reverse_symbol_resolve[lhs];
173
+
174
+ // We need to update all the symbols which depend on lhs
175
+ for (const exprt &item : symbols_to_update_with_new_rhs)
176
+ replace_expr (symbol_resolve, symbol_resolve[item]);
177
+
178
+ // Every time a symbol at the leaves is updated we need to update lhs
179
+ // and the symbols that depend on it
180
+ for (const auto &leaf : leaves)
139
181
{
140
- symbol_resolve[item]=new_rhs;
141
- reverse_symbol_resolve[new_rhs].push_back (item);
182
+ reverse_symbol_resolve[leaf].push_back (lhs);
183
+ for (const exprt &item : symbols_to_update_with_new_rhs)
184
+ reverse_symbol_resolve[leaf].push_back (item);
142
185
}
143
186
}
144
187
@@ -158,9 +201,6 @@ void string_refinementt::set_char_array_equality(
158
201
index_exprt arraycell (rhs, from_integer (i, index_type));
159
202
equal_exprt arrayeq (arraycell, rhs.operands ()[i]);
160
203
add_lemma (arrayeq, false );
161
- #if 0
162
- generator.axioms.push_back(arrayeq);
163
- #endif
164
204
}
165
205
}
166
206
// At least for Java (as it is currently pre-processed), we need not consider
@@ -205,7 +245,8 @@ bool string_refinementt::is_char_array(const typet &type) const
205
245
// / add lemmas to the solver corresponding to the given equation
206
246
// / \param lhs: left hand side of an equality expression
207
247
// / \param rhs: right and side of the equality
208
- // / \return false if the lemmas were added successfully, true otherwise
248
+ // / \return true if the assignemnt needs to be handled by the parent class
249
+ // / via `set_to`
209
250
bool string_refinementt::add_axioms_for_string_assigns (
210
251
const exprt &lhs, const exprt &rhs)
211
252
{
@@ -225,8 +266,8 @@ bool string_refinementt::add_axioms_for_string_assigns(
225
266
}
226
267
else if (rhs.id ()==ID_if)
227
268
{
228
- generator. add_axioms_for_if_array (lhs, to_if_expr ( rhs) );
229
- return false ;
269
+ add_symbol_to_symbol_map (lhs, rhs);
270
+ return true ;
230
271
}
231
272
else
232
273
{
@@ -632,7 +673,7 @@ void string_refinementt::add_lemma(
632
673
// / \return an array expression or an array_of_exprt
633
674
exprt string_refinementt::get_array (const exprt &arr, const exprt &size) const
634
675
{
635
- exprt arr_val=get_array (arr);
676
+ exprt arr_val=simplify_expr ( get_array (arr), ns );
636
677
exprt size_val=supert::get (size);
637
678
size_val=simplify_expr (size_val, ns);
638
679
typet char_type=arr.type ().subtype ();
@@ -1412,6 +1453,30 @@ void string_refinementt::update_index_set(const std::vector<exprt> &cur)
1412
1453
update_index_set (axiom);
1413
1454
}
1414
1455
1456
+ // / An expression representing an array of characters can be in the form of an
1457
+ // / if expression for instance `cond?array1:(cond2:array2:array3)`.
1458
+ // / We return all the array expressions contained in `array_expr`.
1459
+ // / \param array_expr : an expression representing an array
1460
+ // / \return a vector containing symbols and constant arrays contained in the
1461
+ // / expression
1462
+ static std::vector<exprt> sub_arrays (const exprt &array_expr)
1463
+ {
1464
+ if (array_expr.id ()==ID_if)
1465
+ {
1466
+ std::vector<exprt> res1=sub_arrays (to_if_expr (array_expr).true_case ());
1467
+ std::vector<exprt> res2=sub_arrays (to_if_expr (array_expr).false_case ());
1468
+ res1.insert (res1.end (), res2.begin (), res2.end ());
1469
+ return res1;
1470
+ }
1471
+ else
1472
+ {
1473
+ INVARIANT (
1474
+ array_expr.id ()==ID_symbol || array_expr.id ()==ID_array,
1475
+ " character arrays should be symbol, constant array, or if expression" );
1476
+ return std::vector<exprt>(1 , array_expr);
1477
+ }
1478
+ }
1479
+
1415
1480
// / add to the index set all the indices that appear in the formula and the
1416
1481
// / upper bound minus one
1417
1482
// / \par parameters: a string constraint
@@ -1423,17 +1488,13 @@ void string_refinementt::add_to_index_set(const exprt &s, exprt i)
1423
1488
mp_integer mpi;
1424
1489
to_integer (i, mpi);
1425
1490
if (mpi<0 )
1426
- {
1427
- debug () << " add_to_index_set : ignoring negative number " << mpi << eom;
1428
1491
return ;
1429
- }
1430
- }
1431
- if (index_set[s].insert (i).second )
1432
- {
1433
- debug () << " adding to index set of " << from_expr (ns, " " , s)
1434
- << " : " << from_expr (ns, " " , i) << eom;
1435
- current_index_set[s].insert (i);
1436
1492
}
1493
+
1494
+ std::vector<exprt> subs=sub_arrays (s);
1495
+ for (const auto &sub : subs)
1496
+ if (index_set[sub].insert (i).second )
1497
+ current_index_set[sub].insert (i);
1437
1498
}
1438
1499
1439
1500
void string_refinementt::initial_index_set (const string_constraintt &axiom)
@@ -1504,7 +1565,6 @@ void string_refinementt::update_index_set(const exprt &formula)
1504
1565
}
1505
1566
}
1506
1567
1507
-
1508
1568
// Will be used to visit an expression and return the index used
1509
1569
// with the given char array that contains qvar
1510
1570
class find_index_visitort : public const_expr_visitort
0 commit comments