aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/formal/SMTLib2Interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/formal/SMTLib2Interface.cpp')
-rw-r--r--libsolidity/formal/SMTLib2Interface.cpp168
1 files changed, 42 insertions, 126 deletions
diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp
index 8d40c354..63ab1679 100644
--- a/libsolidity/formal/SMTLib2Interface.cpp
+++ b/libsolidity/formal/SMTLib2Interface.cpp
@@ -21,6 +21,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/join.hpp>
+#include <boost/filesystem/operations.hpp>
#include <cstdio>
#include <fstream>
@@ -30,99 +31,31 @@
#include <string>
#include <array>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
using namespace std;
using namespace dev;
using namespace dev::solidity::smt;
-
-//namespace
-//{
-
-//void createSubprocess(FILE*& _readPipe, FILE*& _writePipe)
-//{
-// int pipe_in[2]; /* This is the pipe with wich we write to the child process. */
-// int pipe_out[2]; /* This is the pipe with wich we read from the child process. */
-
-// solAssert(!pipe(pipe_in) && !pipe(pipe_out), "");
-
-// /* Attempt to fork and check for errors */
-// pid_t pid = fork();
-// solAssert(pid != -1, "");
-
-// if (pid)
-// {
-// /* The parent has the non-zero PID. */
-// _readPipe = fdopen(pipe_out[0], "r");
-// _writePipe = fdopen(pipe_in[1], "w");
-// close(pipe_out[1]);
-// close(pipe_in[0]);
-// }
-// else
-// {
-// /* The child has the zero pid returned by fork*/
-// cout << "child" << endl;
-// solAssert(dup2(pipe_out[1], 1) != -1, "");
-// solAssert(dup2(pipe_in[0], 0) != -1, "");
-// solAssert(close(pipe_out[0]) == 0, "");
-// solAssert(close(pipe_out[1]) == 0, "");
-// solAssert(close(pipe_in[0]) == 0, "");
-// solAssert(close(pipe_in[1]) == 0, "");
-// execl("/usr/bin/z3", "z3", "-smt2", "-in", NULL);
-// exit(1); /* Only reached if execl() failed */
-// }
-//}
-
-//}
-
-SMTLib2Interface::SMTLib2Interface()
+SMTLib2Interface::SMTLib2Interface(ReadFile::Callback const& _readFileCallback):
+ m_communicator(_readFileCallback)
{
- // TODO using pipes did not really work, so trying it the hard way for now.
-// createSubprocess(m_solverWrite, m_solverRead);
-// solAssert(m_solverWrite, "Unable to start Z3");
-// solAssert(m_solverRead, "Unable to start Z3");
-// write("(set-option :produce-models true)\n(set-logic QF_LIA)\n");
reset();
}
-SMTLib2Interface::~SMTLib2Interface()
-{
-// if (m_solverWrite)
-// {
-// write("(exit)\n");
-// fflush(m_solverWrite);
-// fclose(m_solverWrite);
-// m_solverWrite = nullptr;
-// }
-// if (m_solverRead)
-// {
-// fclose(m_solverRead);
-// m_solverRead = nullptr;
-// }
-}
-
void SMTLib2Interface::reset()
{
-// write("(reset)\n");
-// write("(set-option :produce-models true)\n");
m_accumulatedOutput.clear();
m_accumulatedOutput.emplace_back();
- write("(set-option :produce-models true)\n(set-logic QF_UFLIA)\n");
+ write("(set-option :produce-models true)");
+ write("(set-logic QF_UFLIA)");
}
void SMTLib2Interface::push()
{
m_accumulatedOutput.emplace_back();
- //write("(push)\n");
}
void SMTLib2Interface::pop()
{
- //write("(pop)\n");
solAssert(!m_accumulatedOutput.empty(), "");
m_accumulatedOutput.pop_back();
}
@@ -136,50 +69,34 @@ Expression SMTLib2Interface::newFunction(string _name, Sort _domain, Sort _codom
(_domain == Sort::Int ? "Int" : "Bool") +
") " +
(_codomain == Sort::Int ? "Int" : "Bool") +
- ")\n"
+ ")"
);
- return Expression(_name, {});
+ return Expression(std::move(_name), {});
}
Expression SMTLib2Interface::newInteger(string _name)
{
- write("(declare-const |" + _name + "| Int)\n");
- return Expression(_name, {});
+ write("(declare-const |" + _name + "| Int)");
+ return Expression(std::move(_name), {});
}
Expression SMTLib2Interface::newBool(string _name)
{
- write("(declare-const |" + _name + "| Bool)\n");
- return Expression(_name, {});
+ write("(declare-const |" + _name + "| Bool)");
+ return Expression(std::move(_name), {});
}
-void SMTLib2Interface::addAssertion(Expression _expr)
+void SMTLib2Interface::addAssertion(Expression const& _expr)
{
- write("(assert " + _expr.toSExpr() + ")\n");
+ write("(assert " + _expr.toSExpr() + ")");
}
pair<CheckResult, vector<string>> SMTLib2Interface::check(vector<Expression> const& _expressionsToEvaluate)
{
- string checks;
- if (_expressionsToEvaluate.empty())
- checks = "(check-sat)\n";
- else
- {
- // TODO make sure these are unique
- for (size_t i = 0; i < _expressionsToEvaluate.size(); i++)
- {
- auto const& e = _expressionsToEvaluate.at(i);
- // TODO they don't have to be ints...
- checks += "(declare-const |EVALEXPR_" + to_string(i) + "| Int)\n";
- checks += "(assert (= |EVALEXPR_" + to_string(i) + "| " + e.toSExpr() + "))\n";
- }
- checks += "(check-sat)\n";
- checks += "(get-value (";
- for (size_t i = 0; i < _expressionsToEvaluate.size(); i++)
- checks += "|EVALEXPR_" + to_string(i) + "| ";
- checks += "))\n";
- }
- string response = communicate(boost::algorithm::join(m_accumulatedOutput, "\n") + checks);
+ string response = m_communicator.communicate(
+ boost::algorithm::join(m_accumulatedOutput, "\n") +
+ checkSatAndGetValuesCommand(_expressionsToEvaluate)
+ );
CheckResult result;
// TODO proper parsing
if (boost::starts_with(response, "sat\n"))
@@ -189,44 +106,43 @@ pair<CheckResult, vector<string>> SMTLib2Interface::check(vector<Expression> con
else if (boost::starts_with(response, "unknown\n"))
result = CheckResult::UNKNOWN;
else
- solAssert(false, "Invalid response to check-sat: " + response);
+ result = CheckResult::ERROR;
vector<string> values;
- if (result != CheckResult::UNSAT)
+ if (result != CheckResult::UNSAT && result != CheckResult::ERROR)
values = parseValues(find(response.cbegin(), response.cend(), '\n'), response.cend());
return make_pair(result, values);
}
-//string SMTLib2Interface::eval(Expression _expr)
-//{
-// write("(get-value (" + _expr.toSExpr() + ")\n");
-// std::string reply = communicate();
-// cout << "<-- Z3: " << reply << endl;
-// // TODO parse
-// return reply;
-//}
-
void SMTLib2Interface::write(string _data)
{
-// cout << " --> Z3: " << _data << endl;
-// solAssert(m_solverWrite, "");
-// solAssert(fputs(_data.c_str(), m_solverWrite) >= 0 || true, "EOF while communicating with Z3.");
-// solAssert(fflush(m_solverWrite) == 0 || true, "");
solAssert(!m_accumulatedOutput.empty(), "");
- m_accumulatedOutput.back() += move(_data);
+ m_accumulatedOutput.back() += move(_data) + "\n";
}
-string SMTLib2Interface::communicate(std::string const& _input)
+string SMTLib2Interface::checkSatAndGetValuesCommand(vector<Expression> const& _expressionsToEvaluate)
{
- ofstream("/tmp/z3exchange.smt2") << _input << "(exit)" << endl;
- FILE* solverOutput = popen("z3 -smt2 /tmp/z3exchange.smt2", "r");
- string result;
- array<char, 128> buffer;
- while (!feof(solverOutput))
- if (fgets(buffer.data(), 127, solverOutput) != nullptr)
- result += buffer.data();
- fclose(solverOutput);
- return result;
+ string command;
+ if (_expressionsToEvaluate.empty())
+ command = "(check-sat)\n";
+ else
+ {
+ // TODO make sure these are unique
+ for (size_t i = 0; i < _expressionsToEvaluate.size(); i++)
+ {
+ auto const& e = _expressionsToEvaluate.at(i);
+ // TODO they don't have to be ints...
+ command += "(declare-const |EVALEXPR_" + to_string(i) + "| Int)\n";
+ command += "(assert (= |EVALEXPR_" + to_string(i) + "| " + e.toSExpr() + "))\n";
+ }
+ command += "(check-sat)\n";
+ command += "(get-value (";
+ for (size_t i = 0; i < _expressionsToEvaluate.size(); i++)
+ command += "|EVALEXPR_" + to_string(i) + "| ";
+ command += "))\n";
+ }
+
+ return command;
}
vector<string> SMTLib2Interface::parseValues(string::const_iterator _start, string::const_iterator _end)