@@ -11,6 +11,7 @@ Author: Daniel Kroening, kroening@kroening.com
11
11
#include < util/arith_tools.h>
12
12
#include < util/format_expr.h>
13
13
#include < util/namespace.h>
14
+ #include < util/replace_expr.h>
14
15
#include < util/std_expr.h>
15
16
#include < util/std_types.h>
16
17
@@ -38,8 +39,8 @@ void arrayst::record_array_index(const index_exprt &index)
38
39
// entry for the root of the equivalence class
39
40
// because this map is accessed during building the error trace
40
41
std::size_t number=arrays.number (index.array ());
41
- index_map[number].insert (index.index ());
42
- update_indices.insert (number);
42
+ if ( index_map[number].insert (index.index ()). second )
43
+ update_indices.insert (number);
43
44
}
44
45
45
46
literalt arrayst::record_array_equality (
@@ -82,11 +83,24 @@ void arrayst::collect_indices(const exprt &expr)
82
83
{
83
84
if (expr.id ()!=ID_index)
84
85
{
86
+ if (expr.id () == ID_lambda)
87
+ array_comprehension_args.insert (
88
+ to_array_comprehension_expr (expr).arg ().get_identifier ());
89
+
85
90
forall_operands (op, expr) collect_indices (*op);
86
91
}
87
92
else
88
93
{
89
94
const index_exprt &e = to_index_expr (expr);
95
+
96
+ if (
97
+ e.index ().id () == ID_symbol &&
98
+ array_comprehension_args.count (
99
+ to_symbol_expr (e.index ()).get_identifier ()) != 0 )
100
+ {
101
+ return ;
102
+ }
103
+
90
104
collect_indices (e.index ()); // necessary?
91
105
92
106
const typet &array_op_type = e.array ().type ();
@@ -214,6 +228,9 @@ void arrayst::collect_arrays(const exprt &a)
214
228
arrays.make_union (a, a.op0 ());
215
229
collect_arrays (a.op0 ());
216
230
}
231
+ else if (a.id () == ID_lambda)
232
+ {
233
+ }
217
234
else
218
235
{
219
236
DATA_INVARIANT (
@@ -257,17 +274,32 @@ void arrayst::add_array_constraints()
257
274
// reduce initial index map
258
275
update_index_map (true );
259
276
260
- // add constraints for if, with, array_of
277
+ // add constraints for if, with, array_of, lambda
278
+ std::set<std::size_t > roots_to_process, updated_roots;
261
279
for (std::size_t i=0 ; i<arrays.size (); i++)
280
+ roots_to_process.insert (arrays.find_number (i));
281
+
282
+ while (!roots_to_process.empty ())
262
283
{
263
- // take a copy as arrays may get modified by add_array_constraints
264
- // in case of nested unbounded arrays
265
- exprt a=arrays[i];
284
+ for (std::size_t i = 0 ; i < arrays.size (); i++)
285
+ {
286
+ if (roots_to_process.count (arrays.find_number (i)) == 0 )
287
+ continue ;
288
+
289
+ // take a copy as arrays may get modified by add_array_constraints
290
+ // in case of nested unbounded arrays
291
+ exprt a = arrays[i];
266
292
267
- add_array_constraints (index_map[arrays.find_number (i)], a);
293
+ add_array_constraints (index_map[arrays.find_number (i)], a);
268
294
269
- // we have to update before it gets used in the next add_* call
270
- update_index_map (false );
295
+ // we have to update before it gets used in the next add_* call
296
+ for (const std::size_t u : update_indices)
297
+ updated_roots.insert (arrays.find_number (u));
298
+ update_index_map (false );
299
+ }
300
+
301
+ roots_to_process = std::move (updated_roots);
302
+ updated_roots.clear ();
271
303
}
272
304
273
305
// add constraints for equalities
@@ -438,6 +470,11 @@ void arrayst::add_array_constraints(
438
470
return add_array_constraints_array_of (index_set, to_array_of_expr (expr));
439
471
else if (expr.id () == ID_array)
440
472
return add_array_constraints_array_constant (index_set, to_array_expr (expr));
473
+ else if (expr.id () == ID_lambda)
474
+ {
475
+ return add_array_constraints_comprehension (
476
+ index_set, to_array_comprehension_expr (expr));
477
+ }
441
478
else if (expr.id ()==ID_symbol ||
442
479
expr.id ()==ID_nondet_symbol ||
443
480
expr.id ()==ID_constant ||
@@ -727,6 +764,28 @@ void arrayst::add_array_constraints_array_constant(
727
764
}
728
765
}
729
766
767
+ void arrayst::add_array_constraints_comprehension (
768
+ const index_sett &index_set,
769
+ const array_comprehension_exprt &expr)
770
+ {
771
+ // we got x=lambda(i: e)
772
+ // get all other array index applications
773
+ // and add constraints x[j]=e[i/j]
774
+
775
+ for (const auto &index : index_set)
776
+ {
777
+ index_exprt index_expr{expr, index};
778
+ exprt comprehension_body = expr.body ();
779
+ replace_expr (expr.arg (), index, comprehension_body);
780
+
781
+ // add constraint
782
+ lazy_constraintt lazy (
783
+ lazy_typet::ARRAY_COMPREHENSION,
784
+ equal_exprt (index_expr, comprehension_body));
785
+ add_array_constraint (lazy, false ); // added immediately
786
+ }
787
+ }
788
+
730
789
void arrayst::add_array_constraints_if (
731
790
const index_sett &index_set,
732
791
const if_exprt &expr)
0 commit comments