Skip to content

Commit 198374a

Browse files
author
Daniel Kroening
committed
boolbvt: introduce scopes
This is the biggest change to the solver interface since it got added to the codebase. Currently, bound identifiers (exists, forall, let) must be unique; the solver looses soundness if that assumption is violated. This change introduces scopes, i.e., the uniqueness requirement is dropped. Nested scoping works as expected. This matches what SMT-LIB does, i.e., the renaming done in the SMT-LIB front-end can be dropped (which is the next commit).
1 parent 610001a commit 198374a

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

src/solvers/flattening/boolbv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ class boolbvt:public arrayst
263263

264264
// strings
265265
numbering<irep_idt> string_numbering;
266+
267+
// scopes
268+
std::size_t scope_counter = 0;
266269
};
267270

268271
#endif // CPROVER_SOLVERS_FLATTENING_BOOLBV_H

src/solvers/flattening/boolbv_let.cpp

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,55 @@ Author: Daniel Kroening, [email protected]
1313

1414
bvt boolbvt::convert_let(const let_exprt &expr)
1515
{
16-
const bvt value_bv=convert_bv(expr.value());
16+
DATA_INVARIANT(
17+
expr.value().type() == expr.symbol().type(),
18+
"let value must have the type of the let symbol");
19+
DATA_INVARIANT(
20+
expr.type() == expr.where().type(),
21+
"let must have the type of the 'where' operand");
1722

18-
// We expect the identifiers of the bound symbols to be unique,
19-
// and thus, these can go straight into the symbol to literal map.
20-
// This property also allows us to cache any subexpressions.
21-
const irep_idt &id=expr.symbol().get_identifier();
23+
const bvt value_bv = convert_bv(expr.value());
24+
25+
bool is_boolean = expr.value().type().id() == ID_bool;
26+
const auto &old_identifier = expr.symbol().get_identifier();
27+
28+
// produce a new identifier
29+
const irep_idt new_identifier =
30+
"boolbvt::scope::" + std::to_string(scope_counter) +
31+
"::" + id2string(old_identifier);
32+
33+
scope_counter++;
2234

2335
// the symbol shall be visible during the recursive call
24-
// to convert_bv
25-
map.set_literals(id, expr.symbol().type(), value_bv);
26-
bvt result_bv=convert_bv(expr.where());
36+
// to convert_bv for 'where'
37+
if(is_boolean)
38+
{
39+
DATA_INVARIANT(value_bv.size() == 1, "boolean values have one bit");
40+
symbols[new_identifier] = value_bv[0];
41+
}
42+
else
43+
map.set_literals(new_identifier, expr.symbol().type(), value_bv);
44+
45+
// rename bound symbol in 'where'
46+
exprt where_renamed = expr.where();
47+
48+
where_renamed.visit_post([old_identifier, new_identifier](exprt &expr) {
49+
if(expr.id() == ID_symbol)
50+
{
51+
auto &symbol_expr = to_symbol_expr(expr);
52+
if(symbol_expr.get_identifier() == old_identifier)
53+
symbol_expr.set_identifier(new_identifier);
54+
}
55+
});
56+
57+
// recursive call
58+
bvt result_bv = convert_bv(where_renamed);
2759

28-
// now remove, no longer needed
29-
map.erase_literals(id, expr.symbol().type());
60+
// the mapping can now be deleted
61+
if(is_boolean)
62+
symbols.erase(new_identifier);
63+
else
64+
map.erase_literals(new_identifier, expr.symbol().type());
3065

3166
return result_bv;
3267
}

0 commit comments

Comments
 (0)