From de6a68911aeef7d14fdd473a9fbbb3e28113ed3e Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 31 Mar 2020 07:46:01 -0700 Subject: [PATCH] New function/delegate casting rules, similar to tuple rules --- IDEHelper/Compiler/BfCompiler.cpp | 9 ++- IDEHelper/Compiler/BfModule.cpp | 3 + IDEHelper/Compiler/BfModuleTypeUtils.cpp | 79 ++++++++++++++++++++-- IDEHelper/Compiler/BfReducer.cpp | 31 ++++++--- IDEHelper/Compiler/BfReducer.h | 2 +- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 35 ++++++---- IDEHelper/Compiler/BfResolvedTypeUtils.h | 3 +- IDEHelper/Tests/src/Delegates.bf | 13 ++++ 8 files changed, 143 insertions(+), 32 deletions(-) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 3c784153..600ec3bc 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -7024,6 +7024,7 @@ void BfCompiler::GenerateAutocompleteInfo() int dispParamIdx = 0; + StringT<64> paramName; for (int paramIdx = 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++) { auto paramKind = methodInstance->GetParamKind(paramIdx); @@ -7083,8 +7084,12 @@ void BfCompiler::GenerateAutocompleteInfo() } else methodText += bfModule->TypeToString(type, BfTypeNameFlag_ResolveGenericParamNames, genericMethodNameOverridesPtr); - methodText += " "; - methodText += methodInstance->GetParamName(paramIdx); + methodInstance->GetParamName(paramIdx, paramName); + if (!paramName.IsEmpty()) + { + methodText += " "; + methodText += paramName; + } if (paramInitializer != NULL) { diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index ec008683..d8a57b92 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -12444,6 +12444,9 @@ void BfModule::CreateDIRetVal() void BfModule::CheckVariableDef(BfLocalVariable* variableDef) { + if (variableDef->mName.IsEmpty()) + return; + BfLocalVarEntry* localVarEntryPtr = NULL; if ((mCurMethodState != NULL) && (mCurMethodState->mLocalVarSet.TryGet(BfLocalVarEntry(variableDef), &localVarEntryPtr))) { diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index dc3751aa..c7f635b3 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -9530,6 +9530,62 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf return BfTypedValue(); } + // Function->Function and Delegate->Delegate where type is compatible but not exact + if (((typedVal.mType->IsDelegate()) || (typedVal.mType->IsFunction())) && + ((typedVal.mType->IsDelegate()) == (toType->IsDelegate())) && + ((typedVal.mType->IsFunction()) == (toType->IsFunction()))) + { + auto fromDelegateType = (BfDelegateType*)typedVal.mType->ToTypeInstance(); + auto toDelegateType = (BfDelegateType*)toType; + + if (fromDelegateType->mReturnType == toDelegateType->mReturnType) + { + auto fromMethodInst = GetRawMethodByName(fromDelegateType, "Invoke"); + auto toMethodInst = GetRawMethodByName(toDelegateType, "Invoke"); + + if ((fromMethodInst->mMethodDef->mCallingConvention == toMethodInst->mMethodDef->mCallingConvention) && + (fromMethodInst->mReturnType == toMethodInst->mReturnType) && + (fromMethodInst->GetParamCount() == toMethodInst->GetParamCount())) + { + bool matched = true; + + StringT<64> fromParamName; + StringT<64> toParamName; + + for (int paramIdx = 0; paramIdx < (int)fromMethodInst->GetParamCount(); paramIdx++) + { + bool nameMatches = true; + + if (!explicitCast) + { + fromMethodInst->GetParamName(paramIdx, fromParamName); + toMethodInst->GetParamName(paramIdx, toParamName); + if ((!fromParamName.IsEmpty()) && (!toParamName.IsEmpty())) + nameMatches = fromParamName == toParamName; + } + + if ((fromMethodInst->GetParamKind(paramIdx) == toMethodInst->GetParamKind(paramIdx)) && + (fromMethodInst->GetParamType(paramIdx) == toMethodInst->GetParamType(paramIdx)) && + (nameMatches)) + { + // Matched, required for implicit/explicit + } + else + { + matched = false; + break; + } + } + + if (matched) + { + BfTypedValue loadedVal = LoadValue(typedVal); + return BfTypedValue(mBfIRBuilder->CreateBitCast(loadedVal.mValue, mBfIRBuilder->MapType(toType)), toType); + } + } + } + } + // Struct truncate if ((typedVal.mType->IsStruct()) && (toType->IsStruct())) { @@ -10012,6 +10068,16 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF auto methodDef = delegateType->mTypeDef->mMethods[0]; + switch (methodDef->mCallingConvention) + { + case BfCallingConvention_Stdcall: + str += "[StdCall] "; + break; + case BfCallingConvention_Fastcall: + str += "[FastCall] "; + break; + } + if (resolvedType->IsDelegateFromTypeRef()) str += "delegate "; else @@ -10024,13 +10090,14 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF str += ", "; auto paramDef = methodDef->mParams[paramIdx]; BfTypeNameFlags innerFlags = (BfTypeNameFlags)(typeNameFlags & ~(BfTypeNameFlag_OmitNamespace | BfTypeNameFlag_OmitOuterType)); - - //TODO: Why was this necessary? It made some errors show incorrectly -// if (delegateType->mIsUnspecializedTypeVariation) -// innerFlags = (BfTypeNameFlags)(innerFlags & ~BfTypeNameFlag_ResolveGenericParamNames); + DoTypeToString(str, delegateType->mParams[paramIdx], innerFlags, genericMethodNameOverrides); - str += " "; - str += paramDef->mName; + + if (!paramDef->mName.IsEmpty()) + { + str += " "; + str += paramDef->mName; + } } str += ")"; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index a9719421..1ba57491 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -4602,7 +4602,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF BfDeferredAstSizedArray params(delegateTypeRef->mParams, mAlloc); BfDeferredAstSizedArray commas(delegateTypeRef->mCommas, mAlloc); - auto closeNode = ParseMethodParams(delegateTypeRef, ¶ms, &commas, BfToken_RParen); + auto closeNode = ParseMethodParams(delegateTypeRef, ¶ms, &commas, BfToken_RParen, false); if (closeNode == NULL) { if (!params.empty()) @@ -6523,7 +6523,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth) if (openToken == NULL) return indexerDeclaration; MEMBER_SET(indexerDeclaration, mOpenBracket, openToken); - auto endToken = ParseMethodParams(indexerDeclaration, ¶ms, &commas, BfToken_RBracket); + auto endToken = ParseMethodParams(indexerDeclaration, ¶ms, &commas, BfToken_RBracket, true); if (endToken == NULL) return indexerDeclaration; MEMBER_SET(indexerDeclaration, mCloseBracket, endToken); @@ -8401,7 +8401,7 @@ BfCommentNode * BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode* return NULL; } -BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl* params, SizedArrayImpl* commas, BfToken endToken) +BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl* params, SizedArrayImpl* commas, BfToken endToken, bool requireNames) { BfAstNode* nameAfterNode = node; @@ -8713,18 +8713,29 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImplmNameNode == NULL) { - auto nameIdentifierNode = ExpectIdentifierAfter(node, "parameter name"); - if (nameIdentifierNode == NULL) + BfAstNode* nameIdentifierNode; + if (requireNames) { - if (!allowNameFail) - return NULL; + nameIdentifierNode = ExpectIdentifierAfter(node, "parameter name"); + if (nameIdentifierNode == NULL) + { + if (!allowNameFail) + return NULL; + } } else + { + nameIdentifierNode = BfNodeDynCast(mVisitorPos.GetNext()); + if (nameIdentifierNode != NULL) + mVisitorPos.MoveNext(); + } + + if (nameIdentifierNode != NULL) { paramDecl->mNameNode = nameIdentifierNode; MoveNode(nameIdentifierNode, paramDecl); - nameAfterNode = nameIdentifierNode; - } + nameAfterNode = nameIdentifierNode; + } } } @@ -8770,7 +8781,7 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm methodDeclaration->mOpenParen = tokenNode; MoveNode(methodDeclaration->mOpenParen, methodDeclaration); - methodDeclaration->mCloseParen = ParseMethodParams(methodDeclaration, params, commas, BfToken_RParen); + methodDeclaration->mCloseParen = ParseMethodParams(methodDeclaration, params, commas, BfToken_RParen, true); // RParen if (methodDeclaration->mCloseParen == NULL) diff --git a/IDEHelper/Compiler/BfReducer.h b/IDEHelper/Compiler/BfReducer.h index 8c260c8e..5fad8b32 100644 --- a/IDEHelper/Compiler/BfReducer.h +++ b/IDEHelper/Compiler/BfReducer.h @@ -179,7 +179,7 @@ public: BfExpression* CheckBinaryOperatorPrecedence(BfBinaryOperatorExpression* binOpExpression); BfExpression* ApplyToFirstExpression(BfUnaryOperatorExpression* unaryOp, BfExpression* target); BfIdentifierNode* ExtractExplicitInterfaceRef(BfAstNode* memberDeclaration, BfIdentifierNode* nameIdentifier, BfTypeReference** outExplicitInterface, BfTokenNode** outExplicitInterfaceDotToken); - BfTokenNode* ParseMethodParams(BfAstNode* node, SizedArrayImpl* params, SizedArrayImpl* commas, BfToken endToken); + BfTokenNode* ParseMethodParams(BfAstNode* node, SizedArrayImpl* params, SizedArrayImpl* commas, BfToken endToken, bool requireNames); BfTokenNode* ReadArguments(BfAstNode* parentNode, BfAstNode* afterNode, SizedArrayImpl* arguments, SizedArrayImpl* commas, BfToken endToken, bool allowSkippedArgs = false, CreateExprFlags createExprFlags = CreateExprFlags_None); void ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, BfBlock* block); BfAstNode* ReadTypeMember(BfTokenNode* node, int depth = 0); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index dc4032b0..e32f267d 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -676,18 +676,22 @@ int BfMethodInstance::GetImplicitParamCount() return 0; } -String BfMethodInstance::GetParamName(int paramIdx) +void BfMethodInstance::GetParamName(int paramIdx, StringImpl& name) { if (paramIdx == -1) { BF_ASSERT(!mMethodDef->mIsStatic); - return "this"; + name = "this"; + return; } if ((mMethodInfoEx != NULL) && (mMethodInfoEx->mClosureInstanceInfo != NULL) && (mMethodDef->mIsLocalMethod)) { if (paramIdx < (int)mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries.size()) - return mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries[paramIdx].mName; + { + name = mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries[paramIdx].mName; + return; + } } BfMethodParam* methodParam = &mParams[paramIdx]; @@ -696,11 +700,19 @@ String BfMethodInstance::GetParamName(int paramIdx) { BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke(); if (methodParam->mDelegateParamNameCombine) - return paramDef->mName + "__" + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx); + name = paramDef->mName + "__" + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx); else - return invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx); + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx, name); + return; } - return paramDef->mName; + name = paramDef->mName; +} + +String BfMethodInstance::GetParamName(int paramIdx) +{ + String paramName; + GetParamName(paramIdx, paramName); + return paramName; } BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType) @@ -2644,11 +2656,6 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash BfTypeReference* fieldType = param->mTypeRef; hashVal = ((hashVal ^ (Hash(fieldType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; hashVal = ((hashVal ^ (HashNode(param->mNameNode))) << 5) - hashVal; - - if (param->mNameNode == NULL) - { - ctx->mFailed = true; - } } return hashVal; @@ -3158,7 +3165,11 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* { if (!Equals(lhsInvokeMethodInstance->GetParamType(paramIdx), rhsDelegateType->mParams[paramIdx]->mTypeRef, ctx)) return false; - if (lhsInvokeMethodInstance->GetParamName(paramIdx) != rhsDelegateType->mParams[paramIdx]->mNameNode->ToString()) + StringView rhsParamName; + if (rhsDelegateType->mParams[paramIdx]->mNameNode != NULL) + rhsParamName = rhsDelegateType->mParams[paramIdx]->mNameNode->ToStringView(); + + if (lhsInvokeMethodInstance->GetParamName(paramIdx) != rhsParamName) return false; } return true; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 75c7e185..6b116ced 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -817,7 +817,8 @@ public: bool IsTestMethod(); int GetParamCount(); int GetImplicitParamCount(); - String GetParamName(int paramIdx); + void GetParamName(int paramIdx, StringImpl& name); + String GetParamName(int paramIdx); BfType* GetParamType(int paramIdx, bool useResolvedType = true); bool GetParamIsSplat(int paramIdx); BfParamKind GetParamKind(int paramIdx); diff --git a/IDEHelper/Tests/src/Delegates.bf b/IDEHelper/Tests/src/Delegates.bf index 004810d4..c2233c18 100644 --- a/IDEHelper/Tests/src/Delegates.bf +++ b/IDEHelper/Tests/src/Delegates.bf @@ -1,3 +1,5 @@ +#pragma warning disable 168 + using System; namespace Tests @@ -137,5 +139,16 @@ namespace Tests ClassA ca = scope .(); ca.TestLambda(); } + + public static void TestCasting() + { + delegate int(int, int) dlg0 = null; + delegate int(int a, int b) dlg1 = dlg0; + delegate int(int a2, int b2) dlg2 = (.)dlg1; + + function int(int, int) func0 = null; + function int(int a, int b) func1 = func0; + function int(int a2, int b2) func2 = (.)func1; + } } }