Skip to content

Commit 96675c2

Browse files
author
Enrico Steffinlongo
committed
Add translation of array_of_exprt to SMT2
1 parent 8fbba35 commit 96675c2

File tree

4 files changed

+78
-19
lines changed

4 files changed

+78
-19
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,9 @@ static smt_termt convert_expr_to_smt(
906906
const array_of_exprt &array_of,
907907
const sub_expression_mapt &converted)
908908
{
909+
// This function is left unimplemented as the `array_of_exprt` nodes are fully
910+
// converted by the incremental decision procedure functions
911+
// (smt2_incremental_decision_proceduret::define_array_function).
909912
UNIMPLEMENTED_FEATURE(
910913
"Generation of SMT formula for array of expression: " + array_of.pretty());
911914
}
@@ -1353,6 +1356,9 @@ static smt_termt convert_expr_to_smt(
13531356
const array_exprt &array_construction,
13541357
const sub_expression_mapt &converted)
13551358
{
1359+
// This function is left unimplemented as the `array_exprt` nodes are fully
1360+
// converted by the incremental decision procedure functions
1361+
// (smt2_incremental_decision_proceduret::define_array_function).
13561362
UNIMPLEMENTED_FEATURE(
13571363
"Generation of SMT formula for array construction expression: " +
13581364
array_construction.pretty());

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static std::vector<exprt> gather_dependent_expressions(const exprt &expr)
7171
if(
7272
can_cast_expr<symbol_exprt>(expr_node) ||
7373
can_cast_expr<array_exprt>(expr_node) ||
74+
can_cast_expr<array_of_exprt>(expr_node) ||
7475
can_cast_expr<nondet_symbol_exprt>(expr_node))
7576
{
7677
dependent_expressions.push_back(expr_node);
@@ -79,17 +80,10 @@ static std::vector<exprt> gather_dependent_expressions(const exprt &expr)
7980
return dependent_expressions;
8081
}
8182

82-
void smt2_incremental_decision_proceduret::define_array_function(
83-
const array_exprt &array)
83+
void smt2_incremental_decision_proceduret::initialize_array_elements(
84+
const array_exprt &array,
85+
const smt_identifier_termt &array_identifier)
8486
{
85-
const smt_sortt array_sort = convert_type_to_smt_sort(array.type());
86-
INVARIANT(
87-
array_sort.cast<smt_array_sortt>(),
88-
"Converting array typed expression to SMT should result in a term of array "
89-
"sort.");
90-
const smt_identifier_termt array_identifier = smt_identifier_termt{
91-
"array_" + std::to_string(array_sequence()), array_sort};
92-
solver_process->send(smt_declare_function_commandt{array_identifier, {}});
9387
const std::vector<exprt> &elements = array.operands();
9488
const typet &index_type = array.type().index_type();
9589
for(std::size_t i = 0; i < elements.size(); ++i)
@@ -100,6 +94,46 @@ void smt2_incremental_decision_proceduret::define_array_function(
10094
convert_expr_to_smt(elements.at(i)))};
10195
solver_process->send(element_definition);
10296
}
97+
}
98+
99+
void smt2_incremental_decision_proceduret::initialize_array_elements(
100+
const array_of_exprt &array,
101+
const smt_identifier_termt &array_identifier)
102+
{
103+
const smt_sortt index_type =
104+
convert_type_to_smt_sort(array.type().index_type());
105+
const smt_identifier_termt array_index_identifier = smt_identifier_termt{
106+
id2string(array_identifier.identifier()) + "_index", index_type};
107+
const std::vector<exprt> &elements = array.operands();
108+
INVARIANT(elements.size() == 1, "array_of_exprt must have only one operand.");
109+
const smt_termt element_value = convert_expr_to_smt(elements.front());
110+
111+
const smt_assert_commandt elements_definition{smt_forall_termt{
112+
{array_index_identifier},
113+
smt_core_theoryt::equal(
114+
smt_array_theoryt::select(array_identifier, array_index_identifier),
115+
element_value)}};
116+
solver_process->send(elements_definition);
117+
}
118+
119+
template <typename EXPRT>
120+
void smt2_incremental_decision_proceduret::define_array_function(
121+
const EXPRT &array)
122+
{
123+
static_assert(
124+
std::is_same<EXPRT, array_exprt>::value ||
125+
std::is_same<EXPRT, array_of_exprt>::value,
126+
"smt2_incremental_decision_proceduret::define_array_function can be "
127+
"applied only to array_exprt and array_of_exprt arguments.");
128+
const smt_sortt array_sort = convert_type_to_smt_sort(array.type());
129+
INVARIANT(
130+
array_sort.cast<smt_array_sortt>(),
131+
"Converting array typed expression to SMT should result in a term of array "
132+
"sort.");
133+
const smt_identifier_termt array_identifier = smt_identifier_termt{
134+
"array_" + std::to_string(array_sequence()), array_sort};
135+
solver_process->send(smt_declare_function_commandt{array_identifier, {}});
136+
initialize_array_elements(array, array_identifier);
103137
expression_identifiers.emplace(array, array_identifier);
104138
}
105139

