CBMC
Loading...
Searching...
No Matches
smt_terms.cpp
Go to the documentation of this file.
1// Author: Diffblue Ltd.
2
3#include "smt_terms.h"
4
5#include <util/arith_tools.h>
6#include <util/mp_arith.h>
7#include <util/range.h>
8
9#include "smt_sorts.h"
10
11#include <algorithm>
12#include <regex>
13
14// Define the irep_idts for terms.
15#define TERM_ID(the_id) \
16 const irep_idt ID_smt_##the_id##_term{"smt_" #the_id "_term"};
17#include "smt_terms.def"
18
19#undef TERM_ID
20
22 : irept{id, {{ID_type, upcast(std::move(sort))}}, {}}
23{
24}
25
26bool smt_termt::operator==(const smt_termt &other) const
27{
28 return irept::operator==(other);
29}
30
31bool smt_termt::operator!=(const smt_termt &other) const
32{
33 return !(*this == other);
34}
35
37{
38 return downcast(find(ID_type));
39}
40
46
48{
49 return get_bool(ID_value);
50}
51
52static bool is_valid_smt_identifier(irep_idt identifier)
53{
54 // The below regex matches a complete string which does not contain the `|`
55 // character. So it would match the string `foo bar`, but not `|foo bar|`.
56 static const std::regex valid{"[^\\|]*"};
57 return std::regex_match(id2string(identifier), valid);
58}
59
61 irep_idt identifier,
62 smt_sortt sort,
63 std::vector<smt_indext> indices)
65{
66 // The below invariant exists as a sanity check that the string being used for
67 // the identifier is in unescaped form. This is because the escaping and
68 // unescaping are implementation details of the printing to string and
69 // response parsing respectively, not part of the underlying data.
72 R"(Identifiers may not contain | characters.)");
74 for(auto &index : indices)
75 {
76 get_sub().push_back(
78 }
79}
80
85
86std::vector<std::reference_wrapper<const smt_indext>>
88{
89 return make_range(get_sub()).map([](const irept &index) {
90 return std::cref(
92 });
93}
94
96 const mp_integer &value,
99{
100 INVARIANT(
101 value < power(mp_integer{2}, get_sort().bit_width()),
102 "value must fit in number of bits available.");
103 INVARIANT(
104 !value.is_negative(),
105 "Negative numbers are not supported by bit vector constants.");
106 set(ID_value, integer2bvrep(value, get_sort().bit_width()));
107}
108
110 const mp_integer &value,
111 std::size_t bit_width)
113{
114}
115
117{
118 return bvrep2integer(get(ID_value), get_sort().bit_width(), false);
119}
120
122{
123 // The below cast is sound because the constructor only allows bit_vector
124 // sorts to be set.
125 return static_cast<const smt_bit_vector_sortt &>(smt_termt::get_sort());
126}
127
129 smt_identifier_termt function_identifier,
130 std::vector<smt_termt> arguments)
131 : smt_termt(ID_smt_function_application_term, function_identifier.get_sort())
132{
134 std::transform(
135 std::make_move_iterator(arguments.begin()),
136 std::make_move_iterator(arguments.end()),
137 std::back_inserter(get_sub()),
138 [](smt_termt &&argument) { return static_cast<irept &&>(argument); });
139}
140
146
147std::vector<std::reference_wrapper<const smt_termt>>
149{
150 return make_range(get_sub()).map([](const irept &argument) {
151 return std::cref(static_cast<const smt_termt &>(argument));
152 });
153}
154
156 std::vector<smt_identifier_termt> bound_variables,
157 smt_termt predicate)
159{
160 INVARIANT(
161 !bound_variables.empty(),
162 "A forall term should bind at least one variable.");
163 std::transform(
164 std::make_move_iterator(bound_variables.begin()),
165 std::make_move_iterator(bound_variables.end()),
166 std::back_inserter(get_sub()),
168 return irept{std::move(bound_variable)};
169 });
170 INVARIANT(
171 predicate.get_sort().cast<smt_bool_sortt>(),
172 "Predicate of forall quantifier is expected to have bool sort.");
173 set(ID_body, std::move(predicate));
174}
175
177{
178 return static_cast<const smt_termt &>(find(ID_body));
179}
180
181std::vector<std::reference_wrapper<const smt_identifier_termt>>
183{
184 return make_range(get_sub()).map([](const irept &variable) {
185 return std::cref(static_cast<const smt_identifier_termt &>(variable));
186 });
187}
188
190 std::vector<smt_identifier_termt> bound_variables,
191 smt_termt predicate)
193{
194 INVARIANT(
195 !bound_variables.empty(),
196 "A exists term should bind at least one variable.");
197 std::transform(
198 std::make_move_iterator(bound_variables.begin()),
199 std::make_move_iterator(bound_variables.end()),
200 std::back_inserter(get_sub()),
202 return irept{std::move(bound_variable)};
203 });
204 INVARIANT(
205 predicate.get_sort().cast<smt_bool_sortt>(),
206 "Predicate of exists quantifier is expected to have bool sort.");
207 set(ID_body, std::move(predicate));
208}
209
211{
212 return static_cast<const smt_termt &>(find(ID_body));
213}
214
215std::vector<std::reference_wrapper<const smt_identifier_termt>>
217{
218 return make_range(get_sub()).map([](const irept &variable) {
219 return std::cref(static_cast<const smt_identifier_termt &>(variable));
220 });
221}
222
223template <typename visitort>
224void accept(const smt_termt &term, const irep_idt &id, visitort &&visitor)
225{
226#define TERM_ID(the_id) \
227 if(id == ID_smt_##the_id##_term) \
228 return visitor.visit(static_cast<const smt_##the_id##_termt &>(term));
229// The include below is marked as nolint because including the same file
230// multiple times is required as part of the x macro pattern.
231#include "smt_terms.def" // NOLINT(build/include)
232#undef TERM_ID
234}
235
240
242{
243 ::accept(*this, id(), std::move(visitor));
244}
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
irep_idt integer2bvrep(const mp_integer &src, std::size_t width)
convert an integer to bit-vector representation with given width This uses two's complement for negat...
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
bool operator==(const irept &other) const
Definition irep.cpp:133
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:412
subt & get_sub()
Definition irep.h:448
const smt_bit_vector_sortt & get_sort() const
smt_bit_vector_constant_termt(const mp_integer &value, smt_bit_vector_sortt)
Definition smt_terms.cpp:95
smt_bool_literal_termt(bool value)
Definition smt_terms.cpp:41
const smt_termt & predicate() const
std::vector< std::reference_wrapper< const smt_identifier_termt > > bound_variables() const
smt_exists_termt(std::vector< smt_identifier_termt > bound_variables, smt_termt predicate)
smt_forall_termt(std::vector< smt_identifier_termt > bound_variables, smt_termt predicate)
const smt_termt & predicate() const
std::vector< std::reference_wrapper< const smt_identifier_termt > > bound_variables() const
const smt_identifier_termt & function_identifier() const
smt_function_application_termt(smt_identifier_termt function_identifier, std::vector< smt_termt > arguments)
Unchecked construction of function application terms.
std::vector< std::reference_wrapper< const smt_termt > > arguments() const
Stores identifiers in unescaped and unquoted form.
Definition smt_terms.h:93
irep_idt identifier() const
Definition smt_terms.cpp:81
smt_identifier_termt(irep_idt identifier, smt_sortt sort, std::vector< smt_indext > indices={})
Constructs an identifier term with the given identifier and sort.
Definition smt_terms.cpp:60
std::vector< std::reference_wrapper< const smt_indext > > indices() const
Definition smt_terms.cpp:87
Class for adding the ability to up and down cast smt_indext to and from irept.
Definition smt_index.h:37
static irept upcast(smt_sortt sort)
Definition smt_sorts.h:66
static const smt_sortt & downcast(const irept &)
Definition smt_sorts.h:72
const smt_sortt & get_sort() const
Definition smt_terms.cpp:36
bool operator==(const smt_termt &) const
Definition smt_terms.cpp:26
void accept(smt_term_const_downcast_visitort &) const
smt_termt()=delete
bool operator!=(const smt_termt &) const
Definition smt_terms.cpp:31
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
STL namespace.
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
Data structure for smt sorts.
void accept(const smt_termt &term, const irep_idt &id, visitort &&visitor)
static bool is_valid_smt_identifier(irep_idt identifier)
Definition smt_terms.cpp:52
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423