1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00

Fixed compond assignment operator overloads

This commit is contained in:
Brian Fiete 2020-02-02 05:30:19 -08:00
parent 0c7597fe60
commit ca64ea1f28
3 changed files with 66 additions and 14 deletions

View file

@ -522,12 +522,22 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
declError = "'public'"; declError = "'public'";
methodDef->mProtection = BfProtection_Public; // Fix it methodDef->mProtection = BfProtection_Public; // Fix it
} }
if (!methodDef->mIsStatic) if (operatorDecl->mAssignOp != BfAssignmentOp_None)
{ {
if (!declError.empty()) if (methodDef->mIsStatic)
declError += " and "; {
declError += "'static'"; Fail("Assignment operator must not be declared 'static'", operatorDecl->mStaticSpecifier);
methodDef->mIsStatic = true; // Fix it }
}
else
{
if (!methodDef->mIsStatic)
{
if (!declError.empty())
declError += " and ";
declError += "'static'";
methodDef->mIsStatic = true; // Fix it
}
} }
if (!declError.empty()) if (!declError.empty())
{ {

View file

@ -14856,26 +14856,68 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
BfTypedValue convVal; BfTypedValue convVal;
if (binaryOp != BfBinaryOp_None) if (binaryOp != BfBinaryOp_None)
{ {
CheckResultForReading(ptr);
BfTypedValue leftValue = ptr;
leftValue = mModule->LoadValue(leftValue);
auto expectedType = ptr.mType; auto expectedType = ptr.mType;
if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift)) if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift))
expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
if ((!rightValue) && (assignExpr->mRight != NULL)) if ((!rightValue) && (assignExpr->mRight != NULL))
{ {
rightValue = mModule->CreateValueFromExpression(assignExpr->mRight, expectedType, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_NoCast)); rightValue = mModule->CreateValueFromExpression(assignExpr->mRight, expectedType, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_NoCast));
} }
CheckResultForReading(ptr); bool handled = false;
BfTypedValue leftValue = ptr;
leftValue = mModule->LoadValue(leftValue);
if (rightValue) if (rightValue)
PerformBinaryOperation(assignExpr->mLeft, assignExpr->mRight, binaryOp, assignExpr->mOpToken, BfBinOpFlag_ForceLeftType, leftValue, rightValue); {
auto checkTypeInst = leftValue.mType->ToTypeInstance();
while (checkTypeInst != NULL)
{
for (auto operatorDef : checkTypeInst->mTypeDef->mOperators)
{
if (operatorDef->mOperatorDeclaration->mAssignOp != assignExpr->mOp)
continue;
auto methodInst = mModule->GetRawMethodInstanceAtIdx(checkTypeInst, operatorDef->mIdx);
if (methodInst->GetParamCount() != 1)
continue;
auto paramType = methodInst->GetParamType(0);
if (!mModule->CanCast(rightValue, paramType))
continue;
auto moduleMethodInstance = mModule->GetMethodInstance(checkTypeInst, operatorDef, BfTypeVector());
BfExprEvaluator exprEvaluator(mModule);
SizedArray<BfIRValue, 1> args;
exprEvaluator.PushThis(assignExpr->mLeft, leftValue, moduleMethodInstance.mMethodInstance, args);
exprEvaluator.PushArg(rightValue, args);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, args);
convVal = leftValue;
handled = true;
break;
}
if (handled)
break;
checkTypeInst = mModule->GetBaseType(checkTypeInst);
}
if (!handled)
PerformBinaryOperation(assignExpr->mLeft, assignExpr->mRight, binaryOp, assignExpr->mOpToken, BfBinOpFlag_ForceLeftType, leftValue, rightValue);
}
convVal = mResult; if (!handled)
mResult = BfTypedValue(); {
convVal = mResult;
mResult = BfTypedValue();
}
if (!convVal) if (!convVal)
return; return;
} }
else else
{ {

View file

@ -16101,7 +16101,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
Fail("Assignment operators must declare one parameter", paramErrorRefNode); Fail("Assignment operators must declare one parameter", paramErrorRefNode);
} }
if (mCurMethodInstance->mReturnType->IsVoid()) if (!mCurMethodInstance->mReturnType->IsVoid())
{ {
Fail("The return type for assignment operator must be 'void'", operatorDef->mOperatorDeclaration->mReturnType); Fail("The return type for assignment operator must be 'void'", operatorDef->mOperatorDeclaration->mReturnType);
} }