@@ -168,9 +202,14 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
168202
solver_process->send(function);
169203
}
170204
}
171-
if(const auto array_expr = expr_try_dynamic_cast<array_exprt>(current))
205+
else if(const auto array_expr = expr_try_dynamic_cast<array_exprt>(current))
172206
define_array_function(*array_expr);
173-
if(
207+
else if(
208+
const auto array_of_expr = expr_try_dynamic_cast<array_of_exprt>(current))
209+
{
210+
define_array_function(*array_of_expr);
211+
}
212+
else if(
174213
const auto nondet_symbol =
175214
expr_try_dynamic_cast<nondet_symbol_exprt>(current))
176215
{
@@ -213,8 +252,7 @@ smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret(
213252
{
214253
solver_process->send(
215254
smt_set_option_commandt{smt_option_produce_modelst{true}});
216-
solver_process->send(smt_set_logic_commandt{
217-
smt_logic_quantifier_free_arrays_uninterpreted_functions_bit_vectorst{}});
255+
solver_process->send(smt_set_logic_commandt{smt_logic_allt{}});
218256
solver_process->send(object_size_function.declaration);
219257
}
220258

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,27 @@ class smt2_incremental_decision_proceduret final
5555
protected:
5656
// Implementation of protected decision_proceduret member function.
5757
resultt dec_solve() override;
58-
/// \brief Defines a function of array sort and asserts the element values.
58+
/// \brief Defines a function of array sort and asserts the element values
59+
/// from `array_exprt` or `array_of_exprt`.
5960
/// \details
6061
/// The new array function identifier is added to the
6162
/// `expression_identifiers` map.
62-
void define_array_function(const array_exprt &array);
63+
/// \note Statically fails if the template type is not a `array_exprt` or
64+
/// `array_of_exprt`.
65+
template <typename EXPRT>
66+
void define_array_function(const EXPRT &array);
67+
/// \brief Sets the state of the array by asserting that each array element is
68+
/// correct.
69+
void initialize_array_elements(
70+
const array_exprt &array,
71+
const smt_identifier_termt &array_identifier);
72+
/// \brief Sets the state of the array by asserting that each array element is
73+
/// correct.
74+
/// \note This function uses a forall SMT2 term. This is not in the SMT 2.6
75+
/// standard, but it has been tested and works on Z3 and CVC5.
76+
void initialize_array_elements(
77+
const array_of_exprt &array,
78+
const smt_identifier_termt &array_identifier);
6379
/// \brief Defines any functions which \p expr depends on, which have not yet
6480
/// been defined, along with their dependencies in turn.
6581
void define_dependent_functions(const exprt &expr);

unit/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,8 @@ TEST_CASE(
171171
test.sent_commands ==
172172
std::vector<smt_commandt>{
173173
smt_set_option_commandt{smt_option_produce_modelst{true}},
174-
smt_set_logic_commandt{
175-
// NOLINTNEXTLINE(whitespace/line_length)
176-
smt_logic_quantifier_free_arrays_uninterpreted_functions_bit_vectorst{}},
174+
smt_set_logic_commandt{// NOLINTNEXTLINE(whitespace/line_length)
175+
smt_logic_allt{}},
177176
test.object_size_function.declaration});
178177
test.sent_commands.clear();
179178
SECTION("Set symbol to true.")

0 commit comments

Comments
 (0)