aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGav Wood <i@gavwood.com>2015-01-30 07:46:19 +0800
committerGav Wood <i@gavwood.com>2015-01-30 07:46:19 +0800
commitf46df7cb92bba6f30184cc47af3aab8cda672048 (patch)
tree13f827931b25db3f931aff495faef6d1fc41f547
parenta604202f33f1f7dc3abda1080e1bc02b2a2cbcb3 (diff)
parentcfb55901cc963523ca1defe232728f195a818228 (diff)
downloaddexon-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.cpp18
-rwxr-xr-xAST.h4
-rw-r--r--Compiler.cpp14
-rw-r--r--Parser.cpp6
-rw-r--r--Types.cpp4
5 files changed, 37 insertions, 9 deletions
diff --git a/AST.cpp b/AST.cpp
index bc6be600..20c117c0 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -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()));
diff --git a/AST.h b/AST.h
index 6c207290..3dc63d33 100755
--- a/AST.h
+++ b/AST.h
@@ -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)
{
diff --git a/Parser.cpp b/Parser.cpp
index 5cfc8f46..812b3263 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -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;
diff --git a/Types.cpp b/Types.cpp
index bebb4be1..afc1c1db 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -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));