Skip to content

Commit bb590f6

Browse files
committed
Add array_exprt to smt conversion
1 parent 9a0dec1 commit bb590f6

File tree

3 files changed

+106
-5
lines changed

3 files changed

+106
-5
lines changed

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <solvers/smt2_incremental/construct_value_expr_from_smt.h>
1414
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
15+
#include <solvers/smt2_incremental/smt_array_theory.h>
1516
#include <solvers/smt2_incremental/smt_commands.h>
1617
#include <solvers/smt2_incremental/smt_core_theory.h>
1718
#include <solvers/smt2_incremental/smt_responses.h>
@@ -64,14 +65,42 @@ static std::vector<exprt> gather_dependent_expressions(const exprt &expr)
6465
{
6566
std::vector<exprt> dependent_expressions;
6667
expr.visit_pre([&](const exprt &expr_node) {
67-
if(can_cast_expr<symbol_exprt>(expr_node))
68+
if(
69+
can_cast_expr<symbol_exprt>(expr_node) ||
70+
can_cast_expr<array_exprt>(expr_node))
6871
{
6972
dependent_expressions.push_back(expr_node);
7073
}
7174
});
7275
return dependent_expressions;
7376
}
7477

78+
void smt2_incremental_decision_proceduret::define_array_function(
79+
const array_exprt &array)
80+
{
81+
const auto array_sort =
82+
convert_type_to_smt_sort(array.type()).cast<smt_array_sortt>();
83+
INVARIANT(
84+
array_sort,
85+
"Converting array typed expression to SMT should result in a term of array "
86+
"sort.");
87+
const smt_identifier_termt array_identifier = smt_identifier_termt{
88+
"array_" + std::to_string(array_sequence()), *array_sort};
89+
solver_process->send(smt_declare_function_commandt{array_identifier, {}});
90+
const std::vector<exprt> &elements = array.operands();
91+
const std::size_t index_width =
92+
array_sort->index_sort().cast<smt_bit_vector_sortt>()->bit_width();
93+
for(std::size_t i = 0; i < elements.size(); ++i)
94+
{
95+
const smt_assert_commandt element_definition{smt_core_theoryt::equal(
96+
smt_array_theoryt::select(
97+
array_identifier, smt_bit_vector_constant_termt{i, index_width}),
98+
convert_expr_to_smt(elements.at(i)))};
99+
solver_process->send(element_definition);
100+
}
101+
expression_identifiers.emplace(array, array_identifier);
102+
}
103+
75104
/// \brief Defines any functions which \p expr depends on, which have not yet
76105
/// been defined, along with their dependencies in turn.
77106
void smt2_incremental_decision_proceduret::define_dependent_functions(
@@ -123,10 +152,29 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
123152
solver_process->send(function);
124153
}
125154
}
155+
if(const auto array_expr = expr_try_dynamic_cast<array_exprt>(current))
156+
define_array_function(*array_expr);
126157
to_be_defined.pop();
127158
}
128159
}
129160

