/* 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 { 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() { Json::StyledWriter writer; if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); if (m_interface.empty()) { Json::Value methods(Json::arrayValue); vector exportedFunctions = m_contractASTNode->getInterfaceFunctions(); for (FunctionDefinition const* f: exportedFunctions) { Json::Value method; Json::Value inputs(Json::arrayValue); Json::Value outputs(Json::arrayValue); auto streamVariables = [&](vector> const& _vars, Json::Value &json) { for (ASTPointer const& var: _vars) { Json::Value input; input["name"] = var->getName(); input["type"] = var->getType()->toString(); json.append(input); } }; method["name"] = f->getName(); streamVariables(f->getParameters(), inputs); method["inputs"] = inputs; streamVariables(f->getReturnParameters(), outputs); method["outputs"] = outputs; methods.append(method); } m_interface = writer.write(methods); } return m_interface; } string const& CompilerStack::getDocumentation() { Json::StyledWriter writer; if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); if (m_documentation.empty()) { Json::Value doc; Json::Value methods(Json::objectValue); for (FunctionDefinition const* f: m_contractASTNode->getInterfaceFunctions()) { Json::Value user; auto strPtr = f->getDocumentation(); if (strPtr) { user["user"] = Json::Value(*strPtr); methods[f->getName()] = user; } } doc["methods"] = methods; m_documentation = writer.write(doc); } return m_documentation; } bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimize) { CompilerStack stack; return stack.compile(_sourceCode, _optimize); } } }