Skip to content

Commit 879e1ab

Browse files
committed
add substitute_symbols(...)
This adds a facility to substitute symbols by expressions that is aware of bound symbols.
1 parent 3cc4812 commit 879e1ab

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

src/util/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ SRC = arith_tools.cpp \
9393
string_hash.cpp \
9494
string_utils.cpp \
9595
structured_data.cpp \
96+
substitute_symbols.cpp \
9697
symbol.cpp \
9798
symbol_table_base.cpp \
9899
symbol_table.cpp \

src/util/substitute_symbols.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*******************************************************************\
2+
3+
Module: Symbol Substitution
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file util/substitute_symbols.cpp
10+
/// Symbol Substitution
11+
12+
#include "substitute_symbols.h"
13+
14+
#include "std_expr.h"
15+
16+
static optionalt<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+
optionalt<exprt>
111+
substitute_symbols(const std::map<irep_idt, exprt> &substitutions, exprt src)
112+
{
113+
return substitute_symbols_rec(substitutions, src);
114+
}

src/util/substitute_symbols.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*******************************************************************\
2+
3+
Module: Symbol Substitution
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_UTIL_SUBSTITUTE_SYMBOLS_H
10+
#define CPROVER_UTIL_SUBSTITUTE_SYMBOLS_H
11+
12+
/// \file util/substitute_symbols.h
13+
/// Symbol Substitution
14+
15+
#include "expr.h"
16+
17+
#include <map>
18+
19+
/// Substitute free occurrences of the variables given
20+
/// by their identifiers in the keys of the map in the
21+
/// given expression. Only symbol_exprt expressions are
22+
/// substituted.
23+
/// \returns expression after substitution,
24+
/// or {} when no substitution took place
25+
optionalt<exprt>
26+
substitute_symbols(const std::map<irep_idt, exprt> &substitutions, exprt);
27+
28+
#endif // CPROVER_UTIL_SUBSTITUTE_SYMBOLS_H

0 commit comments

Comments
 (0)