161+
/// Replaces the sub expressions of \p expr which have been defined as separate
162+
/// functions in the smt solver, using the \p expression_identifiers map.
163+
static exprt substitute_identifiers(
164+
exprt expr,
165+
const std::unordered_map<exprt, smt_identifier_termt, irep_hash>
166+
&expression_identifiers)
167+
{
168+
expr.visit_pre([&](exprt &node) -> void {
169+
auto find_result = expression_identifiers.find(node);
170+
if(find_result == expression_identifiers.cend())
171+
return;
172+
const auto type = find_result->first.type();
173+
node = symbol_exprt{find_result->second.identifier(), type};
174+
});
175+
return expr;
176+
}
177+
130178
smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret(
131179
const namespacet &_ns,
132180
std::unique_ptr<smt_base_solver_processt> _solver_process,
@@ -164,15 +212,20 @@ void smt2_incremental_decision_proceduret::ensure_handle_for_expr_defined(
164212
smt_termt
165213
smt2_incremental_decision_proceduret::convert_expr_to_smt(const exprt &expr)
166214
{
167-
track_expression_objects(expr, ns, object_map);
215+
const exprt substituted =
216+
substitute_identifiers(expr, expression_identifiers);
217+
track_expression_objects(substituted, ns, object_map);
168218
associate_pointer_sizes(
169-
expr,
219+
substituted,
170220
ns,
171221
pointer_sizes_map,
172222
object_map,
173223
object_size_function.make_application);
174224
return ::convert_expr_to_smt(
175-
expr, object_map, pointer_sizes_map, object_size_function.make_application);
225+
substituted,
226+
object_map,
227+
pointer_sizes_map,
228+
object_size_function.make_application);
176229
}
177230

178231
exprt smt2_incremental_decision_proceduret::handle(const exprt &expr)

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ 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.
59+
/// \details
60+
/// The new array function identifier is added to the
61+
/// `expression_identifiers` map.
62+
void define_array_function(const array_exprt &array);
5863
/// \brief Defines any functions which \p expr depends on, which have not yet
5964
/// been defined, along with their dependencies in turn.
6065
void define_dependent_functions(const exprt &expr);
@@ -81,7 +86,7 @@ class smt2_incremental_decision_proceduret final
8186
{
8287
return next_id++;
8388
}
84-
} handle_sequence;
89+
} handle_sequence, array_sequence;
8590

8691
std::unordered_map<exprt, smt_identifier_termt, irep_hash>
8792
expression_handle_identifiers;

unit/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <util/symbol_table.h>
1010

1111
#include <solvers/smt2_incremental/smt2_incremental_decision_procedure.h>
12+
#include <solvers/smt2_incremental/smt_array_theory.h>
1213
#include <solvers/smt2_incremental/smt_commands.h>
1314
#include <solvers/smt2_incremental/smt_core_theory.h>
1415
#include <solvers/smt2_incremental/smt_responses.h>
@@ -517,3 +518,45 @@ TEST_CASE(
517518
}
518519
}
519520
}
521+
522+
TEST_CASE(
523+
"smt2_incremental_decision_proceduret array commands.",
524+
"[core][smt2_incremental]")
525+
{
526+
auto test = decision_procedure_test_environmentt::make();
527+
const auto index_type = signedbv_typet{32};
528+
const symbolt index = make_test_symbol("index", index_type);
529+
const auto value_type = signedbv_typet{8};
530+
const symbolt foo = make_test_symbol("foo", value_type);
531+
const auto array_type = array_typet{value_type, from_integer(2, index_type)};
532+
SECTION("array_exprt - list of literal array elements")
533+
{
534+
const array_exprt array_literal{
535+
{from_integer(9, value_type), from_integer(12, value_type)}, array_type};
536+
test.sent_commands.clear();
537+
test.procedure.set_to(
538+
equal_exprt{
539+
foo.symbol_expr(), index_exprt{array_literal, index.symbol_expr()}},
540+
true);
541+
const auto foo_term = smt_identifier_termt{"foo", smt_bit_vector_sortt{8}};
542+
const auto array_term = smt_identifier_termt{
543+
"array_0",
544+
smt_array_sortt{smt_bit_vector_sortt{32}, smt_bit_vector_sortt{8}}};
545+
const auto index_term =
546+
smt_identifier_termt{"index", smt_bit_vector_sortt{32}};
547+
const std::vector<smt_commandt> expected_commands{
548+
smt_declare_function_commandt{foo_term, {}},
549+
smt_declare_function_commandt{array_term, {}},
550+
smt_assert_commandt{smt_core_theoryt::equal(
551+
smt_array_theoryt::select(
552+
array_term, smt_bit_vector_constant_termt{0, 32}),
553+
smt_bit_vector_constant_termt{9, 8})},
554+
smt_assert_commandt{smt_core_theoryt::equal(
555+
smt_array_theoryt::select(
556+
array_term, smt_bit_vector_constant_termt{1, 32}),
557+
smt_bit_vector_constant_termt{12, 8})},
558+
smt_declare_function_commandt{index_term, {}},
559+
smt_assert_commandt{smt_core_theoryt::equal(
560+
foo_term, smt_array_theoryt::select(array_term, index_term))}};
561+
}
562+
}

0 commit comments

Comments
 (0)