9
9
// / \file
10
10
// / Expression Pretty Printing
11
11
12
+ #include " format_expr.h"
13
+
12
14
#include " arith_tools.h"
13
15
#include " expr.h"
14
16
#include " expr_iterator.h"
15
17
#include " fixedbv.h"
16
- #include " format_expr.h"
17
18
#include " format_type.h"
18
19
#include " ieee_float.h"
19
20
#include " invariant.h"
20
21
#include " mp_arith.h"
21
22
#include " rational.h"
22
23
#include " rational_tools.h"
24
+ #include " std_code.h"
23
25
#include " std_expr.h"
24
26
#include " string2int.h"
27
+ #include " string_utils.h"
25
28
26
- #include < stack>
27
29
#include < ostream>
30
+ #include < stack>
28
31
29
32
// / We use the precendences that most readers expect
30
33
// / (i.e., the ones you learn in primary school),
31
34
// / and stay clear of the surprising ones that C has.
32
- static bool bracket_subexpression (
33
- const exprt &sub_expr,
34
- const exprt &expr)
35
+ static bool bracket_subexpression (const exprt &sub_expr, const exprt &expr)
35
36
{
36
37
// no need for parentheses whenever the subexpression
37
38
// doesn't have operands
@@ -57,9 +58,7 @@ static bool bracket_subexpression(
57
58
58
59
// / This formats a multi-ary expression,
59
60
// / adding parentheses where indicated by \ref bracket_subexpression
60
- static std::ostream &format_rec (
61
- std::ostream &os,
62
- const multi_ary_exprt &src)
61
+ static std::ostream &format_rec (std::ostream &os, const multi_ary_exprt &src)
63
62
{
64
63
bool first = true ;
65
64
@@ -86,18 +85,14 @@ static std::ostream &format_rec(
86
85
87
86
// / This formats a binary expression,
88
87
// / which we do as for multi-ary expressions
89
- static std::ostream &format_rec (
90
- std::ostream &os,
91
- const binary_exprt &src)
88
+ static std::ostream &format_rec (std::ostream &os, const binary_exprt &src)
92
89
{
93
90
return format_rec (os, to_multi_ary_expr (src));
94
91
}
95
92
96
93
// / This formats a unary expression,
97
94
// / adding parentheses very aggressively.
98
- static std::ostream &format_rec (
99
- std::ostream &os,
100
- const unary_exprt &src)
95
+ static std::ostream &format_rec (std::ostream &os, const unary_exprt &src)
101
96
{
102
97
if (src.id () == ID_not)
103
98
os << ' !' ;
@@ -113,9 +108,7 @@ static std::ostream &format_rec(
113
108
}
114
109
115
110
// / This formats a constant
116
- static std::ostream &format_rec (
117
- std::ostream &os,
118
- const constant_exprt &src)
111
+ static std::ostream &format_rec (std::ostream &os, const constant_exprt &src)
119
112
{
120
113
auto type = src.type ().id ();
121
114
@@ -128,22 +121,53 @@ static std::ostream &format_rec(
128
121
else
129
122
return os << src.pretty ();
130
123
}
131
- else if (type == ID_unsignedbv || type == ID_signedbv)
124
+ else if (type == ID_unsignedbv || type == ID_signedbv || type == ID_c_bool )
132
125
return os << *numeric_cast<mp_integer>(src);
133
126
else if (type == ID_integer)
134
127
return os << src.get_value ();
128
+ else if (type == ID_string)
129
+ return os << ' "' << escape (id2string (src.get_value ())) << ' "' ;
135
130
else if (type == ID_floatbv)
136
131
return os << ieee_floatt (src);
132
+ else if (type == ID_pointer && src.is_zero ())
133
+ return os << src.get_value ();
137
134
else
138
135
return os << src.pretty ();
139
136
}
140
137
138
+ std::ostream &fallback_format_rec (std::ostream &os, const exprt &expr)
139
+ {
140
+ os << expr.id ();
141
+
142
+ for (const auto &s : expr.get_named_sub ())
143
+ if (s.first != ID_type)
144
+ os << ' ' << s.first << " =\" " << s.second .id () << ' "' ;
145
+
146
+ if (expr.has_operands ())
147
+ {
148
+ os << ' (' ;
149
+ bool first = true ;
150
+
151
+ for (const auto &op : expr.operands ())
152
+ {
153
+ if (first)
154
+ first = false ;
155
+ else
156
+ os << " , " ;
157
+
158
+ os << format (op);
159
+ }
160
+
161
+ os << ' )' ;
162
+ }
163
+
164
+ return os;
165
+ }
166
+
141
167
// The below generates a string in a generic syntax
142
168
// that is inspired by C/C++/Java, and is meant for debugging
143
169
// purposes.
144
- std::ostream &format_rec (
145
- std::ostream &os,
146
- const exprt &expr)
170
+ std::ostream &format_rec (std::ostream &os, const exprt &expr)
147
171
{
148
172
const auto &id = expr.id ();
149
173
@@ -165,6 +189,12 @@ std::ostream &format_rec(
165
189
<< to_member_expr (expr).get_component_name ();
166
190
else if (id == ID_symbol)
167
191
return os << to_symbol_expr (expr).get_identifier ();
192
+ else if (id == ID_index)
193
+ {
194
+ const auto &index_expr = to_index_expr (expr);
195
+ return os << format (index_expr.array ()) << ' [' << format (index_expr.index ())
196
+ << ' ]' ;
197
+ }
168
198
else if (id == ID_type)
169
199
return format_rec (os, expr.type ());
170
200
else if (id == ID_forall || id == ID_exists)
@@ -199,32 +229,24 @@ std::ostream &format_rec(
199
229
return os << format (if_expr.cond ()) << ' ?' << format (if_expr.true_case ())
200
230
<< ' :' << format (if_expr.false_case ());
201
231
}
202
- else
232
+ else if (id == ID_code)
203
233
{
204
- os << id;
234
+ const auto &code = to_code (expr);
235
+ const irep_idt &statement = code.get_statement ();
205
236
206
- for (const auto &s : expr.get_named_sub ())
207
- if (s.first !=ID_type)
208
- os << ' ' << s.first << " =\" " << s.second .id () << ' "' ;
209
-
210
- if (expr.has_operands ())
237
+ if (statement == ID_assign)
238
+ return os << format (to_code_assign (code).lhs ()) << " = "
239
+ << format (to_code_assign (code).rhs ()) << ' ;' ;
240
+ else if (statement == ID_block)
211
241
{
212
- os << ' (' ;
213
- bool first = true ;
214
-
215
- for (const auto &op : expr.operands ())
216
- {
217
- if (first)
218
- first = false ;
219
- else
220
- os << " , " ;
221
-
222
- os << format (op);
223
- }
224
-
225
- os << ' )' ;
242
+ os << ' {' ;
243
+ for (const auto &s : to_code_block (code).operands ())
244
+ os << ' ' << format (s);
245
+ return os << " }" ;
226
246
}
227
-
228
- return os ;
247
+ else
248
+ return fallback_format_rec (os, expr) ;
229
249
}
250
+ else
251
+ return fallback_format_rec (os, expr);
230
252
}
0 commit comments