Skip to content

Commit 12a0fdc

Browse files
committed
Array reasoning: support let expressions
We may have `let var=expr in array` expressions, which SMT2 conversion generates (and our in-tree SMT2 solver may have to consume).
1 parent b335979 commit 12a0fdc

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/solvers/flattening/arrays.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212
#include <util/json.h>
1313
#include <util/message.h>
1414
#include <util/replace_expr.h>
15+
#include <util/replace_symbol.h>
1516
#include <util/std_expr.h>
1617

1718
#include <solvers/prop/literal_expr.h>
@@ -237,6 +238,11 @@ void arrayst::collect_arrays(const exprt &a)
237238
else if(a.id() == ID_array_comprehension)
238239
{
239240
}
241+
else if(auto let_expr = expr_try_dynamic_cast<let_exprt>(a))
242+
{
243+
arrays.make_union(a, let_expr->where());
244+
collect_arrays(let_expr->where());
245+
}
240246
else
241247
{
242248
DATA_INVARIANT(
@@ -528,6 +534,33 @@ void arrayst::add_array_constraints(
528534
else if(expr.id()==ID_index)
529535
{
530536
}
537+
else if(auto let_expr = expr_try_dynamic_cast<let_exprt>(expr))
538+
{
539+
// we got x=let(a=e, A)
540+
// add x[i]=A[a/e][i]
541+
542+
exprt where = let_expr->where();
543+
replace_symbolt replace_symbol;
544+
for(const auto &binding :
545+
make_range(let_expr->variables()).zip(let_expr->values()))
546+
{
547+
replace_symbol.insert(binding.first, binding.second);
548+
}
549+
replace_symbol(where);
550+
551+
for(const auto &index : index_set)
552+
{
553+
index_exprt index_expr{expr, index};
554+
index_exprt where_indexed{where, index};
555+
556+
// add constraint
557+
lazy_constraintt lazy{
558+
lazy_typet::ARRAY_LET, equal_exprt{index_expr, where_indexed}};
559+
560+
add_array_constraint(lazy, false); // added immediately
561+
array_constraint_count[constraint_typet::ARRAY_LET]++;
562+
}
563+
}
531564
else
532565
{
533566
DATA_INVARIANT(
@@ -875,6 +908,8 @@ std::string arrayst::enum_to_string(constraint_typet type)
875908
return "arrayComprehension";
876909
case constraint_typet::ARRAY_EQUALITY:
877910
return "arrayEquality";
911+
case constraint_typet::ARRAY_LET:
912+
return "arrayLet";
878913
default:
879914
UNREACHABLE;
880915
}

src/solvers/flattening/arrays.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ class arrayst:public equalityt
9393
ARRAY_OF,
9494
ARRAY_TYPECAST,
9595
ARRAY_CONSTANT,
96-
ARRAY_COMPREHENSION
96+
ARRAY_COMPREHENSION,
97+
ARRAY_LET
9798
};
9899

99100
struct lazy_constraintt
@@ -124,7 +125,8 @@ class arrayst:public equalityt
124125
ARRAY_TYPECAST,
125126
ARRAY_CONSTANT,
126127
ARRAY_COMPREHENSION,
127-
ARRAY_EQUALITY
128+
ARRAY_EQUALITY,
129+
ARRAY_LET
128130
};
129131

130132
typedef std::map<constraint_typet, size_t> array_constraint_countt;

0 commit comments

Comments
 (0)