Browse Source

Improved external interface for multi-source and multi-contract compilation.

cl-refactor
Christian 10 years ago
parent
commit
04c8d8bdc0
  1. 2
      alethzero/MainWin.cpp
  2. 7
      libsolidity/BaseTypes.h
  3. 12
      libsolidity/CompilerStack.cpp
  4. 3
      libsolidity/CompilerStack.h
  5. 1
      libsolidity/Exceptions.h
  6. 11
      libsolidity/Parser.cpp
  7. 1
      libsolidity/Parser.h
  8. 10
      libsolidity/Scanner.cpp
  9. 3
      libsolidity/Scanner.h
  10. 41
      libsolidity/SourceReferenceFormatter.cpp
  11. 4
      libsolidity/SourceReferenceFormatter.h
  12. 2
      libweb3jsonrpc/WebThreeStubServer.cpp
  13. 2
      mix/ConstantCompilationModel.cpp
  14. 55
      solc/main.cpp
  15. 1
      test/solidityExpressionCompiler.cpp

2
alethzero/MainWin.cpp

@ -1625,7 +1625,7 @@ void Main::on_data_textChanged()
catch (dev::Exception const& exception)
{
ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler.getScanner());
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
solidity = "<h4>Solidity</h4><pre>" + QString::fromStdString(error.str()).toHtmlEscaped() + "</pre>";
}
catch (...)

7
libsolidity/BaseTypes.h

@ -37,14 +37,13 @@ namespace solidity
*/
struct Location
{
Location(int _start, int _end): start(_start), end(_end) { }
Location(int _start, int _end, std::shared_ptr<std::string const> _sourceName):
start(_start), end(_end), sourceName(_sourceName) { }
Location(): start(-1), end(-1) { }
bool IsValid() const { return !!sourceName && start >= 0 && end >= start; }
std::shared_ptr<std::string> sourceName;
int start;
int end;
std::shared_ptr<std::string const> sourceName;
};
/// Stream output for Location (used e.g. in boost exceptions).

12
libsolidity/CompilerStack.cpp

@ -81,10 +81,20 @@ void CompilerStack::parse(string const& _sourceCode)
parse();
}
void CompilerStack::compile(bool _optimize)
vector<string> CompilerStack::getContractNames()
{
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
vector<string> contractNames;
for (auto const& contract: m_contracts)
contractNames.push_back(contract.first);
return contractNames;
}
void CompilerStack::compile(bool _optimize)
{
if (!m_parseSuccessful)
parse();
for (Source const* source: m_sourceOrder)
for (ASTPointer<ASTNode> const& node: source->ast->getNodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))

3
libsolidity/CompilerStack.h

@ -54,6 +54,9 @@ public:
void parse();
/// Sets the given source code as the only source unit and parses it.
void parse(std::string const& _sourceCode);
/// Returns a list of the contract names in the sources.
std::vector<std::string> getContractNames();
/// Compiles the source units that were prevously added and parsed.
void compile(bool _optimize = false);
/// Parses and compiles the given source code.

1
libsolidity/Exceptions.h

@ -37,7 +37,6 @@ struct DeclarationError: virtual Exception {};
struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {};
typedef boost::error_info<struct tag_sourcePosition, int> errinfo_sourcePosition;
typedef boost::error_info<struct tag_sourceLocation, Location> errinfo_sourceLocation;
}

11
libsolidity/Parser.cpp

