/* This file is part of cpp-ethereum. cpp-ethereum 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. cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> * @date 2014 * Full-stack compiler that converts a source code string to bytecode. */ #include <libsolidity/AST.h> #include <libsolidity/Scanner.h> #include <libsolidity/Parser.h> #include <libsolidity/NameAndTypeResolver.h> #include <libsolidity/Compiler.h> #include <libsolidity/CompilerStack.h> using namespace std; namespace dev { namespace solidity { void CompilerStack::setSource(string const& _sourceCode) { reset(); m_scanner = make_shared<Scanner>(CharStream(_sourceCode)); } void CompilerStack::parse() { if (!m_scanner) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available.")); m_contractASTNode = Parser().parse(m_scanner); NameAndTypeResolver().resolveNamesAndTypes(*m_contractASTNode); m_parseSuccessful = true; } void CompilerStack::parse(string const& _sourceCode) { setSource(_sourceCode); parse(); } bytes const& CompilerStack::compile(bool _optimize) { if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); m_bytecode.clear(); m_compiler = make_shared<Compiler>(); m_compiler->compileContract(*m_contractASTNode); return m_bytecode = m_compiler->getAssembledBytecode(_optimize); } bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize) { parse(_sourceCode); return compile(_optimize); } void CompilerStack::streamAssembly(ostream& _outStream) { if (!m_compiler || m_bytecode.empty()) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); m_compiler->streamAssembly(_outStream); } string const& CompilerStack::getInterface() { if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); if (m_interface.empty()) { stringstream interface; interface << '['; vector<FunctionDefinition const*> exportedFunctions = m_contractASTNode->getInterfaceFunctions(); unsigned functionsCount = exportedFunctions.size(); for (FunctionDefinition const* f: exportedFunctions) { auto streamVariables = [&](vector<ASTPointer<VariableDeclaration>> const& _vars) { unsigned varCount = _vars.size(); for (ASTPointer<VariableDeclaration> const& var: _vars) { interface << "{" << "\"name\":" << escaped(var->getName(), false) << "," << "\"type\":" << escaped(var->getType()->toString(), false) << "}"; if (--varCount > 0) interface << ","; } }; interface << '{' << "\"name\":" << escaped(f->getName(), false) << "," << "\"inputs\":["; streamVariables(f->getParameters()); interface << "]," << "\"outputs\":["; streamVariables(f->getReturnParameters()); interface << "]" << "}"; if (--functionsCount > 0) interface << ","; } interface << ']'; m_interface = interface.str(); } return m_interface; } bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize) { CompilerStack stack; return stack.compile(_sourceCode, _optimize); } } }