Merge pull request #5485 from ethereum/refactorCallableFunction

Refactor callable function
This commit is contained in:
chriseth 2018-11-26 12:34:43 +01:00 committed by GitHub
commit bc137c2eeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 33 deletions

View File

@ -400,42 +400,42 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
} }
} }
void TypeChecker::checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super) void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super)
{ {
FunctionType functionType(function); FunctionType functionType(_function);
FunctionType superType(super); FunctionType superType(_super);
if (!functionType.hasEqualParameterTypes(superType)) if (!functionType.hasEqualParameterTypes(superType))
return; return;
if (!function.annotation().superFunction) if (!_function.annotation().superFunction)
function.annotation().superFunction = &super; _function.annotation().superFunction = &_super;
if (function.visibility() != super.visibility()) if (_function.visibility() != _super.visibility())
{ {
// visibility is enforced to be external in interfaces, but a contract can override that with public // visibility is enforced to be external in interfaces, but a contract can override that with public
if ( if (
super.inContractKind() == ContractDefinition::ContractKind::Interface && _super.inContractKind() == ContractDefinition::ContractKind::Interface &&
function.inContractKind() != ContractDefinition::ContractKind::Interface && _function.inContractKind() != ContractDefinition::ContractKind::Interface &&
function.visibility() == FunctionDefinition::Visibility::Public _function.visibility() == FunctionDefinition::Visibility::Public
) )
return; return;
overrideError(function, super, "Overriding function visibility differs."); overrideError(_function, _super, "Overriding function visibility differs.");
} }
else if (function.stateMutability() != super.stateMutability()) else if (_function.stateMutability() != _super.stateMutability())
overrideError( overrideError(
function, _function,
super, _super,
"Overriding function changes state mutability from \"" + "Overriding function changes state mutability from \"" +
stateMutabilityToString(super.stateMutability()) + stateMutabilityToString(_super.stateMutability()) +
"\" to \"" + "\" to \"" +
stateMutabilityToString(function.stateMutability()) + stateMutabilityToString(_function.stateMutability()) +
"\"." "\"."
); );
else if (functionType != superType) else if (functionType != superType)
overrideError(function, super, "Overriding function return types differ."); overrideError(_function, _super, "Overriding function return types differ.");
} }
void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message) void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message)

View File

@ -442,10 +442,11 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function)) if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function))
continue; continue;
seenFunctions.insert(function); seenFunctions.insert(function);
FunctionType funType(*function, false); if (function->parameters().empty())
if (auto fun = funType.asMemberFunction(true, true)) continue;
if (_type.isImplicitlyConvertibleTo(*fun->selfType())) FunctionTypePointer fun = FunctionType(*function, false).asCallableFunction(true, true);
members.push_back(MemberList::Member(function->name(), fun, function)); if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
members.push_back(MemberList::Member(function->name(), fun, function));
} }
} }
return members; return members;
@ -1970,7 +1971,7 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con
for (auto const& it: m_contract.interfaceFunctions()) for (auto const& it: m_contract.interfaceFunctions())
members.push_back(MemberList::Member( members.push_back(MemberList::Member(
it.second->declaration().name(), it.second->declaration().name(),
it.second->asMemberFunction(m_contract.isLibrary()), it.second->asCallableFunction(m_contract.isLibrary()),
&it.second->declaration() &it.second->declaration()
)); ));
} }
@ -3059,10 +3060,10 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con
); );
} }
FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) const FunctionTypePointer FunctionType::asCallableFunction(bool _inLibrary, bool _bound) const
{ {
if (_bound && m_parameterTypes.empty()) if (_bound)
return FunctionTypePointer(); solAssert(!m_parameterTypes.empty(), "");
TypePointers parameterTypes; TypePointers parameterTypes;
for (auto const& t: m_parameterTypes) for (auto const& t: m_parameterTypes)
@ -3201,7 +3202,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current
if (function->isVisibleAsLibraryMember()) if (function->isVisibleAsLibraryMember())
members.push_back(MemberList::Member( members.push_back(MemberList::Member(
function->name(), function->name(),
FunctionType(*function).asMemberFunction(true), FunctionType(*function).asCallableFunction(true),
function function
)); ));
if (isBase) if (isBase)

View File

@ -1154,14 +1154,13 @@ public:
/// of the parameters to false. /// of the parameters to false.
TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const; TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const;
/// @returns a copy of this function type where all return parameters of dynamic size are /// @returns a copy of this function type where the location of reference types is changed
/// removed and the location of reference types is changed from CallData to Memory. /// from CallData to Memory. This is the type that would be used when the function is
/// This is needed if external functions are called on other contracts, as they cannot return /// called, as opposed to the parameter types that are available inside the function body.
/// dynamic values. /// Also supports variants to be used for library or bound calls.
/// Returns empty shared pointer on a failure. Namely, if a bound function has no parameters.
/// @param _inLibrary if true, uses DelegateCall as location. /// @param _inLibrary if true, uses DelegateCall as location.
/// @param _bound if true, the arguments are placed as `arg1.functionName(arg2, ..., argn)`. /// @param _bound if true, the function type is set to be bound.
FunctionTypePointer asMemberFunction(bool _inLibrary, bool _bound = false) const; FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const;
private: private:
static TypePointers parseElementaryTypeVector(strings const& _types); static TypePointers parseElementaryTypeVector(strings const& _types);

View File

@ -414,7 +414,7 @@ FunctionDefinition const& CompilerContext::resolveVirtualFunction(
if ( if (
function->name() == name && function->name() == name &&
!function->isConstructor() && !function->isConstructor() &&
FunctionType(*function).hasEqualParameterTypes(functionType) FunctionType(*function).asCallableFunction(false)->hasEqualParameterTypes(functionType)
) )
return *function; return *function;
solAssert(false, "Super function " + name + " not found."); solAssert(false, "Super function " + name + " not found.");