Add userDefinedFunctionType helper function

This commit is contained in:
wechman 2022-09-26 13:27:45 +02:00
parent 577a5bb7a4
commit 5cf88593fd
5 changed files with 44 additions and 33 deletions

View File

@ -1740,14 +1740,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
if (userDefinedOperatorResult)
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
FunctionType const* userDefinedFunctionType = nullptr;
if (userDefinedOperatorResult)
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
userDefinedOperatorResult.get()->libraryFunction() ?
*userDefinedOperatorResult.get()->typeViaContractName() :
*userDefinedOperatorResult.get()->type()
);
FunctionType const* userDefinedFunctionType = _operation.userDefinedFunctionType();
TypeResult builtinResult = subExprType->unaryOperatorResult(op);
solAssert(!builtinResult || !userDefinedOperatorResult);
@ -1790,20 +1783,14 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
_operation.annotation().isConstant = false;
// Check if the operator is built-in or user-defined.
Result<FunctionDefinition const*> userDefinedOperatorResult = leftType->operatorDefinition(
Result<FunctionDefinition const*> operatorDefinitionResult = leftType->operatorDefinition(
_operation.getOperator(),
*currentDefinitionScope(),
false // _unaryOperation
);
if (userDefinedOperatorResult)
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
FunctionType const* userDefinedFunctionType = nullptr;
if (userDefinedOperatorResult)
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
userDefinedOperatorResult.get()->libraryFunction() ?
*userDefinedOperatorResult.get()->typeViaContractName() :
*userDefinedOperatorResult.get()->type()
);
if (operatorDefinitionResult)
_operation.annotation().userDefinedFunction = operatorDefinitionResult;
FunctionType const* userDefinedFunctionType = _operation.userDefinedFunctionType();
_operation.annotation().isPure =
*_operation.leftExpression().annotation().isPure &&
*_operation.rightExpression().annotation().isPure &&
@ -1812,12 +1799,12 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
TypeResult builtinResult = leftType->binaryOperatorResult(_operation.getOperator(), rightType);
// Either the operator is user-defined or built-in.
solAssert(!userDefinedOperatorResult || !builtinResult);
solAssert(!operatorDefinitionResult || !builtinResult);
Type const* commonType = leftType;
if (builtinResult)
commonType = builtinResult.get();
else if (userDefinedOperatorResult)
else if (operatorDefinitionResult)
{
Type const* normalizedParameterType = userDefinedFunctionType->parameterTypes().at(0);
Type const* normalizedLeftType = leftType;
@ -1860,7 +1847,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
" and " +
rightType->humanReadableName() + "." +
(!builtinResult.message().empty() ? " " + builtinResult.message() : "") +
(!userDefinedOperatorResult.message().empty() ? " " + userDefinedOperatorResult.message() : "")
(!operatorDefinitionResult.message().empty() ? " " + operatorDefinitionResult.message() : "")
);
_operation.annotation().commonType = commonType;

View File

@ -907,6 +907,34 @@ OperationAnnotation& UnaryOperation::annotation() const
return initAnnotation<OperationAnnotation>();
}
FunctionType const* UnaryOperation::userDefinedFunctionType() const
{
if (!annotation().userDefinedFunction.set())
return nullptr;
FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction;
solAssert(userDefinedFunction);
return dynamic_cast<FunctionType const*>(
userDefinedFunction->libraryFunction() ?
userDefinedFunction->typeViaContractName() :
userDefinedFunction->type()
);
}
FunctionType const* BinaryOperation::userDefinedFunctionType() const
{
if (!annotation().userDefinedFunction.set())
return nullptr;
FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction;
solAssert(userDefinedFunction);
return dynamic_cast<FunctionType const*>(
userDefinedFunction->libraryFunction() ?
userDefinedFunction->typeViaContractName() :
userDefinedFunction->type()
);
}
BinaryOperationAnnotation& BinaryOperation::annotation() const
{
return initAnnotation<BinaryOperationAnnotation>();

View File

@ -2068,6 +2068,8 @@ public:
bool isPrefixOperation() const { return m_isPrefix; }
Expression const& subExpression() const { return *m_subExpression; }
FunctionType const* userDefinedFunctionType() const;
OperationAnnotation& annotation() const override;
private:
@ -2101,6 +2103,8 @@ public:
Expression const& rightExpression() const { return *m_right; }
Token getOperator() const { return m_operator; }
FunctionType const* userDefinedFunctionType() const;
BinaryOperationAnnotation& annotation() const override;
private:

View File

@ -420,9 +420,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
"Only file-level functions and library functions can be bound to a user type operator."
);
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
function->libraryFunction() ? function->typeViaContractName() : function->type()
);
FunctionType const* functionType = _unaryOperation.userDefinedFunctionType();
solAssert(functionType);
functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
@ -548,9 +546,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
function->isFree() || function->libraryFunction(),
"Only file-level functions and library functions can be bound to a user type operator."
);
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
function->libraryFunction() ? function->typeViaContractName() : function->type()
);
FunctionType const* functionType = _binaryOperation.userDefinedFunctionType();
solAssert(functionType);
functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
solAssert(functionType);

View File

@ -685,9 +685,7 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation)
"Only file-level functions and library functions can be bound to a user type operator."
);
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
function->libraryFunction() ? function->typeViaContractName() : function->type()
);
FunctionType const* functionType = _unaryOperation.userDefinedFunctionType();
solAssert(functionType);
functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
solAssert(functionType);
@ -832,9 +830,7 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
"Only file-level functions and library functions can be bound to a user type operator."
);
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
function->libraryFunction() ? function->typeViaContractName() : function->type()
);
FunctionType const* functionType = _binOp.userDefinedFunctionType();
solAssert(functionType);
functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
solAssert(functionType);