Skip to content

Commit 89a9604

Browse files
committed
Add support for validating get-value responses with bit vectors
The template parameter is specified for mapping to upper case characters to fix a warning compiling on Ubuntu 18. This warning was related to `std::toupper` being declared with the deprecated `throw ()` in the standard library and the meaning of this changing between C++ versions.
1 parent 820294a commit 89a9604

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/solvers/smt2_incremental/smt_response_validation.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717

1818
#include <solvers/smt2_incremental/smt_response_validation.h>
1919

20+
#include <util/mp_arith.h>
21+
#include <util/range.h>
22+
23+
#include <regex>
24+
2025
template <class smtt>
2126
response_or_errort<smtt>::response_or_errort(smtt smt) : smt{std::move(smt)}
2227
{
@@ -206,10 +211,50 @@ static optionalt<smt_termt> valid_smt_bool(const irept &parse_tree)
206211
return {};
207212
}
208213

214+
static optionalt<smt_termt> valid_smt_binary(const std::string &text)
215+
{
216+
static const std::regex binary_format{"#b[01]+"};
217+
if(!std::regex_match(text, binary_format))
218+
return {};
219+
const mp_integer value = string2integer({text.begin() + 2, text.end()}, 2);
220+
// Width is number of bit values minus the "#b" prefix.
221+
const std::size_t width = text.size() - 2;
222+
return {smt_bit_vector_constant_termt{value, width}};
223+
}
224+
225+
static optionalt<smt_termt> valid_smt_hex(const std::string &text)
226+
{
227+
static const std::regex hex_format{"#x[0-9A-Za-z]+"};
228+
if(!std::regex_match(text, hex_format))
229+
return {};
230+
const std::string hex{text.begin() + 2, text.end()};
231+
// SMT-LIB 2 allows hex characters to be upper of lower case, but they should
232+
// be upper case for mp_integer.
233+
const mp_integer value =
234+
string2integer(make_range(hex).map<std::function<int(int)>>(toupper), 16);
235+
const std::size_t width = (text.size() - 2) * 4;
236+
return {smt_bit_vector_constant_termt{value, width}};
237+
}
238+
239+
static optionalt<smt_termt>
240+
valid_smt_bit_vector_constant(const irept &parse_tree)
241+
{
242+
if(!parse_tree.get_sub().empty() || parse_tree.id().empty())
243+
return {};
244+
const auto value_string = id2string(parse_tree.id());
245+
if(const auto smt_binary = valid_smt_binary(value_string))
246+
return *smt_binary;
247+
if(const auto smt_hex = valid_smt_hex(value_string))
248+
return *smt_hex;
249+
return {};
250+
}
251+
209252
static response_or_errort<smt_termt> validate_term(const irept &parse_tree)
210253
{
211254
if(const auto smt_bool = valid_smt_bool(parse_tree))
212255
return response_or_errort<smt_termt>{*smt_bool};
256+
if(const auto bit_vector_constant = valid_smt_bit_vector_constant(parse_tree))
257+
return response_or_errort<smt_termt>{*bit_vector_constant};
213258
return response_or_errort<smt_termt>{"Unrecognised SMT term - \"" +
214259
print_parse_tree(parse_tree) + "\"."};
215260
}

unit/solvers/smt2_incremental/smt_response_validation.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <testing-utils/use_catch.h>
55

66
#include <solvers/smt2_incremental/smt_response_validation.h>
7+
#include <util/mp_arith.h>
78

89
// Debug printer for `smt_responset`. This will be used by the catch framework
910
// for printing in the case of failed checks / requirements.
@@ -111,4 +112,21 @@ TEST_CASE("smt get-value response validation", "[core][smt2_incremental]")
111112
smt_identifier_termt{"a", smt_bool_sortt{}},
112113
smt_bool_literal_termt{false}}}});
113114
}
115+
SECTION("Bit vector sorted values.")
116+
{
117+
const response_or_errort<smt_responset> response_255 =
118+
validate_smt_response(*smt2irep("((a #xff))").parsed_output);
119+
CHECK(
120+
*response_255.get_if_valid() ==
121+
smt_get_value_responset{{smt_get_value_responset::valuation_pairt{
122+
smt_identifier_termt{"a", smt_bit_vector_sortt{8}},
123+
smt_bit_vector_constant_termt{255, 8}}}});
124+
const response_or_errort<smt_responset> response_42 =
125+
validate_smt_response(*smt2irep("((a #b00101010))").parsed_output);
126+
CHECK(
127+
*response_42.get_if_valid() ==
128+
smt_get_value_responset{{smt_get_value_responset::valuation_pairt{
129+
smt_identifier_termt{"a", smt_bit_vector_sortt{8}},
130+
smt_bit_vector_constant_termt{42, 8}}}});
131+
}
114132
}

0 commit comments

Comments
 (0)