mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Refactor StandardCompiler to split into input parsing/validating and compilation steps.
This commit is contained in:
parent
0eb799424d
commit
8b20ecb558
@ -127,16 +127,6 @@ bool hashMatchesContent(string const& _hash, string const& _content)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StringMap createSourceList(Json::Value const& _input)
|
|
||||||
{
|
|
||||||
StringMap sources;
|
|
||||||
Json::Value const& jsonSources = _input["sources"];
|
|
||||||
if (jsonSources.isObject())
|
|
||||||
for (auto const& sourceName: jsonSources.getMemberNames())
|
|
||||||
sources[sourceName] = jsonSources[sourceName]["content"].asString();
|
|
||||||
return sources;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isArtifactRequested(Json::Value const& _outputSelection, string const& _artifact)
|
bool isArtifactRequested(Json::Value const& _outputSelection, string const& _artifact)
|
||||||
{
|
{
|
||||||
for (auto const& artifact: _outputSelection)
|
for (auto const& artifact: _outputSelection)
|
||||||
@ -365,9 +355,9 @@ boost::optional<Json::Value> checkOutputSelection(Json::Value const& _outputSele
|
|||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/// Validates the optimizer settings and returns them in a parsed object.
|
||||||
|
/// On error returns the json-formatted error message.
|
||||||
boost::optional<Json::Value> StandardCompiler::parseOptimizerSettings(Json::Value const& _jsonInput)
|
boost::variant<OptimiserSettings, Json::Value> parseOptimizerSettings(Json::Value const& _jsonInput)
|
||||||
{
|
{
|
||||||
if (auto result = checkOptimizerKeys(_jsonInput))
|
if (auto result = checkOptimizerKeys(_jsonInput))
|
||||||
return *result;
|
return *result;
|
||||||
@ -417,14 +407,14 @@ boost::optional<Json::Value> StandardCompiler::parseOptimizerSettings(Json::Valu
|
|||||||
return formatFatalError("JSONError", "The \"yulDetails\" optimizer setting cannot have any settings yet.");
|
return formatFatalError("JSONError", "The \"yulDetails\" optimizer setting cannot have any settings yet.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_compilerStack.setOptimiserSettings(std::move(settings));
|
return std::move(settings);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
boost::variant<StandardCompiler::InputsAndSettings, Json::Value> StandardCompiler::parseInput(Json::Value const& _input)
|
||||||
{
|
{
|
||||||
m_compilerStack.reset(false);
|
InputsAndSettings ret;
|
||||||
|
|
||||||
if (!_input.isObject())
|
if (!_input.isObject())
|
||||||
return formatFatalError("JSONError", "Input is not a JSON object.");
|
return formatFatalError("JSONError", "Input is not a JSON object.");
|
||||||
@ -443,7 +433,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
if (sources.empty())
|
if (sources.empty())
|
||||||
return formatFatalError("JSONError", "No input sources specified.");
|
return formatFatalError("JSONError", "No input sources specified.");
|
||||||
|
|
||||||
Json::Value errors = Json::arrayValue;
|
ret.errors = Json::arrayValue;
|
||||||
|
|
||||||
for (auto const& sourceName: sources.getMemberNames())
|
for (auto const& sourceName: sources.getMemberNames())
|
||||||
{
|
{
|
||||||
@ -459,14 +449,14 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
{
|
{
|
||||||
string content = sources[sourceName]["content"].asString();
|
string content = sources[sourceName]["content"].asString();
|
||||||
if (!hash.empty() && !hashMatchesContent(hash, content))
|
if (!hash.empty() && !hashMatchesContent(hash, content))
|
||||||
errors.append(formatError(
|
ret.errors.append(formatError(
|
||||||
false,
|
false,
|
||||||
"IOError",
|
"IOError",
|
||||||
"general",
|
"general",
|
||||||
"Mismatch between content and supplied hash for \"" + sourceName + "\""
|
"Mismatch between content and supplied hash for \"" + sourceName + "\""
|
||||||
));
|
));
|
||||||
else
|
else
|
||||||
m_compilerStack.addSource(sourceName, content);
|
ret.sources[sourceName] = content;
|
||||||
}
|
}
|
||||||
else if (sources[sourceName]["urls"].isArray())
|
else if (sources[sourceName]["urls"].isArray())
|
||||||
{
|
{
|
||||||
@ -484,7 +474,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
if (result.success)
|
if (result.success)
|
||||||
{
|
{
|
||||||
if (!hash.empty() && !hashMatchesContent(hash, result.responseOrErrorMessage))
|
if (!hash.empty() && !hashMatchesContent(hash, result.responseOrErrorMessage))
|
||||||
errors.append(formatError(
|
ret.errors.append(formatError(
|
||||||
false,
|
false,
|
||||||
"IOError",
|
"IOError",
|
||||||
"general",
|
"general",
|
||||||
@ -492,7 +482,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
));
|
));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_compilerStack.addSource(sourceName, result.responseOrErrorMessage);
|
ret.sources[sourceName] = result.responseOrErrorMessage;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -504,7 +494,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
for (auto const& failure: failures)
|
for (auto const& failure: failures)
|
||||||
{
|
{
|
||||||
/// If the import succeeded, let mark all the others as warnings, otherwise all of them are errors.
|
/// If the import succeeded, let mark all the others as warnings, otherwise all of them are errors.
|
||||||
errors.append(formatError(
|
ret.errors.append(formatError(
|
||||||
found ? true : false,
|
found ? true : false,
|
||||||
"IOError",
|
"IOError",
|
||||||
"general",
|
"general",
|
||||||
@ -547,7 +537,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
"\"smtlib2Responses." + hashString + "\" must be a string."
|
"\"smtlib2Responses." + hashString + "\" must be a string."
|
||||||
);
|
);
|
||||||
|
|
||||||
m_compilerStack.addSMTLib2Response(hash, smtlib2Responses[hashString].asString());
|
ret.smtLib2Responses[hash] = smtlib2Responses[hashString].asString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,29 +554,31 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
boost::optional<langutil::EVMVersion> version = langutil::EVMVersion::fromString(settings["evmVersion"].asString());
|
boost::optional<langutil::EVMVersion> version = langutil::EVMVersion::fromString(settings["evmVersion"].asString());
|
||||||
if (!version)
|
if (!version)
|
||||||
return formatFatalError("JSONError", "Invalid EVM version requested.");
|
return formatFatalError("JSONError", "Invalid EVM version requested.");
|
||||||
m_compilerStack.setEVMVersion(*version);
|
ret.evmVersion = *version;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.isMember("remappings") && !settings["remappings"].isArray())
|
if (settings.isMember("remappings") && !settings["remappings"].isArray())
|
||||||
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings.");
|
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings.");
|
||||||
|
|
||||||
vector<CompilerStack::Remapping> remappings;
|
|
||||||
for (auto const& remapping: settings.get("remappings", Json::Value()))
|
for (auto const& remapping: settings.get("remappings", Json::Value()))
|
||||||
{
|
{
|
||||||
if (!remapping.isString())
|
if (!remapping.isString())
|
||||||
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings");
|
return formatFatalError("JSONError", "\"settings.remappings\" must be an array of strings");
|
||||||
if (auto r = CompilerStack::parseRemapping(remapping.asString()))
|
if (auto r = CompilerStack::parseRemapping(remapping.asString()))
|
||||||
remappings.emplace_back(std::move(*r));
|
ret.remappings.emplace_back(std::move(*r));
|
||||||
else
|
else
|
||||||
return formatFatalError("JSONError", "Invalid remapping: \"" + remapping.asString() + "\"");
|
return formatFatalError("JSONError", "Invalid remapping: \"" + remapping.asString() + "\"");
|
||||||
}
|
}
|
||||||
m_compilerStack.setRemappings(remappings);
|
|
||||||
|
|
||||||
if (settings.isMember("optimizer"))
|
if (settings.isMember("optimizer"))
|
||||||
if (auto result = parseOptimizerSettings(settings["optimizer"]))
|
{
|
||||||
return *result;
|
auto optimiserSettings = parseOptimizerSettings(settings["optimizer"]);
|
||||||
|
if (optimiserSettings.type() == typeid(Json::Value))
|
||||||
|
return boost::get<Json::Value>(std::move(optimiserSettings)); // was an error
|
||||||
|
else
|
||||||
|
ret.optimiserSettings = boost::get<OptimiserSettings>(std::move(optimiserSettings));
|
||||||
|
}
|
||||||
|
|
||||||
map<string, h160> libraries;
|
|
||||||
Json::Value jsonLibraries = settings.get("libraries", Json::Value(Json::objectValue));
|
Json::Value jsonLibraries = settings.get("libraries", Json::Value(Json::objectValue));
|
||||||
if (!jsonLibraries.isObject())
|
if (!jsonLibraries.isObject())
|
||||||
return formatFatalError("JSONError", "\"libraries\" is not a JSON object.");
|
return formatFatalError("JSONError", "\"libraries\" is not a JSON object.");
|
||||||
@ -616,7 +608,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// @TODO use libraries only for the given source
|
// @TODO use libraries only for the given source
|
||||||
libraries[library] = h160(address);
|
ret.libraries[library] = h160(address);
|
||||||
}
|
}
|
||||||
catch (dev::BadHexCharacter const&)
|
catch (dev::BadHexCharacter const&)
|
||||||
{
|
{
|
||||||
@ -627,32 +619,52 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_compilerStack.setLibraries(libraries);
|
|
||||||
|
|
||||||
Json::Value metadataSettings = settings.get("metadata", Json::Value());
|
Json::Value metadataSettings = settings.get("metadata", Json::Value());
|
||||||
|
|
||||||
if (auto result = checkMetadataKeys(metadataSettings))
|
if (auto result = checkMetadataKeys(metadataSettings))
|
||||||
return *result;
|
return *result;
|
||||||
|
|
||||||
m_compilerStack.useMetadataLiteralSources(metadataSettings.get("useLiteralContent", Json::Value(false)).asBool());
|
ret.metadataLiteralSources = metadataSettings.get("useLiteralContent", Json::Value(false)).asBool();
|
||||||
|
|
||||||
Json::Value outputSelection = settings.get("outputSelection", Json::Value());
|
Json::Value outputSelection = settings.get("outputSelection", Json::Value());
|
||||||
|
|
||||||
if (auto jsonError = checkOutputSelection(outputSelection))
|
if (auto jsonError = checkOutputSelection(outputSelection))
|
||||||
return *jsonError;
|
return *jsonError;
|
||||||
|
|
||||||
m_compilerStack.setRequestedContractNames(requestedContractNames(outputSelection));
|
ret.outputSelection = std::move(outputSelection);
|
||||||
|
|
||||||
bool const binariesRequested = isBinaryRequested(outputSelection);
|
return std::move(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSettings _inputsAndSettings)
|
||||||
|
{
|
||||||
|
CompilerStack compilerStack(m_readFile);
|
||||||
|
|
||||||
|
StringMap sourceList = std::move(_inputsAndSettings.sources);
|
||||||
|
for (auto const& source: sourceList)
|
||||||
|
compilerStack.addSource(source.first, source.second);
|
||||||
|
for (auto const& smtLib2Response: _inputsAndSettings.smtLib2Responses)
|
||||||
|
compilerStack.addSMTLib2Response(smtLib2Response.first, smtLib2Response.second);
|
||||||
|
compilerStack.setEVMVersion(_inputsAndSettings.evmVersion);
|
||||||
|
compilerStack.setRemappings(_inputsAndSettings.remappings);
|
||||||
|
compilerStack.setOptimiserSettings(std::move(_inputsAndSettings.optimiserSettings));
|
||||||
|
compilerStack.setLibraries(_inputsAndSettings.libraries);
|
||||||
|
compilerStack.useMetadataLiteralSources(_inputsAndSettings.metadataLiteralSources);
|
||||||
|
compilerStack.setRequestedContractNames(requestedContractNames(_inputsAndSettings.outputSelection));
|
||||||
|
|
||||||
|
Json::Value errors = std::move(_inputsAndSettings.errors);
|
||||||
|
|
||||||
|
bool const binariesRequested = isBinaryRequested(_inputsAndSettings.outputSelection);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (binariesRequested)
|
if (binariesRequested)
|
||||||
m_compilerStack.compile();
|
compilerStack.compile();
|
||||||
else
|
else
|
||||||
m_compilerStack.parseAndAnalyze();
|
compilerStack.parseAndAnalyze();
|
||||||
|
|
||||||
for (auto const& error: m_compilerStack.errors())
|
for (auto const& error: compilerStack.errors())
|
||||||
{
|
{
|
||||||
Error const& err = dynamic_cast<Error const&>(*error);
|
Error const& err = dynamic_cast<Error const&>(*error);
|
||||||
|
|
||||||
@ -735,8 +747,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const analysisSuccess = m_compilerStack.state() >= CompilerStack::State::AnalysisSuccessful;
|
bool const analysisSuccess = compilerStack.state() >= CompilerStack::State::AnalysisSuccessful;
|
||||||
bool const compilationSuccess = m_compilerStack.state() == CompilerStack::State::CompilationSuccessful;
|
bool const compilationSuccess = compilerStack.state() == CompilerStack::State::CompilationSuccessful;
|
||||||
|
|
||||||
/// Inconsistent state - stop here to receive error reports from users
|
/// Inconsistent state - stop here to receive error reports from users
|
||||||
if (((binariesRequested && !compilationSuccess) || !analysisSuccess) && errors.empty())
|
if (((binariesRequested && !compilationSuccess) || !analysisSuccess) && errors.empty())
|
||||||
@ -745,27 +757,27 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
Json::Value output = Json::objectValue;
|
Json::Value output = Json::objectValue;
|
||||||
|
|
||||||
if (errors.size() > 0)
|
if (errors.size() > 0)
|
||||||
output["errors"] = errors;
|
output["errors"] = std::move(errors);
|
||||||
|
|
||||||
if (!m_compilerStack.unhandledSMTLib2Queries().empty())
|
if (!compilerStack.unhandledSMTLib2Queries().empty())
|
||||||
for (string const& query: m_compilerStack.unhandledSMTLib2Queries())
|
for (string const& query: compilerStack.unhandledSMTLib2Queries())
|
||||||
output["auxiliaryInputRequested"]["smtlib2queries"]["0x" + keccak256(query).hex()] = query;
|
output["auxiliaryInputRequested"]["smtlib2queries"]["0x" + keccak256(query).hex()] = query;
|
||||||
|
|
||||||
output["sources"] = Json::objectValue;
|
output["sources"] = Json::objectValue;
|
||||||
unsigned sourceIndex = 0;
|
unsigned sourceIndex = 0;
|
||||||
for (string const& sourceName: analysisSuccess ? m_compilerStack.sourceNames() : vector<string>())
|
for (string const& sourceName: analysisSuccess ? compilerStack.sourceNames() : vector<string>())
|
||||||
{
|
{
|
||||||
Json::Value sourceResult = Json::objectValue;
|
Json::Value sourceResult = Json::objectValue;
|
||||||
sourceResult["id"] = sourceIndex++;
|
sourceResult["id"] = sourceIndex++;
|
||||||
if (isArtifactRequested(outputSelection, sourceName, "", "ast"))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "ast"))
|
||||||
sourceResult["ast"] = ASTJsonConverter(false, m_compilerStack.sourceIndices()).toJson(m_compilerStack.ast(sourceName));
|
sourceResult["ast"] = ASTJsonConverter(false, compilerStack.sourceIndices()).toJson(compilerStack.ast(sourceName));
|
||||||
if (isArtifactRequested(outputSelection, sourceName, "", "legacyAST"))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, "", "legacyAST"))
|
||||||
sourceResult["legacyAST"] = ASTJsonConverter(true, m_compilerStack.sourceIndices()).toJson(m_compilerStack.ast(sourceName));
|
sourceResult["legacyAST"] = ASTJsonConverter(true, compilerStack.sourceIndices()).toJson(compilerStack.ast(sourceName));
|
||||||
output["sources"][sourceName] = sourceResult;
|
output["sources"][sourceName] = sourceResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value contractsOutput = Json::objectValue;
|
Json::Value contractsOutput = Json::objectValue;
|
||||||
for (string const& contractName: analysisSuccess ? m_compilerStack.contractNames() : vector<string>())
|
for (string const& contractName: analysisSuccess ? compilerStack.contractNames() : vector<string>())
|
||||||
{
|
{
|
||||||
size_t colon = contractName.rfind(':');
|
size_t colon = contractName.rfind(':');
|
||||||
solAssert(colon != string::npos, "");
|
solAssert(colon != string::npos, "");
|
||||||
@ -774,47 +786,47 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
|
|||||||
|
|
||||||
// ABI, documentation and metadata
|
// ABI, documentation and metadata
|
||||||
Json::Value contractData(Json::objectValue);
|
Json::Value contractData(Json::objectValue);
|
||||||
if (isArtifactRequested(outputSelection, file, name, "abi"))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "abi"))
|
||||||
contractData["abi"] = m_compilerStack.contractABI(contractName);
|
contractData["abi"] = compilerStack.contractABI(contractName);
|
||||||
if (isArtifactRequested(outputSelection, file, name, "metadata"))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "metadata"))
|
||||||
contractData["metadata"] = m_compilerStack.metadata(contractName);
|
contractData["metadata"] = compilerStack.metadata(contractName);
|
||||||
if (isArtifactRequested(outputSelection, file, name, "userdoc"))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "userdoc"))
|
||||||
contractData["userdoc"] = m_compilerStack.natspecUser(contractName);
|
contractData["userdoc"] = compilerStack.natspecUser(contractName);
|
||||||
if (isArtifactRequested(outputSelection, file, name, "devdoc"))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "devdoc"))
|
||||||
contractData["devdoc"] = m_compilerStack.natspecDev(contractName);
|
contractData["devdoc"] = compilerStack.natspecDev(contractName);
|
||||||
|
|
||||||
// EVM
|
// EVM
|
||||||
Json::Value evmData(Json::objectValue);
|
Json::Value evmData(Json::objectValue);
|
||||||
// @TODO: add ir
|
// @TODO: add ir
|
||||||
if (compilationSuccess && isArtifactRequested(outputSelection, file, name, "evm.assembly"))
|
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.assembly"))
|
||||||
evmData["assembly"] = m_compilerStack.assemblyString(contractName, createSourceList(_input));
|
evmData["assembly"] = compilerStack.assemblyString(contractName, sourceList);
|
||||||
if (compilationSuccess && isArtifactRequested(outputSelection, file, name, "evm.legacyAssembly"))
|
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.legacyAssembly"))
|
||||||
evmData["legacyAssembly"] = m_compilerStack.assemblyJSON(contractName, createSourceList(_input));
|
evmData["legacyAssembly"] = compilerStack.assemblyJSON(contractName, sourceList);
|
||||||
if (isArtifactRequested(outputSelection, file, name, "evm.methodIdentifiers"))
|
if (isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.methodIdentifiers"))
|
||||||
evmData["methodIdentifiers"] = m_compilerStack.methodIdentifiers(contractName);
|
evmData["methodIdentifiers"] = compilerStack.methodIdentifiers(contractName);
|
||||||
if (compilationSuccess && isArtifactRequested(outputSelection, file, name, "evm.gasEstimates"))
|
if (compilationSuccess && isArtifactRequested(_inputsAndSettings.outputSelection, file, name, "evm.gasEstimates"))
|
||||||
evmData["gasEstimates"] = m_compilerStack.gasEstimates(contractName);
|
evmData["gasEstimates"] = compilerStack.gasEstimates(contractName);
|
||||||
|
|
||||||
if (compilationSuccess && isArtifactRequested(
|
if (compilationSuccess && isArtifactRequested(
|
||||||
outputSelection,
|
_inputsAndSettings.outputSelection,
|
||||||
file,
|
file,
|
||||||
name,
|
name,
|
||||||
{ "evm.bytecode", "evm.bytecode.object", "evm.bytecode.opcodes", "evm.bytecode.sourceMap", "evm.bytecode.linkReferences" }
|
{ "evm.bytecode", "evm.bytecode.object", "evm.bytecode.opcodes", "evm.bytecode.sourceMap", "evm.bytecode.linkReferences" }
|
||||||
))
|
))
|
||||||
evmData["bytecode"] = collectEVMObject(
|
evmData["bytecode"] = collectEVMObject(
|
||||||
m_compilerStack.object(contractName),
|
compilerStack.object(contractName),
|
||||||
m_compilerStack.sourceMapping(contractName)
|
compilerStack.sourceMapping(contractName)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (compilationSuccess && isArtifactRequested(
|
if (compilationSuccess && isArtifactRequested(
|
||||||
outputSelection,
|
_inputsAndSettings.outputSelection,
|
||||||
file,
|
file,
|
||||||
name,
|
name,
|
||||||
{ "evm.deployedBytecode", "evm.deployedBytecode.object", "evm.deployedBytecode.opcodes", "evm.deployedBytecode.sourceMap", "evm.deployedBytecode.linkReferences" }
|
{ "evm.deployedBytecode", "evm.deployedBytecode.object", "evm.deployedBytecode.opcodes", "evm.deployedBytecode.sourceMap", "evm.deployedBytecode.linkReferences" }
|
||||||
))
|
))
|
||||||
evmData["deployedBytecode"] = collectEVMObject(
|
evmData["deployedBytecode"] = collectEVMObject(
|
||||||
m_compilerStack.runtimeObject(contractName),
|
compilerStack.runtimeObject(contractName),
|
||||||
m_compilerStack.runtimeSourceMapping(contractName)
|
compilerStack.runtimeSourceMapping(contractName)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!evmData.empty())
|
if (!evmData.empty())
|
||||||
@ -837,7 +849,11 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return compileInternal(_input);
|
auto parsed = parseInput(_input);
|
||||||
|
if (parsed.type() == typeid(InputsAndSettings))
|
||||||
|
return compileSolidity(boost::get<InputsAndSettings>(std::move(parsed)));
|
||||||
|
else
|
||||||
|
return boost::get<Json::Value>(std::move(parsed));
|
||||||
}
|
}
|
||||||
catch (Json::LogicError const& _exception)
|
catch (Json::LogicError const& _exception)
|
||||||
{
|
{
|
||||||
@ -849,11 +865,11 @@ Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept
|
|||||||
}
|
}
|
||||||
catch (Exception const& _exception)
|
catch (Exception const& _exception)
|
||||||
{
|
{
|
||||||
return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compileInternal: " + boost::diagnostic_information(_exception));
|
return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compile: " + boost::diagnostic_information(_exception));
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compileInternal");
|
return formatFatalError("InternalCompilerError", "Internal exception in StandardCompiler::compile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <libsolidity/interface/CompilerStack.h>
|
#include <libsolidity/interface/CompilerStack.h>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
@ -42,8 +43,8 @@ public:
|
|||||||
/// Creates a new StandardCompiler.
|
/// Creates a new StandardCompiler.
|
||||||
/// @param _readFile callback to used to read files for import statements. Must return
|
/// @param _readFile callback to used to read files for import statements. Must return
|
||||||
/// and must not emit exceptions.
|
/// and must not emit exceptions.
|
||||||
explicit StandardCompiler(ReadCallback::Callback const& _readFile = ReadCallback::Callback())
|
explicit StandardCompiler(ReadCallback::Callback const& _readFile = ReadCallback::Callback()):
|
||||||
: m_compilerStack(_readFile), m_readFile(_readFile)
|
m_readFile(_readFile)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,13 +56,25 @@ public:
|
|||||||
std::string compile(std::string const& _input) noexcept;
|
std::string compile(std::string const& _input) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Validaes and applies the optimizer settings.
|
struct InputsAndSettings
|
||||||
/// On error returns the json-formatted error message.
|
{
|
||||||
boost::optional<Json::Value> parseOptimizerSettings(Json::Value const& _settings);
|
Json::Value errors;
|
||||||
|
std::map<std::string, std::string> sources;
|
||||||
|
std::map<h256, std::string> smtLib2Responses;
|
||||||
|
langutil::EVMVersion evmVersion;
|
||||||
|
std::vector<CompilerStack::Remapping> remappings;
|
||||||
|
OptimiserSettings optimiserSettings = OptimiserSettings::minimal();
|
||||||
|
std::map<std::string, h160> libraries;
|
||||||
|
bool metadataLiteralSources = false;
|
||||||
|
Json::Value outputSelection;
|
||||||
|
};
|
||||||
|
|
||||||
Json::Value compileInternal(Json::Value const& _input);
|
/// Parses the input json (and potentially invokes the read callback) and either returns
|
||||||
|
/// it in condensed form or an error as a json object.
|
||||||
|
boost::variant<InputsAndSettings, Json::Value> parseInput(Json::Value const& _input);
|
||||||
|
|
||||||
|
Json::Value compileSolidity(InputsAndSettings _inputsAndSettings);
|
||||||
|
|
||||||
CompilerStack m_compilerStack;
|
|
||||||
ReadCallback::Callback m_readFile;
|
ReadCallback::Callback m_readFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user