Skip to content

Commit c5fa708

Browse files
author
Lukasz A.J. Wrona
committed
Refactor integer conversions
1 parent f99c8ff commit c5fa708

File tree

1 file changed

+62
-73
lines changed

1 file changed

+62
-73
lines changed

src/solvers/refinement/string_refinement.cpp

+62-73
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,40 @@ Author: Alberto Griggio, [email protected]
3535
#include <java_bytecode/java_types.h>
3636
#include <util/optional.h>
3737

38+
/// Convert exprt to a specific type. Throw bad_cast if conversion
39+
/// cannot be performed
40+
/// Generic case doesn't exist, specialize for different types accordingly
41+
/// TODO: this should go to util
42+
template<typename T>
43+
optionalt<T> expr_cast(const exprt&);
44+
45+
template<>
46+
optionalt<mp_integer> expr_cast<mp_integer>(const exprt& expr)
47+
{
48+
mp_integer out;
49+
if(to_integer(expr, out))
50+
return { };
51+
return out;
52+
}
53+
54+
template<>
55+
optionalt<std::size_t> expr_cast<std::size_t>(const exprt& expr)
56+
{
57+
if (const auto tmp=expr_cast<mp_integer>(expr))
58+
{
59+
if(tmp->is_long() && *tmp >= 0)
60+
return tmp->to_long();
61+
}
62+
return { };
63+
}
64+
65+
template<typename T>
66+
T expr_cast_v(const exprt& expr) {
67+
const auto maybe=expr_cast<T>(expr);
68+
INVARIANT(maybe, "Bad conversion");
69+
return *maybe;
70+
}
71+
3872
static bool validate(const string_refinementt::infot &info)
3973
{
4074
PRECONDITION(info.ns);
@@ -296,33 +330,6 @@ bool string_refinementt::add_axioms_for_string_assigns(
296330
return true;
297331
}
298332

299-
/// Convert exprt to a specific type. Throw bad_cast if conversion
300-
/// cannot be performed
301-
/// Generic case doesn't exist, specialize for different types accordingly
302-
/// TODO: this should go to util
303-
template<typename T>
304-
optionalt<T> expr_cast(const exprt&);
305-
306-
template<>
307-
optionalt<mp_integer> expr_cast<mp_integer>(const exprt& expr)
308-
{
309-
mp_integer out;
310-
if(to_integer(expr, out))
311-
return { };
312-
return out;
313-
}
314-
315-
template<>
316-
optionalt<std::size_t> expr_cast<std::size_t>(const exprt& expr)
317-
{
318-
if (const auto tmp=expr_cast<mp_integer>(expr))
319-
{
320-
if(tmp->is_long() && *tmp >= 0)
321-
return tmp->to_long();
322-
}
323-
return { };
324-
}
325-
326333
/// If the expression is of type string, then adds constants to the index set to
327334
/// force the solver to pick concrete values for each character, and fill the
328335
/// maps `found_length` and `found_content`.
@@ -343,10 +350,9 @@ void string_refinementt::concretize_string(const exprt &expr)
343350
exprt content=str.content();
344351
replace_expr(symbol_resolve, content);
345352
found_length[content]=length;
346-
const auto string_length=expr_cast<std::size_t>(length);
347-
INVARIANT(string_length, "Bad integer conversion");
353+
const auto string_length=expr_cast_v<std::size_t>(length);
348354
INVARIANT(
349-
*string_length<=generator.max_string_length,
355+
string_length<=generator.max_string_length,
350356
string_refinement_invariantt("string length must be less than the max "
351357
"length"));
352358
if(index_set[str.content()].empty())
@@ -357,14 +363,11 @@ void string_refinementt::concretize_string(const exprt &expr)
357363
for(const auto &i : index_set[str.content()])
358364
{
359365
const exprt simple_i=simplify_expr(get(i), ns);
360-
mp_integer mpi_index;
361-
bool conversion_failure=to_integer(simple_i, mpi_index);
362-
if(!conversion_failure && mpi_index>=0 && mpi_index<*string_length)
366+
if(const auto index=expr_cast<std::size_t>(simple_i))
363367
{
364368
const exprt str_i=simplify_expr(str[simple_i], ns);
365369
const exprt value=simplify_expr(get(str_i), ns);
366-
std::size_t index=mpi_index.to_long();
367-
map.emplace(index, value);
370+
map.emplace(*index, value);
368371
}
369372
else
370373
{
@@ -904,10 +907,9 @@ exprt fill_in_array_with_expr(const exprt &expr, std::size_t string_max_length)
904907
// statements
905908
const with_exprt with_expr=to_with_expr(it);
906909
const exprt &then_expr=with_expr.new_value();
907-
const auto index=expr_cast<std::size_t>(with_expr.where());
908-
INVARIANT(index, "Bad integer conversion");
909-
if(*index<string_max_length)
910-
initial_map.emplace(*index, then_expr);
910+
const auto index=expr_cast_v<std::size_t>(with_expr.where());
911+
if(index<string_max_length)
912+
initial_map.emplace(index, then_expr);
911913
}
912914

913915
array_exprt result(to_array_type(expr.type()));
@@ -1026,23 +1028,18 @@ static exprt negation_of_not_contains_constraint(
10261028
const symbol_exprt &univ_var)
10271029
{
10281030
// If the for all is vacuously true, the negation is false.
1029-
exprt lbu=axiom.univ_lower_bound();
1030-
exprt ubu=axiom.univ_upper_bound();
1031+
const exprt lbu=axiom.univ_lower_bound();
1032+
const exprt ubu=axiom.univ_upper_bound();
10311033
if(lbu.id()==ID_constant && ubu.id()==ID_constant)
10321034
{
1033-
mp_integer lb_int, ub_int;
1034-
to_integer(to_constant_expr(lbu), lb_int);
1035-
to_integer(to_constant_expr(ubu), ub_int);
1036-
if(ub_int<=lb_int)
1035+
const auto lb_int=expr_cast<mp_integer>(lbu);
1036+
const auto ub_int=expr_cast<mp_integer>(ubu);
1037+
if(!lb_int || !ub_int || *ub_int<=*lb_int)
10371038
return false_exprt();
10381039
}
10391040

1040-
exprt lbe=axiom.exists_lower_bound();
1041-
exprt ube=axiom.exists_upper_bound();
1042-
1043-
mp_integer lbe_int, ube_int;
1044-
to_integer(to_constant_expr(lbe), lbe_int);
1045-
to_integer(to_constant_expr(ube), ube_int);
1041+
const auto lbe=expr_cast_v<mp_integer>(axiom.exists_lower_bound());
1042+
const auto ube=expr_cast_v<mp_integer>(axiom.exists_upper_bound());
10461043

10471044
// If the premise is false, the implication is trivially true, so the
10481045
// negation is false.
@@ -1056,7 +1053,7 @@ static exprt negation_of_not_contains_constraint(
10561053
// The negated existential becomes an universal, and this is the unrolling of
10571054
// that universal quantifier.
10581055
std::vector<exprt> conjuncts;
1059-
for(mp_integer i=lbe_int; i<ube_int; ++i)
1056+
for(mp_integer i=lbe; i<ube; ++i)
10601057
{
10611058
const constant_exprt i_exprt=from_integer(i, univ_var.type());
10621059
const equal_exprt equal_chars(
@@ -1085,10 +1082,9 @@ static exprt negation_of_constraint(const string_constraintt &axiom)
10851082
exprt ub=axiom.upper_bound();
10861083
if(lb.id()==ID_constant && ub.id()==ID_constant)
10871084
{
1088-
mp_integer lb_int, ub_int;
1089-
to_integer(to_constant_expr(lb), lb_int);
1090-
to_integer(to_constant_expr(ub), ub_int);
1091-
if(ub_int<=lb_int)
1085+
const auto lb_int=expr_cast<mp_integer>(lb);
1086+
const auto ub_int=expr_cast<mp_integer>(ub);
1087+
if(!lb_int || !ub_int || ub_int<=lb_int)
10921088
return false_exprt();
10931089
}
10941090

@@ -1512,18 +1508,12 @@ static std::vector<exprt> sub_arrays(const exprt &array_expr)
15121508
void string_refinementt::add_to_index_set(const exprt &s, exprt i)
15131509
{
15141510
simplify(i, ns);
1515-
if(i.id()==ID_constant)
1511+
if(i.id()!=ID_constant || expr_cast<size_t>(i))
15161512
{
1517-
mp_integer mpi;
1518-
to_integer(i, mpi);
1519-
if(mpi<0)
1520-
return;
1513+
for(const auto &sub : sub_arrays(s))
1514+
if(index_set[sub].insert(i).second)
1515+
current_index_set[sub].insert(i);
15211516
}
1522-
1523-
std::vector<exprt> subs=sub_arrays(s);
1524-
for(const auto &sub : subs)
1525-
if(index_set[sub].insert(i).second)
1526-
current_index_set[sub].insert(i);
15271517
}
15281518

15291519
void string_refinementt::initial_index_set(const string_constraintt &axiom)
@@ -1707,14 +1697,13 @@ exprt substitute_array_lists(exprt expr, size_t string_max_length)
17071697
array_typet arr_type(char_type, infinity_exprt(char_type));
17081698
exprt ret_expr=array_of_exprt(from_integer(0, char_type), arr_type);
17091699

1710-
for(size_t i=0; i<expr.operands().size()/2; i++)
1700+
for(size_t i=0; i<expr.operands().size(); i+=2)
17111701
{
1712-
const exprt &index=expr.operands()[i*2];
1713-
const exprt &value=expr.operands()[i*2+1];
1714-
mp_integer index_value;
1715-
bool not_constant=to_integer(index, index_value);
1716-
if(not_constant ||
1717-
(index_value>=0 && index_value<string_max_length))
1702+
const exprt &index=expr.operands()[i];
1703+
const exprt &value=expr.operands()[i+1];
1704+
const auto index_value=expr_cast<std::size_t>(index);
1705+
if(!index.is_constant() ||
1706+
(index_value && *index_value<string_max_length))
17181707
ret_expr=with_exprt(ret_expr, index, value);
17191708
}
17201709
return ret_expr;

0 commit comments

Comments
 (0)