/* 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 #include using namespace std; namespace dev { namespace solidity { CompilerStack::CompilerStack():m_interfaceHandler(make_shared()){} 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); } std::string const* CompilerStack::getJsonDocumentation(enum documentationType _type) { if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); auto createOrReturnDoc = [this, _type](std::unique_ptr& _doc) { if(!_doc) { _doc = m_interfaceHandler->getDocumentation(m_contractASTNode, _type); } }; switch (_type) { case NATSPEC_USER: createOrReturnDoc(m_userDocumentation); return m_userDocumentation.get(); case NATSPEC_DEV: createOrReturnDoc(m_devDocumentation); return m_devDocumentation.get(); case ABI_INTERFACE: createOrReturnDoc(m_interface); return m_interface.get(); } BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Internal error")); return nullptr; } bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize) { CompilerStack stack; return stack.compile(_sourceCode, _optimize); } } }