Support all fractional constants.

This commit is contained in:
chriseth 2022-06-01 17:53:33 +02:00
parent cd3b7e333d
commit 68bfbdb2a6
2 changed files with 38 additions and 19 deletions

View File

@ -411,8 +411,6 @@ void BooleanLPSolver::addLetBindings(Expression const& _let, LetBindings& _letBi
optional<Literal> BooleanLPSolver::parseLiteral(smtutil::Expression const& _expr, LetBindings _letBindings)
{
// TODO constanst true/false?
if (_expr.name == "let")
{
addLetBindings(_expr, _letBindings);
@ -430,6 +428,11 @@ optional<Literal> BooleanLPSolver::parseLiteral(smtutil::Expression const& _expr
else
varIndex = std::get<size_t>(binding);
}
else if (_expr.name == "true" || _expr.name == "false")
{
// TODO handle this better
solAssert(false, "True/false literals not implemented");
}
else
varIndex = state().variables.at(_expr.name);
solAssert(isBooleanVariable(varIndex));
@ -594,7 +597,7 @@ optional<LinearExpression> BooleanLPSolver::parseLinearSum(smtutil::Expression c
// This will result in nullopt unless one of them is a constant.
return parseLinearSum(_expr.arguments.at(0), _letBindings) * parseLinearSum(_expr.arguments.at(1), _letBindings);
}
else if (_expr.name == "/")
else if (_expr.name == "/" || _expr.name == "div")
{
solAssert(_expr.arguments.size() == 2);
optional<LinearExpression> left = parseLinearSum(_expr.arguments.at(0), _letBindings);
@ -614,19 +617,42 @@ optional<LinearExpression> BooleanLPSolver::parseLinearSum(smtutil::Expression c
}
else
{
cerr << _expr.toString() << endl;
cerr << "Invalid operator " << _expr.name << endl;
// cerr << _expr.toString() << endl;
// cerr << "Invalid operator " << _expr.name << endl;
return std::nullopt;
}
}
namespace
{
bool isNumber(string const& _expr)
{
return !_expr.empty() && (isDigit(_expr.front()) || _expr.front() == '.');
}
rational parseRational(string const& _atom)
{
size_t decimal = _atom.find('.');
if (decimal == string::npos)
return rational(bigint(_atom));
unsigned shift = static_cast<unsigned>(_atom.size() - decimal - 1);
rational r(
bigint(string(_atom.substr(0, decimal)) + string(_atom.substr(decimal + 1))),
pow(bigint(10), shift)
);
// cerr << _atom << endl;
// cerr << r << endl;
return r;
}
}
bool BooleanLPSolver::isLiteral(smtutil::Expression const& _expr) const
{
if (!_expr.arguments.empty())
return false;
solAssert(!_expr.name.empty(), "");
return
('0' <= _expr.name[0] && _expr.name[0] <= '9') ||
isNumber(_expr.name) ||
_expr.name == "true" ||
_expr.name == "false";
}
@ -635,8 +661,8 @@ optional<LinearExpression> BooleanLPSolver::parseFactor(smtutil::Expression cons
{
solAssert(_expr.arguments.empty(), "");
solAssert(!_expr.name.empty(), "");
if ('0' <= _expr.name[0] && _expr.name[0] <= '9')
return LinearExpression::constant(rational(bigint(_expr.name)));
if (isNumber(_expr.name))
return LinearExpression::constant(parseRational(_expr.name));
else if (_expr.name == "true")
// TODO do we want to do this?
return LinearExpression::constant(1);

View File

@ -129,21 +129,14 @@ string_view command(SMTLib2Expression const& _expr)
return get<string_view>(items.front().data);
}
// TODO If we want to return rational here, we need smtutil::Expression to support rationals...
u256 parseRational(string_view _atom)
{
if (_atom.size() >= 3 && _atom.at(_atom.size() - 1) == '0' && _atom.at(_atom.size() - 2) == '.')
return parseRational(_atom.substr(0, _atom.size() - 2));
else
return u256(_atom);
}
smtutil::Expression toSMTUtilExpression(SMTLib2Expression const& _expr, map<string, SortPointer> const& _variableSorts)
{
return std::visit(GenericVisitor{
[&](string_view const& _atom) {
if (isDigit(_atom.front()) || _atom.front() == '.')
return Expression(parseRational(_atom).str(), {}, SortProvider::realSort);
if (_atom == "true" || _atom == "false")
return Expression(_atom == "true");
else if (isDigit(_atom.front()) || _atom.front() == '.')
return Expression(string(_atom), {}, SortProvider::realSort);
else
return Expression(string(_atom), {}, _variableSorts.at(string(_atom)));
},