Skip to content

Commit 835af93

Browse files
author
Daniel Kroening
authored
Merge pull request #5160 from diffblue/let_with_multiple_bindings
Let with multiple bindings
2 parents afac9c7 + cd0d0f6 commit 835af93

File tree

4 files changed

+72
-34
lines changed

4 files changed

+72
-34
lines changed

src/solvers/flattening/boolbv_let.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,34 @@ Author: Daniel Kroening, [email protected]
88

99
#include "boolbv.h"
1010

11+
#include <util/range.h>
1112
#include <util/std_expr.h>
1213
#include <util/std_types.h>
1314

1415
bvt boolbvt::convert_let(const let_exprt &expr)
1516
{
16-
const bvt value_bv=convert_bv(expr.value());
17+
const auto &variables = expr.variables();
18+
const auto &values = expr.values();
1719

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();
20+
for(auto &binding : make_range(variables).zip(values))
21+
{
22+
const bvt value_bv = convert_bv(binding.second);
23+
24+
// We expect the identifiers of the bound symbols to be unique,
25+
// and thus, these can go straight into the symbol to literal map.
26+
// This property also allows us to cache any subexpressions.
27+
const irep_idt &id = binding.first.get_identifier();
28+
29+
// the symbol shall be visible during the recursive call
30+
// to convert_bv
31+
map.set_literals(id, binding.first.type(), value_bv);
32+
}
2233

23-
// the symbol shall be visible during the recursive call
24-
// to convert_bv
25-
map.set_literals(id, expr.symbol().type(), value_bv);
2634
bvt result_bv=convert_bv(expr.where());
2735

2836
// now remove, no longer needed
29-
map.erase_literals(id, expr.symbol().type());
37+
for(auto &variable : variables)
38+
map.erase_literals(variable.get_identifier(), variable.type());
3039

3140
return result_bv;
3241
}

src/solvers/prop/prop_conv_solver.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Author: Daniel Kroening, [email protected]
88

99
#include "prop_conv_solver.h"
1010

11+
#include <util/range.h>
12+
1113
#include <algorithm>
1214

1315
bool prop_conv_solvert::is_in_conflict(const exprt &expr) const
@@ -308,23 +310,35 @@ literalt prop_conv_solvert::convert_bool(const exprt &expr)
308310
else if(expr.id() == ID_let)
309311
{
310312
const let_exprt &let_expr = to_let_expr(expr);
313+
const auto &variables = let_expr.variables();
314+
const auto &values = let_expr.values();
311315

312316
// first check whether this is all boolean
313-
if(
314-
let_expr.value().type().id() == ID_bool &&
315-
let_expr.where().type().id() == ID_bool)
317+
const bool all_boolean =
318+
let_expr.where().type().id() == ID_bool &&
319+
std::all_of(values.begin(), values.end(), [](const exprt &e) {
320+
return e.type().id() == ID_bool;
321+
});
322+
323+
if(all_boolean)
316324
{
317-
literalt value = convert(let_expr.value());
325+
for(auto &binding : make_range(variables).zip(values))
326+
{
327+
literalt value_converted = convert(binding.second);
328+
329+
// We expect the identifier of the bound symbols to be unique,
330+
// and thus, these can go straight into the symbol map.
331+
// This property also allows us to cache any subexpressions.
332+
const irep_idt &id = binding.first.get_identifier();
333+
symbols[id] = value_converted;
334+
}
318335

319-
// We expect the identifier of the bound symbols to be unique,
320-
// and thus, these can go straight into the symbol map.
321-
// This property also allows us to cache any subexpressions.
322-
const irep_idt &id = let_expr.symbol().get_identifier();
323-
symbols[id] = value;
324336
literalt result = convert(let_expr.where());
325337

326338
// remove again
327-
symbols.erase(id);
339+
for(auto &variable : variables)
340+
symbols.erase(variable.get_identifier());
341+
328342
return result;
329343
}
330344
}

src/solvers/smt2/smt2_conv.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Author: Daniel Kroening, [email protected]
2222
#include <util/invariant.h>
2323
#include <util/mathematical_expr.h>
2424
#include <util/pointer_offset_size.h>
25+
#include <util/range.h>
2526
#include <util/std_expr.h>
2627
#include <util/std_types.h>
2728
#include <util/string2int.h>
@@ -1855,11 +1856,28 @@ void smt2_convt::convert_expr(const exprt &expr)
18551856
else if(expr.id()==ID_let)
18561857
{
18571858
const let_exprt &let_expr=to_let_expr(expr);
1858-
out << "(let ((";
1859-
convert_expr(let_expr.symbol());
1860-
out << ' ';
1861-
convert_expr(let_expr.value());
1862-
out << ")) ";
1859+
const auto &variables = let_expr.variables();
1860+
const auto &values = let_expr.values();
1861+
1862+
out << "(let (";
1863+
bool first = true;
1864+
1865+
for(auto &binding : make_range(variables).zip(values))
1866+
{
1867+
if(first)
1868+
first = false;
1869+
else
1870+
out << ' ';
1871+
1872+
out << '(';
1873+
convert_expr(binding.first);
1874+
out << ' ';
1875+
convert_expr(binding.second);
1876+
out << ')';
1877+
}
1878+
1879+
out << ") "; // bindings
1880+
18631881
convert_expr(let_expr.where());
18641882
out << ')'; // let
18651883
}

src/solvers/smt2/smt2_parser.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,21 +208,18 @@ exprt smt2_parsert::let_expression()
208208
b.first = add_fresh_id(b.first, b.second);
209209
}
210210

211-
exprt expr=expression();
211+
exprt where = expression();
212212

213213
if(next_token() != smt2_tokenizert::CLOSE)
214214
throw error("expected ')' after let");
215215

216-
exprt result=expr;
216+
binding_exprt::variablest variables;
217+
exprt::operandst values;
217218

218-
// go backwards, build let_expr
219-
for(auto r_it=bindings.rbegin(); r_it!=bindings.rend(); r_it++)
219+
for(const auto &b : bindings)
220220
{
221-
const let_exprt let(
222-
symbol_exprt(r_it->first, r_it->second.type()),
223-
r_it->second,
224-
result);
225-
result=let;
221+
variables.push_back(symbol_exprt(b.first, b.second.type()));
222+
values.push_back(b.second);
226223
}
227224

228225
// we keep these in the id_map in order to retain globally
@@ -231,7 +228,7 @@ exprt smt2_parsert::let_expression()
231228
// restore renamings
232229
renaming_map=old_renaming_map;
233230

234-
return result;
231+
return let_exprt(variables, values, where);
235232
}
236233

237234
exprt smt2_parsert::quantifier_expression(irep_idt id)

0 commit comments

Comments
 (0)