@ -39,7 +39,8 @@ namespace solidity
class Parser::ASTNodeFactory
{
public:
ASTNodeFactory(Parser const& _parser): m_parser(_parser), m_location(_parser.getPosition(), -1) {}
ASTNodeFactory(Parser const& _parser):
m_parser(_parser), m_location(_parser.getPosition(), -1, _parser.getSourceName()) {}
void markEndPosition() { m_location.end = m_parser.getEndPosition(); }
void setLocationEmpty() { m_location.end = m_location.start; }
@ -81,6 +82,11 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
return nodeFactory.createNode<SourceUnit>(nodes);
}
std::shared_ptr<const string> const& Parser::getSourceName() const
{
return m_scanner->getSourceName();
}
int Parser::getPosition() const
{
return m_scanner->getCurrentLocation().start;
@ -579,7 +585,8 @@ ASTPointer<ASTString> Parser::getLiteralAndAdvance()
ParserError Parser::createParserError(string const& _description) const
{
return ParserError() << errinfo_sourcePosition(getPosition()) << errinfo_comment(_description);
return ParserError() << errinfo_sourceLocation(Location(getPosition(), getPosition(), getSourceName()))
<< errinfo_comment(_description);
}

1
libsolidity/Parser.h

@ -35,6 +35,7 @@ class Parser
{
public:
ASTPointer<SourceUnit> parse(std::shared_ptr<Scanner> const& _scanner);
std::shared_ptr<std::string const> const& getSourceName() const;
private:
class ASTNodeFactory;

10
libsolidity/Scanner.cpp

@ -143,16 +143,10 @@ private:
}; // end of LiteralScope class
void Scanner::reset(CharStream const& _source, std::string const& _sourceName)
void Scanner::reset(CharStream const& _source, string const& _sourceName)
{
m_source = _source;
shared_ptr<string> sourceName = make_shared<string>(_sourceName);
m_currentToken.location.sourceName = sourceName;
m_nextToken.location.sourceName = sourceName;
m_skippedComment.location.sourceName = sourceName;
m_nextSkippedComment.location.sourceName = sourceName;
m_sourceName = make_shared<string const>(_sourceName);
reset();
}

3
libsolidity/Scanner.h

@ -142,6 +142,8 @@ public:
std::string const& peekLiteral() const { return m_nextToken.literal; }
///@}
std::shared_ptr<std::string const> const& getSourceName() const { return m_sourceName; }
///@{
///@name Error printing helper functions
/// Functions that help pretty-printing parse errors
@ -206,6 +208,7 @@ private:
TokenDesc m_nextToken; // desc for next token (one token look-ahead)
CharStream m_source;
std::shared_ptr<std::string const> m_sourceName;
/// one character look-ahead, equals 0 at end of input
char m_char;

41
libsolidity/SourceReferenceFormatter.cpp

@ -21,6 +21,7 @@
*/
#include <libsolidity/SourceReferenceFormatter.h>
#include <libsolidity/CompilerStack.h>
#include <libsolidity/Scanner.h>
#include <libsolidity/Exceptions.h>
@ -38,7 +39,6 @@ void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
int startLine;
int startColumn;
tie(startLine, startColumn) = _scanner.translatePositionToLineColumn(_location.start);
_stream << "starting at line " << (startLine + 1) << ", column " << (startColumn + 1) << "\n";
int endLine;
int endColumn;
tie(endLine, endColumn) = _scanner.translatePositionToLineColumn(_location.end);
@ -58,37 +58,28 @@ void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
<< "Spanning multiple lines.\n";
}
void SourceReferenceFormatter::printSourcePosition(ostream& _stream,
int _position,
const Scanner& _scanner)
{
int line;
int column;
tie(line, column) = _scanner.translatePositionToLineColumn(_position);
_stream << "at line " << (line + 1) << ", column " << (column + 1) << endl
<< _scanner.getLineAtPosition(_position) << endl
<< string(column, ' ') << "^" << endl;
}
void SourceReferenceFormatter::printExceptionInformation(ostream& _stream,
Exception const& _exception,
string const& _name,
Scanner const& _scanner)
CompilerStack& _compiler)
{
_stream << _name;
if (string const* description = boost::get_error_info<errinfo_comment>(_exception))
_stream << ": " << *description;
Location const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
Scanner const* scanner;
if (int const* position = boost::get_error_info<errinfo_sourcePosition>(_exception))
if (location)
{
_stream << " ";
printSourcePosition(_stream, *position, _scanner);
}
if (Location const* location = boost::get_error_info<errinfo_sourceLocation>(_exception))
{
_stream << " ";
printSourceLocation(_stream, *location, _scanner);
scanner = &_compiler.getScanner(*location->sourceName);
int startLine;
int startColumn;
tie(startLine, startColumn) = scanner->translatePositionToLineColumn(location->start);
_stream << *location->sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": ";
}
_stream << _name;
if (string const* description = boost::get_error_info<errinfo_comment>(_exception))
_stream << ": " << *description << endl;
if (location)
printSourceLocation(_stream, *location, *scanner);
}
}

4
libsolidity/SourceReferenceFormatter.h

