CBMC
Loading...
Searching...
No Matches
expr2statement_list.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Conversion from Expression or Type to Statement List
4
5Author: Matthias Weiss, matthias.weiss@diffblue.com
6
7\*******************************************************************/
8
10
11#include <ansi-c/expr2c.h>
12
13#include <util/namespace.h>
14#include <util/std_expr.h>
15#include <util/suffix.h>
16#include <util/symbol.h>
17
18#include <cstring>
19#include <iostream>
20
22#define AND 'A'
23
25#define OR 'O'
26
28#define XOR 'X'
29
31#define NOT_POSTFIX 'N'
32
34#define NOT "NOT"
35
37#define OPERAND_SEPARATOR ' '
38
40#define LINE_SEPARATOR ";\n"
41
44#define NESTING_OPEN_LINE_SEPARATOR "(;\n"
45
48#define NESTING_CLOSED_LINE_SEPARATOR ");\n"
49
51#define REFERENCE_FLAG '#'
52
54#define SCOPE_SEPARATOR "::"
55
63static std::vector<exprt>
64instrument_equal_operands(const exprt &lhs, const exprt &rhs)
65{
66 std::vector<exprt> result;
67 if(ID_not != lhs.id() && ID_not != rhs.id())
68 {
69 // lhs == rhs is equivalent to X lhs; XN rhs;
70 result.push_back(lhs);
71 result.push_back(not_exprt{rhs});
72 }
73 else if(ID_not != lhs.id() && ID_not == rhs.id())
74 {
75 // lhs == !rhs is equivalent to X lhs; X rhs;
76 result.push_back(lhs);
77 result.push_back(to_not_expr(rhs).op());
78 }
79 else if(ID_not == lhs.id() && ID_not != rhs.id())
80 {
81 // !lhs == rhs is equivalent to X lhs; X rhs;
82 result.push_back(to_not_expr(lhs).op());
83 result.push_back(rhs);
84 }
85 else // ID_not == lhs.id() && ID_not == rhs.id()
86 {
87 // !lhs == !rhs is equivalent to X lhs; XN rhs;
88 result.push_back(to_not_expr(lhs).op());
89 result.push_back(rhs);
90 }
91 return result;
92}
93
98static bool is_not_bool(const exprt &expr)
99{
100 if(!expr.is_boolean())
101 return true;
102 for(const exprt &op : expr.operands())
103 if(!op.is_boolean())
104 return true;
105 return false;
106}
107
108std::string expr2stl(const exprt &expr, const namespacet &ns)
109{
111
112 return expr2stl.convert(expr);
113}
114
115std::string type2stl(const typet &type, const namespacet &ns)
116{
117 // TODO: Implement type2stl.
118 // Expand this section so that it is able to properly convert from
119 // CBMC types to STL code.
120 return type2c(type, ns);
121}
122
124 : inside_bit_string(false), is_reference(false), ns(ns)
125{
126}
127
128std::string expr2stlt::convert(const exprt &expr)
129{
130 // Redirect to expr2c if no boolean expression.
131 if(is_not_bool(expr))
132 return expr2c(expr, ns);
133
134 if(ID_and == expr.id())
135 convert(to_and_expr(expr));
136 else if(ID_or == expr.id())
137 convert(to_or_expr(expr));
138 else if(ID_xor == expr.id())
139 convert(to_xor_expr(expr));
140 else if(ID_notequal == expr.id())
142 else if(ID_equal == expr.id())
143 convert(to_equal_expr(expr));
144 else if(ID_symbol == expr.id())
145 convert(to_symbol_expr(expr));
146 else if(ID_not == expr.id() && to_not_expr(expr).op().is_boolean())
147 convert(to_not_expr(expr));
148 else // TODO: support more instructions in expr2stl.
149 return expr2c(expr, ns);
150
151 return result.str();
152}
153
155{
156 std::vector<exprt> operands = expr.operands();
157 convert_multiary_bool(operands, AND);
158}
159
161{
162 std::vector<exprt> operands = expr.operands();
163 convert_multiary_bool(operands, OR);
164}
165
167{
168 std::vector<exprt> operands = expr.operands();
169 convert_multiary_bool(operands, XOR);
170}
171
173{
174 std::vector<exprt> operands = expr.operands();
175 convert_multiary_bool(operands, XOR);
176}
177
179{
180 std::vector<exprt> operands =
181 instrument_equal_operands(expr.lhs(), expr.rhs());
182 convert_multiary_bool(operands, XOR);
183}
184
186{
187 // If a NOT expression is being handled here it must always mark the
188 // beginning of a new bit string.
190
191 if(ID_symbol == expr.op().id())
192 {
193 // Use AN to load the symbol.
194 is_reference = true;
196 convert(to_symbol_expr(expr.op()));
198 }
199 else
200 {
201 // Use NOT to negate the RLO after the wrapped expression was loaded.
202 convert(expr.op());
204 }
205}
206
208{
209 if(is_reference)
210 {
212 is_reference = false;
213 }
215}
216
218 std::vector<exprt> &operands,
219 const char operation)
220{
222 convert_multiary_bool_operands(operands, operation);
223 else
224 {
226 convert_multiary_bool_operands(operands, operation);
227 }
228}
229
231 const std::vector<exprt> &operands,
232 const char operation)
233{
234 for(const exprt &op : operands)
235 {
236 if(ID_not == op.id())
237 {
238 result << operation << NOT_POSTFIX;
240 }
241 else
242 {
243 result << operation;
245 }
246 }
247}
248
250{
251 if(op.id() == ID_symbol)
252 {
253 is_reference = true;
257 }
258 else
259 {
260 inside_bit_string = false;
262 convert(op);
264 }
265}
266
267void expr2stlt::convert_first_non_trivial_operand(std::vector<exprt> &operands)
268{
270 for(auto it{begin(operands)}; it != end(operands); ++it)
271 {
272 if(
273 (ID_symbol == it->id()) ||
274 (ID_not == it->id() && ID_symbol == to_not_expr(*it).op().id()))
275 continue;
276 else
277 {
278 non_trivial_op = *it;
279 operands.erase(it);
280 break;
281 }
282 }
283 // Important for some scenarios: Convert complex op first, set bit string
284 // flag to true afterwards.
285 if(non_trivial_op.is_not_nil())
287
288 inside_bit_string = true;
289}
290
292{
293 const symbolt *symbol;
294 std::string shorthand = id2string(identifier);
295 if(
296 !ns.lookup(identifier, symbol) && !symbol->base_name.empty() &&
298 return symbol->base_name;
299
300 const std::string::size_type pos = shorthand.rfind(SCOPE_SEPARATOR);
301 if(pos != std::string::npos)
302 shorthand.erase(0, pos + std::strlen(SCOPE_SEPARATOR));
303
304 return shorthand;
305}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Boolean AND.
Definition std_expr.h:2125
exprt & lhs()
Definition std_expr.h:668
exprt & rhs()
Definition std_expr.h:678
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
bool empty() const
Definition dstring.h:89
Equality.
Definition std_expr.h:1366
Class for saving the internal state of the conversion process.
void convert_multiary_bool(std::vector< exprt > &operands, const char operation)
Iterates through all the given operands and converts them depending on the operation.
void convert_bool_operand(const exprt &op)
Converts a single boolean operand and introduces an additional nesting layer if needed.
std::string convert(const exprt &expr)
Invokes the conversion process for the given expression and calls itself recursively in the process.
void convert_multiary_bool_operands(const std::vector< exprt > &operands, const char operation)
Iterates through all the given operands and converts them depending on the operation.
void convert_first_non_trivial_operand(std::vector< exprt > &operands)
Iterates through all the given operands in search for the first non-trivial operand (that encloses al...
bool is_reference
Flag to specify if the next symbol to convert is a reference to a variable.
expr2stlt(const namespacet &ns)
Creates a new instance of the converter.
const namespacet & ns
Contains the symbol table of the current program to convert.
irep_idt id_shorthand(const irep_idt &identifier)
Returns the given identifier in a form that is compatible with STL by looking up the symbol or cuttin...
std::stringstream result
Used for saving intermediate results of the conversion process.
bool inside_bit_string
Internal representation of the FC bit in STL.
Base class for all expressions.
Definition expr.h:56
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:224
operandst & operands()
Definition expr.h:94
const irep_idt & id() const
Definition irep.h:388
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:94
Boolean negation.
Definition std_expr.h:2454
Disequality.
Definition std_expr.h:1425
Boolean OR.
Definition std_expr.h:2270
Expression to hold a symbol (variable)
Definition std_expr.h:131
const irep_idt & get_identifier() const
Definition std_expr.h:160
Symbol table entry.
Definition symbol.h:28
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:391
Boolean XOR.
Definition std_expr.h:2370
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition expr2c.cpp:4155
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
Definition expr2c.cpp:4171
#define NESTING_OPEN_LINE_SEPARATOR
Separator for the end of an instruction that introduces a new layer of nesting.
#define SCOPE_SEPARATOR
CBMC-internal separator for variable scopes.
#define NOT_POSTFIX
Postfix for any negated boolean instruction.
#define REFERENCE_FLAG
Prefix for the reference to any variable.
#define OPERAND_SEPARATOR
Separator between the instruction code and it's operand.
#define OR
STL code for an OR instruction.
#define XOR
STL code for a XOR instruction.
std::string expr2stl(const exprt &expr, const namespacet &ns)
Converts a given expression to human-readable STL code.
std::string type2stl(const typet &type, const namespacet &ns)
Converts a given type to human-readable STL code.
#define LINE_SEPARATOR
Separator between the end of an instruction and the next one.
#define NESTING_CLOSED_LINE_SEPARATOR
Separator for the end of an instruction that closes a nesting layer.
#define AND
STL code for an AND instruction.
static std::vector< exprt > instrument_equal_operands(const exprt &lhs, const exprt &rhs)
Modifies the parameters of a binary equal expression with the help of its symmetry properties.
#define NOT
STL code for a NOT instruction.
static bool is_not_bool(const exprt &expr)
Checks if the expression or one of its parameters is not of type bool.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
literalt pos(literalt a)
Definition literal.h:194
bool is_reference(const typet &type)
Returns true if the type is a reference.
#define PRECONDITION(CONDITION)
Definition invariant.h:463
API to expression classes.
const and_exprt & to_and_expr(const exprt &expr)
Cast an exprt to a and_exprt.
Definition std_expr.h:2172
const xor_exprt & to_xor_expr(const exprt &expr)
Cast an exprt to a xor_exprt.
Definition std_expr.h:2395
const or_exprt & to_or_expr(const exprt &expr)
Cast an exprt to a or_exprt.
Definition std_expr.h:2317
const notequal_exprt & to_notequal_expr(const exprt &expr)
Cast an exprt to an notequal_exprt.
Definition std_expr.h:1450
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition std_expr.h:2479
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition std_expr.h:1407
bool has_suffix(const std::string &s, const std::string &suffix)
Definition suffix.h:17
Symbol table entry.