diff --git a/IDEHelper/Compiler/BfMangler.cpp b/IDEHelper/Compiler/BfMangler.cpp index 257e5633..989bb87f 100644 --- a/IDEHelper/Compiler/BfMangler.cpp +++ b/IDEHelper/Compiler/BfMangler.cpp @@ -1214,6 +1214,11 @@ bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl& { name += "_"; name += methodDef->mParams[paramIdx]->mName; + if (methodDef->mParams[paramIdx]->mParamKind == BfParamKind_VarArgs) + { + name += "__varargs"; + continue; + } typeVec.push_back(BfNodeDynCast(methodDef->mParams[paramIdx]->mTypeRef)->mType); } name += '@'; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index b2ac8df9..fba3451e 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -7628,7 +7628,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty directTypeRef->Init(returnType); methodDef->mReturnTypeRef = directTypeRef; delegateInfo->mReturnType = returnType; - delegateInfo->mHasExplicitThis = unspecializedDelegateInfo->mHasExplicitThis; + delegateInfo->mHasExplicitThis = unspecializedDelegateInfo->mHasExplicitThis; + delegateInfo->mHasVarArgs = unspecializedDelegateInfo->mHasVarArgs; int paramIdx = 0; for (int paramIdx = 0; paramIdx < (int)paramTypes.size(); paramIdx++) @@ -10197,13 +10198,28 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula bool hasMutSpecifier = false; bool isFirst = true; bool isDelegate = delegateTypeRef->mTypeToken->GetToken() == BfToken_Delegate; + bool hasVarArgs = false; Array paramTypes; - for (auto param : delegateTypeRef->mParams) + for (int paramIdx = 0; paramIdx < delegateTypeRef->mParams.size(); paramIdx++) { + auto param = delegateTypeRef->mParams[paramIdx]; BfResolveTypeRefFlags resolveTypeFlags = BfResolveTypeRefFlag_AllowRef; if ((param->mNameNode != NULL) && (param->mNameNode->Equals("this"))) resolveTypeFlags = (BfResolveTypeRefFlags)(resolveTypeFlags | BfResolveTypeRefFlag_NoWarnOnMut); + + if (paramIdx == delegateTypeRef->mParams.size() - 1) + { + if (auto dotTypeRef = BfNodeDynCast(param->mTypeRef)) + { + if (dotTypeRef->mDotToken->mToken == BfToken_DotDotDot) + { + hasVarArgs = true; + continue; + } + } + } + auto paramType = ResolveTypeRef(param->mTypeRef, BfPopulateType_Declaration, resolveTypeFlags); if (paramType == NULL) { @@ -10319,7 +10335,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula } auto directTypeRef = BfAstNode::ZeroedAlloc(); - delegateInfo->mDirectAllocNodes.push_back(directTypeRef); + delegateInfo->mDirectAllocNodes.push_back(directTypeRef); if (typeDef->mIsDelegate) directTypeRef->Init(delegateType); else @@ -10332,6 +10348,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula methodDef->mReturnTypeRef = directTypeRef; delegateInfo->mReturnType = returnType; delegateInfo->mHasExplicitThis = functionThisType != NULL; + delegateInfo->mHasVarArgs = hasVarArgs; auto hashVal = mContext->mResolvedTypes.Hash(typeRef, &lookupCtx); @@ -10361,11 +10378,18 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula paramDef->mName = paramName; if ((paramIdx == 0) && (functionThisType != NULL)) paramDef->mParamKind = BfParamKind_ExplicitThis; - methodDef->mParams.push_back(paramDef); + methodDef->mParams.push_back(paramDef); delegateInfo->mParams.Add(paramType); } + if (delegateInfo->mHasVarArgs) + { + BfParameterDef* paramDef = new BfParameterDef(); + paramDef->mParamKind = BfParamKind_VarArgs; + methodDef->mParams.push_back(paramDef); + } + typeDef->mMethods.push_back(methodDef); if (failed) @@ -13073,6 +13097,12 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF auto paramDef = methodDef->mParams[paramIdx]; BfTypeNameFlags innerFlags = (BfTypeNameFlags)(typeNameFlags & ~(BfTypeNameFlag_OmitNamespace | BfTypeNameFlag_OmitOuterType | BfTypeNameFlag_ExtendedInfo)); + if (paramDef->mParamKind == BfParamKind_VarArgs) + { + str += "..."; + continue; + } + auto paramType = delegateInfo->mParams[paramIdx]; if ((paramIdx == 0) && (delegateInfo->mHasExplicitThis)) { diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 87b263c4..b00c8d54 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -9262,12 +9262,22 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm methodDeclaration->mOpenParen = tokenNode; MoveNode(methodDeclaration->mOpenParen, methodDeclaration); - if (auto nextToken = BfNodeDynCast(mVisitorPos.GetNext())) + bool isFunction = false; + bool isDelegate = false; + if ((mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Function)) + isFunction = true; + else if ((mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Delegate)) + isDelegate = true; + + if ((!isFunction) && (!isDelegate)) { - if (nextToken->mToken == BfToken_This) + if (auto nextToken = BfNodeDynCast(mVisitorPos.GetNext())) { - MEMBER_SET(methodDeclaration, mThisToken, nextToken); - mVisitorPos.MoveNext(); + if (nextToken->mToken == BfToken_This) + { + MEMBER_SET(methodDeclaration, mThisToken, nextToken); + mVisitorPos.MoveNext(); + } } } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 57d66b6a..26044546 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -2736,6 +2736,7 @@ BfResolvedTypeSet::~BfResolvedTypeSet() #define HASH_DELEGATE 11 #define HASH_CONSTEXPR 12 #define HASH_GLOBAL 13 +#define HASH_DOTDOTDOT 14 BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType) { @@ -2808,16 +2809,24 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) auto methodDef = typeInst->mTypeDef->mMethods[0]; BF_ASSERT(methodDef->mName == "Invoke"); - BF_ASSERT(delegateInfo->mParams.size() == methodDef->mParams.size()); + + int infoParamCount = (int)delegateInfo->mParams.size(); + if (delegateInfo->mHasVarArgs) + infoParamCount++; + + BF_ASSERT(infoParamCount == methodDef->mParams.size()); for (int paramIdx = 0; paramIdx < delegateInfo->mParams.size(); paramIdx++) - { + { // Parse attributes? hashVal = ((hashVal ^ (Hash(delegateInfo->mParams[paramIdx], ctx))) << 5) - hashVal; String paramName = methodDef->mParams[paramIdx]->mName; int nameHash = (int)Hash64(paramName.c_str(), (int)paramName.length()); hashVal = ((hashVal ^ (nameHash)) << 5) - hashVal; } + + if (delegateInfo->mHasVarArgs) + hashVal = ((hashVal ^ HASH_DOTDOTDOT) << 5) - hashVal; return hashVal; } @@ -3397,8 +3406,9 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash bool isFirstParam = true; - for (auto param : delegateTypeRef->mParams) + for (int paramIdx = 0; paramIdx < delegateTypeRef->mParams.size(); paramIdx++) { + auto param = delegateTypeRef->mParams[paramIdx]; // Parse attributes? BfTypeReference* fieldType = param->mTypeRef; @@ -3410,8 +3420,20 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash fieldType = refNode->mElementType; } } + + if (paramIdx == delegateTypeRef->mParams.size() - 1) + { + if (auto dotTypeRef = BfNodeDynCastExact(fieldType)) + { + if (dotTypeRef->mDotToken->mToken == BfToken_DotDotDot) + { + hashVal = ((hashVal ^ HASH_DOTDOTDOT) << 5) - hashVal; + continue; + } + } + } - hashVal = ((hashVal ^ (Hash(fieldType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(fieldType, ctx, (BfHashFlags)(BfHashFlag_AllowRef)))) << 5) - hashVal; hashVal = ((hashVal ^ (HashNode(param->mNameNode))) << 5) - hashVal; isFirstParam = true; } @@ -3511,8 +3533,8 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash hashVal = ((hashVal ^ (Hash(resultType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; return hashVal; } - else if (auto dotTypeRef = BfNodeDynCastExact(typeRef)) - { + else if (auto dotTypeRef = BfNodeDynCastExact(typeRef)) + { ctx->mModule->ResolveTypeRef(dotTypeRef, BfPopulateType_Identity, ctx->mResolveFlags); ctx->mFailed = true; return 0; @@ -4009,7 +4031,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* return false; bool handled = false; - auto lhsThisType = lhsDelegateInfo->mParams[0]; + auto lhsThisType = lhsDelegateInfo->mParams[0]; auto rhsThisType = ctx->mModule->ResolveTypeRef(param0->mTypeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoWarnOnMut | BfResolveTypeRefFlag_AllowRef)); bool wantsMutating = false; @@ -4032,11 +4054,16 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* } } - if (lhsDelegateInfo->mParams.size() != (int)rhsDelegateType->mParams.size()) + int lhsParamsCount = (int)lhsDelegateInfo->mParams.size(); + if (lhsDelegateInfo->mHasVarArgs) + lhsParamsCount++; + + if (lhsParamsCount != (int)rhsDelegateType->mParams.size()) return false; for (int paramIdx = paramRefOfs; paramIdx < lhsDelegateInfo->mParams.size(); paramIdx++) { - if (!Equals(lhsDelegateInfo->mParams[paramIdx], rhsDelegateType->mParams[paramIdx]->mTypeRef, ctx)) + auto paramTypeRef = rhsDelegateType->mParams[paramIdx]->mTypeRef; + if (!Equals(lhsDelegateInfo->mParams[paramIdx], paramTypeRef, ctx)) return false; StringView rhsParamName; if (rhsDelegateType->mParams[paramIdx]->mNameNode != NULL) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 167488e3..4e8172bc 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -32,7 +32,8 @@ enum BfResolveTypeRefFlags BfResolveTypeRefFlag_NoReify = 0x200, BfResolveTypeRefFlag_NoCreate = 0x400, BfResolveTypeRefFlag_NoWarnOnMut = 0x800, - BfResolveTypeRefFlag_DisallowComptime = 0x1000 + BfResolveTypeRefFlag_DisallowComptime = 0x1000, + BfResolveTypeRefFlag_AllowDotDotDot = 0x2000 }; enum BfTypeNameFlags : uint16 @@ -443,12 +444,14 @@ public: BfType* mReturnType; Array mParams; bool mHasExplicitThis; + bool mHasVarArgs; public: BfDelegateInfo() { mReturnType = NULL; mHasExplicitThis = false; + mHasVarArgs = false; } ~BfDelegateInfo() @@ -2478,7 +2481,8 @@ public: { BfHashFlag_None = 0, BfHashFlag_AllowRef = 1, - BfHashFlag_AllowGenericParamConstValue = 2 + BfHashFlag_AllowGenericParamConstValue = 2, + BfHashFlag_AllowDotDotDot = 4, }; class LookupContext