diff options
author | Gav Wood <i@gavwood.com> | 2015-01-30 07:46:19 +0800 |
---|---|---|
committer | Gav Wood <i@gavwood.com> | 2015-01-30 07:46:19 +0800 |
commit | f46df7cb92bba6f30184cc47af3aab8cda672048 (patch) | |
tree | 13f827931b25db3f931aff495faef6d1fc41f547 | |
parent | a604202f33f1f7dc3abda1080e1bc02b2a2cbcb3 (diff) | |
parent | cfb55901cc963523ca1defe232728f195a818228 (diff) | |
download | dexon-solidity-f46df7cb92bba6f30184cc47af3aab8cda672048.tar dexon-solidity-f46df7cb92bba6f30184cc47af3aab8cda672048.tar.gz dexon-solidity-f46df7cb92bba6f30184cc47af3aab8cda672048.tar.bz2 dexon-solidity-f46df7cb92bba6f30184cc47af3aab8cda672048.tar.lz dexon-solidity-f46df7cb92bba6f30184cc47af3aab8cda672048.tar.xz dexon-solidity-f46df7cb92bba6f30184cc47af3aab8cda672048.tar.zst dexon-solidity-f46df7cb92bba6f30184cc47af3aab8cda672048.zip |
Merge branch 'sol_defaultFunction' of https://github.com/chriseth/cpp-ethereum into chriseth-sol_defaultFunction
-rw-r--r-- | AST.cpp | 18 | ||||
-rwxr-xr-x | AST.h | 4 | ||||
-rw-r--r-- | Compiler.cpp | 14 | ||||
-rw-r--r-- | Parser.cpp | 6 | ||||
-rw-r--r-- | Types.cpp | 4 |
5 files changed, 37 insertions, 9 deletions
@@ -56,7 +56,12 @@ void ContractDefinition::checkTypeRequirements() FunctionDefinition const* constructor = getConstructor(); if (constructor && !constructor->getReturnParameters().empty()) BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError( - "Non-empty \"returns\" directive for constructor.")); + "Non-empty \"returns\" directive for constructor.")); + + FunctionDefinition const* fallbackFunction = getFallbackFunction(); + if (fallbackFunction && fallbackFunction->getScope() == this && !fallbackFunction->getParameters().empty()) + BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError( + "Fallback function cannot take parameters.")); for (ASTPointer<ModifierDefinition> const& modifier: getFunctionModifiers()) modifier->checkTypeRequirements(); @@ -99,6 +104,15 @@ FunctionDefinition const* ContractDefinition::getConstructor() const return nullptr; } +FunctionDefinition const* ContractDefinition::getFallbackFunction() const +{ + for (ContractDefinition const* contract: getLinearizedBaseContracts()) + for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions()) + if (f->getName().empty()) + return f.get(); + return nullptr; +} + void ContractDefinition::checkIllegalOverrides() const { // TODO unify this at a later point. for this we need to put the constness and the access specifier @@ -147,7 +161,7 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::getIn for (ContractDefinition const* contract: getLinearizedBaseContracts()) { for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions()) - if (f->isPublic() && !f->isConstructor() && functionsSeen.count(f->getName()) == 0) + if (f->isPublic() && !f->isConstructor() && !f->getName().empty() && functionsSeen.count(f->getName()) == 0) { functionsSeen.insert(f->getName()); FixedHash<4> hash(dev::sha3(f->getCanonicalSignature())); @@ -235,8 +235,10 @@ public: std::vector<ContractDefinition const*> const& getLinearizedBaseContracts() const { return m_linearizedBaseContracts; } void setLinearizedBaseContracts(std::vector<ContractDefinition const*> const& _bases) { m_linearizedBaseContracts = _bases; } - /// Returns the constructor or nullptr if no constructor was specified + /// Returns the constructor or nullptr if no constructor was specified. FunctionDefinition const* getConstructor() const; + /// Returns the fallback function or nullptr if no constructor was specified. + FunctionDefinition const* getFallbackFunction() const; private: void checkIllegalOverrides() const; diff --git a/Compiler.cpp b/Compiler.cpp index 1fa31ce7..3c46d455 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -146,8 +146,8 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) map<FixedHash<4>, const eth::AssemblyItem> callDataUnpackerEntryPoints; // retrieve the function signature hash from the calldata - m_context << u256(1) << u256(0); - CompilerUtils(m_context).loadFromMemory(0, 4, false, true); + if (!interfaceFunctions.empty()) + CompilerUtils(m_context).loadFromMemory(0, 4, false, true); // stack now is: 1 0 <funhash> for (auto const& it: interfaceFunctions) @@ -156,7 +156,15 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) m_context << eth::dupInstruction(1) << u256(FixedHash<4>::Arith(it.first)) << eth::Instruction::EQ; m_context.appendConditionalJumpTo(callDataUnpackerEntryPoints.at(it.first)); } - m_context << eth::Instruction::STOP; // function not found + if (FunctionDefinition const* fallback = _contract.getFallbackFunction()) + { + eth::AssemblyItem returnTag = m_context.pushNewTag(); + fallback->accept(*this); + m_context << returnTag; + appendReturnValuePacker(FunctionType(*fallback).getReturnParameterTypes()); + } + else + m_context << eth::Instruction::STOP; // function not found for (auto const& it: interfaceFunctions) { @@ -189,7 +189,11 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral()); expectToken(Token::FUNCTION); - ASTPointer<ASTString> name(expectIdentifierToken()); + ASTPointer<ASTString> name; + if (m_scanner->getCurrentToken() == Token::LPAREN) + name = make_shared<ASTString>(); // anonymous function + else + name = expectIdentifierToken(); ASTPointer<ParameterList> parameters(parseParameterList()); bool isDeclaredConst = false; vector<ASTPointer<ModifierInvocation>> modifiers; @@ -494,7 +494,7 @@ MemberList const& ContractType::getMembers() const { for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts()) for (ASTPointer<FunctionDefinition> const& function: base->getDefinedFunctions()) - if (!function->isConstructor()) + if (!function->isConstructor() && !function->getName().empty()) members.insert(make_pair(function->getName(), make_shared<FunctionType>(*function, true))); } else @@ -808,7 +808,7 @@ MemberList const& TypeType::getMembers() const // We are accessing the type of a base contract, so add all public and private // functions. Note that this does not add inherited functions on purpose. for (ASTPointer<FunctionDefinition> const& f: contract.getDefinedFunctions()) - if (!f->isConstructor()) + if (!f->isConstructor() && !f->getName().empty()) members[f->getName()] = make_shared<FunctionType>(*f); } m_members.reset(new MemberList(members)); |