Rename Type::userDefinedOperator to Type::operatorDefinition

This commit is contained in:
wechman 2022-09-23 13:35:38 +02:00
parent 7983167732
commit d730e92dde
3 changed files with 48 additions and 44 deletions

View File

@ -1731,13 +1731,15 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
// Check if the operator is built-in or user-defined. // Check if the operator is built-in or user-defined.
Result<FunctionDefinition const*> userDefinedOperatorResult = subExprType->userDefinedOperator( Result<FunctionDefinition const*> userDefinedOperatorResult = subExprType->operatorDefinition(
_operation.getOperator(), _operation.getOperator(),
*currentDefinitionScope(), *currentDefinitionScope(),
true // _unaryOperation true // _unaryOperation
); );
if (userDefinedOperatorResult) if (userDefinedOperatorResult)
_operation.annotation().userDefinedFunction = userDefinedOperatorResult; _operation.annotation().userDefinedFunction = userDefinedOperatorResult;
FunctionType const* userDefinedFunctionType = nullptr; FunctionType const* userDefinedFunctionType = nullptr;
if (userDefinedOperatorResult) if (userDefinedOperatorResult)
userDefinedFunctionType = &dynamic_cast<FunctionType const&>( userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
@ -1788,7 +1790,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
_operation.annotation().isConstant = false; _operation.annotation().isConstant = false;
// Check if the operator is built-in or user-defined. // Check if the operator is built-in or user-defined.
Result<FunctionDefinition const*> userDefinedOperatorResult = leftType->userDefinedOperator( Result<FunctionDefinition const*> userDefinedOperatorResult = leftType->operatorDefinition(
_operation.getOperator(), _operation.getOperator(),
*currentDefinitionScope(), *currentDefinitionScope(),
false // _unaryOperation false // _unaryOperation
@ -1867,11 +1869,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
TypeProvider::boolean() : TypeProvider::boolean() :
commonType; commonType;
if (_operation.getOperator() == Token::Exp || _operation.getOperator() == Token::SHL)
if (
!userDefinedOperatorResult &&
(_operation.getOperator() == Token::Exp || _operation.getOperator() == Token::SHL)
)
{ {
string operation = _operation.getOperator() == Token::Exp ? "exponentiation" : "shift"; string operation = _operation.getOperator() == Token::Exp ? "exponentiation" : "shift";
if ( if (
@ -3832,8 +3830,9 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
solAssert(m_errorReporter.hasErrors()); solAssert(m_errorReporter.hasErrors());
return; return;
} }
solAssert(_usingFor.typeName()->annotation().type); Type const* usingForType = _usingFor.typeName()->annotation().type;
if (Declaration const* typeDefinition = _usingFor.typeName()->annotation().type->typeDefinition()) solAssert(usingForType);
if (Declaration const* typeDefinition = usingForType->typeDefinition())
{ {
if (typeDefinition->scope() != m_currentSourceUnit) if (typeDefinition->scope() != m_currentSourceUnit)
m_errorReporter.typeError( m_errorReporter.typeError(
@ -3867,9 +3866,10 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
return; return;
} }
solAssert(_usingFor.typeName()->annotation().type); Type const* usingForType = _usingFor.typeName()->annotation().type;
solAssert(usingForType);
if (_usingFor.typeName()->annotation().type->category() == Type::Category::Enum) if (usingForType->category() == Type::Category::Enum)
m_errorReporter.typeError( m_errorReporter.typeError(
9921_error, 9921_error,
_usingFor.location(), _usingFor.location(),
@ -3878,7 +3878,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
Type const* normalizedType = TypeProvider::withLocationIfReference( Type const* normalizedType = TypeProvider::withLocationIfReference(
DataLocation::Storage, DataLocation::Storage,
_usingFor.typeName()->annotation().type usingForType
); );
solAssert(normalizedType); solAssert(normalizedType);
@ -3909,7 +3909,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
3100_error, 3100_error,
path->location(), path->location(),
"The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+
"cannot be bound to the type \"" + _usingFor.typeName()->annotation().type->canonicalName() + "cannot be bound to the type \"" + usingForType->canonicalName() +
"\" because the type cannot be implicitly converted to the first argument" + "\" because the type cannot be implicitly converted to the first argument" +
" of the function (\"" + functionType->selfType()->humanReadableName() + "\")" + " of the function (\"" + functionType->selfType()->humanReadableName() + "\")" +
( (
@ -3920,7 +3920,9 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
); );
else if (operator_) else if (operator_)
{ {
if (!_usingFor.typeName()->annotation().type->typeDefinition()) TypePointers const& parameterTypes = functionType->parameterTypesIncludingSelf();
size_t const parameterCount = parameterTypes.size();
if (!usingForType->typeDefinition())
{ {
m_errorReporter.typeError( m_errorReporter.typeError(
5332_error, 5332_error,
@ -3937,9 +3939,9 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
TokenTraits::isCompareOp(*operator_) TokenTraits::isCompareOp(*operator_)
) && ) &&
( (
functionType->parameterTypesIncludingSelf().size() != 2 || parameterCount != 2 ||
*functionType->parameterTypesIncludingSelf().at(0) != *parameterTypes.at(0) !=
*functionType->parameterTypesIncludingSelf().at(1) *parameterTypes.at(1)
) )
) )
m_errorReporter.typeError( m_errorReporter.typeError(
@ -3947,7 +3949,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
path->location(), path->location(),
"The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+
"needs to have two parameters of type " + "needs to have two parameters of type " +
_usingFor.typeName()->annotation().type->canonicalName() + usingForType->canonicalName() +
" and the same data location to be used for the operator " + " and the same data location to be used for the operator " +
TokenTraits::friendlyName(*operator_) + TokenTraits::friendlyName(*operator_) +
"." "."
@ -3956,10 +3958,10 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
!TokenTraits::isBinaryOp(*operator_) && !TokenTraits::isBinaryOp(*operator_) &&
TokenTraits::isUnaryOp(*operator_) && TokenTraits::isUnaryOp(*operator_) &&
( (
functionType->parameterTypesIncludingSelf().size() != 1 || parameterCount != 1 ||
( (
*TypeProvider::withLocationIfReference(DataLocation::Storage, functionType->parameterTypesIncludingSelf().front()) != *TypeProvider::withLocationIfReference(DataLocation::Storage, parameterTypes.front()) !=
*TypeProvider::withLocationIfReference(DataLocation::Storage, _usingFor.typeName()->annotation().type) *TypeProvider::withLocationIfReference(DataLocation::Storage, usingForType)
) )
) )
) )
@ -3968,27 +3970,27 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
path->location(), path->location(),
"The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+
"needs to have exactly one parameter of type " + "needs to have exactly one parameter of type " +
_usingFor.typeName()->annotation().type->canonicalName() + usingForType->canonicalName() +
" to be used for the operator " + " to be used for the operator " +
TokenTraits::friendlyName(*operator_) + TokenTraits::friendlyName(*operator_) +
"." "."
); );
else if ( else if (
( (
functionType->parameterTypesIncludingSelf().size() == 2 && parameterCount == 2 &&
( (
(*functionType->parameterTypesIncludingSelf().at(0) != *functionType->parameterTypesIncludingSelf().at(1)) || (*parameterTypes.at(0) != *parameterTypes.at(1)) ||
( (
*TypeProvider::withLocationIfReference(DataLocation::Storage, functionType->parameterTypesIncludingSelf().at(0)) != *TypeProvider::withLocationIfReference(DataLocation::Storage, parameterTypes.at(0)) !=
*TypeProvider::withLocationIfReference(DataLocation::Storage, _usingFor.typeName()->annotation().type) *TypeProvider::withLocationIfReference(DataLocation::Storage, usingForType)
) )
) )
) || ) ||
( (
functionType->parameterTypesIncludingSelf().size() == 1 && parameterCount == 1 &&
( (
*TypeProvider::withLocationIfReference(DataLocation::Storage, functionType->parameterTypesIncludingSelf().at(0)) != *TypeProvider::withLocationIfReference(DataLocation::Storage, parameterTypes.at(0)) !=
*TypeProvider::withLocationIfReference(DataLocation::Storage, _usingFor.typeName()->annotation().type) *TypeProvider::withLocationIfReference(DataLocation::Storage, usingForType)
) )
) )
) )
@ -4003,8 +4005,8 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
"." "."
); );
else if ( else if (
functionType->parameterTypesIncludingSelf().size() != 1 && parameterCount != 1 &&
functionType->parameterTypesIncludingSelf().size() != 2 parameterCount != 2
) )
m_errorReporter.typeError( m_errorReporter.typeError(
8112_error, 8112_error,
@ -4017,9 +4019,11 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
"." "."
); );
TypePointers const& returnParameterTypes = functionType->returnParameterTypes();
size_t const returnParameterCount = returnParameterTypes.size();
if ( if (
TokenTraits::isCompareOp(*operator_) && TokenTraits::isCompareOp(*operator_) &&
(functionType->returnParameterTypes().size() != 1 || *functionType->returnParameterTypes().front() != *TypeProvider::boolean()) (returnParameterCount != 1 || *returnParameterTypes.front() != *TypeProvider::boolean())
) )
m_errorReporter.typeError( m_errorReporter.typeError(
7995_error, 7995_error,
@ -4033,10 +4037,10 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
else if (!TokenTraits::isCompareOp(*operator_)) else if (!TokenTraits::isCompareOp(*operator_))
{ {
if ( if (
functionType->returnParameterTypes().size() != 1 || returnParameterCount != 1 ||
( (
*TypeProvider::withLocationIfReference(DataLocation::Storage, functionType->returnParameterTypes().front()) != *TypeProvider::withLocationIfReference(DataLocation::Storage, returnParameterTypes.front()) !=
*TypeProvider::withLocationIfReference(DataLocation::Storage, _usingFor.typeName()->annotation().type) *TypeProvider::withLocationIfReference(DataLocation::Storage, usingForType)
) )
) )
m_errorReporter.typeError( m_errorReporter.typeError(
@ -4044,12 +4048,12 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
path->location(), path->location(),
"The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+
"needs to return exactly one value of type " + "needs to return exactly one value of type " +
_usingFor.typeName()->annotation().type->canonicalName() + usingForType->canonicalName() +
" to be used for the operator " + " to be used for the operator " +
TokenTraits::friendlyName(*operator_) + TokenTraits::friendlyName(*operator_) +
"." "."
); );
else if (*functionType->returnParameterTypes().front() != *functionType->parameterTypesIncludingSelf().front()) else if (*returnParameterTypes.front() != *parameterTypes.front())
m_errorReporter.typeError( m_errorReporter.typeError(
3605_error, 3605_error,
path->location(), path->location(),

View File

@ -386,7 +386,7 @@ vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, AS
} }
Result<FunctionDefinition const*> Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const Result<FunctionDefinition const*> Type::operatorDefinition(Token _token, ASTNode const& _scope, bool _unaryOperation) const
{ {
if (!typeDefinition() || !util::contains(overridableOperators, _token)) if (!typeDefinition() || !util::contains(overridableOperators, _token))
return nullptr; return nullptr;
@ -409,12 +409,12 @@ Result<FunctionDefinition const*> Type::userDefinedOperator(Token _token, ASTNod
if (auto const* referenceType = dynamic_cast<ReferenceType const*>(normalizedType)) if (auto const* referenceType = dynamic_cast<ReferenceType const*>(normalizedType))
normalizedType = TypeProvider::withLocationIfReference(referenceType->location(), normalizedType); normalizedType = TypeProvider::withLocationIfReference(referenceType->location(), normalizedType);
Type const* normalizedParameterType = functionType->parameterTypes().front(); Type const* normalizedFirstParameterType = functionType->parameterTypes().front();
if (auto const* referenceType = dynamic_cast<ReferenceType const*>(normalizedParameterType)) if (auto const* referenceType = dynamic_cast<ReferenceType const*>(normalizedFirstParameterType))
normalizedParameterType = TypeProvider::withLocationIfReference(referenceType->location(), normalizedParameterType); normalizedFirstParameterType = TypeProvider::withLocationIfReference(referenceType->location(), normalizedFirstParameterType);
if ( if (
*normalizedType == *normalizedParameterType && *normalizedType == *normalizedFirstParameterType &&
( (
(_unaryOperation && function.parameterList().parameters().size() == 1) || (_unaryOperation && function.parameterList().parameters().size() == 1) ||
(!_unaryOperation && function.parameterList().parameters().size() == 2) (!_unaryOperation && function.parameterList().parameters().size() == 2)

View File

@ -377,7 +377,7 @@ public:
/// Clears all internally cached values (if any). /// Clears all internally cached values (if any).
virtual void clearCache() const; virtual void clearCache() const;
util::Result<FunctionDefinition const*> userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const; util::Result<FunctionDefinition const*> operatorDefinition(Token _token, ASTNode const& _scope, bool _unaryOperation) const;
private: private:
/// @returns a member list containing all members added to this type by `using for` directives. /// @returns a member list containing all members added to this type by `using for` directives.