@@ -283,6 +283,7 @@ exprt smt2_convt::get(const exprt &expr) const
283283
284284 if (it!=identifier_map.end ())
285285 return it->second .value ;
286+ return expr;
286287 }
287288 else if (expr.id ()==ID_nondet_symbol)
288289 {
@@ -319,6 +320,15 @@ exprt smt2_convt::get(const exprt &expr) const
319320 }
320321 else if (expr.is_constant ())
321322 return expr;
323+ else if (const auto &array = expr_try_dynamic_cast<array_exprt>(expr))
324+ {
325+ exprt array_copy = *array;
326+ for (auto &element : array_copy.operands ())
327+ {
328+ element = get (element);
329+ }
330+ return array_copy;
331+ }
322332
323333 return nil_exprt ();
324334}
@@ -464,31 +474,85 @@ constant_exprt smt2_convt::parse_literal(
464474exprt smt2_convt::parse_array (
465475 const irept &src,
466476 const array_typet &type)
477+ {
478+ std::unordered_map<int64_t , exprt> operands_map;
479+ walk_array_tree (&operands_map, src, type);
480+ exprt::operandst operands;
481+ // Try to find the default value, if there is none then set it
482+ auto maybe_default_op = operands_map.find (-1 );
483+ exprt default_op;
484+ if (maybe_default_op == operands_map.end ())
485+ default_op = nil_exprt ();
486+ else
487+ default_op = maybe_default_op->second ;
488+ int64_t i = 0 ;
489+ auto maybe_size = numeric_cast<std::int64_t >(type.size ());
490+ if (maybe_size.has_value ())
491+ {
492+ while (i < maybe_size.value ())
493+ {
494+ auto found_op = operands_map.find (i);
495+ if (found_op != operands_map.end ())
496+ operands.emplace_back (found_op->second );
497+ else
498+ operands.emplace_back (default_op);
499+ i++;
500+ }
501+ }
502+ else
503+ {
504+ // Array size is unknown, keep adding with known indexes in order
505+ // until we fail to find one.
506+ auto found_op = operands_map.find (i);
507+ while (found_op != operands_map.end ())
508+ {
509+ operands.emplace_back (found_op->second );
510+ i++;
511+ found_op = operands_map.find (i);
512+ }
513+ operands.emplace_back (default_op);
514+ }
515+ return array_exprt (operands, type);
516+ }
517+
518+ void smt2_convt::walk_array_tree (
519+ std::unordered_map<int64_t , exprt> *operands_map,
520+ const irept &src,
521+ const array_typet &type)
467522{
468523 if (src.get_sub ().size ()==4 && src.get_sub ()[0 ].id ()==" store" )
469524 {
525+ // This is the SMT syntax being parsed here
470526 // (store array index value)
471- if (src.get_sub ().size ()!=4 )
472- return nil_exprt ();
473-
474- exprt array=parse_array (src.get_sub ()[1 ], type);
475- exprt index=parse_rec (src.get_sub ()[2 ], type.size ().type ());
476- exprt value=parse_rec (src.get_sub ()[3 ], type.subtype ());
477-
478- return with_exprt (array, index, value);
527+ // Recurse
528+ walk_array_tree (operands_map, src.get_sub ()[1 ], type);
529+ const auto index_expr = parse_rec (src.get_sub ()[2 ], type.size ().type ());
530+ const constant_exprt index_constant = to_constant_expr (index_expr);
531+ mp_integer tempint;
532+ bool failure = to_integer (index_constant, tempint);
533+ if (failure)
534+ return ;
535+ long index = tempint.to_long ();
536+ exprt value = parse_rec (src.get_sub ()[3 ], type.subtype ());
537+ operands_map->emplace (index, value);
538+ }
539+ else if (src.get_sub ().size () == 3 && src.get_sub ()[0 ].id () == " let" )
540+ {
541+ // This is produced by Z3
542+ // (let (....) (....))
543+ walk_array_tree (
544+ operands_map, src.get_sub ()[1 ].get_sub ()[0 ].get_sub ()[1 ], type);
545+ walk_array_tree (operands_map, src.get_sub ()[2 ], type);
479546 }
480547 else if (src.get_sub ().size ()==2 &&
481548 src.get_sub ()[0 ].get_sub ().size ()==3 &&
482549 src.get_sub ()[0 ].get_sub ()[0 ].id ()==" as" &&
483550 src.get_sub ()[0 ].get_sub ()[1 ].id ()==" const" )
484551 {
485- // This is produced by Z3.
486- // ((as const (Array (_ BitVec 64) (_ BitVec 8))) #x00)))
487- exprt value=parse_rec (src.get_sub ()[1 ], type.subtype ());
488- return array_of_exprt (value, type);
552+ // (as const type_info default_value)
553+ exprt default_value = parse_rec (src.get_sub ()[1 ], type.subtype ());
554+ operands_map->emplace (-1 , default_value);
489555 }
490- else
491- return nil_exprt ();
492556}
493557
494558exprt smt2_convt::parse_union (
0 commit comments