2727// / return a success status followed by the actual response of interest.
2828static smt_responset get_response_to_command (
2929 smt_base_solver_processt &solver_process,
30- const smt_commandt &command)
30+ const smt_commandt &command,
31+ const std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
3132{
3233 solver_process.send (command);
33- auto response = solver_process.receive_response ();
34+ auto response = solver_process.receive_response (identifier_table );
3435 if (response.cast <smt_success_responset>())
35- return solver_process.receive_response ();
36+ return solver_process.receive_response (identifier_table );
3637 else
3738 return response;
3839}
@@ -84,6 +85,7 @@ void smt2_incremental_decision_proceduret::initialize_array_elements(
8485 const array_exprt &array,
8586 const smt_identifier_termt &array_identifier)
8687{
88+ identifier_table.emplace (array_identifier.identifier (), array_identifier);
8789 const std::vector<exprt> &elements = array.operands ();
8890 const typet &index_type = array.type ().index_type ();
8991 for (std::size_t i = 0 ; i < elements.size (); ++i)
@@ -135,13 +137,15 @@ void send_function_definition(
135137 const irep_idt &symbol_identifier,
136138 const std::unique_ptr<smt_base_solver_processt> &solver_process,
137139 std::unordered_map<exprt, smt_identifier_termt, irep_hash>
138- &expression_identifiers)
140+ &expression_identifiers,
141+ std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
139142{
140143 const smt_declare_function_commandt function{
141144 smt_identifier_termt (
142145 symbol_identifier, convert_type_to_smt_sort (expr.type ())),
143146 {}};
144147 expression_identifiers.emplace (expr, function.identifier ());
148+ identifier_table.emplace (symbol_identifier, function.identifier ());
145149 solver_process->send (function);
146150}
147151
@@ -183,7 +187,8 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
183187 *symbol_expr,
184188 symbol_expr->get_identifier (),
185189 solver_process,
186- expression_identifiers);
190+ expression_identifiers,
191+ identifier_table);
187192 }
188193 else
189194 {
@@ -192,6 +197,7 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
192197 const smt_define_function_commandt function{
193198 symbol->name , {}, convert_expr_to_smt (symbol->value )};
194199 expression_identifiers.emplace (*symbol_expr, function.identifier ());
200+ identifier_table.emplace (identifier, function.identifier ());
195201 solver_process->send (function);
196202 }
197203 }
@@ -210,7 +216,8 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
210216 *nondet_symbol,
211217 nondet_symbol->get_identifier (),
212218 solver_process,
213- expression_identifiers);
219+ expression_identifiers,
220+ identifier_table);
214221 }
215222 to_be_defined.pop ();
216223 }
@@ -263,12 +270,36 @@ void smt2_incremental_decision_proceduret::ensure_handle_for_expr_defined(
263270 smt_define_function_commandt function{
264271 " B" + std::to_string (handle_sequence ()), {}, convert_expr_to_smt (expr)};
265272 expression_handle_identifiers.emplace (expr, function.identifier ());
273+ identifier_table.emplace (
274+ function.identifier ().identifier (), function.identifier ());
266275 solver_process->send (function);
267276}
268277
278+ void smt2_incremental_decision_proceduret::define_index_identifiers (
279+ const exprt &expr)
280+ {
281+ expr.visit_pre ([&](const exprt &expr_node) {
282+ if (!can_cast_type<array_typet>(expr_node.type ()))
283+ return ;
284+ if (const auto with_expr = expr_try_dynamic_cast<with_exprt>(expr_node))
285+ {
286+ const auto index_expr = with_expr->where ();
287+ const auto index_term = convert_expr_to_smt (index_expr);
288+ const auto index_identifier = " index_" + std::to_string (index_sequence ());
289+ const auto index_definition =
290+ smt_define_function_commandt{index_identifier, {}, index_term};
291+ expression_identifiers.emplace (index_expr, index_definition.identifier ());
292+ identifier_table.emplace (index_identifier, index_definition.identifier ());
293+ solver_process->send (
294+ smt_define_function_commandt{index_identifier, {}, index_term});
295+ }
296+ });
297+ }
298+
269299smt_termt
270300smt2_incremental_decision_proceduret::convert_expr_to_smt (const exprt &expr)
271301{
302+ define_index_identifiers (expr);
272303 const exprt substituted =
273304 substitute_identifiers (expr, expression_identifiers);
274305 track_expression_objects (substituted, ns, object_map);
@@ -310,13 +341,82 @@ static optionalt<smt_termt> get_identifier(
310341 return {};
311342}
312343
344+ array_exprt smt2_incremental_decision_proceduret::get_expr (
345+ const smt_termt &array,
346+ const array_typet &type) const
347+ {
348+ INVARIANT (
349+ type.is_complete (), " Array size is required for getting array values." );
350+ const auto size = numeric_cast<std::size_t >(get (type.size ()));
351+ INVARIANT (
352+ size,
353+ " Size of array must be convertible to std::size_t for getting array value" );
354+ std::vector<exprt> elements;
355+ const auto index_type = type.index_type ();
356+ elements.reserve (*size);
357+ for (std::size_t index = 0 ; index < size; ++index)
358+ {
359+ elements.push_back (get_expr (
360+ smt_array_theoryt::select (
361+ array,
362+ ::convert_expr_to_smt (
363+ from_integer (index, index_type),
364+ object_map,
365+ pointer_sizes_map,
366+ object_size_function.make_application)),
367+ type.element_type()));
368+ }
369+ return array_exprt{elements, type};
370+ }
371+
372+ exprt smt2_incremental_decision_proceduret::get_expr (
373+ const smt_termt &descriptor,
374+ const typet &type) const
375+ {
376+ const smt_get_value_commandt get_value_command{descriptor};
377+ const smt_responset response = get_response_to_command (
378+ *solver_process, get_value_command, identifier_table);
379+ const auto get_value_response = response.cast <smt_get_value_responset>();
380+ if (!get_value_response)
381+ {
382+ throw analysis_exceptiont{
383+ " Expected get-value response from solver, but received - " +
384+ response.pretty ()};
385+ }
386+ if (get_value_response->pairs ().size () > 1 )
387+ {
388+ throw analysis_exceptiont{
389+ " Expected single valuation pair in get-value response from solver, but "
390+ " received multiple pairs - " +
391+ response.pretty ()};
392+ }
393+ return construct_value_expr_from_smt (
394+ get_value_response->pairs ()[0 ].get ().value (), type);
395+ }
396+
313397exprt smt2_incremental_decision_proceduret::get (const exprt &expr) const
314398{
315399 log.conditional_output (log.debug (), [&](messaget::mstreamt &debug) {
316400 debug << " `get` - \n " + expr.pretty (2 , 0 ) << messaget::eom;
317401 });
318- optionalt<smt_termt> descriptor =
319- get_identifier (expr, expression_handle_identifiers, expression_identifiers);
402+ auto descriptor = [&]() -> optionalt<smt_termt> {
403+ if (const auto index_expr = expr_try_dynamic_cast<index_exprt>(expr))
404+ {
405+ const auto array = get_identifier (
406+ index_expr->array (),
407+ expression_handle_identifiers,
408+ expression_identifiers);
409+ const auto index = get_identifier (
410+ index_expr->index (),
411+ expression_handle_identifiers,
412+ expression_identifiers);
413+ if (!array || !index)
414+ return {};
415+ return smt_array_theoryt::select (*array, *index);
416+ }
417+ return get_identifier (
418+ expr, expression_handle_identifiers, expression_identifiers);
419+ }();
320420 if (!descriptor)
321421 {
322422 if (gather_dependent_expressions (expr).empty ())
@@ -349,25 +449,13 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
349449 return expr;
350450 }
351451 }
352- const smt_get_value_commandt get_value_command{*descriptor};
353- const smt_responset response =
354- get_response_to_command (*solver_process, get_value_command);
355- const auto get_value_response = response.cast <smt_get_value_responset>();
356- if (!get_value_response)
357- {
358- throw analysis_exceptiont{
359- " Expected get-value response from solver, but received - " +
360- response.pretty ()};
361- }
362- if (get_value_response->pairs ().size () > 1 )
452+ if (const auto array_type = type_try_dynamic_cast<array_typet>(expr.type ()))
363453 {
364- throw analysis_exceptiont{
365- " Expected single valuation pair in get-value response from solver, but "
366- " received multiple pairs - " +
367- response.pretty ()};
454+ if (array_type->is_incomplete ())
455+ return expr;
456+ return get_expr (*descriptor, *array_type);
368457 }
369- return construct_value_expr_from_smt (
370- get_value_response->pairs ()[0 ].get ().value (), expr.type ());
458+ return get_expr (*descriptor, expr.type ());
371459}
372460
373461void smt2_incremental_decision_proceduret::print_assignment (
@@ -464,8 +552,8 @@ decision_proceduret::resultt smt2_incremental_decision_proceduret::dec_solve()
464552{
465553 ++number_of_solver_calls;
466554 define_object_sizes ();
467- const smt_responset result =
468- get_response_to_command ( *solver_process, smt_check_sat_commandt{});
555+ const smt_responset result = get_response_to_command (
556+ *solver_process, smt_check_sat_commandt{}, identifier_table );
469557 if (const auto check_sat_response = result.cast <smt_check_sat_responset>())
470558 {
471559 if (check_sat_response->kind ().cast <smt_unknown_responset>())
0 commit comments