aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/interface/CompilerStack.cpp61
-rw-r--r--libsolidity/interface/CompilerStack.h19
2 files changed, 63 insertions, 17 deletions
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index b09435a8..79855060 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -57,7 +57,7 @@ using namespace dev;
using namespace dev::solidity;
CompilerStack::CompilerStack(ReadFile::Callback const& _readFile):
- m_readFile(_readFile), m_parseSuccessful(false) {}
+ m_readFile(_readFile) {}
void CompilerStack::setRemappings(vector<string> const& _remappings)
{
@@ -79,7 +79,6 @@ void CompilerStack::setRemappings(vector<string> const& _remappings)
void CompilerStack::reset(bool _keepSources)
{
- m_parseSuccessful = false;
if (_keepSources)
for (auto sourcePair: m_sources)
sourcePair.second.reset();
@@ -94,6 +93,7 @@ void CompilerStack::reset(bool _keepSources)
m_sourceOrder.clear();
m_contracts.clear();
m_errors.clear();
+ m_stackState = Empty;
}
bool CompilerStack::addSource(string const& _name, string const& _content, bool _isLibrary)
@@ -102,6 +102,7 @@ bool CompilerStack::addSource(string const& _name, string const& _content, bool
reset(true);
m_sources[_name].scanner = make_shared<Scanner>(CharStream(_content), _name);
m_sources[_name].isLibrary = _isLibrary;
+ m_stackState = SourcesSet;
return existed;
}
@@ -114,9 +115,10 @@ void CompilerStack::setSource(string const& _sourceCode)
bool CompilerStack::parse()
{
//reset
+ if(m_stackState != SourcesSet)
+ return false;
m_errors.clear();
ASTNode::resetID();
- m_parseSuccessful = false;
if (SemVerVersion{string(VersionString)}.isPrerelease())
{
@@ -128,14 +130,12 @@ bool CompilerStack::parse()
vector<string> sourcesToParse;
for (auto const& s: m_sources)
sourcesToParse.push_back(s.first);
- map<string, SourceUnit const*> sourceUnitsByName;
for (size_t i = 0; i < sourcesToParse.size(); ++i)
{
string const& path = sourcesToParse[i];
Source& source = m_sources[path];
source.scanner->reset();
source.ast = Parser(m_errors).parse(source.scanner);
- sourceUnitsByName[path] = source.ast.get();
if (!source.ast)
solAssert(!Error::containsOnlyWarnings(m_errors), "Parser returned null but did not report error.");
else
@@ -150,10 +150,19 @@ bool CompilerStack::parse()
}
}
}
- if (!Error::containsOnlyWarnings(m_errors))
- // errors while parsing. should stop before type checking
+ if (Error::containsOnlyWarnings(m_errors))
+ {
+ m_stackState = ParsingSuccessful;
+ return true;
+ }
+ else
return false;
+}
+bool CompilerStack::analyze()
+{
+ if (m_stackState < ParsingSuccessful)
+ return false;
resolveImports();
bool noErrors = true;
@@ -173,6 +182,9 @@ bool CompilerStack::parse()
if (!resolver.registerDeclarations(*source->ast))
return false;
+ map<string, SourceUnit const*> sourceUnitsByName;
+ for (auto& source: m_sources)
+ sourceUnitsByName[source.first] = source.second.ast.get();
for (Source const* source: m_sourceOrder)
if (!resolver.performImports(*source->ast, sourceUnitsByName))
return false;
@@ -235,8 +247,13 @@ bool CompilerStack::parse()
noErrors = false;
}
- m_parseSuccessful = noErrors;
- return m_parseSuccessful;
+ if (noErrors)
+ {
+ m_stackState = AnalysisSuccessful;
+ return true;
+ }
+ else
+ return false;
}
bool CompilerStack::parse(string const& _sourceCode)
@@ -245,9 +262,20 @@ bool CompilerStack::parse(string const& _sourceCode)
return parse();
}
+bool CompilerStack::parseAndAnalyze()
+{
+ return parse() && analyze();
+}
+
+bool CompilerStack::parseAndAnalyze(std::string const& _sourceCode)
+{
+ setSource(_sourceCode);
+ return parseAndAnalyze();
+}
+
vector<string> CompilerStack::contractNames() const
{
- if (!m_parseSuccessful)
+ if (m_stackState < AnalysisSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
vector<string> contractNames;
for (auto const& contract: m_contracts)
@@ -258,8 +286,8 @@ vector<string> CompilerStack::contractNames() const
bool CompilerStack::compile(bool _optimize, unsigned _runs, map<string, h160> const& _libraries)
{
- if (!m_parseSuccessful)
- if (!parse())
+ if (m_stackState < AnalysisSuccessful)
+ if (!parseAndAnalyze())
return false;
m_optimize = _optimize;
@@ -272,12 +300,13 @@ bool CompilerStack::compile(bool _optimize, unsigned _runs, map<string, h160> co
if (auto contract = dynamic_cast<ContractDefinition const*>(node.get()))
compileContract(*contract, compiledContracts);
this->link();
+ m_stackState = CompilationSuccessful;
return true;
}
bool CompilerStack::compile(string const& _sourceCode, bool _optimize, unsigned _runs)
{
- return parse(_sourceCode) && compile(_optimize, _runs);
+ return parseAndAnalyze(_sourceCode) && compile(_optimize, _runs);
}
void CompilerStack::link()
@@ -419,7 +448,7 @@ Json::Value const& CompilerStack::interface(string const& _contractName) const
Json::Value const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const
{
- if (!m_parseSuccessful)
+ if (m_stackState < AnalysisSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
return metadata(contract(_contractName), _type);
@@ -427,7 +456,7 @@ Json::Value const& CompilerStack::metadata(string const& _contractName, Document
Json::Value const& CompilerStack::metadata(Contract const& _contract, DocumentationType _type) const
{
- if (!m_parseSuccessful)
+ if (m_stackState < AnalysisSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
solAssert(_contract.contract, "");
@@ -458,7 +487,7 @@ Json::Value const& CompilerStack::metadata(Contract const& _contract, Documentat
string const& CompilerStack::onChainMetadata(string const& _contractName) const
{
- if (!m_parseSuccessful)
+ if (m_stackState != CompilationSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
return contract(_contractName).onChainMetadata;
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index d46c99be..c1d344ca 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -103,6 +103,16 @@ public:
/// Sets the given source code as the only source unit apart from standard sources and parses it.
/// @returns false on error.
bool parse(std::string const& _sourceCode);
+ /// performs the analyisis steps (imports, scopesetting, syntaxCheck, referenceResolving,
+ /// typechecking, staticAnalysis) on previously set sources
+ /// @returns false on error.
+ bool analyze();
+ /// Parses and analyzes all source units that were added
+ /// @returns false on error.
+ bool parseAndAnalyze();
+ /// Sets the given source code as the only source unit apart from standard sources and parses and analyzes it.
+ /// @returns false on error.
+ bool parseAndAnalyze(std::string const& _sourceCode);
/// @returns a list of the contract names in the sources.
std::vector<std::string> contractNames() const;
std::string defaultContractName() const;
@@ -226,6 +236,13 @@ private:
mutable std::unique_ptr<std::string const> sourceMapping;
mutable std::unique_ptr<std::string const> runtimeSourceMapping;
};
+ enum State {
+ Empty,
+ SourcesSet,
+ ParsingSuccessful,
+ AnalysisSuccessful,
+ CompilationSuccessful
+ };
/// Loads the missing sources from @a _ast (named @a _path) using the callback
/// @a m_readFile and stores the absolute paths of all imports in the AST annotations.
@@ -266,7 +283,6 @@ private:
/// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum
/// "context:prefix=target"
std::vector<Remapping> m_remappings;
- bool m_parseSuccessful;
std::map<std::string const, Source> m_sources;
std::shared_ptr<GlobalContext> m_globalContext;
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>> m_scopes;
@@ -275,6 +291,7 @@ private:
std::string m_formalTranslation;
ErrorList m_errors;
bool m_metadataLiteralSources = false;
+ State m_stackState = Empty;
};
}