Skip to content

Commit b257100

Browse files
committed
Fetch value of array elements individually from solver
1 parent 4fe1831 commit b257100

File tree

3 files changed

+85
-17
lines changed

3 files changed

+85
-17
lines changed

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,59 @@ static optionalt<smt_termt> get_identifier(
319319
return {};
320320
}
321321

322+
array_exprt smt2_incremental_decision_proceduret::get_expr(
323+
const smt_termt &array,
324+
const array_typet &type) const
325+
{
326+
INVARIANT(
327+
type.is_complete(), "Array size is required for getting array values.");
328+
const auto size = numeric_cast<std::size_t>(get(type.size()));
329+
INVARIANT(
330+
size,
331+
"Size of array must be convertible to std::size_t for getting array value");
332+
std::vector<exprt> elements;
333+
const auto index_type = type.index_type();
334+
elements.reserve(*size);
335+
for(std::size_t index = 0; index < size; ++index)
336+
{
337+
elements.push_back(get_expr(
338+
smt_array_theoryt::select(
339+
array,
340+
::convert_expr_to_smt(
341+
from_integer(index, index_type),
342+
object_map,
343+
pointer_sizes_map,
344+
object_size_function.make_application)),
345+
type.element_type()));
346+
}
347+
return array_exprt{elements, type};
348+
}
349+
350+
exprt smt2_incremental_decision_proceduret::get_expr(
351+
const smt_termt &descriptor,
352+
const typet &type) const
353+
{
354+
const smt_get_value_commandt get_value_command{descriptor};
355+
const smt_responset response = get_response_to_command(
356+
*solver_process, get_value_command, identifier_table);
357+
const auto get_value_response = response.cast<smt_get_value_responset>();
358+
if(!get_value_response)
359+
{
360+
throw analysis_exceptiont{
361+
"Expected get-value response from solver, but received - " +
362+
response.pretty()};
363+
}
364+
if(get_value_response->pairs().size() > 1)
365+
{
366+
throw analysis_exceptiont{
367+
"Expected single valuation pair in get-value response from solver, but "
368+
"received multiple pairs - " +
369+
response.pretty()};
370+
}
371+
return construct_value_expr_from_smt(
372+
get_value_response->pairs()[0].get().value(), type);
373+
}
374+
322375
exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
323376
{
324377
log.conditional_output(log.debug(), [&](messaget::mstreamt &debug) {
@@ -359,25 +412,13 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
359412
return expr;
360413
}
361414
}
362-
const smt_get_value_commandt get_value_command{*descriptor};
363-
const smt_responset response = get_response_to_command(
364-
*solver_process, get_value_command, identifier_table);
365-
const auto get_value_response = response.cast<smt_get_value_responset>();
366-
if(!get_value_response)
415+
if(const auto array_type = type_try_dynamic_cast<array_typet>(expr.type()))
367416
{
368-
throw analysis_exceptiont{
369-
"Expected get-value response from solver, but received - " +
370-
response.pretty()};
371-
}
372-
if(get_value_response->pairs().size() > 1)
373-
{
374-
throw analysis_exceptiont{
375-
"Expected single valuation pair in get-value response from solver, but "
376-
"received multiple pairs - " +
377-
response.pretty()};
417+
if(array_type->is_incomplete())
418+
return expr;
419+
return get_expr(*descriptor, *array_type);
378420
}
379-
return construct_value_expr_from_smt(
380-
get_value_response->pairs()[0].get().value(), expr.type());
421+
return get_expr(*descriptor, expr.type());
381422
}
382423

383424
void smt2_incremental_decision_proceduret::print_assignment(

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ class smt2_incremental_decision_proceduret final
5252
void push() override;
5353
void pop() override;
5454

55+
/// Gets the value of \p descriptor from the solver and returns the solver
56+
/// response expressed as an exprt of type \p type. This is an implementation
57+
/// detail of the `get(exprt)` member function.
58+
exprt get_expr(const smt_termt &descriptor, const typet &type) const;
59+
array_exprt get_expr(const smt_termt &array, const array_typet &type) const;
60+
5561
protected:
5662
// Implementation of protected decision_proceduret member function.
5763
resultt dec_solve() override;

unit/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,27 @@ TEST_CASE(
616616
smt_assert_commandt{smt_core_theoryt::equal(
617617
foo_term, smt_array_theoryt::select(array_term, index_term))}};
618618
REQUIRE(test.sent_commands == expected_commands);
619+
620+
SECTION("Get values of array literal")
621+
{
622+
test.sent_commands.clear();
623+
test.mock_responses = {
624+
// get-value response for array_size
625+
smt_get_value_responset{
626+
{{{smt_bit_vector_constant_termt{2, 32}},
627+
smt_bit_vector_constant_termt{2, 32}}}},
628+
// get-value response for first element
629+
smt_get_value_responset{
630+
{{{smt_array_theoryt::select(
631+
array_term, smt_bit_vector_constant_termt{0, 32})},
632+
smt_bit_vector_constant_termt{9, 8}}}},
633+
// get-value response for second element
634+
smt_get_value_responset{
635+
{{{smt_array_theoryt::select(
636+
array_term, smt_bit_vector_constant_termt{1, 32})},
637+
smt_bit_vector_constant_termt{12, 8}}}}};
638+
REQUIRE(test.procedure.get(array_literal) == array_literal);
639+
}
619640
}
620641
SECTION("array_of_exprt - all elements set to a given value")
621642
{

0 commit comments

Comments
 (0)