mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Allow running Eldarica from the command line
This commit is contained in:
@@ -149,10 +149,13 @@ set(sources
|
||||
interface/Natspec.h
|
||||
interface/OptimiserSettings.h
|
||||
interface/ReadFile.h
|
||||
interface/SMTSolverCommand.cpp
|
||||
interface/SMTSolverCommand.h
|
||||
interface/StandardCompiler.cpp
|
||||
interface/StandardCompiler.h
|
||||
interface/StorageLayout.cpp
|
||||
interface/StorageLayout.h
|
||||
interface/UniversalCallback.h
|
||||
interface/Version.cpp
|
||||
interface/Version.h
|
||||
lsp/DocumentHoverHandler.cpp
|
||||
@@ -181,5 +184,5 @@ set(sources
|
||||
)
|
||||
|
||||
add_library(solidity ${sources})
|
||||
target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost fmt::fmt-header-only)
|
||||
target_link_libraries(solidity PUBLIC yul evmasm langutil smtutil solutil Boost::boost fmt::fmt-header-only Threads::Threads)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <libsolidity/formal/BMC.h>
|
||||
|
||||
#include <libsolidity/formal/ModelChecker.h>
|
||||
#include <libsolidity/formal/SymbolicTypes.h>
|
||||
|
||||
#include <libsmtutil/SMTPortfolio.h>
|
||||
@@ -40,7 +41,7 @@ BMC::BMC(
|
||||
UniqueErrorReporter& _errorReporter,
|
||||
map<h256, string> const& _smtlib2Responses,
|
||||
ReadCallback::Callback const& _smtCallback,
|
||||
ModelCheckerSettings const& _settings,
|
||||
ModelCheckerSettings _settings,
|
||||
CharStreamProvider const& _charStreamProvider
|
||||
):
|
||||
SMTEncoder(_context, _settings, _errorReporter, _charStreamProvider),
|
||||
@@ -61,15 +62,14 @@ BMC::BMC(
|
||||
|
||||
void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>, smt::EncodingContext::IdCompare> _solvedTargets)
|
||||
{
|
||||
if (m_interface->solvers() == 0)
|
||||
// At this point every enabled solver is available.
|
||||
if (!m_settings.solvers.cvc4 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3)
|
||||
{
|
||||
m_errorReporter.warning(
|
||||
7710_error,
|
||||
SourceLocation(),
|
||||
"BMC analysis was not possible since no SMT solver was found and enabled."
|
||||
#ifdef HAVE_Z3_DLOPEN
|
||||
" Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3."
|
||||
#endif
|
||||
" The accepted solvers for BMC are cvc4 and z3."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
langutil::UniqueErrorReporter& _errorReporter,
|
||||
std::map<h256, std::string> const& _smtlib2Responses,
|
||||
ReadCallback::Callback const& _smtCallback,
|
||||
ModelCheckerSettings const& _settings,
|
||||
ModelCheckerSettings _settings,
|
||||
langutil::CharStreamProvider const& _charStreamProvider
|
||||
);
|
||||
|
||||
|
||||
+37
-30
@@ -18,6 +18,8 @@
|
||||
|
||||
#include <libsolidity/formal/CHC.h>
|
||||
|
||||
#include <libsolidity/formal/ModelChecker.h>
|
||||
|
||||
#ifdef HAVE_Z3
|
||||
#include <libsmtutil/Z3CHCInterface.h>
|
||||
#endif
|
||||
@@ -62,7 +64,7 @@ CHC::CHC(
|
||||
UniqueErrorReporter& _errorReporter,
|
||||
map<util::h256, string> const& _smtlib2Responses,
|
||||
ReadCallback::Callback const& _smtCallback,
|
||||
ModelCheckerSettings const& _settings,
|
||||
ModelCheckerSettings _settings,
|
||||
CharStreamProvider const& _charStreamProvider
|
||||
):
|
||||
SMTEncoder(_context, _settings, _errorReporter, _charStreamProvider),
|
||||
@@ -73,32 +75,30 @@ CHC::CHC(
|
||||
|
||||
void CHC::analyze(SourceUnit const& _source)
|
||||
{
|
||||
if (!shouldAnalyze(_source))
|
||||
return;
|
||||
|
||||
bool usesZ3 = m_settings.solvers.z3;
|
||||
#ifdef HAVE_Z3_DLOPEN
|
||||
if (m_settings.solvers.z3 && !Z3Interface::available())
|
||||
{
|
||||
usesZ3 = false;
|
||||
m_errorReporter.warning(
|
||||
8158_error,
|
||||
SourceLocation(),
|
||||
"z3 was selected as a Horn solver for CHC analysis but libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " was not found."
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!usesZ3 && !m_settings.solvers.smtlib2)
|
||||
// At this point every enabled solver is available.
|
||||
if (!m_settings.solvers.eld && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3)
|
||||
{
|
||||
m_errorReporter.warning(
|
||||
7649_error,
|
||||
SourceLocation(),
|
||||
"CHC analysis was not possible since no Horn solver was found and enabled."
|
||||
" The accepted solvers for CHC are Eldarica and z3."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_settings.solvers.eld && m_settings.solvers.z3)
|
||||
m_errorReporter.warning(
|
||||
5798_error,
|
||||
SourceLocation(),
|
||||
"Multiple Horn solvers were selected for CHC."
|
||||
" CHC only supports one solver at a time, therefore only z3 will be used."
|
||||
" If you wish to use Eldarica, please enable Eldarica only."
|
||||
);
|
||||
|
||||
if (!shouldAnalyze(_source))
|
||||
return;
|
||||
|
||||
resetSourceAnalysis();
|
||||
|
||||
auto sources = sourceDependencies(_source);
|
||||
@@ -115,7 +115,8 @@ void CHC::analyze(SourceUnit const& _source)
|
||||
|
||||
bool ranSolver = true;
|
||||
// If ranSolver is true here it's because an SMT solver callback was
|
||||
// actually given and the queries were solved.
|
||||
// actually given and the queries were solved,
|
||||
// or Eldarica was chosen and was present in the system.
|
||||
if (auto const* smtLibInterface = dynamic_cast<CHCSmtLib2Interface const*>(m_interface.get()))
|
||||
ranSolver = smtLibInterface->unhandledQueries().empty();
|
||||
if (!ranSolver)
|
||||
@@ -994,24 +995,27 @@ void CHC::resetSourceAnalysis()
|
||||
ArraySlicePredicate::reset();
|
||||
m_blockCounter = 0;
|
||||
|
||||
bool usesZ3 = false;
|
||||
#ifdef HAVE_Z3
|
||||
usesZ3 = m_settings.solvers.z3 && Z3Interface::available();
|
||||
if (usesZ3)
|
||||
// At this point every enabled solver is available.
|
||||
// If more than one Horn solver is selected we go with z3.
|
||||
// We still need the ifdef because of Z3CHCInterface.
|
||||
if (m_settings.solvers.z3)
|
||||
{
|
||||
/// z3::fixedpoint does not have a reset mechanism, so we need to create another.
|
||||
#ifdef HAVE_Z3
|
||||
// z3::fixedpoint does not have a reset mechanism, so we need to create another.
|
||||
m_interface = std::make_unique<Z3CHCInterface>(m_settings.timeout);
|
||||
auto z3Interface = dynamic_cast<Z3CHCInterface const*>(m_interface.get());
|
||||
solAssert(z3Interface, "");
|
||||
m_context.setSolver(z3Interface->z3Interface());
|
||||
}
|
||||
#else
|
||||
solAssert(false);
|
||||
#endif
|
||||
if (!usesZ3)
|
||||
}
|
||||
if (!m_settings.solvers.z3)
|
||||
{
|
||||
solAssert(m_settings.solvers.smtlib2);
|
||||
solAssert(m_settings.solvers.smtlib2 || m_settings.solvers.eld);
|
||||
|
||||
if (!m_interface)
|
||||
m_interface = make_unique<CHCSmtLib2Interface>(m_smtlib2Responses, m_smtCallback, m_settings.timeout);
|
||||
m_interface = make_unique<CHCSmtLib2Interface>(m_smtlib2Responses, m_smtCallback, m_settings.solvers, m_settings.timeout);
|
||||
|
||||
auto smtlib2Interface = dynamic_cast<CHCSmtLib2Interface*>(m_interface.get());
|
||||
solAssert(smtlib2Interface, "");
|
||||
@@ -1551,9 +1555,10 @@ tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query
|
||||
{
|
||||
case CheckResult::SATISFIABLE:
|
||||
{
|
||||
#ifdef HAVE_Z3
|
||||
// We still need the ifdef because of Z3CHCInterface.
|
||||
if (m_settings.solvers.z3)
|
||||
{
|
||||
#ifdef HAVE_Z3
|
||||
// Even though the problem is SAT, Spacer's pre processing makes counterexamples incomplete.
|
||||
// We now disable those optimizations and check whether we can still solve the problem.
|
||||
auto* spacer = dynamic_cast<Z3CHCInterface*>(m_interface.get());
|
||||
@@ -1569,8 +1574,10 @@ tuple<CheckResult, smtutil::Expression, CHCSolverInterface::CexGraph> CHC::query
|
||||
cex = std::move(cexNoOpt);
|
||||
|
||||
spacer->setSpacerOptions(true);
|
||||
}
|
||||
#else
|
||||
solAssert(false);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CheckResult::UNSATISFIABLE:
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
langutil::UniqueErrorReporter& _errorReporter,
|
||||
std::map<util::h256, std::string> const& _smtlib2Responses,
|
||||
ReadCallback::Callback const& _smtCallback,
|
||||
ModelCheckerSettings const& _settings,
|
||||
ModelCheckerSettings _settings,
|
||||
langutil::CharStreamProvider const& _charStreamProvider
|
||||
);
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
#ifdef HAVE_Z3
|
||||
#include <libsmtutil/Z3Interface.h>
|
||||
#endif
|
||||
#ifdef HAVE_Z3_DLOPEN
|
||||
#include <z3_version.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux) || defined(__APPLE__)
|
||||
#include <boost/process.hpp>
|
||||
#endif
|
||||
|
||||
#include <range/v3/algorithm/any_of.hpp>
|
||||
#include <range/v3/view.hpp>
|
||||
@@ -29,6 +36,7 @@ using namespace solidity;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::smtutil;
|
||||
|
||||
ModelChecker::ModelChecker(
|
||||
ErrorReporter& _errorReporter,
|
||||
@@ -46,13 +54,11 @@ ModelChecker::ModelChecker(
|
||||
}
|
||||
|
||||
// TODO This should be removed for 0.9.0.
|
||||
void ModelChecker::enableAllEnginesIfPragmaPresent(vector<shared_ptr<SourceUnit>> const& _sources)
|
||||
bool ModelChecker::isPragmaPresent(vector<shared_ptr<SourceUnit>> const& _sources)
|
||||
{
|
||||
bool hasPragma = ranges::any_of(_sources, [](auto _source) {
|
||||
return ranges::any_of(_sources, [](auto _source) {
|
||||
return _source && _source->annotation().experimentalFeatures.count(ExperimentalFeature::SMTChecker);
|
||||
});
|
||||
if (hasPragma)
|
||||
m_settings.engine = ModelCheckerEngine::All();
|
||||
}
|
||||
|
||||
void ModelChecker::checkRequestedSourcesAndContracts(vector<shared_ptr<SourceUnit>> const& _sources)
|
||||
@@ -135,9 +141,12 @@ vector<string> ModelChecker::unhandledQueries()
|
||||
return m_bmc.unhandledQueries() + m_chc.unhandledQueries();
|
||||
}
|
||||
|
||||
solidity::smtutil::SMTSolverChoice ModelChecker::availableSolvers()
|
||||
SMTSolverChoice ModelChecker::availableSolvers()
|
||||
{
|
||||
smtutil::SMTSolverChoice available = smtutil::SMTSolverChoice::SMTLIB2();
|
||||
#if defined(__linux) || defined(__APPLE__)
|
||||
available.eld = !boost::process::search_path("eld").empty();
|
||||
#endif
|
||||
#ifdef HAVE_Z3
|
||||
available.z3 = solidity::smtutil::Z3Interface::available();
|
||||
#endif
|
||||
@@ -146,3 +155,47 @@ solidity::smtutil::SMTSolverChoice ModelChecker::availableSolvers()
|
||||
#endif
|
||||
return available;
|
||||
}
|
||||
|
||||
SMTSolverChoice ModelChecker::checkRequestedSolvers(SMTSolverChoice _enabled, ErrorReporter& _errorReporter)
|
||||
{
|
||||
SMTSolverChoice availableSolvers{ModelChecker::availableSolvers()};
|
||||
|
||||
if (_enabled.cvc4 && !availableSolvers.cvc4)
|
||||
{
|
||||
_enabled.cvc4 = false;
|
||||
_errorReporter.warning(
|
||||
4902_error,
|
||||
SourceLocation(),
|
||||
"Solver CVC4 was selected for SMTChecker but it is not available."
|
||||
);
|
||||
}
|
||||
|
||||
if (_enabled.eld && !availableSolvers.eld)
|
||||
{
|
||||
_enabled.eld = false;
|
||||
_errorReporter.warning(
|
||||
4458_error,
|
||||
SourceLocation(),
|
||||
#if defined(__linux) || defined(__APPLE__)
|
||||
"Solver Eldarica was selected for SMTChecker but it was not found in the system."
|
||||
#else
|
||||
"Solver Eldarica was selected for SMTChecker but it is only supported on Linux and MacOS."
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
if (_enabled.z3 && !availableSolvers.z3)
|
||||
{
|
||||
_enabled.z3 = false;
|
||||
_errorReporter.warning(
|
||||
8158_error,
|
||||
SourceLocation(),
|
||||
"Solver z3 was selected for SMTChecker but it is not available."
|
||||
#ifdef HAVE_Z3_DLOPEN
|
||||
" libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " was not found."
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
);
|
||||
|
||||
// TODO This should be removed for 0.9.0.
|
||||
void enableAllEnginesIfPragmaPresent(std::vector<std::shared_ptr<SourceUnit>> const& _sources);
|
||||
static bool isPragmaPresent(std::vector<std::shared_ptr<SourceUnit>> const& _sources);
|
||||
|
||||
/// Generates error messages if the requested sources and contracts
|
||||
/// do not exist.
|
||||
@@ -74,6 +74,10 @@ public:
|
||||
/// @returns SMT solvers that are available via the C++ API.
|
||||
static smtutil::SMTSolverChoice availableSolvers();
|
||||
|
||||
/// @returns the intersection of the enabled and available solvers,
|
||||
/// reporting warnings when a solver is enabled but not available.
|
||||
static smtutil::SMTSolverChoice checkRequestedSolvers(smtutil::SMTSolverChoice _enabled, langutil::ErrorReporter& _errorReporter);
|
||||
|
||||
private:
|
||||
/// Error reporter from CompilerStack.
|
||||
/// We need to append m_uniqueErrorReporter
|
||||
|
||||
@@ -153,7 +153,7 @@ struct ModelCheckerSettings
|
||||
ModelCheckerEngine engine = ModelCheckerEngine::None();
|
||||
ModelCheckerInvariants invariants = ModelCheckerInvariants::Default();
|
||||
bool showUnproved = false;
|
||||
smtutil::SMTSolverChoice solvers = smtutil::SMTSolverChoice::All();
|
||||
smtutil::SMTSolverChoice solvers = smtutil::SMTSolverChoice::Z3();
|
||||
ModelCheckerTargets targets = ModelCheckerTargets::Default();
|
||||
std::optional<unsigned> timeout;
|
||||
|
||||
|
||||
@@ -47,13 +47,13 @@ using namespace solidity::frontend;
|
||||
|
||||
SMTEncoder::SMTEncoder(
|
||||
smt::EncodingContext& _context,
|
||||
ModelCheckerSettings const& _settings,
|
||||
ModelCheckerSettings _settings,
|
||||
UniqueErrorReporter& _errorReporter,
|
||||
langutil::CharStreamProvider const& _charStreamProvider
|
||||
):
|
||||
m_errorReporter(_errorReporter),
|
||||
m_context(_context),
|
||||
m_settings(_settings),
|
||||
m_settings(std::move(_settings)),
|
||||
m_charStreamProvider(_charStreamProvider)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class SMTEncoder: public ASTConstVisitor
|
||||
public:
|
||||
SMTEncoder(
|
||||
smt::EncodingContext& _context,
|
||||
ModelCheckerSettings const& _settings,
|
||||
ModelCheckerSettings _settings,
|
||||
langutil::UniqueErrorReporter& _errorReporter,
|
||||
langutil::CharStreamProvider const& _charStreamProvider
|
||||
);
|
||||
@@ -483,7 +483,7 @@ protected:
|
||||
/// Stores the context of the encoding.
|
||||
smt::EncodingContext& m_context;
|
||||
|
||||
ModelCheckerSettings const& m_settings;
|
||||
ModelCheckerSettings m_settings;
|
||||
|
||||
/// Character stream for each source,
|
||||
/// used for retrieving source text of expressions for e.g. counter-examples.
|
||||
|
||||
@@ -577,9 +577,18 @@ bool CompilerStack::analyze()
|
||||
|
||||
if (noErrors)
|
||||
{
|
||||
ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile);
|
||||
// Run SMTChecker
|
||||
|
||||
auto allSources = util::applyMap(m_sourceOrder, [](Source const* _source) { return _source->ast; });
|
||||
modelChecker.enableAllEnginesIfPragmaPresent(allSources);
|
||||
if (ModelChecker::isPragmaPresent(allSources))
|
||||
m_modelCheckerSettings.engine = ModelCheckerEngine::All();
|
||||
|
||||
// m_modelCheckerSettings is spread to engines and solver interfaces,
|
||||
// so we need to check whether the enabled ones are available before building the classes.
|
||||
if (m_modelCheckerSettings.engine.any())
|
||||
m_modelCheckerSettings.solvers = ModelChecker::checkRequestedSolvers(m_modelCheckerSettings.solvers, m_errorReporter);
|
||||
|
||||
ModelChecker modelChecker(m_errorReporter, *this, m_smtlib2Responses, m_modelCheckerSettings, m_readFile);
|
||||
modelChecker.checkRequestedSourcesAndContracts(allSources);
|
||||
for (Source const* source: m_sourceOrder)
|
||||
if (source->ast)
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
#include <libsolidity/interface/SMTSolverCommand.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
#include <libsolutil/CommonIO.h>
|
||||
#include <libsolutil/Exceptions.h>
|
||||
#include <libsolutil/Keccak256.h>
|
||||
#include <libsolutil/TemporaryDirectory.h>
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/process.hpp>
|
||||
|
||||
using solidity::langutil::InternalCompilerError;
|
||||
using solidity::util::errinfo_comment;
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
SMTSolverCommand::SMTSolverCommand(string _solverCmd) : m_solverCmd(_solverCmd) {}
|
||||
|
||||
ReadCallback::Result SMTSolverCommand::solve(string const& _kind, string const& _query)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_kind != ReadCallback::kindString(ReadCallback::Kind::SMTQuery))
|
||||
solAssert(false, "SMTQuery callback used as callback kind " + _kind);
|
||||
|
||||
auto tempDir = solidity::util::TemporaryDirectory("smt");
|
||||
util::h256 queryHash = util::keccak256(_query);
|
||||
auto queryFileName = tempDir.path() / ("query_" + queryHash.hex() + ".smt2");
|
||||
|
||||
auto queryFile = boost::filesystem::ofstream(queryFileName);
|
||||
queryFile << _query;
|
||||
|
||||
auto eldBin = boost::process::search_path(m_solverCmd);
|
||||
|
||||
if (eldBin.empty())
|
||||
return ReadCallback::Result{false, m_solverCmd + " binary not found."};
|
||||
|
||||
boost::process::ipstream pipe;
|
||||
boost::process::child eld(
|
||||
eldBin,
|
||||
queryFileName,
|
||||
boost::process::std_out > pipe
|
||||
);
|
||||
|
||||
vector<string> data;
|
||||
string line;
|
||||
while (eld.running() && std::getline(pipe, line))
|
||||
if (!line.empty())
|
||||
data.push_back(line);
|
||||
|
||||
eld.wait();
|
||||
|
||||
return ReadCallback::Result{true, boost::join(data, "\n")};
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return ReadCallback::Result{false, "Unknown exception in SMTQuery callback: " + boost::current_exception_diagnostic_information()};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/interface/ReadFile.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
/// SMTSolverCommand wraps an SMT solver called via its binary in the OS.
|
||||
class SMTSolverCommand
|
||||
{
|
||||
public:
|
||||
SMTSolverCommand(std::string _solverCmd);
|
||||
|
||||
/// Calls an SMT solver with the given query.
|
||||
frontend::ReadCallback::Result solve(std::string const& _kind, std::string const& _query);
|
||||
|
||||
frontend::ReadCallback::Callback solver()
|
||||
{
|
||||
return [this](std::string const& _kind, std::string const& _query) { return solve(_kind, _query); };
|
||||
}
|
||||
|
||||
private:
|
||||
/// The name of the solver's binary.
|
||||
std::string const m_solverCmd;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/interface/FileReader.h>
|
||||
#include <libsolidity/interface/SMTSolverCommand.h>
|
||||
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
/// UniversalCallback is used to wrap both FileReader and SMTSolverCommand
|
||||
/// callbacks in a single callback. It uses the Kind of the callback to
|
||||
/// determine which to call internally.
|
||||
class UniversalCallback
|
||||
{
|
||||
public:
|
||||
UniversalCallback(FileReader& _fileReader, SMTSolverCommand& _solver) :
|
||||
m_fileReader{_fileReader},
|
||||
m_solver{_solver}
|
||||
{}
|
||||
|
||||
frontend::ReadCallback::Callback callback()
|
||||
{
|
||||
return [this](std::string const& _kind, std::string const& _data) -> ReadCallback::Result {
|
||||
if (_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile))
|
||||
return m_fileReader.readFile(_kind, _data);
|
||||
else if (_kind == ReadCallback::kindString(ReadCallback::Kind::SMTQuery))
|
||||
return m_solver.solve(_kind, _data);
|
||||
solAssert(false, "Unknown callback kind.");
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
FileReader& m_fileReader;
|
||||
SMTSolverCommand& m_solver;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user