Skip to content

Commit c2e1cb6

Browse files
authored
Merge pull request #6827 from diffblue/replace_symbol_with_bindings
replace_symbolt with bindings
2 parents ba7ad3d + e46d2f3 commit c2e1cb6

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

src/util/replace_symbol.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,41 @@ bool replace_symbolt::replace(exprt &dest) const
101101
if(!replace_symbol_expr(to_symbol_expr(dest)))
102102
return false;
103103
}
104+
else if(dest.id() == ID_let)
105+
{
106+
auto &let_expr = to_let_expr(dest);
107+
108+
// first replace the assigned value expressions
109+
for(auto &op : let_expr.values())
110+
if(replace(op))
111+
result = false;
112+
113+
// now set up the binding
114+
auto old_bindings = bindings;
115+
for(auto &variable : let_expr.variables())
116+
bindings.insert(variable.get_identifier());
117+
118+
// now replace in the 'where' expression
119+
if(!replace(let_expr.where()))
120+
result = false;
121+
122+
bindings = std::move(old_bindings);
123+
}
124+
else if(
125+
dest.id() == ID_array_comprehension || dest.id() == ID_exists ||
126+
dest.id() == ID_forall || dest.id() == ID_lambda)
127+
{
128+
auto &binding_expr = to_binding_expr(dest);
129+
130+
auto old_bindings = bindings;
131+
for(auto &binding : binding_expr.variables())
132+
bindings.insert(binding.get_identifier());
133+
134+
if(!replace(binding_expr.where()))
135+
result = false;
136+
137+
bindings = std::move(old_bindings);
138+
}
104139
else
105140
{
106141
Forall_operands(it, dest)
@@ -136,7 +171,10 @@ bool replace_symbolt::have_to_replace(const exprt &dest) const
136171
if(dest.id()==ID_symbol)
137172
{
138173
const irep_idt &identifier = to_symbol_expr(dest).get_identifier();
139-
return replaces_symbol(identifier);
174+
if(bindings.find(identifier) != bindings.end())
175+
return false;
176+
else
177+
return replaces_symbol(identifier);
140178
}
141179

142180
forall_operands(it, dest)

src/util/replace_symbol.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ Author: Daniel Kroening, [email protected]
1717

1818
#include "expr.h"
1919

20+
#include <set>
2021
#include <unordered_map>
2122

22-
/// Replace expression or type symbols by an expression or type, respectively.
23-
/// The resolved type of the symbol must match the type of the replacement.
23+
/// Replace a symbol expression by a given expression.
24+
/// The type of the symbol must match the type of the replacement.
25+
/// This class is aware of symbol hiding caused by bindings
26+
/// such as forall, exists, and the like.
2427
class replace_symbolt
2528
{
2629
public:
@@ -88,6 +91,7 @@ class replace_symbolt
8891

8992
protected:
9093
expr_mapt expr_map;
94+
mutable std::set<irep_idt> bindings;
9195

9296
virtual bool replace_symbol_expr(symbol_exprt &dest) const;
9397

src/util/std_expr.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3090,12 +3090,29 @@ inline void validate_expr(const binding_exprt &binding_expr)
30903090
inline const binding_exprt &to_binding_expr(const exprt &expr)
30913091
{
30923092
PRECONDITION(
3093-
expr.id() == ID_forall || expr.id() == ID_exists || expr.id() == ID_lambda);
3093+
expr.id() == ID_forall || expr.id() == ID_exists ||
3094+
expr.id() == ID_lambda || expr.id() == ID_array_comprehension);
30943095
const binding_exprt &ret = static_cast<const binding_exprt &>(expr);
30953096
validate_expr(ret);
30963097
return ret;
30973098
}
30983099

3100+
/// \brief Cast an exprt to a \ref binding_exprt
3101+
///
3102+
/// \a expr must be known to be \ref binding_exprt.
3103+
///
3104+
/// \param expr: Source expression
3105+
/// \return Object of type \ref binding_exprt
3106+
inline binding_exprt &to_binding_expr(exprt &expr)
3107+
{
3108+
PRECONDITION(
3109+
expr.id() == ID_forall || expr.id() == ID_exists ||
3110+
expr.id() == ID_lambda || expr.id() == ID_array_comprehension);
3111+
binding_exprt &ret = static_cast<binding_exprt &>(expr);
3112+
validate_expr(ret);
3113+
return ret;
3114+
}
3115+
30993116
/// \brief A let expression
31003117
class let_exprt : public binary_exprt
31013118
{

0 commit comments

Comments
 (0)