From 64d646e130a600b6b5b463b9d7acc65ca2d7c93a Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 4 Nov 2024 06:06:46 -0500 Subject: [PATCH] params operator implicit cast, params generic inference fix --- IDEHelper/Compiler/BfExprEvaluator.cpp | 72 ++++++++++++++++++++++---- IDEHelper/Compiler/BfModule.cpp | 4 +- IDEHelper/Tests/src/MethodCalls.bf | 17 ++++++ 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 34739968..438048b6 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -1980,9 +1980,16 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Params) { - paramsParamIdx = paramIdx; - if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) - wantType = wantType->GetUnderlyingType(); + if ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0) + { + // Match to entire thing + } + else + { + paramsParamIdx = paramIdx; + if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) + wantType = wantType->GetUnderlyingType(); + } } if (!genericInferContext.InferGenericArgument(methodInstance, type, wantType, argTypedValue.mValue)) @@ -22954,15 +22961,60 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, } else { - auto isValid = false; - auto genericTypeInst = mResult.mType->ToGenericTypeInstance(); - if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) - isValid = true; - else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray())) - isValid = true; + auto origValue = mResult; + auto isValid = false; + + for (int pass = 0; pass < 2; pass++) + { + auto typeInst = mResult.mType->ToTypeInstance(); + auto genericTypeInst = mResult.mType->ToGenericTypeInstance(); + if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) + isValid = true; + else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray())) + isValid = true; + else if ((typeInst != NULL) && (pass == 0)) + { + BfBaseClassWalker baseClassWalker(typeInst, NULL, mModule); + + BfType* bestCastType = NULL; + while (true) + { + auto entry = baseClassWalker.Next(); + auto checkType = entry.mTypeInstance; + if (checkType == NULL) + break; + for (auto operatorDef : checkType->mTypeDef->mOperators) + { + if (operatorDef->mOperatorDeclaration->mIsConvOperator) + { + if (operatorDef->IsExplicit()) + continue; + + auto methodInstance = mModule->GetRawMethodInstanceAtIdx(typeInst, operatorDef->mIdx); + + auto checkType = methodInstance->mReturnType; + if (checkType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)) + bestCastType = checkType; + else if ((checkType->IsArray()) || (checkType->IsSizedArray())) + bestCastType = checkType; + } + } + } + + if (bestCastType == NULL) + break; + auto castTypedValue = mModule->Cast(opToken, mResult, bestCastType, BfCastFlags_SilentFail); + if (!castTypedValue) + break; + mResult = castTypedValue; + } + else + break; + } + if (!isValid) { - mModule->Fail(StrFormat("A 'params' expression cannot be used on type '%s'", mModule->TypeToString(mResult.mType).c_str()), opToken); + mModule->Fail(StrFormat("A 'params' expression cannot be used on type '%s'", mModule->TypeToString(origValue.mType).c_str()), opToken); } } } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index d6687bb7..ca0c8337 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -2861,8 +2861,8 @@ bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* me if (curCheckType != NULL) { allowPrivate |= IsInnerType(curCheckType->mTypeDef, memberOwner->mTypeDef); - if (memberOwner->mTypeDef->IsGlobalsContainer()) - allowPrivate |= curCheckType->mTypeDef->mNamespace.StartsWith(memberOwner->mTypeDef->mNamespace); + if (memberOwner->mTypeDef->IsGlobalsContainer()) + allowPrivate |= curCheckType->mTypeDef->mNamespace == memberOwner->mTypeDef->mNamespace; } if (allowPrivate) flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_AllowPrivate | BfProtectionCheckFlag_CheckedPrivate); diff --git a/IDEHelper/Tests/src/MethodCalls.bf b/IDEHelper/Tests/src/MethodCalls.bf index bd80fdb0..e34ad96c 100644 --- a/IDEHelper/Tests/src/MethodCalls.bf +++ b/IDEHelper/Tests/src/MethodCalls.bf @@ -1,4 +1,6 @@ using System; +using System.Collections; + namespace Tests { class MethodCalls @@ -205,6 +207,16 @@ namespace Tests static int sIdx = 0; static int GetNext() => ++sIdx; + public static float ParamsTest(params Span span) + { + return span[0]; + } + + public static T ParamsTest2(params Span span) + { + return span[0]; + } + [Test] public static void TestBasics() { @@ -273,6 +285,11 @@ namespace Tests Test.Assert(Named(p3:GetNext(), p2:GetNext(), p1:GetNext()) == 10321); Test.Assert(Named(p2:GetNext(), p1:GetNext(), p0:GetNext()) == 20654); Test.Assert(Named(p1:9) == 30193); + + List fList = scope .(); + fList.Add(1.2f); + Test.Assert(ParamsTest(params fList) == 1.2f); + Test.Assert(ParamsTest2(params fList) == 1.2f); } } }