string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback _readCallback) { Json::Value output(Json::objectValue); Json::Value errors(Json::arrayValue); CompilerStack::ReadFileCallback readCallback; if (_readCallback) { readCallback = [=](string const& _path) { char* contents_c = nullptr; char* error_c = nullptr; _readCallback(_path.c_str(), &contents_c, &error_c); CompilerStack::ReadFileResult result; result.success = true; if (!contents_c && !error_c) { result.success = false; result.contentsOrErrorMesage = "File not found."; } if (contents_c) { result.success = true; result.contentsOrErrorMesage = string(contents_c); free(contents_c); } if (error_c) { result.success = false; result.contentsOrErrorMesage = string(error_c); free(error_c); } return result; }; } CompilerStack compiler(readCallback); auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return compiler.scanner(_sourceName); }; bool success = false; try { compiler.addSources(_sources); bool succ = compiler.compile(_optimize); for (auto const& error: compiler.errors()) { auto err = dynamic_pointer_cast<Error const>(error); errors.append(formatError( *error, (err->type() == Error::Type::Warning) ? "Warning" : "Error", scannerFromSourceName )); } success = succ; // keep success false on exception } catch (Error const& error) { errors.append(formatError(error, error.typeName(), scannerFromSourceName)); } catch (CompilerError const& exception) { errors.append(formatError(exception, "Compiler error", scannerFromSourceName)); } catch (InternalCompilerError const& exception) { errors.append(formatError(exception, "Internal compiler error", scannerFromSourceName)); } catch (Exception const& exception) { errors.append("Exception during compilation: " + boost::diagnostic_information(exception)); } catch (...) { errors.append("Unknown exception during compilation."); } if (errors.size() > 0) output["errors"] = errors; if (success) { try { output["contracts"] = Json::Value(Json::objectValue); for (string const& contractName: compiler.contractNames()) { Json::Value contractData(Json::objectValue); contractData["interface"] = compiler.interface(contractName); contractData["bytecode"] = compiler.object(contractName).toHex(); contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex(); contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode); contractData["functionHashes"] = functionHashes(compiler.contractDefinition(contractName)); contractData["gasEstimates"] = estimateGas(compiler, contractName); auto sourceMap = compiler.sourceMapping(contractName); contractData["srcmap"] = sourceMap ? *sourceMap : ""; auto runtimeSourceMap = compiler.runtimeSourceMapping(contractName); contractData["srcmapRuntime"] = runtimeSourceMap ? *runtimeSourceMap : ""; ostringstream unused; contractData["assembly"] = compiler.streamAssembly(unused, contractName, _sources, true); output["contracts"][contractName] = contractData; } } catch (...) { output["errors"].append("Unknown exception while generating contract data output."); } try { // Do not taint the internal error list ErrorList formalErrors; if (compiler.prepareFormalAnalysis(&formalErrors)) output["formal"]["why3"] = compiler.formalTranslation(); if (!formalErrors.empty()) { Json::Value errors(Json::arrayValue); for (auto const& error: formalErrors) errors.append(formatError( *error, (error->type() == Error::Type::Warning) ? "Warning" : "Error", scannerFromSourceName )); output["formal"]["errors"] = errors; } } catch (...) { output["errors"].append("Unknown exception while generating formal method output."); } try { // Indices into this array are used to abbreviate source names in source locations. output["sourceList"] = Json::Value(Json::arrayValue); for (auto const& source: compiler.sourceNames()) output["sourceList"].append(source); output["sources"] = Json::Value(Json::objectValue); for (auto const& source: compiler.sourceNames()) output["sources"][source]["AST"] = ASTJsonConverter(compiler.ast(source), compiler.sourceIndices()).json(); } catch (...) { output["errors"].append("Unknown exception while generating source name output."); } } try { return Json::FastWriter().write(output); } catch (...) { return "{\"errors\":[\"Unknown error while generating JSON.\"]}"; } }