Skip to content

Commit 24bc600

Browse files
committed
extract substitute_symbols(...) into separate file
1) The substitute_symbols_rec(...) function in std_expr.cpp is extracted into a separate file and is made available to external users as substitute_symbols(...). 2) substitute_symbols is now aware of array_comprehension expressions.
1 parent a7ba766 commit 24bc600

File tree

5 files changed

+148
-96
lines changed

5 files changed

+148
-96
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/std_expr.cpp

Lines changed: 2 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111
#include "namespace.h"
1212
#include "pointer_expr.h"
1313
#include "range.h"
14+
#include "substitute_symbols.h"
1415

1516
#include <map>
1617

@@ -165,100 +166,6 @@ void let_exprt::validate(const exprt &expr, const validation_modet vm)
165166
}
166167
}
167168

168-
static optionalt<exprt> substitute_symbols_rec(
169-
const std::map<irep_idt, exprt> &substitutions,
170-
exprt src)
171-
{
172-
if(src.id() == ID_symbol)
173-
{
174-
auto s_it = substitutions.find(to_symbol_expr(src).get_identifier());
175-
if(s_it == substitutions.end())
176-
return {};
177-
else
178-
return s_it->second;
179-
}
180-
else if(
181-
src.id() == ID_forall || src.id() == ID_exists || src.id() == ID_lambda)
182-
{
183-
const auto &binding_expr = to_binding_expr(src);
184-
185-
// bindings may be nested,
186-
// which may hide some of our substitutions
187-
auto new_substitutions = substitutions;
188-
for(const auto &variable : binding_expr.variables())
189-
new_substitutions.erase(variable.get_identifier());
190-
191-
auto op_result =
192-
substitute_symbols_rec(new_substitutions, binding_expr.where());
193-
if(op_result.has_value())
194-
return binding_exprt(
195-
src.id(),
196-
binding_expr.variables(),
197-
op_result.value(),
198-
binding_expr.type());
199-
else
200-
return {};
201-
}
202-
else if(src.id() == ID_let)
203-
{
204-
auto new_let_expr = to_let_expr(src); // copy
205-
const auto &binding_expr = to_let_expr(src).binding();
206-
207-
// bindings may be nested,
208-
// which may hide some of our substitutions
209-
auto new_substitutions = substitutions;
210-
for(const auto &variable : binding_expr.variables())
211-
new_substitutions.erase(variable.get_identifier());
212-
213-
bool op_changed = false;
214-
215-
for(auto &op : new_let_expr.values())
216-
{
217-
auto op_result = substitute_symbols_rec(new_substitutions, op);
218-
219-
if(op_result.has_value())
220-
{
221-
op = op_result.value();
222-
op_changed = true;
223-
}
224-
}
225-
226-
auto op_result =
227-
substitute_symbols_rec(new_substitutions, binding_expr.where());
228-
if(op_result.has_value())
229-
{
230-
new_let_expr.where() = op_result.value();
231-
op_changed = true;
232-
}
233-
234-
if(op_changed)
235-
return std::move(new_let_expr);
236-
else
237-
return {};
238-
}
239-
240-
if(!src.has_operands())
241-
return {};
242-
243-
bool op_changed = false;
244-
245-
for(auto &op : src.operands())
246-
{
247-
auto op_result = substitute_symbols_rec(substitutions, op);
248-
249-
if(op_result.has_value())
250-
{
251-
op = op_result.value();
252-
op_changed = true;
253-
}
254-
}
255-
256-
if(op_changed)
257-
return src;
258-
else
259-
return {};
260-
}
261-
262169
exprt binding_exprt::instantiate(const operandst &values) const
263170
{
264171
// number of values must match the number of bound variables
@@ -281,7 +188,7 @@ exprt binding_exprt::instantiate(const operandst &values) const
281188
substitutions[variables[i].get_identifier()] = values[i];
282189

283190
// now recurse downwards and substitute in 'where'
284-
auto substitute_result = substitute_symbols_rec(substitutions, where());
191+
auto substitute_result = substitute_symbols(substitutions, where());
285192

286193
if(substitute_result.has_value())
287194
return substitute_result.value();

src/util/std_expr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3090,7 +3090,8 @@ 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_array_comprehension || expr.id() == ID_forall ||
3094+
expr.id() == ID_exists || expr.id() == ID_lambda);
30943095
const binding_exprt &ret = static_cast<const binding_exprt &>(expr);
30953096
validate_expr(ret);
30963097
return ret;

src/util/substitute_symbols.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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_array_comprehension || src.id() == ID_forall ||
30+
src.id() == ID_exists || src.id() == ID_lambda)
31+
{
32+
const auto &binding_expr = to_binding_expr(src);
33+
34+
// bindings may be nested,
35+
// which may hide some of our substitutions
36+
auto new_substitutions = substitutions;
37+
for(const auto &variable : binding_expr.variables())
38+
new_substitutions.erase(variable.get_identifier());
39+
40+
auto op_result =
41+
substitute_symbols_rec(new_substitutions, binding_expr.where());
42+
if(op_result.has_value())
43+
{
44+
auto new_binding_expr = binding_expr; // copy
45+
new_binding_expr.where() = std::move(op_result.value());
46+
return std::move(new_binding_expr);
47+
}
48+
else
49+
return {};
50+
}
51+
else if(src.id() == ID_let)
52+
{
53+
auto new_let_expr = to_let_expr(src); // copy
54+
const auto &binding_expr = to_let_expr(src).binding();
55+
56+
// bindings may be nested,
57+
// which may hide some of our substitutions
58+
auto new_substitutions = substitutions;
59+
for(const auto &variable : binding_expr.variables())
60+
new_substitutions.erase(variable.get_identifier());
61+
62+
bool op_changed = false;
63+
64+
for(auto &op : new_let_expr.values())
65+
{
66+
auto op_result = substitute_symbols_rec(new_substitutions, op);
67+
68+
if(op_result.has_value())
69+
{
70+
op = op_result.value();
71+
op_changed = true;
72+
}
73+
}
74+
75+
auto op_result =
76+
substitute_symbols_rec(new_substitutions, binding_expr.where());
77+
if(op_result.has_value())
78+
{
79+
new_let_expr.where() = op_result.value();
80+
op_changed = true;
81+
}
82+
83+
if(op_changed)
84+
return std::move(new_let_expr);
85+
else
86+
return {};
87+
}
88+
89+
if(!src.has_operands())
90+
return {};
91+
92+
bool op_changed = false;
93+
94+
for(auto &op : src.operands())
95+
{
96+
auto op_result = substitute_symbols_rec(substitutions, op);
97+
98+
if(op_result.has_value())
99+
{
100+
op = op_result.value();
101+
op_changed = true;
102+
}
103+
}
104+
105+
if(op_changed)
106+
return src;
107+
else
108+
return {};
109+
}
110+
111+
optionalt<exprt>
112+
substitute_symbols(const std::map<irep_idt, exprt> &substitutions, exprt src)
113+
{
114+
return substitute_symbols_rec(substitutions, src);
115+
}

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)