27
27
// / return a success status followed by the actual response of interest.
28
28
static smt_responset get_response_to_command (
29
29
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)
31
32
{
32
33
solver_process.send (command);
33
- auto response = solver_process.receive_response ();
34
+ auto response = solver_process.receive_response (identifier_table );
34
35
if (response.cast <smt_success_responset>())
35
- return solver_process.receive_response ();
36
+ return solver_process.receive_response (identifier_table );
36
37
else
37
38
return response;
38
39
}
@@ -84,6 +85,7 @@ void smt2_incremental_decision_proceduret::initialize_array_elements(
84
85
const array_exprt &array,
85
86
const smt_identifier_termt &array_identifier)
86
87
{
88
+ identifier_table.emplace (array_identifier.identifier (), array_identifier);
87
89
const std::vector<exprt> &elements = array.operands ();
88
90
const typet &index_type = array.type ().index_type ();
89
91
for (std::size_t i = 0 ; i < elements.size (); ++i)
@@ -135,13 +137,15 @@ void send_function_definition(
135
137
const irep_idt &symbol_identifier,
136
138
const std::unique_ptr<smt_base_solver_processt> &solver_process,
137
139
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)
139
142
{
140
143
const smt_declare_function_commandt function{
141
144
smt_identifier_termt (
142
145
symbol_identifier, convert_type_to_smt_sort (expr.type ())),
143
146
{}};
144
147
expression_identifiers.emplace (expr, function.identifier ());
148
+ identifier_table.emplace (symbol_identifier, function.identifier ());
145
149
solver_process->send (function);
146
150
}
147
151
@@ -183,7 +187,8 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
183
187
*symbol_expr,
184
188
symbol_expr->get_identifier (),
185
189
solver_process,
186
- expression_identifiers);
190
+ expression_identifiers,
191
+ identifier_table);
187
192
}
188
193
else
189
194
{
@@ -192,6 +197,7 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
192
197
const smt_define_function_commandt function{
193
198
symbol->name , {}, convert_expr_to_smt (symbol->value )};
194
199
expression_identifiers.emplace (*symbol_expr, function.identifier ());
200
+ identifier_table.emplace (identifier, function.identifier ());
195
201
solver_process->send (function);
196
202
}
197
203
}
@@ -210,7 +216,8 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
210
216
*nondet_symbol,
211
217
nondet_symbol->get_identifier (),
212
218
solver_process,
213
- expression_identifiers);
219
+ expression_identifiers,
220
+ identifier_table);
214
221
}
215
222
to_be_defined.pop ();
216
223
}
@@ -263,12 +270,36 @@ void smt2_incremental_decision_proceduret::ensure_handle_for_expr_defined(
263
270
smt_define_function_commandt function{
264
271
" B" + std::to_string (handle_sequence ()), {}, convert_expr_to_smt (expr)};
265
272
expression_handle_identifiers.emplace (expr, function.identifier ());
273
+ identifier_table.emplace (
274
+ function.identifier ().identifier (), function.identifier ());
266
275
solver_process->send (function);
267
276
}
268
277
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
+
269
299
smt_termt
270
300
smt2_incremental_decision_proceduret::convert_expr_to_smt (const exprt &expr)
271
301
{
302
+ define_index_identifiers (expr);
272
303
const exprt substituted =
273
304
substitute_identifiers (expr, expression_identifiers);
274
305
track_expression_objects (substituted, ns, object_map);
@@ -310,13 +341,82 @@ static optionalt<smt_termt> get_identifier(
310
341
return {};
311
342
}
312
343
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
+
313
397
exprt smt2_incremental_decision_proceduret::get (const exprt &expr) const
314
398
{
315
399
log.conditional_output (log.debug (), [&](messaget::mstreamt &debug) {
316
400
debug << " `get` - \n " + expr.pretty (2 , 0 ) << messaget::eom;
317
401
});
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
+ }();
320
420
if (!descriptor)
321
421
{
322
422
if (gather_dependent_expressions (expr).empty ())
@@ -349,25 +449,13 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
349
449
return expr;
350
450
}
351
451
}
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 ()))
363
453
{
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);
368
457
}
369
- return construct_value_expr_from_smt (
370
- get_value_response->pairs ()[0 ].get ().value (), expr.type ());
458
+ return get_expr (*descriptor, expr.type ());
371
459
}
372
460
373
461
void smt2_incremental_decision_proceduret::print_assignment (
@@ -464,8 +552,8 @@ decision_proceduret::resultt smt2_incremental_decision_proceduret::dec_solve()
464
552
{
465
553
++number_of_solver_calls;
466
554
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 );
469
557
if (const auto check_sat_response = result.cast <smt_check_sat_responset>())
470
558
{
471
559
if (check_sat_response->kind ().cast <smt_unknown_responset>())
0 commit comments