diff options
Diffstat (limited to 'libsolidity/interface/CompilerStack.cpp')
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 160 |
1 files changed, 122 insertions, 38 deletions
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index c28e926b..476721db 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -42,26 +42,8 @@ using namespace std; using namespace dev; using namespace dev::solidity; -const map<string, string> StandardSources = map<string, string>{ - {"coin", R"(import "CoinReg";import "Config";import "configUser";contract coin is configUser{function coin(bytes3 name, uint denom) {CoinReg(Config(configAddr()).lookup(3)).register(name, denom);}})"}, - {"Coin", R"(contract Coin{function isApprovedFor(address _target,address _proxy)constant returns(bool _r){}function isApproved(address _proxy)constant returns(bool _r){}function sendCoinFrom(address _from,uint256 _val,address _to){}function coinBalanceOf(address _a)constant returns(uint256 _r){}function sendCoin(uint256 _val,address _to){}function coinBalance()constant returns(uint256 _r){}function approve(address _a){}})"}, - {"CoinReg", R"(contract CoinReg{function count()constant returns(uint256 r){}function info(uint256 i)constant returns(address addr,bytes3 name,uint256 denom){}function register(bytes3 name,uint256 denom){}function unregister(){}})"}, - {"configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xc6d9d2cd449a754c494264e1809c50e34d64562b;}})"}, - {"Config", R"(contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}})"}, - {"mortal", R"(import "owned";contract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }})"}, - {"named", R"(import "Config";import "NameReg";import "configUser";contract named is configUser {function named(bytes32 name) {NameReg(Config(configAddr()).lookup(1)).register(name);}})"}, - {"NameReg", R"(contract NameReg{function register(bytes32 name){}function addressOf(bytes32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(bytes32 name){}})"}, - {"owned", R"(contract owned{function owned(){owner = msg.sender;}modifier onlyowner(){if(msg.sender==owner)_}address owner;})"}, - {"service", R"(import "Config";import "configUser";contract service is configUser{function service(uint _n){Config(configAddr()).register(_n, this);}})"}, - {"std", R"(import "owned";import "mortal";import "Config";import "configUser";import "NameReg";import "named";)"} -}; - -CompilerStack::CompilerStack(bool _addStandardSources, ReadFileCallback const& _readFile): - m_readFile(_readFile), m_parseSuccessful(false) -{ - if (_addStandardSources) - addSources(StandardSources, true); // add them as libraries -} +CompilerStack::CompilerStack(ReadFileCallback const& _readFile): + m_readFile(_readFile), m_parseSuccessful(false) {} void CompilerStack::setRemappings(vector<string> const& _remappings) { @@ -81,7 +63,7 @@ void CompilerStack::setRemappings(vector<string> const& _remappings) swap(m_remappings, remappings); } -void CompilerStack::reset(bool _keepSources, bool _addStandardSources) +void CompilerStack::reset(bool _keepSources) { m_parseSuccessful = false; if (_keepSources) @@ -90,8 +72,6 @@ void CompilerStack::reset(bool _keepSources, bool _addStandardSources) else { m_sources.clear(); - if (_addStandardSources) - addSources(StandardSources, true); } m_globalContext.reset(); m_sourceOrder.clear(); @@ -253,9 +233,11 @@ void CompilerStack::link(const std::map<string, h160>& _libraries) } } -bool CompilerStack::prepareFormalAnalysis() +bool CompilerStack::prepareFormalAnalysis(ErrorList* _errors) { - Why3Translator translator(m_errors); + if (!_errors) + _errors = &m_errors; + Why3Translator translator(*_errors); for (Source const* source: m_sourceOrder) if (!translator.process(*source->ast)) return false; @@ -277,6 +259,28 @@ eth::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _con return currentContract.compiler ? &contract(_contractName).compiler->runtimeAssemblyItems() : nullptr; } +string const* CompilerStack::sourceMapping(string const& _contractName) const +{ + Contract const& c = contract(_contractName); + if (!c.sourceMapping) + { + if (auto items = assemblyItems(_contractName)) + c.sourceMapping.reset(new string(computeSourceMapping(*items))); + } + return c.sourceMapping.get(); +} + +string const* CompilerStack::runtimeSourceMapping(string const& _contractName) const +{ + Contract const& c = contract(_contractName); + if (!c.runtimeSourceMapping) + { + if (auto items = runtimeAssemblyItems(_contractName)) + c.runtimeSourceMapping.reset(new string(computeSourceMapping(*items))); + } + return c.runtimeSourceMapping.get(); +} + eth::LinkerObject const& CompilerStack::object(string const& _contractName) const { return contract(_contractName).object; @@ -298,7 +302,7 @@ dev::h256 CompilerStack::contractCodeHash(string const& _contractName) const if (obj.bytecode.empty() || !obj.linkReferences.empty()) return dev::h256(); else - return dev::sha3(obj.bytecode); + return dev::keccak256(obj.bytecode); } Json::Value CompilerStack::streamAssembly(ostream& _outStream, string const& _contractName, StringMap _sourceCodes, bool _inJsonFormat) const @@ -313,14 +317,25 @@ Json::Value CompilerStack::streamAssembly(ostream& _outStream, string const& _co } } -string const& CompilerStack::interface(string const& _contractName) const +vector<string> CompilerStack::sourceNames() const { - return metadata(_contractName, DocumentationType::ABIInterface); + vector<string> names; + for (auto const& s: m_sources) + names.push_back(s.first); + return names; +} + +map<string, unsigned> CompilerStack::sourceIndices() const +{ + map<string, unsigned> indices; + for (auto const& s: m_sources) + indices[s.first] = indices.size(); + return indices; } -string const& CompilerStack::solidityInterface(string const& _contractName) const +string const& CompilerStack::interface(string const& _contractName) const { - return metadata(_contractName, DocumentationType::ABISolidityInterface); + return metadata(_contractName, DocumentationType::ABIInterface); } string const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const @@ -343,9 +358,6 @@ string const& CompilerStack::metadata(string const& _contractName, Documentation case DocumentationType::ABIInterface: doc = ¤tContract.interface; break; - case DocumentationType::ABISolidityInterface: - doc = ¤tContract.solidityInterface; - break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type.")); } @@ -543,7 +555,7 @@ string CompilerStack::absolutePath(string const& _path, string const& _reference result = result.parent_path(); else if (*it != ".") result /= *it; - return result.string(); + return result.generic_string(); } void CompilerStack::compileContract( @@ -584,10 +596,9 @@ CompilerStack::Contract const& CompilerStack::contract(string const& _contractNa if (_contractName.empty()) // try to find some user-supplied contract for (auto const& it: m_sources) - if (!StandardSources.count(it.first)) - for (ASTPointer<ASTNode> const& node: it.second.ast->nodes()) - if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) - contractName = contract->name(); + for (ASTPointer<ASTNode> const& node: it.second.ast->nodes()) + if (auto contract = dynamic_cast<ContractDefinition const*>(node.get())) + contractName = contract->name(); auto it = m_contracts.find(contractName); if (it == m_contracts.end()) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Contract " + _contractName + " not found.")); @@ -602,3 +613,76 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co return it->second; } + +string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) const +{ + string ret; + map<string, unsigned> sourceIndicesMap = sourceIndices(); + int prevStart = -1; + int prevLength = -1; + int prevSourceIndex = -1; + char prevJump = 0; + for (auto const& item: _items) + { + if (!ret.empty()) + ret += ";"; + + SourceLocation const& location = item.location(); + int length = location.start != -1 && location.end != -1 ? location.end - location.start : -1; + int sourceIndex = + location.sourceName && sourceIndicesMap.count(*location.sourceName) ? + sourceIndicesMap.at(*location.sourceName) : + -1; + char jump = '-'; + if (item.getJumpType() == eth::AssemblyItem::JumpType::IntoFunction) + jump = 'i'; + else if (item.getJumpType() == eth::AssemblyItem::JumpType::OutOfFunction) + jump = 'o'; + + unsigned components = 4; + if (jump == prevJump) + { + components--; + if (sourceIndex == prevSourceIndex) + { + components--; + if (length == prevLength) + { + components--; + if (location.start == prevStart) + components--; + } + } + } + + if (components-- > 0) + { + if (location.start != prevStart) + ret += std::to_string(location.start); + if (components-- > 0) + { + ret += ':'; + if (length != prevLength) + ret += std::to_string(length); + if (components-- > 0) + { + ret += ':'; + if (sourceIndex != prevSourceIndex) + ret += std::to_string(sourceIndex); + if (components-- > 0) + { + ret += ':'; + if (jump != prevJump) + ret += jump; + } + } + } + } + + prevStart = location.start; + prevLength = length; + prevSourceIndex = sourceIndex; + prevJump = jump; + } + return ret; +} |