diff options
author | chriseth <c@ethdev.com> | 2015-09-11 01:40:07 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-09-11 21:21:37 +0800 |
commit | 976c380b615f71c9e5b59c9b6bcadefbd79c086f (patch) | |
tree | 6ce25599b74529619f4421a9bd3db76eecb80b80 /libsolidity | |
parent | a9edc7b1a601747f96e47fe60a5fc10df489696f (diff) | |
download | dexon-solidity-976c380b615f71c9e5b59c9b6bcadefbd79c086f.tar dexon-solidity-976c380b615f71c9e5b59c9b6bcadefbd79c086f.tar.gz dexon-solidity-976c380b615f71c9e5b59c9b6bcadefbd79c086f.tar.bz2 dexon-solidity-976c380b615f71c9e5b59c9b6bcadefbd79c086f.tar.lz dexon-solidity-976c380b615f71c9e5b59c9b6bcadefbd79c086f.tar.xz dexon-solidity-976c380b615f71c9e5b59c9b6bcadefbd79c086f.tar.zst dexon-solidity-976c380b615f71c9e5b59c9b6bcadefbd79c086f.zip |
Possibility to call library functions.
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/CompilerContext.h | 2 | ||||
-rw-r--r-- | libsolidity/ExpressionCompiler.cpp | 18 | ||||
-rw-r--r-- | libsolidity/Types.cpp | 38 | ||||
-rw-r--r-- | libsolidity/Types.h | 8 |
4 files changed, 48 insertions, 18 deletions
diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 34b63a9c..39f4e75f 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -112,6 +112,8 @@ public: void appendProgramSize() { return m_asm.appendProgramSize(); } /// Adds data to the data section, pushes a reference to the stack eth::AssemblyItem appendData(bytes const& _data) { return m_asm.append(_data); } + /// Appends the address (virtual, will be filled in by linker) of a library. + void appendLibraryAddress(std::string const& _identifier) { m_asm.appendLibraryAddress(_identifier); } /// Resets the stack of visited nodes with a new stack having only @c _node void resetVisitedNodes(ASTNode const* _node); /// Pops the stack of visited nodes diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 9cecf6b6..b22a78dc 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -772,9 +772,15 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) if (dynamic_cast<ContractType const*>(type.actualType().get())) { - auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.referencedDeclaration()); - solAssert(!!function, "Function not found in member access"); - m_context << m_context.functionEntryLabel(*function).pushTag(); + auto const& funType = dynamic_cast<FunctionType const&>(*_memberAccess.type()); + if (funType.location() != FunctionType::Location::Internal) + m_context << funType.externalIdentifier(); + else + { + auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.referencedDeclaration()); + solAssert(!!function, "Function not found in member access"); + m_context << m_context.functionEntryLabel(*function).pushTag(); + } } else if (auto enumType = dynamic_cast<EnumType const*>(type.actualType().get())) m_context << enumType->memberValue(_memberAccess.memberName()); @@ -923,9 +929,11 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) utils().convertType(*variable->value()->type(), *variable->type()); } } - else if (dynamic_cast<ContractDefinition const*>(declaration)) + else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration)) { - // no-op + if (contract->isLibrary()) + //@todo name should be unique, change once we have module management + m_context.appendLibraryAddress(contract->name()); } else if (dynamic_cast<EventDefinition const*>(declaration)) { diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index d1c59ba5..5bc7cd43 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -971,7 +971,7 @@ MemberList const& ContractType::members() const for (auto const& it: m_contract.interfaceFunctions()) members.push_back(MemberList::Member( it.second->declaration().name(), - it.second->asMemberFunction(), + it.second->asMemberFunction(false), &it.second->declaration() )); m_members.reset(new MemberList(members)); @@ -1538,7 +1538,7 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con ); } -FunctionTypePointer FunctionType::asMemberFunction() const +FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary) const { TypePointers parameterTypes; for (auto const& t: m_parameterTypes) @@ -1563,7 +1563,7 @@ FunctionTypePointer FunctionType::asMemberFunction() const returnParameterTypes, m_parameterNames, returnParameterNames, - m_location, + _inLibrary ? Location::CallCode : m_location, m_arbitraryParameters, m_declaration, m_gasSet, @@ -1633,21 +1633,39 @@ u256 TypeType::storageSize() const << errinfo_comment("Storage size of non-storable type type requested.")); } +unsigned TypeType::sizeOnStack() const +{ + if (auto contractType = dynamic_cast<ContractType const*>(m_actualType.get())) + if (contractType->contractDefinition().isLibrary()) + return 1; + return 0; +} + MemberList const& TypeType::members() const { // We need to lazy-initialize it because of recursive references. if (!m_members) { MemberList::MemberMap members; - if (m_actualType->category() == Category::Contract && m_currentContract != nullptr) + if (m_actualType->category() == Category::Contract) { ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_actualType).contractDefinition(); - vector<ContractDefinition const*> currentBases = m_currentContract->linearizedBaseContracts(); - if (find(currentBases.begin(), currentBases.end(), &contract) != currentBases.end()) - // We are accessing the type of a base contract, so add all public and protected - // members. Note that this does not add inherited functions on purpose. - for (Declaration const* decl: contract.inheritableMembers()) - members.push_back(MemberList::Member(decl->name(), decl->type(), decl)); + if (contract.isLibrary()) + for (auto const& it: contract.interfaceFunctions()) + members.push_back(MemberList::Member( + it.second->declaration().name(), + it.second->asMemberFunction(true), // use callcode + &it.second->declaration() + )); + else if (m_currentContract != nullptr) + { + vector<ContractDefinition const*> currentBases = m_currentContract->linearizedBaseContracts(); + if (find(currentBases.begin(), currentBases.end(), &contract) != currentBases.end()) + // We are accessing the type of a base contract, so add all public and protected + // members. Note that this does not add inherited functions on purpose. + for (Declaration const* decl: contract.inheritableMembers()) + members.push_back(MemberList::Member(decl->name(), decl->type(), decl)); + } } else if (m_actualType->category() == Category::Enum) { diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 17ae0ce0..11218b7a 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -517,7 +517,7 @@ private: }; /** - * The type of a contract instance, there is one distinct type for each contract definition. + * The type of a contract instance or library, there is one distinct type for each contract definition. */ class ContractType: public Type { @@ -788,7 +788,8 @@ public: /// removed and the location of reference types is changed from CallData to Memory. /// This is needed if external functions are called on other contracts, as they cannot return /// dynamic values. - FunctionTypePointer asMemberFunction() const; + /// @param _inLibrary if true, uses CallCode as location. + FunctionTypePointer asMemberFunction(bool _inLibrary) const; private: static TypePointers parseElementaryTypeVector(strings const& _types); @@ -851,6 +852,7 @@ public: /** * The type of a type reference. The type of "uint32" when used in "a = uint32(2)" is an example * of a TypeType. + * For super contracts or libraries, this has members directly. */ class TypeType: public Type { @@ -865,7 +867,7 @@ public: virtual bool canBeStored() const override { return false; } virtual u256 storageSize() const override; virtual bool canLiveOutsideStorage() const override { return false; } - virtual unsigned sizeOnStack() const override { return 0; } + virtual unsigned sizeOnStack() const override; virtual std::string toString(bool _short) const override { return "type(" + m_actualType->toString(_short) + ")"; } virtual MemberList const& members() const override; |