diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index 41c60639..f7f30c20 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -522,12 +522,22 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio declError = "'public'"; methodDef->mProtection = BfProtection_Public; // Fix it } - if (!methodDef->mIsStatic) + if (operatorDecl->mAssignOp != BfAssignmentOp_None) { - if (!declError.empty()) - declError += " and "; - declError += "'static'"; - methodDef->mIsStatic = true; // Fix it + if (methodDef->mIsStatic) + { + Fail("Assignment operator must not be declared 'static'", operatorDecl->mStaticSpecifier); + } + } + else + { + if (!methodDef->mIsStatic) + { + if (!declError.empty()) + declError += " and "; + declError += "'static'"; + methodDef->mIsStatic = true; // Fix it + } } if (!declError.empty()) { diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index f399ed03..2801430f 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -14856,26 +14856,68 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool BfTypedValue convVal; if (binaryOp != BfBinaryOp_None) { + CheckResultForReading(ptr); + BfTypedValue leftValue = ptr; + leftValue = mModule->LoadValue(leftValue); + auto expectedType = ptr.mType; if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift)) expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); if ((!rightValue) && (assignExpr->mRight != NULL)) - { + { rightValue = mModule->CreateValueFromExpression(assignExpr->mRight, expectedType, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_NoCast)); } - CheckResultForReading(ptr); - BfTypedValue leftValue = ptr; - leftValue = mModule->LoadValue(leftValue); + bool handled = false; 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 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; - mResult = BfTypedValue(); + if (!handled) + { + convVal = mResult; + mResult = BfTypedValue(); + } + if (!convVal) - return; + return; } else { diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 9b918d59..35b3666d 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -16101,7 +16101,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) 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); }