solver: support let with multiple bindings
This avoids deeply recursive expressions.
This commit is contained in:
parent
afac9c7224
commit
f8cfad349b
|
@ -8,25 +8,34 @@ Author: Daniel Kroening, kroening@kroening.com
|
|||
|
||||
#include "boolbv.h"
|
||||
|
||||
#include <util/range.h>
|
||||
#include <util/std_expr.h>
|
||||
#include <util/std_types.h>
|
||||
|
||||
bvt boolbvt::convert_let(const let_exprt &expr)
|
||||
{
|
||||
const bvt value_bv=convert_bv(expr.value());
|
||||
const auto &variables = expr.variables();
|
||||
const auto &values = expr.values();
|
||||
|
||||
// We expect the identifiers of the bound symbols to be unique,
|
||||
// and thus, these can go straight into the symbol to literal map.
|
||||
// This property also allows us to cache any subexpressions.
|
||||
const irep_idt &id=expr.symbol().get_identifier();
|
||||
for(auto &binding : make_range(variables).zip(values))
|
||||
{
|
||||
const bvt value_bv = convert_bv(binding.second);
|
||||
|
||||
// We expect the identifiers of the bound symbols to be unique,
|
||||
// and thus, these can go straight into the symbol to literal map.
|
||||
// This property also allows us to cache any subexpressions.
|
||||
const irep_idt &id = binding.first.get_identifier();
|
||||
|
||||
// the symbol shall be visible during the recursive call
|
||||
// to convert_bv
|
||||
map.set_literals(id, binding.first.type(), value_bv);
|
||||
}
|
||||
|
||||
// the symbol shall be visible during the recursive call
|
||||
// to convert_bv
|
||||
map.set_literals(id, expr.symbol().type(), value_bv);
|
||||
bvt result_bv=convert_bv(expr.where());
|
||||
|
||||
// now remove, no longer needed
|
||||
map.erase_literals(id, expr.symbol().type());
|
||||
for(auto &variable : variables)
|
||||
map.erase_literals(variable.get_identifier(), variable.type());
|
||||
|
||||
return result_bv;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ Author: Daniel Kroening, kroening@kroening.com
|
|||
|
||||
#include "prop_conv_solver.h"
|
||||
|
||||
#include <util/range.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
bool prop_conv_solvert::is_in_conflict(const exprt &expr) const
|
||||
|
@ -308,23 +310,35 @@ literalt prop_conv_solvert::convert_bool(const exprt &expr)
|
|||
else if(expr.id() == ID_let)
|
||||
{
|
||||
const let_exprt &let_expr = to_let_expr(expr);
|
||||
const auto &variables = let_expr.variables();
|
||||
const auto &values = let_expr.values();
|
||||
|
||||
// first check whether this is all boolean
|
||||
if(
|
||||
let_expr.value().type().id() == ID_bool &&
|
||||
let_expr.where().type().id() == ID_bool)
|
||||
{
|
||||
literalt value = convert(let_expr.value());
|
||||
const bool all_boolean =
|
||||
let_expr.where().type().id() == ID_bool &&
|
||||
std::all_of(values.begin(), values.end(), [](const exprt &e) {
|
||||
return e.type().id() == ID_bool;
|
||||
});
|
||||
|
||||
if(all_boolean)
|
||||
{
|
||||
for(auto &binding : make_range(variables).zip(values))
|
||||
{
|
||||
literalt value_converted = convert(binding.second);
|
||||
|
||||
// We expect the identifier of the bound symbols to be unique,
|
||||
// and thus, these can go straight into the symbol map.
|
||||
// This property also allows us to cache any subexpressions.
|
||||
const irep_idt &id = binding.first.get_identifier();
|
||||
symbols[id] = value_converted;
|
||||
}
|
||||
|
||||
// We expect the identifier of the bound symbols to be unique,
|
||||
// and thus, these can go straight into the symbol map.
|
||||
// This property also allows us to cache any subexpressions.
|
||||
const irep_idt &id = let_expr.symbol().get_identifier();
|
||||
symbols[id] = value;
|
||||
literalt result = convert(let_expr.where());
|
||||
|
||||
// remove again
|
||||
symbols.erase(id);
|
||||
for(auto &variable : variables)
|
||||
symbols.erase(variable.get_identifier());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue