@@ -217,81 +217,145 @@ std::ostream &fallback_format_rec(std::ostream &os, const exprt &expr)
217217 return os;
218218}
219219
220- // The below generates a string in a generic syntax
220+ class format_expr_configt
221+ {
222+ public:
223+ format_expr_configt ()
224+ {
225+ setup ();
226+ }
227+
228+ using formattert =
229+ std::function<std::ostream &(std::ostream &, const exprt &)>;
230+ using expr_mapt = std::unordered_map<irep_idt, formattert>;
231+
232+ expr_mapt expr_map;
233+
234+ // / find the formatter for a given expression
235+ const formattert &find_formatter (const exprt &);
236+
237+ private:
238+ // / setup the expressions we can format
239+ void setup ();
240+
241+ formattert fallback;
242+ };
243+
244+ // The below generates textual output in a generic syntax
221245// that is inspired by C/C++/Java, and is meant for debugging
222246// purposes.
223- std::ostream & format_rec (std::ostream &os, const exprt &expr )
247+ void format_expr_configt::setup ( )
224248{
225- const auto &id = expr.id ();
226-
227- if (
228- id == ID_plus || id == ID_mult || id == ID_and || id == ID_or ||
229- id == ID_xor)
230- {
249+ auto multi_ary_expr =
250+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
231251 return format_rec (os, to_multi_ary_expr (expr));
232- }
233- else if (
234- id == ID_lt || id == ID_gt || id == ID_ge || id == ID_le || id == ID_div ||
235- id == ID_minus || id == ID_implies || id == ID_equal || id == ID_notequal)
236- {
252+ };
253+
254+ expr_map[ID_plus] = multi_ary_expr;
255+ expr_map[ID_mult] = multi_ary_expr;
256+ expr_map[ID_and] = multi_ary_expr;
257+ expr_map[ID_or] = multi_ary_expr;
258+ expr_map[ID_xor] = multi_ary_expr;
259+
260+ auto binary_expr = [](std::ostream &os, const exprt &expr) -> std::ostream & {
237261 return format_rec (os, to_binary_expr (expr));
238- }
239- else if (id == ID_not || id == ID_unary_minus)
262+ };
263+
264+ expr_map[ID_lt] = binary_expr;
265+ expr_map[ID_gt] = binary_expr;
266+ expr_map[ID_ge] = binary_expr;
267+ expr_map[ID_le] = binary_expr;
268+ expr_map[ID_div] = binary_expr;
269+ expr_map[ID_minus] = binary_expr;
270+ expr_map[ID_implies] = binary_expr;
271+ expr_map[ID_equal] = binary_expr;
272+ expr_map[ID_notequal] = binary_expr;
273+
274+ auto unary_expr = [](std::ostream &os, const exprt &expr) -> std::ostream & {
240275 return format_rec (os, to_unary_expr (expr));
241- else if (id == ID_constant)
276+ };
277+
278+ expr_map[ID_not] = unary_expr;
279+ expr_map[ID_unary_minus] = unary_expr;
280+
281+ expr_map[ID_constant] =
282+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
242283 return format_rec (os, to_constant_expr (expr));
243- else if (id == ID_typecast)
284+ };
285+
286+ expr_map[ID_typecast] =
287+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
244288 return os << " cast(" << format (to_typecast_expr (expr).op ()) << " , "
245289 << format (expr.type ()) << ' )' ;
246- else if (
247- id == ID_byte_extract_little_endian || id == ID_byte_extract_big_endian)
248- {
290+ };
291+
292+ auto byte_extract =
293+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
249294 const auto &byte_extract_expr = to_byte_extract_expr (expr);
250- return os << id << ' (' << format (byte_extract_expr.op ()) << " , "
295+ return os << expr. id () << ' (' << format (byte_extract_expr.op ()) << " , "
251296 << format (byte_extract_expr.offset ()) << " , "
252297 << format (byte_extract_expr.type ()) << ' )' ;
253- }
254- else if (id == ID_byte_update_little_endian || id == ID_byte_update_big_endian)
255- {
298+ };
299+
300+ expr_map[ID_byte_extract_little_endian] = byte_extract;
301+ expr_map[ID_byte_extract_big_endian] = byte_extract;
302+
303+ auto byte_update = [](std::ostream &os, const exprt &expr) -> std::ostream & {
256304 const auto &byte_update_expr = to_byte_update_expr (expr);
257- return os << id << ' (' << format (byte_update_expr.op ()) << " , "
305+ return os << expr. id () << ' (' << format (byte_update_expr.op ()) << " , "
258306 << format (byte_update_expr.offset ()) << " , "
259307 << format (byte_update_expr.value ()) << " , "
260308 << format (byte_update_expr.type ()) << ' )' ;
261- }
262- else if (id == ID_member)
309+ };
310+
311+ expr_map[ID_byte_update_little_endian] = byte_update;
312+ expr_map[ID_byte_update_big_endian] = byte_update;
313+
314+ expr_map[ID_member] =
315+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
263316 return os << format (to_member_expr (expr).op ()) << ' .'
264317 << to_member_expr (expr).get_component_name ();
265- else if (id == ID_symbol)
318+ };
319+
320+ expr_map[ID_symbol] =
321+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
266322 return os << to_symbol_expr (expr).get_identifier ();
267- else if (id == ID_index)
268- {
323+ };
324+
325+ expr_map[ID_index] =
326+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
269327 const auto &index_expr = to_index_expr (expr);
270328 return os << format (index_expr.array ()) << ' [' << format (index_expr.index ())
271329 << ' ]' ;
272- }
273- else if (id == ID_type)
330+ };
331+
332+ expr_map[ID_type] =
333+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
274334 return format_rec (os, expr.type ());
275- else if (id == ID_forall)
276- {
335+ };
336+
337+ expr_map[ID_forall] =
338+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
277339 return os << u8" \u2200 " << format (to_quantifier_expr (expr).symbol ())
278340 << " : " << format (to_quantifier_expr (expr).symbol ().type ())
279341 << " . " << format (to_quantifier_expr (expr).where ());
280- }
281- else if (id == ID_exists)
282- {
342+ };
343+
344+ expr_map[ID_exists] =
345+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
283346 return os << u8" \u2203 " << format (to_quantifier_expr (expr).symbol ())
284347 << " : " << format (to_quantifier_expr (expr).symbol ().type ())
285348 << " . " << format (to_quantifier_expr (expr).where ());
286- }
287- else if (id == ID_let)
288- {
349+ };
350+
351+ expr_map[ID_let] = [](std::ostream &os, const exprt &expr) -> std::ostream & {
289352 return os << " LET " << format (to_let_expr (expr).symbol ()) << " = "
290353 << format (to_let_expr (expr).value ()) << " IN "
291354 << format (to_let_expr (expr).where ());
292- }
293- else if (id == ID_lambda)
294- {
355+ };
356+
357+ expr_map[ID_lambda] =
358+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
295359 const auto &lambda_expr = to_lambda_expr (expr);
296360
297361 os << u8" \u03bb " ;
@@ -309,9 +373,9 @@ std::ostream &format_rec(std::ostream &os, const exprt &expr)
309373 }
310374
311375 return os << " . " << format (lambda_expr.where ());
312- }
313- else if (id == ID_array || id == ID_struct)
314- {
376+ };
377+
378+ auto compound = [](std::ostream &os, const exprt &expr) -> std::ostream & {
315379 os << " { " ;
316380
317381 bool first = true ;
@@ -327,16 +391,20 @@ std::ostream &format_rec(std::ostream &os, const exprt &expr)
327391 }
328392
329393 return os << " }" ;
330- }
331- else if (id == ID_if)
332- {
394+ };
395+
396+ expr_map[ID_array] = compound;
397+ expr_map[ID_struct] = compound;
398+
399+ expr_map[ID_if] = [](std::ostream &os, const exprt &expr) -> std::ostream & {
333400 const auto &if_expr = to_if_expr (expr);
334401 return os << ' (' << format (if_expr.cond ()) << " ? "
335402 << format (if_expr.true_case ()) << " : "
336403 << format (if_expr.false_case ()) << ' )' ;
337- }
338- else if (id == ID_code)
339- {
404+ };
405+
406+ expr_map[ID_code] =
407+ [](std::ostream &os, const exprt &expr) -> std::ostream & {
340408 const auto &code = to_code (expr);
341409 const irep_idt &statement = code.get_statement ();
342410
@@ -377,7 +445,27 @@ std::ostream &format_rec(std::ostream &os, const exprt &expr)
377445 }
378446 else
379447 return fallback_format_rec (os, expr);
380- }
381- else
448+ };
449+
450+ fallback = [](std::ostream &os, const exprt &expr) -> std::ostream & {
382451 return fallback_format_rec (os, expr);
452+ };
453+ }
454+
455+ const format_expr_configt::formattert &
456+ format_expr_configt::find_formatter (const exprt &expr)
457+ {
458+ auto m_it = expr_map.find (expr.id ());
459+ if (m_it == expr_map.end ())
460+ return fallback;
461+ else
462+ return m_it->second ;
463+ }
464+
465+ format_expr_configt format_expr_config;
466+
467+ std::ostream &format_rec (std::ostream &os, const exprt &expr)
468+ {
469+ auto &formatter = format_expr_config.find_formatter (expr);
470+ return formatter (os, expr);
383471}
0 commit comments