@ -34,14 +34,14 @@ namespace solidity
{
class Scanner; // forward
class CompilerStack; // forward
struct SourceReferenceFormatter
{
public:
static void printSourceLocation(std::ostream& _stream, Location const& _location, Scanner const& _scanner);
static void printSourcePosition(std::ostream& _stream, int _position, Scanner const& _scanner);
static void printExceptionInformation(std::ostream& _stream, Exception const& _exception,
std::string const& _name, Scanner const& _scanner);
std::string const& _name, CompilerStack& _compiler);
};
}

2
libweb3jsonrpc/WebThreeStubServer.cpp

@ -510,7 +510,7 @@ std::string WebThreeStubServer::eth_solidity(std::string const& _code)
catch (dev::Exception const& exception)
{
ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler.getScanner());
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler);
cwarn << "Solidity compilation error: " << error.str();
}
catch (...)

2
mix/ConstantCompilationModel.cpp

@ -46,7 +46,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code)
catch (dev::Exception const& _exception)
{
ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", compiler.getScanner());
solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", compiler);
res.success = false;
res.comment = QString::fromStdString(error.str()).toHtmlEscaped();
res.hexCode = "";

55
solc/main.cpp

@ -59,7 +59,7 @@ void version()
int main(int argc, char** argv)
{
string infile;
vector<string> infiles;
bool optimize = false;
for (int i = 1; i < argc; ++i)
{
@ -71,49 +71,52 @@ int main(int argc, char** argv)
else if (arg == "-V" || arg == "--version")
version();
else
infile = argv[i];
infiles.push_back(argv[i]);
}
string sourceCode;
if (infile.empty())
map<string, string> sourceCodes;
if (infiles.empty())
{
string s;
while (!cin.eof())
{
getline(cin, s);
sourceCode.append(s);
sourceCodes["<stdin>"].append(s);
}
}
else
sourceCode = asString(dev::contents(infile));
for (string const& infile: infiles)
sourceCodes[infile] = asString(dev::contents(infile));
CompilerStack compiler;
try
{
compiler.compile(sourceCode, optimize);
for (auto const& sourceCode: sourceCodes)
compiler.addSource(sourceCode.first, sourceCode.second);
compiler.compile(optimize);
}
catch (ParserError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler.getScanner());
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Parser error", compiler);
return -1;
}
catch (DeclarationError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler.getScanner());
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Declaration error", compiler);
return -1;
}
catch (TypeError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler.getScanner());
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Type error", compiler);
return -1;
}
catch (CompilerError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler.getScanner());
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Compiler error", compiler);
return -1;
}
catch (InternalCompilerError const& exception)
{
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler.getScanner());
SourceReferenceFormatter::printExceptionInformation(cerr, exception, "Internal compiler error", compiler);
return -1;
}
catch (Exception const& exception)
@ -127,15 +130,25 @@ int main(int argc, char** argv)
return -1;
}
cout << "Syntax tree for the source unit:" << endl;
ASTPrinter printer(compiler.getAST(), sourceCode);
printer.print(cout);
cout << "EVM assembly:" << endl;
compiler.streamAssembly(cout);
cout << "Opcodes:" << endl;
cout << eth::disassemble(compiler.getBytecode()) << endl;
cout << "Binary: " << toHex(compiler.getBytecode()) << endl;
cout << "Interface specification: " << compiler.getInterface() << endl;
cout << "Syntax trees:" << endl << endl;
for (auto const& sourceCode: sourceCodes)
{
cout << endl << "======= " << sourceCode.first << " =======" << endl;
ASTPrinter printer(compiler.getAST(sourceCode.first), sourceCode.second);
printer.print(cout);
}
vector<string> contracts = compiler.getContractNames();
cout << endl << "Contracts:" << endl;
for (string const& contract: contracts)
{
cout << endl << "======= " << contract << " =======" << endl
<< "EVM assembly:" << endl;
compiler.streamAssembly(cout, contract);
cout << "Opcodes:" << endl
<< eth::disassemble(compiler.getBytecode(contract)) << endl
<< "Binary: " << toHex(compiler.getBytecode(contract)) << endl
<< "Interface specification: " << compiler.getInterface(contract) << endl;
}
return 0;
}

1
test/solidityExpressionCompiler.cpp

@ -113,6 +113,7 @@ bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _
return instructions;
}
BOOST_FAIL("No contract found in source.");
return bytes();
}
} // end anonymous namespace

Loading…
Cancel
Save