CBMC
substitute_symbols.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Symbol Substitution
4 
5 Author: Daniel Kroening, dkr@amazon.com
6 
7 \*******************************************************************/
8 
11 
12 #include "substitute_symbols.h"
13 
14 #include "std_expr.h"
15 
16 static std::optional<exprt> substitute_symbols_rec(
17  const std::map<irep_idt, exprt> &substitutions,
18  exprt src)
19 {
20  if(src.id() == ID_symbol)
21  {
22  auto s_it = substitutions.find(to_symbol_expr(src).get_identifier());
23  if(s_it == substitutions.end())
24  return {};
25  else
26  return s_it->second;
27  }
28  else if(
29  src.id() == ID_forall || src.id() == ID_exists || src.id() == ID_lambda)
30  {
31  const auto &binding_expr = to_binding_expr(src);
32 
33  // bindings may be nested,
34  // which may hide some of our substitutions
35  auto new_substitutions = substitutions;
36  for(const auto &variable : binding_expr.variables())
37  new_substitutions.erase(variable.get_identifier());
38 
39  auto op_result =
40  substitute_symbols_rec(new_substitutions, binding_expr.where());
41  if(op_result.has_value())
42  {
43  auto new_binding_expr = binding_expr; // copy
44  new_binding_expr.where() = std::move(op_result.value());
45  return std::move(new_binding_expr);
46  }
47  else
48  return {};
49  }
50  else if(src.id() == ID_let)
51  {
52  auto new_let_expr = to_let_expr(src); // copy
53  const auto &binding_expr = to_let_expr(src).binding();
54 
55  // bindings may be nested,
56  // which may hide some of our substitutions
57  auto new_substitutions = substitutions;
58  for(const auto &variable : binding_expr.variables())
59  new_substitutions.erase(variable.get_identifier());
60 
61  bool op_changed = false;
62 
63  for(auto &op : new_let_expr.values())
64  {
65  auto op_result = substitute_symbols_rec(new_substitutions, op);
66 
67  if(op_result.has_value())
68  {
69  op = op_result.value();
70  op_changed = true;
71  }
72  }
73 
74  auto op_result =
75  substitute_symbols_rec(new_substitutions, binding_expr.where());
76  if(op_result.has_value())
77  {
78  new_let_expr.where() = op_result.value();
79  op_changed = true;
80  }
81 
82  if(op_changed)
83  return std::move(new_let_expr);
84  else
85  return {};
86  }
87 
88  if(!src.has_operands())
89  return {};
90 
91  bool op_changed = false;
92 
93  for(auto &op : src.operands())
94  {
95  auto op_result = substitute_symbols_rec(substitutions, op);
96 
97  if(op_result.has_value())
98  {
99  op = op_result.value();
100  op_changed = true;
101  }
102  }
103 
104  if(op_changed)
105  return src;
106  else
107  return {};
108 }
109 
110 std::optional<exprt>
111 substitute_symbols(const std::map<irep_idt, exprt> &substitutions, exprt src)
112 {
113  return substitute_symbols_rec(substitutions, src);
114 }
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
operandst & operands()
Definition: expr.h:94
const irep_idt & id() const
Definition: irep.h:384
binding_exprt & binding()
Definition: std_expr.h:3224
API to expression classes.
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition: std_expr.h:3320
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const binding_exprt & to_binding_expr(const exprt &expr)
Cast an exprt to a binding_exprt.
Definition: std_expr.h:3168
static std::optional< exprt > substitute_symbols_rec(const std::map< irep_idt, exprt > &substitutions, exprt src)
std::optional< exprt > substitute_symbols(const std::map< irep_idt, exprt > &substitutions, exprt src)
Substitute free occurrences of the variables given by their identifiers in the keys of the map in the...
Symbol Substitution.