diff options
author | Lefteris Karapetsas <lefteris@refu.co> | 2015-01-29 23:39:30 +0800 |
---|---|---|
committer | Lefteris Karapetsas <lefteris@refu.co> | 2015-01-30 00:11:13 +0800 |
commit | 005100c4867f133e86a2675be0dd9370fed3e191 (patch) | |
tree | d41b83ef3066a24b94a152b9e7866db5f35eff2a | |
parent | 77384af827d7d941620552c4f5f740c3b7c576ef (diff) | |
download | dexon-solidity-005100c4867f133e86a2675be0dd9370fed3e191.tar.gz dexon-solidity-005100c4867f133e86a2675be0dd9370fed3e191.tar.zst dexon-solidity-005100c4867f133e86a2675be0dd9370fed3e191.zip |
Contract Interface Functions now return FunctionType
- Enchanced Function Type by declaration so that it can provide all the
required information at each place interface functions are consumed
- Changed all places where interface functions was used.
- Simplified Mix's FunctionDefinition code
-rw-r--r-- | AST.cpp | 21 | ||||
-rwxr-xr-x | AST.h | 6 | ||||
-rw-r--r-- | Compiler.cpp | 6 | ||||
-rw-r--r-- | InterfaceHandler.cpp | 44 | ||||
-rw-r--r-- | Types.cpp | 46 | ||||
-rw-r--r-- | Types.h | 15 |
6 files changed, 98 insertions, 40 deletions
@@ -66,24 +66,25 @@ void ContractDefinition::checkTypeRequirements() // check for hash collisions in function signatures set<FixedHash<4>> hashes; - for (auto const& hashAndFunction: getInterfaceFunctionList()) + for (auto const& it: getInterfaceFunctionList()) { - FixedHash<4> const& hash = std::get<0>(hashAndFunction); + FixedHash<4> const& hash = it.first; if (hashes.count(hash)) BOOST_THROW_EXCEPTION(createTypeError( std::string("Function signature hash collision for ") + - std::get<1>(hashAndFunction)->getCanonicalSignature(std::get<2>(hashAndFunction)->getName()))); + it.second->getCanonicalSignature())); hashes.insert(hash); } } -map<FixedHash<4>, FunctionDescription> ContractDefinition::getInterfaceFunctions() const +map<FixedHash<4>, std::shared_ptr<FunctionType const>> ContractDefinition::getInterfaceFunctions() const { auto exportedFunctionList = getInterfaceFunctionList(); - map<FixedHash<4>, FunctionDescription> exportedFunctions; + map<FixedHash<4>, std::shared_ptr<FunctionType const>> exportedFunctions; for (auto const& it: exportedFunctionList) - exportedFunctions.insert(make_pair(std::get<0>(it), FunctionDescription(std::get<1>(it), std::get<2>(it)))); + // exportedFunctions.insert(make_pair(std::get<0>(it), FunctionDescription(std::get<1>(it), std::get<2>(it)))); + exportedFunctions.insert(it); solAssert(exportedFunctionList.size() == exportedFunctions.size(), "Hash collision at Function Definition Hash calculation"); @@ -138,12 +139,12 @@ void ContractDefinition::checkIllegalOverrides() const } } -vector<tuple<FixedHash<4>, std::shared_ptr<FunctionType const>, Declaration const*>> const& ContractDefinition::getInterfaceFunctionList() const +vector<pair<FixedHash<4>, shared_ptr<FunctionType const>>> const& ContractDefinition::getInterfaceFunctionList() const { if (!m_interfaceFunctionList) { set<string> functionsSeen; - m_interfaceFunctionList.reset(new vector<tuple<FixedHash<4>, std::shared_ptr<FunctionType const>, Declaration const*>>()); + m_interfaceFunctionList.reset(new vector<pair<FixedHash<4>, shared_ptr<FunctionType const>>>()); for (ContractDefinition const* contract: getLinearizedBaseContracts()) { for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions()) @@ -151,7 +152,7 @@ vector<tuple<FixedHash<4>, std::shared_ptr<FunctionType const>, Declaration cons { functionsSeen.insert(f->getName()); FixedHash<4> hash(dev::sha3(f->getCanonicalSignature())); - m_interfaceFunctionList->push_back(make_tuple(hash, make_shared<FunctionType>(*f, false), f.get())); + m_interfaceFunctionList->push_back(make_pair(hash, make_shared<FunctionType>(*f, false))); } for (ASTPointer<VariableDeclaration> const& v: contract->getStateVariables()) @@ -160,7 +161,7 @@ vector<tuple<FixedHash<4>, std::shared_ptr<FunctionType const>, Declaration cons FunctionType ftype(*v); functionsSeen.insert(v->getName()); FixedHash<4> hash(dev::sha3(ftype.getCanonicalSignature(v->getName()))); - m_interfaceFunctionList->push_back(make_tuple(hash, make_shared<FunctionType>(*v), v.get())); + m_interfaceFunctionList->push_back(make_pair(hash, make_shared<FunctionType>(*v))); } } } @@ -294,7 +294,7 @@ public: /// @returns a map of canonical function signatures to FunctionDefinitions /// as intended for use by the ABI. - std::map<FixedHash<4>, FunctionDescription> getInterfaceFunctions() const; + std::map<FixedHash<4>, std::shared_ptr<FunctionType const>> getInterfaceFunctions() const; /// List of all (direct and indirect) base contracts in order from derived to base, including /// the contract itself. Available after name resolution @@ -307,7 +307,7 @@ public: private: void checkIllegalOverrides() const; - std::vector<std::tuple<FixedHash<4>, std::shared_ptr<FunctionType const>, Declaration const*>> const& getInterfaceFunctionList() const; + std::vector<std::pair<FixedHash<4>, std::shared_ptr<FunctionType const>>> const& getInterfaceFunctionList() const; std::vector<ASTPointer<InheritanceSpecifier>> m_baseContracts; std::vector<ASTPointer<StructDefinition>> m_definedStructs; @@ -316,7 +316,7 @@ private: std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers; std::vector<ContractDefinition const*> m_linearizedBaseContracts; - mutable std::unique_ptr<std::vector<std::tuple<FixedHash<4>, std::shared_ptr<FunctionType const>, Declaration const*>>> m_interfaceFunctionList; + mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, std::shared_ptr<FunctionType const>>>> m_interfaceFunctionList; }; class InheritanceSpecifier: public ASTNode diff --git a/Compiler.cpp b/Compiler.cpp index 93784adf..33a71bca 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -142,7 +142,7 @@ void Compiler::appendConstructorCall(FunctionDefinition const& _constructor) void Compiler::appendFunctionSelector(ContractDefinition const& _contract) { - map<FixedHash<4>, FunctionDescription> interfaceFunctions = _contract.getInterfaceFunctions(); + map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.getInterfaceFunctions(); map<FixedHash<4>, const eth::AssemblyItem> callDataUnpackerEntryPoints; // retrieve the function signature hash from the calldata @@ -160,11 +160,11 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) for (auto const& it: interfaceFunctions) { - FunctionType const* functionType = it.second.getFunctionType(); + FunctionTypePointer functionType = it.second; m_context << callDataUnpackerEntryPoints.at(it.first); eth::AssemblyItem returnTag = m_context.pushNewTag(); appendCalldataUnpacker(functionType->getParameterTypes()); - m_context.appendJumpTo(m_context.getFunctionEntryLabel(*it.second.getDeclaration())); + m_context.appendJumpTo(m_context.getFunctionEntryLabel(*it.second->getDeclaration())); m_context << returnTag; appendReturnValuePacker(functionType->getReturnParameterTypes()); } diff --git a/InterfaceHandler.cpp b/InterfaceHandler.cpp index 9b632778..dd569946 100644 --- a/InterfaceHandler.cpp +++ b/InterfaceHandler.cpp @@ -45,23 +45,27 @@ std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinitio Json::Value inputs(Json::arrayValue); Json::Value outputs(Json::arrayValue); - auto populateParameters = [](vector<ParamDescription> const& _params) + auto populateParameters = [](vector<string> const& _paramNames, + vector<string> const& _paramTypes) { Json::Value params(Json::arrayValue); - for (auto const& param: _params) + solAssert(_paramNames.size() == _paramTypes.size(), "Names and types vector size does not match"); + for (unsigned i = 0; i < _paramNames.size(); ++i) { Json::Value input; - input["name"] = param.getName(); - input["type"] = param.getType(); + input["name"] = _paramNames[i]; + input["type"] = _paramTypes[i]; params.append(input); } return params; }; - method["name"] = it.second.getName(); - method["constant"] = it.second.isConstant(); - method["inputs"] = populateParameters(it.second.getParameters()); - method["outputs"] = populateParameters(it.second.getReturnParameters()); + method["name"] = it.second->getDeclaration()->getName(); + method["constant"] = it.second->isConstant(); + method["inputs"] = populateParameters(it.second->getParameterNames(), + it.second->getParameterTypeNames()); + method["outputs"] = populateParameters(it.second->getReturnParameterNames(), + it.second->getReturnParameterTypeNames()); methods.append(method); } return std::unique_ptr<std::string>(new std::string(m_writer.write(methods))); @@ -72,16 +76,20 @@ unique_ptr<string> InterfaceHandler::getABISolidityInterface(ContractDefinition string ret = "contract " + _contractDef.getName() + "{"; for (auto const& it: _contractDef.getInterfaceFunctions()) { - auto populateParameters = [](vector<ParamDescription> const& _params) + auto populateParameters = [](vector<string> const& _paramNames, + vector<string> const& _paramTypes) { string r = ""; - for (auto const& param: _params) - r += (r.size() ? "," : "(") + param.getType() + " " + param.getName(); + solAssert(_paramNames.size() == _paramTypes.size(), "Names and types vector size does not match"); + for (unsigned i = 0; i < _paramNames.size(); ++i) + r += (r.size() ? "," : "(") + _paramTypes[i] + " " + _paramNames[i]; return r.size() ? r + ")" : "()"; }; - ret += "function " + it.second.getName() + populateParameters(it.second.getParameters()) + (it.second.isConstant() ? "constant " : ""); - if (it.second.getReturnParameters().size()) - ret += "returns" + populateParameters(it.second.getReturnParameters()); + ret += "function " + it.second->getDeclaration()->getName() + + populateParameters(it.second->getParameterNames(), it.second->getParameterTypeNames()) + + (it.second->isConstant() ? "constant " : ""); + if (it.second->getReturnParameterTypes().size()) + ret += "returns" + populateParameters(it.second->getReturnParameterNames(), it.second->getReturnParameterTypeNames()); else if (ret.back() == ' ') ret.pop_back(); ret += "{}"; @@ -97,7 +105,7 @@ std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(ContractDefi for (auto const& it: _contractDef.getInterfaceFunctions()) { Json::Value user; - auto strPtr = it.second.getDocumentation(); + auto strPtr = it.second->getDocumentation(); if (strPtr) { resetUser(); @@ -105,7 +113,7 @@ std::unique_ptr<std::string> InterfaceHandler::getUserDocumentation(ContractDefi if (!m_notice.empty()) {// since @notice is the only user tag if missing function should not appear user["notice"] = Json::Value(m_notice); - methods[it.second.getSignature()] = user; + methods[it.second->getCanonicalSignature()] = user; } } } @@ -138,7 +146,7 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(ContractDefin for (auto const& it: _contractDef.getInterfaceFunctions()) { Json::Value method; - auto strPtr = it.second.getDocumentation(); + auto strPtr = it.second->getDocumentation(); if (strPtr) { resetDev(); @@ -161,7 +169,7 @@ std::unique_ptr<std::string> InterfaceHandler::getDevDocumentation(ContractDefin method["return"] = m_return; if (!method.empty()) // add the function, only if we have any documentation to add - methods[it.second.getSignature()] = method; + methods[it.second->getCanonicalSignature()] = method; } } doc["methods"] = methods; @@ -499,7 +499,7 @@ MemberList const& ContractType::getMembers() const } else for (auto const& it: m_contract.getInterfaceFunctions()) - members[it.second.getName()] = it.second.getFunctionTypeShared(); + members[it.second->getDeclaration()->getName()] = it.second; m_members.reset(new MemberList(members)); } return *m_members; @@ -522,7 +522,7 @@ u256 ContractType::getFunctionIdentifier(string const& _functionName) const { auto interfaceFunctions = m_contract.getInterfaceFunctions(); for (auto const& it: m_contract.getInterfaceFunctions()) - if (it.second.getName() == _functionName) + if (it.second->getDeclaration()->getName() == _functionName) return FixedHash<4>::Arith(it.first); return Invalid256; @@ -589,12 +589,15 @@ u256 StructType::getStorageOffsetOfMember(string const& _name) const } FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal): - m_location(_isInternal ? Location::INTERNAL : Location::EXTERNAL) + m_location(_isInternal ? Location::INTERNAL : Location::EXTERNAL), + m_isConstant(_function.isDeclaredConst()), + m_declaration(&_function) { TypePointers params; vector<string> paramNames; TypePointers retParams; vector<string> retParamNames; + params.reserve(_function.getParameters().size()); paramNames.reserve(_function.getParameters().size()); for (ASTPointer<VariableDeclaration> const& var: _function.getParameters()) @@ -616,7 +619,7 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal } FunctionType::FunctionType(VariableDeclaration const& _varDecl): - m_location(Location::EXTERNAL) + m_location(Location::EXTERNAL), m_isConstant(true), m_declaration(&_varDecl) { TypePointers params({}); vector<string> paramNames({}); @@ -711,7 +714,13 @@ MemberList const& FunctionType::getMembers() const string FunctionType::getCanonicalSignature(std::string const& _name) const { - string ret = _name + "("; + std::string funcName = _name; + if (_name == "") + { + solAssert(m_declaration != nullptr, "Function type without name needs a declaration"); + funcName = m_declaration->getName(); + } + string ret = funcName + "("; for (auto it = m_parameterTypes.cbegin(); it != m_parameterTypes.cend(); ++it) ret += (*it)->toString() + (it + 1 == m_parameterTypes.cend() ? "" : ","); @@ -734,6 +743,33 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con m_gasSet || _setGas, m_valueSet || _setValue); } +vector<string> const FunctionType::getParameterTypeNames() const +{ + vector<string> names; + for (TypePointer const& t: m_parameterTypes) + names.push_back(t->toString()); + + return names; +} + +vector<string> const FunctionType::getReturnParameterTypeNames() const +{ + vector<string> names; + for (TypePointer const& t: m_returnParameterTypes) + names.push_back(t->toString()); + + return names; +} + +ASTPointer<ASTString> FunctionType::getDocumentation() const +{ + auto function = dynamic_cast<FunctionDefinition const*>(m_declaration); + if (function) + return function->getDocumentation(); + + return ASTPointer<ASTString>(); +} + bool MappingType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) @@ -41,6 +41,7 @@ namespace solidity class Type; // forward class FunctionType; // forward using TypePointer = std::shared_ptr<Type const>; +using FunctionTypePointer = std::shared_ptr<FunctionType const>; using TypePointers = std::vector<TypePointer>; /** @@ -371,8 +372,10 @@ public: TypePointers const& getParameterTypes() const { return m_parameterTypes; } std::vector<std::string> const& getParameterNames() const { return m_parameterNames; } + std::vector<std::string> const getParameterTypeNames() const; TypePointers const& getReturnParameterTypes() const { return m_returnParameterTypes; } std::vector<std::string> const& getReturnParameterNames() const { return m_returnParameterNames; } + std::vector<std::string> const getReturnParameterTypeNames() const; virtual bool operator==(Type const& _other) const override; virtual std::string toString() const override; @@ -383,7 +386,15 @@ public: virtual MemberList const& getMembers() const override; Location const& getLocation() const { return m_location; } - std::string getCanonicalSignature(std::string const& _name) const; + /// @returns the canonical signature of this function type given the function name + /// If @a _name is not provided (empty string) then the @c m_declaration member of the + /// function type is used + std::string getCanonicalSignature(std::string const& _name = "") const; + Declaration const* getDeclaration() const { return m_declaration; } + bool isConstant() const { return m_isConstant; } + /// @return A shared pointer of an ASTString. + /// Can contain a nullptr in which case indicates absence of documentation + ASTPointer<ASTString> getDocumentation() const; bool gasSet() const { return m_gasSet; } bool valueSet() const { return m_valueSet; } @@ -402,7 +413,9 @@ private: Location const m_location; bool const m_gasSet = false; ///< true iff the gas value to be used is on the stack bool const m_valueSet = false; ///< true iff the value to be sent is on the stack + bool m_isConstant; mutable std::unique_ptr<MemberList> m_members; + Declaration const* m_declaration = nullptr; }; /** |