/* 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 . */ /** * @author Christian * @date 2014 * Full-stack compiler that converts a source code string to bytecode. */ #include #include #include #include #include #include #include using namespace std; namespace dev { namespace solidity { void CompilerStack::setSource(string const& _sourceCode) { reset(); m_scanner = make_shared(CharStream(_sourceCode)); } void CompilerStack::parse() { if (!m_scanner) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available.")); m_contractASTNode = Parser().parse(m_scanner); m_globalContext = make_shared(); m_globalContext->setCurrentContract(*m_contractASTNode); NameAndTypeResolver(m_globalContext->getDeclarations()).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(); m_compiler->compileContract(*m_contractASTNode, m_globalContext->getMagicVariables()); 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 exportedFunctions = m_contractASTNode->getInterfaceFunctions(); unsigned functionsCount = exportedFunctions.size(); for (FunctionDefinition const* f: exportedFunctions) { auto streamVariables = [&](vector> const& _vars) { unsigned varCount = _vars.size(); for (ASTPointer 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); } } }