Skip to content

Commit dab0ddf

Browse files
author
Daniel Kroening
committed
prop_conv_solvert: introduce scopes
1 parent 6c46e2c commit dab0ddf

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

src/solvers/prop/prop_conv_solver.cpp

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,16 @@ literalt prop_conv_solvert::convert(const exprt &expr)
145145
if(!result.second)
146146
return result.first->second;
147147

148+
// new entry
149+
if(record_cache_iterators)
150+
cache_iterators.push_back(result.first);
151+
148152
literalt literal = convert_bool(expr);
149153

150154
// insert into cache
151155

152156
result.first->second = literal;
157+
153158
if(freeze_all && !literal.is_constant())
154159
prop.set_frozen(literal);
155160

@@ -276,23 +281,47 @@ literalt prop_conv_solvert::convert_bool(const exprt &expr)
276281
const let_exprt &let_expr = to_let_expr(expr);
277282

278283
// first check whether this is all boolean
279-
if(
280-
let_expr.value().type().id() == ID_bool &&
281-
let_expr.where().type().id() == ID_bool)
284+
DATA_INVARIANT(
285+
let_expr.value().type().id() == ID_bool,
286+
"Boolean let must have Boolean value");
287+
DATA_INVARIANT(
288+
let_expr.where().type().id() == ID_bool,
289+
"Boolean let must have Boolean subexpression");
290+
291+
literalt value = convert(let_expr.value());
292+
293+
const irep_idt &id = let_expr.symbol().get_identifier();
294+
auto emplace_result = symbols.emplace(id, literalt());
295+
literalt old_variable;
296+
297+
// We do not expect the identifier to be unique; in particular, nesting
298+
// is supported. Thus, do we need to save a value from an outer scope?
299+
if(!emplace_result.second)
282300
{
283-
literalt value = convert(let_expr.value());
284-
285-
// We expect the identifier of the bound symbols to be unique,
286-
// and thus, these can go straight into the symbol map.
287-
// This property also allows us to cache any subexpressions.
288-
const irep_idt &id = let_expr.symbol().get_identifier();
289-
symbols[id] = value;
290-
literalt result = convert(let_expr.where());
291-
292-
// remove again
293-
symbols.erase(id);
294-
return result;
301+
// insertion did not take place
302+
old_variable = emplace_result.first->second;
303+
emplace_result.first->second = value;
295304
}
305+
306+
// record all newly added cache entries
307+
bool previous_record_cache_iterators = record_cache_iterators;
308+
std::size_t previous_cache_iterators_size = cache_iterators.size();
309+
record_cache_iterators = true;
310+
311+
// recursive call
312+
literalt result = convert(let_expr.where());
313+
314+
// clear cache_iterators that use the bound symbol from the cache
315+
cache_iterators.resize(previous_cache_iterators_size);
316+
record_cache_iterators = previous_record_cache_iterators;
317+
318+
// remove/restore symbol
319+
if(emplace_result.second)
320+
emplace_result.first->second = old_variable;
321+
else
322+
symbols.erase(emplace_result.first);
323+
324+
return result;
296325
}
297326

298327
return convert_rest(expr);

src/solvers/prop/prop_conv_solver.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010
#define CPROVER_SOLVERS_PROP_PROP_CONV_SOLVER_H
1111

1212
#include <map>
13+
#include <stack>
1314
#include <string>
1415

1516
#include <util/expr.h>
@@ -127,6 +128,11 @@ class prop_conv_solvert : public prop_convt, public solver_resource_limitst
127128
// cache
128129
cachet cache;
129130

131+
// record the subexpressions that use the scoped variable,
132+
// in order to clear them from the cache after we are done
133+
std::vector<cachet::iterator> cache_iterators;
134+
bool record_cache_iterators = false;
135+
130136
virtual void ignoring(const exprt &expr);
131137

132138
// deliberately protected now to protect lower-level API

0 commit comments

Comments
 (0)