CBMC
Loading...
Searching...
No Matches
format_expr.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Expression Pretty Printing
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "format_expr.h"
13
14#include "arith_tools.h"
15#include "bitvector_expr.h"
16#include "byte_operators.h"
17#include "expr_util.h"
18#include "floatbv_expr.h"
19#include "format_type.h"
20#include "ieee_float.h"
21#include "mathematical_expr.h"
22#include "mp_arith.h"
23#include "pointer_expr.h"
24#include "string_utils.h"
25
26#include <map>
27#include <ostream>
28
29// expressions that are rendered with infix operators
31{
32 const char *rep;
33};
34
35const std::map<irep_idt, infix_opt> infix_map = {
36 {ID_plus, {"+"}},
37 {ID_minus, {"-"}},
38 {ID_mult, {"*"}},
39 {ID_div, {"/"}},
40 {ID_equal, {"="}},
41 {ID_notequal, {u8"\u2260"}}, // /=, U+2260
42 {ID_and, {u8"\u2227"}}, // wedge, U+2227
43 {ID_or, {u8"\u2228"}}, // vee, U+2228
44 {ID_xor, {u8"\u2295"}}, // + in circle, U+2295
45 {ID_implies, {u8"\u21d2"}}, // =>, U+21D2
46 {ID_le, {u8"\u2264"}}, // <=, U+2264
47 {ID_ge, {u8"\u2265"}}, // >=, U+2265
48 {ID_lt, {"<"}},
49 {ID_gt, {">"}},
50};
51
55static bool bracket_subexpression(const exprt &sub_expr, const exprt &expr)
56{
57 // no need for parentheses whenever the subexpression
58 // doesn't have operands
59 if(!sub_expr.has_operands())
60 return false;
61
62 // no need if subexpression isn't an infix operator
63 if(infix_map.find(sub_expr.id()) == infix_map.end())
64 return false;
65
66 // * and / bind stronger than + and -
67 if(
68 (sub_expr.id() == ID_mult || sub_expr.id() == ID_div) &&
69 (expr.id() == ID_plus || expr.id() == ID_minus))
70 return false;
71
72 // ==, !=, <, <=, >, >= bind stronger than && and ||
73 if(
74 (sub_expr.id() == ID_equal || sub_expr.id() == ID_notequal ||
75 sub_expr.id() == ID_lt || sub_expr.id() == ID_gt ||
76 sub_expr.id() == ID_le || sub_expr.id() == ID_ge) &&
77 (expr.id() == ID_and || expr.id() == ID_or))
78 return false;
79
80 // +, -, *, / bind stronger than ==, !=, <, <=, >, >=
81 if(
82 (sub_expr.id() == ID_plus || sub_expr.id() == ID_minus ||
83 sub_expr.id() == ID_mult || sub_expr.id() == ID_div) &&
84 (expr.id() == ID_equal || expr.id() == ID_notequal || expr.id() == ID_lt ||
85 expr.id() == ID_gt || expr.id() == ID_le || expr.id() == ID_ge))
86 {
87 return false;
88 }
89
90 return true;
91}
92
95static std::ostream &format_rec(std::ostream &os, const multi_ary_exprt &src)
96{
97 bool first = true;
98
99 std::string operator_str = id2string(src.id()); // default
100
101 if(src.id() == ID_equal && to_equal_expr(src).op0().is_boolean())
102 {
103 operator_str = u8"\u21d4"; // <=>, U+21D4
104 }
105 else
106 {
107 auto infix_map_it = infix_map.find(src.id());
108 if(infix_map_it != infix_map.end())
109 operator_str = infix_map_it->second.rep;
110 }
111
112 for(const auto &op : src.operands())
113 {
114 if(first)
115 first = false;
116 else
117 os << ' ' << operator_str << ' ';
118
119 const bool need_parentheses = bracket_subexpression(op, src);
120
122 os << '(';
123
124 os << format(op);
125
127 os << ')';
128 }
129
130 return os;
131}
132
135static std::ostream &format_rec(std::ostream &os, const binary_exprt &src)
136{
137 return format_rec(os, to_multi_ary_expr(src));
138}
139
142static std::ostream &format_rec(std::ostream &os, const unary_exprt &src)
143{
144 if(src.id() == ID_not)
145 os << u8"\u00ac"; // neg, U+00AC
146 else if(src.id() == ID_unary_minus)
147 os << '-';
148 else if(src.id() == ID_count_leading_zeros)
149 os << "clz";
150 else if(src.id() == ID_count_trailing_zeros)
151 os << "ctz";
152 else if(src.id() == ID_find_first_set)
153 os << "ffs";
154 else
155 return os << src.pretty();
156
157 if(src.op().has_operands())
158 return os << '(' << format(src.op()) << ')';
159 else
160 return os << format(src.op());
161}
162
164static std::ostream &format_rec(std::ostream &os, const ternary_exprt &src)
165{
166 os << src.id() << '(' << format(src.op0()) << ", " << format(src.op1())
167 << ", " << format(src.op2()) << ')';
168 return os;
169}
170
172static std::ostream &format_rec(std::ostream &os, const constant_exprt &src)
173{
174 auto type = src.type().id();
175
176 if(type == ID_bool)
177 {
178 if(src.is_true())
179 return os << "true";
180 else if(src.is_false())
181 return os << "false";
182 else
183 return os << src.pretty();
184 }
185 else if(
186 type == ID_unsignedbv || type == ID_signedbv || type == ID_c_bool ||
187 type == ID_c_bit_field)
189 else if(type == ID_bv)
190 {
191 // These do not have a numerical interpretation.
192 // We'll print the 0/1 bit pattern, starting with the bit
193 // that has the highest index. We use vector notation
194 // [...] to avoid confusion with decimal numbers.
195 auto width = to_bv_type(src.type()).get_width();
196 std::string result;
197 result.reserve(width + 2);
198 auto &value = src.get_value();
199 result += '[';
200 for(std::size_t i = 0; i < width; i++)
201 result += get_bvrep_bit(value, width, width - i - 1) ? '1' : '0';
202 result += ']';
203 return os << result;
204 }
205 else if(
206 type == ID_integer || type == ID_natural || type == ID_rational ||
207 type == ID_real || type == ID_range)
208 {
209 return os << src.get_value();
210 }
211 else if(type == ID_string)
212 return os << '"' << escape(id2string(src.get_value())) << '"';
213 else if(type == ID_floatbv)
214 return os << ieee_float_valuet(src);
215 else if(type == ID_pointer)
216 {
217 if(src.is_null_pointer())
218 return os << ID_NULL;
219 else if(
220 src.get_value() == "INVALID" || src.get_value().starts_with("INVALID-"))
221 {
222 return os << "INVALID-POINTER";
223 }
224 else
225 {
226 const auto &pointer_type = to_pointer_type(src.type());
227 const auto width = pointer_type.get_width();
228 auto int_value = bvrep2integer(src.get_value(), width, false);
229 return os << "pointer(0x" << integer2string(int_value, 16) << ", "
230 << format(pointer_type.base_type()) << ')';
231 }
232 }
233 else if(type == ID_c_enum_tag)
234 {
235 return os << string2integer(id2string(src.get_value()), 16);
236 }
237 else
238 return os << src.pretty();
239}
240
241std::ostream &fallback_format_rec(std::ostream &os, const exprt &expr)
242{
243 os << expr.id();
244
245 for(const auto &s : expr.get_named_sub())
246 if(s.first != ID_type && s.first != ID_C_source_location)
247 os << ' ' << s.first << "=\"" << s.second.id() << '"';
248
249 if(expr.has_operands())
250 {
251 os << '(';
252 bool first = true;
253
254 for(const auto &op : expr.operands())
255 {
256 if(first)
257 first = false;
258 else
259 os << ", ";
260
261 os << format(op);
262 }
263
264 os << ')';
265 }
266
267 return os;
268}
269
271{
272public:
274 {
275 setup();
276 }
277
279 std::function<std::ostream &(std::ostream &, const exprt &)>;
280 using expr_mapt = std::unordered_map<irep_idt, formattert>;
281
283
285 const formattert &find_formatter(const exprt &);
286
287private:
289 void setup();
290
292};
293
294// The below generates textual output in a generic syntax
295// that is inspired by C/C++/Java, and is meant for debugging
296// purposes.
298{
299 auto multi_ary_expr =
300 [](std::ostream &os, const exprt &expr) -> std::ostream & {
301 return format_rec(os, to_multi_ary_expr(expr));
302 };
303
309
310 auto binary_infix_expr =
311 [](std::ostream &os, const exprt &expr) -> std::ostream & {
312 return format_rec(os, to_binary_expr(expr));
313 };
314
324
325 auto binary_prefix_expr =
326 [](std::ostream &os, const exprt &expr) -> std::ostream & {
327 os << expr.id() << '(' << format(to_binary_expr(expr).op0()) << ", "
328 << format(to_binary_expr(expr).op1()) << ')';
329 return os;
330 };
331
334
335 auto unary_expr = [](std::ostream &os, const exprt &expr) -> std::ostream & {
336 return format_rec(os, to_unary_expr(expr));
337 };
338
341
343 [](std::ostream &os, const exprt &expr) -> std::ostream & {
344 return os << expr.id() << '(' << format(to_unary_expr(expr).op()) << ')';
345 };
346
351
352 auto ternary_expr =
353 [](std::ostream &os, const exprt &expr) -> std::ostream & {
354 return format_rec(os, to_ternary_expr(expr));
355 };
356
363
365 [](std::ostream &os, const exprt &expr) -> std::ostream & {
366 return format_rec(os, to_constant_expr(expr));
367 };
368
370 [](std::ostream &os, const exprt &expr) -> std::ostream & {
371 const auto &address_of = to_address_of_expr(expr);
372 return os << "address_of(" << format(address_of.object()) << ')';
373 };
374
376 [](std::ostream &os, const exprt &expr) -> std::ostream & {
378 return os << format(annotated_pointer.symbolic_pointer());
379 };
380
382 [](std::ostream &os, const exprt &expr) -> std::ostream & {
383 return os << "cast(" << format(to_typecast_expr(expr).op()) << ", "
384 << format(expr.type()) << ')';
385 };
386
388 [](std::ostream &os, const exprt &expr) -> std::ostream & {
389 return os << "zero_extend(" << format(to_zero_extend_expr(expr).op())
390 << ", " << format(expr.type()) << ')';
391 };
392
394 [](std::ostream &os, const exprt &expr) -> std::ostream & {
396 return os << "floatbv_typecast(" << format(floatbv_typecast_expr.op())
397 << ", " << format(floatbv_typecast_expr.type()) << ", "
398 << format(floatbv_typecast_expr.rounding_mode()) << ')';
399 };
400
401 auto byte_extract =
402 [](std::ostream &os, const exprt &expr) -> std::ostream & {
403 const auto &byte_extract_expr = to_byte_extract_expr(expr);
404 return os << expr.id() << '(' << format(byte_extract_expr.op()) << ", "
405 << format(byte_extract_expr.offset()) << ", "
406 << format(byte_extract_expr.type()) << ')';
407 };
408
411
412 auto byte_update = [](std::ostream &os, const exprt &expr) -> std::ostream & {
413 const auto &byte_update_expr = to_byte_update_expr(expr);
414 return os << expr.id() << '(' << format(byte_update_expr.op()) << ", "
415 << format(byte_update_expr.offset()) << ", "
416 << format(byte_update_expr.value()) << ", "
417 << format(byte_update_expr.type()) << ')';
418 };
419
422
424 [](std::ostream &os, const exprt &expr) -> std::ostream & {
425 return os << format(to_member_expr(expr).op()) << '.'
426 << to_member_expr(expr).get_component_name();
427 };
428
430 [](std::ostream &os, const exprt &expr) -> std::ostream & {
431 return os << to_symbol_expr(expr).get_identifier();
432 };
433
435 [](std::ostream &os, const exprt &expr) -> std::ostream & {
436 const auto &index_expr = to_index_expr(expr);
437 return os << format(index_expr.array()) << '[' << format(index_expr.index())
438 << ']';
439 };
440
442 [](std::ostream &os, const exprt &expr) -> std::ostream & {
443 return format_rec(os, expr.type());
444 };
445
447 [](std::ostream &os, const exprt &expr) -> std::ostream & {
448 os << u8"\u2200 ";
449 bool first = true;
450 for(const auto &symbol : to_quantifier_expr(expr).variables())
451 {
452 if(first)
453 first = false;
454 else
455 os << ", ";
456 os << format(symbol) << " : " << format(symbol.type());
457 }
458 return os << " . " << format(to_quantifier_expr(expr).where());
459 };
460
462 [](std::ostream &os, const exprt &expr) -> std::ostream & {
463 os << u8"\u2203 ";
464 bool first = true;
465 for(const auto &symbol : to_quantifier_expr(expr).variables())
466 {
467 if(first)
468 first = false;
469 else
470 os << ", ";
471 os << format(symbol) << " : " << format(symbol.type());
472 }
473 return os << " . " << format(to_quantifier_expr(expr).where());
474 };
475
476 expr_map[ID_let] = [](std::ostream &os, const exprt &expr) -> std::ostream & {
477 const auto &let_expr = to_let_expr(expr);
478
479 os << "LET ";
480
481 bool first = true;
482
483 const auto &values = let_expr.values();
484 auto values_it = values.begin();
485 for(auto &v : let_expr.variables())
486 {
487 if(first)
488 first = false;
489 else
490 os << ", ";
491
492 os << format(v) << " = " << format(*values_it);
493 ++values_it;
494 }
495
496 return os << " IN " << format(let_expr.where());
497 };
498
500 [](std::ostream &os, const exprt &expr) -> std::ostream & {
501 const auto &lambda_expr = to_lambda_expr(expr);
502
503 os << u8"\u03bb ";
504
505 bool first = true;
506
507 for(auto &v : lambda_expr.variables())
508 {
509 if(first)
510 first = false;
511 else
512 os << ", ";
513
514 os << format(v);
515 }
516
517 return os << " . " << format(lambda_expr.where());
518 };
519
520 auto compound = [](std::ostream &os, const exprt &expr) -> std::ostream & {
521 os << "{ ";
522
523 bool first = true;
524
525 for(const auto &op : expr.operands())
526 {
527 if(first)
528 first = false;
529 else
530 os << ", ";
531
532 os << format(op);
533 }
534
535 return os << " }";
536 };
537
538 expr_map[ID_array] = compound;
539 expr_map[ID_struct] = compound;
540
542 [](std::ostream &os, const exprt &expr) -> std::ostream & {
543 const auto &array_of_expr = to_array_of_expr(expr);
544 return os << "array_of(" << format(array_of_expr.what()) << ')';
545 };
546
547 expr_map[ID_if] = [](std::ostream &os, const exprt &expr) -> std::ostream & {
548 const auto &if_expr = to_if_expr(expr);
549 return os << '(' << format(if_expr.cond()) << " ? "
550 << format(if_expr.true_case()) << " : "
551 << format(if_expr.false_case()) << ')';
552 };
553
555 [](std::ostream &os, const exprt &expr) -> std::ostream & {
556 return os << '"' << expr.get_string(ID_value) << '"';
557 };
558
560 [](std::ostream &os, const exprt &expr) -> std::ostream & {
562 os << format(function_application_expr.function()) << '(';
563 bool first = true;
564 for(auto &argument : function_application_expr.arguments())
565 {
566 if(first)
567 first = false;
568 else
569 os << ", ";
570 os << format(argument);
571 }
572 os << ')';
573 return os;
574 };
575
577 [](std::ostream &os, const exprt &expr) -> std::ostream & {
578 const auto &dereference_expr = to_dereference_expr(expr);
579 os << '*';
580 if(dereference_expr.pointer().id() != ID_symbol)
581 os << '(' << format(dereference_expr.pointer()) << ')';
582 else
583 os << format(dereference_expr.pointer());
584 return os;
585 };
586
588 [](std::ostream &os, const exprt &expr) -> std::ostream & {
589 const auto &saturating_minus = to_saturating_minus_expr(expr);
590 return os << "saturating-(" << format(saturating_minus.lhs()) << ", "
591 << format(saturating_minus.rhs()) << ')';
592 };
593
595 [](std::ostream &os, const exprt &expr) -> std::ostream & {
596 const auto &saturating_plus = to_saturating_plus_expr(expr);
597 return os << "saturating+(" << format(saturating_plus.lhs()) << ", "
598 << format(saturating_plus.rhs()) << ')';
599 };
600
602 [](std::ostream &os, const exprt &expr) -> std::ostream & {
604 return os << u8"\u275d" << object_address_expr.object_identifier()
605 << u8"\u275e";
606 };
607
609 [](std::ostream &os, const exprt &expr) -> std::ostream & {
610 const auto &object_size_expr = to_object_size_expr(expr);
611 return os << "object_size(" << format(object_size_expr.op()) << ')';
612 };
613
615 [](std::ostream &os, const exprt &expr) -> std::ostream & {
617 return os << "pointer_offset(" << format(pointer_offset_expr.op()) << ')';
618 };
619
621 [](std::ostream &os, const exprt &expr) -> std::ostream & {
622 const auto &field_address_expr = to_field_address_expr(expr);
623 return os << format(field_address_expr.base()) << u8".\u275d"
624 << field_address_expr.component_name() << u8"\u275e";
625 };
626
627 fallback = [](std::ostream &os, const exprt &expr) -> std::ostream & {
628 return fallback_format_rec(os, expr);
629 };
630}
631
634{
635 auto m_it = expr_map.find(expr.id());
636 if(m_it == expr_map.end())
637 return fallback;
638 else
639 return m_it->second;
640}
641
643
648
649std::ostream &format_rec(std::ostream &os, const exprt &expr)
650{
652 return formatter(os, expr);
653}
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
bool get_bvrep_bit(const irep_idt &src, std::size_t width, std::size_t bit_index)
Get a bit with given index from bit-vector representation.
API to expression classes for bitvectors.
const saturating_minus_exprt & to_saturating_minus_expr(const exprt &expr)
Cast an exprt to a saturating_minus_exprt.
const saturating_plus_exprt & to_saturating_plus_expr(const exprt &expr)
Cast an exprt to a saturating_plus_exprt.
const zero_extend_exprt & to_zero_extend_expr(const exprt &expr)
Cast an exprt to a zero_extend_exprt.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
Expression classes for byte-level operators.
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
A base class for binary expressions.
Definition std_expr.h:638
std::size_t get_width() const
Definition std_types.h:925
A constant literal expression.
Definition std_expr.h:3118
const irep_idt & get_value() const
Definition std_expr.h:3126
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition std_expr.cpp:25
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
bool has_operands() const
Return true if there is at least one operand.
Definition expr.h:91
bool is_true() const
Return whether the expression is a constant representing true.
Definition expr.cpp:27
bool is_false() const
Return whether the expression is a constant representing false.
Definition expr.cpp:34
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
std::function< std::ostream &(std::ostream &, const exprt &)> formattert
void setup()
setup the expressions we can format
std::unordered_map< irep_idt, formattert > expr_mapt
const formattert & find_formatter(const exprt &)
find the formatter for a given expression
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irep_idt & id() const
Definition irep.h:388
named_subt & get_named_sub()
Definition irep.h:450
A base class for multi-ary expressions Associativity is not specified.
Definition std_expr.h:912
const typet & base_type() const
The type of the data what we point to.
An expression with three operands.
Definition std_expr.h:67
exprt & op0()
Definition expr.h:133
exprt & op1()
Definition expr.h:136
exprt & op2()
Definition expr.h:139
Generic base class for unary expressions.
Definition std_expr.h:361
const exprt & op() const
Definition std_expr.h:391
Deprecated expression utility functions.
API to expression classes for floating-point arithmetic.
const floatbv_typecast_exprt & to_floatbv_typecast_expr(const exprt &expr)
Cast an exprt to a floatbv_typecast_exprt.
static format_containert< T > format(const T &o)
Definition format.h:37
static bool bracket_subexpression(const exprt &sub_expr, const exprt &expr)
We use the precendences that most readers expect (i.e., the ones you learn in primary school),...
format_expr_configt format_expr_config
const std::map< irep_idt, infix_opt > infix_map
void add_format_hook(irep_idt id, format_expr_configt::formattert formatter)
std::ostream & fallback_format_rec(std::ostream &os, const exprt &expr)
static std::ostream & format_rec(std::ostream &os, const multi_ary_exprt &src)
This formats a multi-ary expression, adding parentheses where indicated by bracket_subexpression.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
API to expression classes for 'mathematical' expressions.
const quantifier_exprt & to_quantifier_expr(const exprt &expr)
Cast an exprt to a quantifier_exprt.
const function_application_exprt & to_function_application_expr(const exprt &expr)
Cast an exprt to a function_application_exprt.
const lambda_exprt & to_lambda_expr(const exprt &expr)
Cast an exprt to a lambda_exprt.
const mp_integer string2integer(const std::string &n, unsigned base)
Definition mp_arith.cpp:54
const std::string integer2string(const mp_integer &n, unsigned base)
Definition mp_arith.cpp:103
API to expression classes for Pointers.
const annotated_pointer_constant_exprt & to_annotated_pointer_constant_expr(const exprt &expr)
Cast an exprt to an annotated_pointer_constant_exprt.
const object_address_exprt & to_object_address_expr(const exprt &expr)
Cast an exprt to an object_address_exprt.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
const pointer_offset_exprt & to_pointer_offset_expr(const exprt &expr)
Cast an exprt to a pointer_offset_exprt.
const field_address_exprt & to_field_address_expr(const exprt &expr)
Cast an exprt to an field_address_exprt.
const object_size_exprt & to_object_size_expr(const exprt &expr)
Cast an exprt to a object_size_exprt.
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition std_expr.h:1603
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const ternary_exprt & to_ternary_expr(const exprt &expr)
Cast an exprt to a ternary_exprt.
Definition std_expr.h:116
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:715
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:426
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:987
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition std_expr.h:3456
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2582
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3064
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3173
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
std::string escape(const std::string &s)
Generic escaping of strings; this is not meant to be a particular programming language.
const char * rep