aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/formal/CVC4Interface.cpp
diff options
context:
space:
mode:
authorLeonardo Alt <leonardoaltt@gmail.com>2018-04-07 00:01:40 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2018-04-17 19:26:58 +0800
commitae3350ae0320d140a427d2fa318e7002745a73a5 (patch)
treee4da5e3619baa56b09509004c58b1b5d12594e48 /libsolidity/formal/CVC4Interface.cpp
parent842fd0cd2cef3c11c392b7820e178fd0d034fa07 (diff)
downloaddexon-solidity-ae3350ae0320d140a427d2fa318e7002745a73a5.tar
dexon-solidity-ae3350ae0320d140a427d2fa318e7002745a73a5.tar.gz
dexon-solidity-ae3350ae0320d140a427d2fa318e7002745a73a5.tar.bz2
dexon-solidity-ae3350ae0320d140a427d2fa318e7002745a73a5.tar.lz
dexon-solidity-ae3350ae0320d140a427d2fa318e7002745a73a5.tar.xz
dexon-solidity-ae3350ae0320d140a427d2fa318e7002745a73a5.tar.zst
dexon-solidity-ae3350ae0320d140a427d2fa318e7002745a73a5.zip
[SMTChecker] Integration with CVC4
Diffstat (limited to 'libsolidity/formal/CVC4Interface.cpp')
-rw-r--r--libsolidity/formal/CVC4Interface.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp
new file mode 100644
index 00000000..dba5823a
--- /dev/null
+++ b/libsolidity/formal/CVC4Interface.cpp
@@ -0,0 +1,200 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <libsolidity/formal/CVC4Interface.h>
+
+#include <libsolidity/interface/Exceptions.h>
+
+#include <libdevcore/CommonIO.h>
+
+using namespace std;
+using namespace dev;
+using namespace dev::solidity::smt;
+
+CVC4Interface::CVC4Interface():
+ m_solver(&m_context)
+{
+ reset();
+}
+
+void CVC4Interface::reset()
+{
+ m_constants.clear();
+ m_functions.clear();
+ m_solver.reset();
+ m_solver.setOption("produce-models", true);
+}
+
+void CVC4Interface::push()
+{
+ m_solver.push();
+}
+
+void CVC4Interface::pop()
+{
+ m_solver.pop();
+}
+
+Expression CVC4Interface::newFunction(string _name, Sort _domain, Sort _codomain)
+{
+ CVC4::Type fType = m_context.mkFunctionType(cvc4Sort(_domain), cvc4Sort(_codomain));
+ m_functions.insert({_name, m_context.mkVar(_name.c_str(), fType)});
+ return SolverInterface::newFunction(move(_name), _domain, _codomain);
+}
+
+Expression CVC4Interface::newInteger(string _name)
+{
+ m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.integerType())});
+ return SolverInterface::newInteger(move(_name));
+}
+
+Expression CVC4Interface::newBool(string _name)
+{
+ m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.booleanType())});
+ return SolverInterface::newBool(std::move(_name));
+}
+
+void CVC4Interface::addAssertion(Expression const& _expr)
+{
+ try
+ {
+ m_solver.assertFormula(toCVC4Expr(_expr));
+ }
+ catch (CVC4::TypeCheckingException const&)
+ {
+ solAssert(false, "");
+ }
+ catch (CVC4::LogicException const&)
+ {
+ solAssert(false, "");
+ }
+ catch (CVC4::UnsafeInterruptException const&)
+ {
+ solAssert(false, "");
+ }
+}
+
+pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const& _expressionsToEvaluate)
+{
+ CheckResult result;
+ vector<string> values;
+ try
+ {
+ switch (m_solver.checkSat().isSat())
+ {
+ case CVC4::Result::SAT:
+ result = CheckResult::SATISFIABLE;
+ break;
+ case CVC4::Result::UNSAT:
+ result = CheckResult::UNSATISFIABLE;
+ break;
+ case CVC4::Result::SAT_UNKNOWN:
+ result = CheckResult::UNKNOWN;
+ break;
+ default:
+ solAssert(false, "");
+ }
+
+ if (result != CheckResult::UNSATISFIABLE && !_expressionsToEvaluate.empty())
+ {
+ for (Expression const& e: _expressionsToEvaluate)
+ values.push_back(toString(m_solver.getValue(toCVC4Expr(e))));
+ }
+ }
+ catch (CVC4::Exception & e)
+ {
+ result = CheckResult::ERROR;
+ values.clear();
+ }
+
+ return make_pair(result, values);
+}
+
+CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
+{
+ if (_expr.arguments.empty() && m_constants.count(_expr.name))
+ return m_constants.at(_expr.name);
+ vector<CVC4::Expr> arguments;
+ for (auto const& arg: _expr.arguments)
+ arguments.push_back(toCVC4Expr(arg));
+
+ string const& n = _expr.name;
+ if (m_functions.count(n))
+ return m_context.mkExpr(CVC4::kind::APPLY_UF, m_functions[n], arguments);
+ else if (m_constants.count(n))
+ {
+ solAssert(arguments.empty(), "");
+ return m_constants.at(n);
+ }
+ else if (arguments.empty())
+ {
+ if (n == "true")
+ return m_context.mkConst(true);
+ else if (n == "false")
+ return m_context.mkConst(false);
+ else
+ // We assume it is an integer...
+ return m_context.mkConst(CVC4::Rational(n));
+ }
+
+ solAssert(_expr.hasCorrectArity(), "");
+ if (n == "ite")
+ return arguments[0].iteExpr(arguments[1], arguments[2]);
+ else if (n == "not")
+ return arguments[0].notExpr();
+ else if (n == "and")
+ return arguments[0].andExpr(arguments[1]);
+ else if (n == "or")
+ return arguments[0].orExpr(arguments[1]);
+ else if (n == "=")
+ return m_context.mkExpr(CVC4::kind::EQUAL, arguments[0], arguments[1]);
+ else if (n == "<")
+ return m_context.mkExpr(CVC4::kind::LT, arguments[0], arguments[1]);
+ else if (n == "<=")
+ return m_context.mkExpr(CVC4::kind::LEQ, arguments[0], arguments[1]);
+ else if (n == ">")
+ return m_context.mkExpr(CVC4::kind::GT, arguments[0], arguments[1]);
+ else if (n == ">=")
+ return m_context.mkExpr(CVC4::kind::GEQ, arguments[0], arguments[1]);
+ else if (n == "+")
+ return m_context.mkExpr(CVC4::kind::PLUS, arguments[0], arguments[1]);
+ else if (n == "-")
+ return m_context.mkExpr(CVC4::kind::MINUS, arguments[0], arguments[1]);
+ else if (n == "*")
+ return m_context.mkExpr(CVC4::kind::MULT, arguments[0], arguments[1]);
+ else if (n == "/")
+ return m_context.mkExpr(CVC4::kind::INTS_DIVISION_TOTAL, arguments[0], arguments[1]);
+ // Cannot reach here.
+ solAssert(false, "");
+ return arguments[0];
+}
+
+CVC4::Type CVC4Interface::cvc4Sort(Sort _sort)
+{
+ switch (_sort)
+ {
+ case Sort::Bool:
+ return m_context.booleanType();
+ case Sort::Int:
+ return m_context.integerType();
+ default:
+ break;
+ }
+ solAssert(false, "");
+ // Cannot be reached.
+ return m_context.integerType();
+}