From b49e513494ce20ce9b2fe7bec4da200ae879a84c Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 3 Dec 2020 07:50:36 -0800 Subject: [PATCH] Reworked binary operators and transformability --- IDEHelper/Compiler/BfDefBuilder.cpp | 5 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 88 ++++++++----------------- IDEHelper/Compiler/BfSystem.h | 1 + IDEHelper/Tests/src/ExtensionMethods.bf | 3 +- IDEHelper/Tests/src/Operators.bf | 12 ++++ 5 files changed, 45 insertions(+), 64 deletions(-) diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index a496b56a..97040c6c 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -831,7 +831,10 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef } else { - methodDef->mCommutableKind = BfCommutableKind_Forward; + if (methodDef->mIsOperator) + methodDef->mCommutableKind = BfCommutableKind_Operator; + else + methodDef->mCommutableKind = BfCommutableKind_Forward; } } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 6c5c42fa..24130487 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -45,6 +45,9 @@ BfBaseClassWalker::BfBaseClassWalker(BfType* typeA, BfType* typeB, BfModule* mod { mMayBeFromInterface = false; + if (typeB == typeA) + typeB = NULL; + if ((typeA != NULL) && (!typeA->IsInterface())) mTypes[0] = typeA->ToTypeInstance(); else @@ -19731,13 +19734,12 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod BfBinaryOp findBinaryOp = binaryOp; bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual); - BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp); - BfBinaryOp flippedBinaryOp = BfGetFlippedBinaryOp(findBinaryOp); - BfBinaryOp flippedOppositeBinaryOp = BfGetFlippedBinaryOp(oppositeBinaryOp); - + for (int pass = 0; pass < 2; pass++) { + BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp); bool foundOp = false; + bool foundCommutableOps = false; SizedArray args; BfResolvedArg leftArg; @@ -19776,6 +19778,16 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod for (auto operatorDef : checkType->mTypeDef->mOperators) { + if (operatorDef->mCommutableKind == BfCommutableKind_Operator) + { + foundCommutableOps = true; + } + else + { + if (pass == 1) + continue; + } + bool allowOp = operatorDef->mOperatorDeclaration->mBinOp == findBinaryOp; if ((isComparison) && (operatorDef->mOperatorDeclaration->mBinOp == BfBinaryOp_Compare)) allowOp = true; @@ -19809,7 +19821,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod } } } - else if (operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp) + else if ((operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp) && (operatorDef->mCommutableKind == BfCommutableKind_Operator)) oppositeOperatorDefs.Add(operatorDef); } @@ -19861,8 +19873,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod methodMatcher.FlushAmbiguityError(); auto matchedOp = ((BfOperatorDeclaration*)methodMatcher.mBestMethodDef->mMethodDeclaration)->mBinOp; - bool invertResult = matchedOp == oppositeBinaryOp; - + bool invertResult = matchedOp == oppositeBinaryOp; + auto methodDef = methodMatcher.mBestMethodDef; auto autoComplete = GetAutoComplete(); bool wasCapturingMethodInfo = false; @@ -19961,33 +19973,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod works = true; } } - if ((flippedBinaryOp != BfBinaryOp_None) && (opConstraint.mBinaryOp == flippedBinaryOp)) - { - if ((mModule->CanCast(args[1].mTypedValue, opConstraint.mLeftType)) && - (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType))) - { - works = true; - } - } - - if (((oppositeBinaryOp != BfBinaryOp_None) && (opConstraint.mBinaryOp == oppositeBinaryOp)) || - (opConstraint.mBinaryOp == BfBinaryOp_Compare)) - { - if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType)) && - (mModule->CanCast(args[1].mTypedValue, opConstraint.mLeftType))) - { - works = true; - } - } - if ((flippedOppositeBinaryOp != BfBinaryOp_None) && (opConstraint.mBinaryOp == flippedOppositeBinaryOp)) - { - if ((mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)) && - (mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType))) - { - works = true; - } - } - + if ((isComparison) && (opConstraint.mBinaryOp == BfBinaryOp_Compare)) { if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) && @@ -20041,38 +20027,16 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod } } - if ((!foundOp) || (pass == 1)) + if (!foundCommutableOps) break; - - switch (findBinaryOp) - { - case BfBinaryOp_Equality: - case BfBinaryOp_StrictEquality: - case BfBinaryOp_InEquality: - case BfBinaryOp_StrictInEquality: - case BfBinaryOp_Compare: - // Still works - break; - case BfBinaryOp_LessThan: - findBinaryOp = BfBinaryOp_GreaterThanOrEqual; - break; - case BfBinaryOp_LessThanOrEqual: - findBinaryOp = BfBinaryOp_GreaterThan; - break; - case BfBinaryOp_GreaterThan: - findBinaryOp = BfBinaryOp_LessThanOrEqual; - break; - case BfBinaryOp_GreaterThanOrEqual: - findBinaryOp = BfBinaryOp_LessThan; - break; - default: - findBinaryOp = BfBinaryOp_None; - break; - } + if (pass == 1) + break; + + findBinaryOp = BfGetFlippedBinaryOp(findBinaryOp); if (findBinaryOp == BfBinaryOp_None) break; - } + } } } diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index e29eeacb..8d0f3edd 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -694,6 +694,7 @@ enum BfImportKind : int8 enum BfCommutableKind : int8 { BfCommutableKind_None, + BfCommutableKind_Operator, BfCommutableKind_Forward, BfCommutableKind_Reverse, }; diff --git a/IDEHelper/Tests/src/ExtensionMethods.bf b/IDEHelper/Tests/src/ExtensionMethods.bf index f2e43b5f..90238e28 100644 --- a/IDEHelper/Tests/src/ExtensionMethods.bf +++ b/IDEHelper/Tests/src/ExtensionMethods.bf @@ -52,7 +52,8 @@ namespace Tests static { public static int CompareIt(this T self, T other) - where bool: operator T < T + where bool : operator T < T + where bool : operator T > T { if(self < other) return -1; diff --git a/IDEHelper/Tests/src/Operators.bf b/IDEHelper/Tests/src/Operators.bf index e6f1ab93..f178080c 100644 --- a/IDEHelper/Tests/src/Operators.bf +++ b/IDEHelper/Tests/src/Operators.bf @@ -30,6 +30,12 @@ namespace Tests newVal.mA = val.mA + 1; return newVal; } + + [Commutable] + public static bool operator<(StructA lhs, StructB rhs) + { + return lhs.mA < rhs.mB; + } } struct StructB @@ -226,6 +232,12 @@ namespace Tests StructB sb1; sb1.mB = 12; + Test.Assert(sa1 < sb0); + Test.Assert(!(sa1 >= sb0)); + + Test.Assert(sb0 > sa1); + Test.Assert(!(sb0 <= sa1)); + StructA sa3 = sa0 + sb0; Test.Assert(sa3.mA == 1012);