From 421cace0177f37bf9ec157440d262602c88a6cd2 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sun, 16 Feb 2025 11:36:14 -0800 Subject: [PATCH] Expanding support for `params` in delegates, `params` tuple support --- BeefLibs/corlib/src/Tuple.bf | 5 + BeefySysLib/util/String.h | 8 +- IDE/mintest/minlib/src/System/Object.bf | 5 + IDEHelper/Compiler/BfCompiler.cpp | 2 + IDEHelper/Compiler/BfCompiler.h | 1 + IDEHelper/Compiler/BfExprEvaluator.cpp | 62 ++++++++---- IDEHelper/Compiler/BfModule.cpp | 107 +++++++++++++++------ IDEHelper/Compiler/BfModule.h | 3 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 12 ++- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 28 +++++- IDEHelper/Tests/src/Params.bf | 29 ++++++ 11 files changed, 203 insertions(+), 59 deletions(-) create mode 100644 BeefLibs/corlib/src/Tuple.bf create mode 100644 IDEHelper/Tests/src/Params.bf diff --git a/BeefLibs/corlib/src/Tuple.bf b/BeefLibs/corlib/src/Tuple.bf new file mode 100644 index 00000000..3a45d312 --- /dev/null +++ b/BeefLibs/corlib/src/Tuple.bf @@ -0,0 +1,5 @@ +namespace System; + +struct Tuple +{ +} \ No newline at end of file diff --git a/BeefySysLib/util/String.h b/BeefySysLib/util/String.h index 4804d7c3..d5945303 100644 --- a/BeefySysLib/util/String.h +++ b/BeefySysLib/util/String.h @@ -551,10 +551,12 @@ protected: if ((mAllocSizeAndFlags & AttrFlags) == StrPtrFlag) { // It's a reference - char* newPtr = AllocPtr(this->mLength); - memcpy(newPtr, this->mPtr, this->mLength + 1); + int allocSize = (int)BF_MAX(GetAllocSize(), this->mLength + 1); + char* newPtr = AllocPtr(allocSize); + memcpy(newPtr, this->mPtr, this->mLength); + newPtr[this->mLength] = 0; this->mPtr = newPtr; - mAllocSizeAndFlags = this->mLength | DynAllocFlag | StrPtrFlag; + mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag; } } diff --git a/IDE/mintest/minlib/src/System/Object.bf b/IDE/mintest/minlib/src/System/Object.bf index f2a47c3f..431680cf 100644 --- a/IDE/mintest/minlib/src/System/Object.bf +++ b/IDE/mintest/minlib/src/System/Object.bf @@ -213,6 +213,11 @@ namespace System public static extern bool Equals(T val1, T val2); } + struct Tuple + { + + } + struct Function : int { diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index aacada68..7a40decb 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -478,6 +478,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mTypeTypeDef = NULL; mUnboundAttributeTypeDef = NULL; mValueTypeTypeDef = NULL; + mTupleTypeDef = NULL; mResultTypeDef = NULL; mObsoleteAttributeTypeDef = NULL; mErrorAttributeTypeDef = NULL; @@ -7334,6 +7335,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mTypeTypeDef = _GetRequiredType("System.Type"); mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute"); mValueTypeTypeDef = _GetRequiredType("System.ValueType"); + mTupleTypeDef = _GetRequiredType("System.Tuple"); mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute"); mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute"); mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute"); diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 906dfe1e..dada8f41 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -379,6 +379,7 @@ public: BfTypeDef* mTypeTypeDeclDef; BfTypeDef* mTypeTypeDef; BfTypeDef* mValueTypeTypeDef; + BfTypeDef* mTupleTypeDef; BfTypeDef* mResultTypeDef; BfTypeDef* mGCTypeDef; BfTypeDef* mGenericIEnumerableTypeDef; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index b676f68e..441a3cc7 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -14741,30 +14741,19 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam if (invokeMethodInstance != NULL) { - for (int paramIdx = 0; paramIdx < (int)invokeMethodInstance->mMethodDef->mParams.size(); paramIdx++) + for (int paramIdx = 0; paramIdx < (int)invokeMethodInstance->GetParamCount(); paramIdx++) { - auto invokeParamDef = invokeMethodInstance->mMethodDef->mParams[paramIdx]; - - BfParameterDef* paramDef = new BfParameterDef(); - paramDef->mParamDeclaration = tempParamDecls.Alloc(); - BfAstNode::Zero(paramDef->mParamDeclaration); - - BfLocalVariable* localVar = new BfLocalVariable(); + BfLocalVariable* localVar = new BfLocalVariable(); if (paramIdx < (int)lambdaBindExpr->mParams.size()) { localVar->mName = lambdaBindExpr->mParams[paramIdx]->ToString(); - localVar->mNameNode = lambdaBindExpr->mParams[paramIdx]; - paramDef->mParamDeclaration->mNameNode = lambdaBindExpr->mParams[paramIdx]; + localVar->mNameNode = lambdaBindExpr->mParams[paramIdx]; } else { mModule->AssertErrorState(); - localVar->mName = invokeParamDef->mName; - paramDef->mParamDeclaration->mNameNode = NULL; - } - paramDef->mName = localVar->mName; - methodDef->mParams.push_back(paramDef); - + localVar->mName = invokeMethodInstance->GetParamName(paramIdx); + } localVar->mResolvedType = invokeMethodInstance->GetParamType(paramIdx); mModule->PopulateType(localVar->mResolvedType); localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional; @@ -14773,15 +14762,41 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam auto rootMethodState = methodState.GetRootMethodState(); localVar->mLocalVarId = rootMethodState->mCurLocalVarId++; - mModule->DoAddLocalVariable(localVar); + mModule->DoAddLocalVariable(localVar); - if (autoComplete != NULL) - autoComplete->CheckLocalDef(BfNodeDynCast(paramDef->mParamDeclaration->mNameNode), methodState.mLocals.back()); auto resolvePassData = mModule->mCompiler->mResolvePassData; if (resolvePassData != NULL) - resolvePassData->HandleLocalReference(BfNodeDynCast(paramDef->mParamDeclaration->mNameNode), mModule->mCurTypeInstance->mTypeDef, + resolvePassData->HandleLocalReference(BfNodeDynCast(localVar->mNameNode), mModule->mCurTypeInstance->mTypeDef, mModule->mCurMethodInstance->mMethodDef, localVar->mLocalVarId); } + + for (int paramIdx = 0; paramIdx < (int)invokeMethodInstance->mMethodDef->mParams.size(); paramIdx++) + { + auto invokeParamDef = invokeMethodInstance->mMethodDef->mParams[paramIdx]; + + BfParameterDef* paramDef = new BfParameterDef(); + paramDef->mParamDeclaration = tempParamDecls.Alloc(); + BfAstNode::Zero(paramDef->mParamDeclaration); + paramDef->mTypeRef = invokeParamDef->mTypeRef; + paramDef->mParamKind = invokeParamDef->mParamKind; + + if ((paramIdx < (int)lambdaBindExpr->mParams.size()) && (invokeMethodInstance->GetParamKind(paramIdx) != BfParamKind_DelegateParam)) + { + //TODO: Not always correct if we have a 'params' + paramDef->mParamDeclaration->mNameNode = lambdaBindExpr->mParams[paramIdx]; + paramDef->mName = paramDef->mParamDeclaration->mNameNode->ToString(); + } + else + { + paramDef->mParamDeclaration->mNameNode = NULL; + paramDef->mName = invokeParamDef->mName; + } + + methodDef->mParams.push_back(paramDef); + + if (autoComplete != NULL) + autoComplete->CheckLocalDef(BfNodeDynCast(paramDef->mParamDeclaration->mNameNode), methodState.mLocals.back()); + } } bool isAutocomplete = mModule->mCompiler->IsAutocomplete(); @@ -24091,12 +24106,17 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp rightTypedValueExpr.mRefNode = opToken; auto valueTypeEmpty = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mBaseType->mBaseType), {}); + + SizedArray tupleEmptyMembers; + tupleEmptyMembers.Add(valueTypeEmpty); + auto tupleTypeEmpty = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(mModule->ResolveTypeDef(mModule->mCompiler->mTupleTypeDef)), tupleEmptyMembers); + SizedArray enumMembers; enumMembers.Add(valueTypeEmpty); auto enumValue = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mBaseType), enumMembers); SizedArray tupleMembers; - tupleMembers.Add(valueTypeEmpty); + tupleMembers.Add(tupleTypeEmpty); tupleMembers.Add(mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1)); auto tupleValue = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mFieldInstances[0].mResolvedType), tupleMembers); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 00df31c4..a24fc7f8 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -3617,25 +3617,22 @@ void BfModule::FatalError(const StringImpl& error, const char* file, int line, i BfpSystem_FatalError(fullError.c_str(), "FATAL MODULE ERROR"); } -void BfModule::FatalError(const StringImpl& error, BfAstNode* refNode) +void BfModule::FatalError(const StringImpl& error, BfFailHandleKind failHandleKind) { - if (refNode != NULL) - { - auto parser = refNode->GetParserData(); - if (parser != NULL) - { - int line = -1; - int lineChar = -1; - parser->GetLineCharAtIdx(refNode->mSrcStart, line, lineChar); - if (line != -1) - FatalError(error, parser->mFileName.c_str(), line, lineChar); - } - } - FatalError(error); + if (failHandleKind == BfFailHandleKind_Normal) + FatalError(error); + else if (failHandleKind == BfFailHandleKind_Soft) + InternalError(error); } void BfModule::InternalError(const StringImpl& error, BfAstNode* refNode, const char* file, int line) { + static bool isInside = false; + if (isInside) + return; + + isInside = true; + String fullError = error; if (file != NULL) @@ -3652,6 +3649,8 @@ void BfModule::InternalError(const StringImpl& error, BfAstNode* refNode, const fullError += StrFormat("\nSource Location: %s:%d", mCurFilePosition.mFileInstance->mParser->mFileName.c_str(), mCurFilePosition.mCurLine + 1); Fail(String("INTERNAL ERROR: ") + fullError, refNode); + + isInside = false; } void BfModule::NotImpl(BfAstNode* astNode) @@ -16018,6 +16017,8 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo void BfModule::DoAddLocalVariable(BfLocalVariable* localVar) { + BF_ASSERT(localVar->mResolvedType != NULL); + while (localVar->mName.StartsWith('@')) { localVar->mNamePrefixCount++; @@ -17064,7 +17065,7 @@ void BfModule::AssertErrorState() if (mCompiler->mPassInstance->HasFailed()) return; - InternalError("Compiler in invalid state but AssertErrorState failed to prior error"); + InternalError("Compiler in invalid state but AssertErrorState failed to detect prior error"); } void BfModule::AssertParseErrorState() @@ -20008,14 +20009,17 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp { if (compositeVariableIdx == -1) { - compositeVariableIdx = (int)mCurMethodState->mLocals.size(); - - BfLocalVariable* localVar = new BfLocalVariable(); auto paramInst = &methodInstance->mParams[paramIdx]; auto paramDef = methodDef->mParams[paramInst->mParamDefIdx]; + + compositeVariableIdx = (int)mCurMethodState->mLocals.size(); + BfLocalVariable* localVar = new BfLocalVariable(); localVar->mName = paramDef->mName; localVar->mNamePrefixCount = paramDef->mNamePrefixCount; - localVar->mResolvedType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam); + if (paramDef->mTypeRef != NULL) + localVar->mResolvedType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam); + if (localVar->mResolvedType == NULL) + localVar->mResolvedType = GetPrimitiveType(BfTypeCode_None); localVar->mCompositeCount = 0; DoAddLocalVariable(localVar); } @@ -20064,9 +20068,9 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp if (genericParamInstance->mTypeConstraint != NULL) { auto typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance(); - if ((genericParamInstance->mTypeConstraint->IsDelegate()) || (genericParamInstance->mTypeConstraint->IsFunction()) || + if ((genericParamInstance->mTypeConstraint->IsDelegate()) || (genericParamInstance->mTypeConstraint->IsFunction()) || (genericParamInstance->mTypeConstraint->IsTuple()) || ((typeInstConstraint != NULL) && - ((typeInstConstraint->IsInstanceOf(mCompiler->mDelegateTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef))))) + ((typeInstConstraint->IsInstanceOf(mCompiler->mDelegateTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mTupleTypeDef))))) { BfLocalVariable* localVar = new BfLocalVariable(); localVar->mName = paramDef->mName; @@ -24965,10 +24969,43 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool isValid = true; addParams = false; } + else if (resolvedParamType->IsTuple()) + { + auto tupleType = (BfTupleType*)resolvedParamType; + PopulateType(tupleType); + + hadDelegateParams = true; + + // This means we copy the params from a delegate + BfMethodParam methodParam; + methodParam.mResolvedType = resolvedParamType; + methodParam.mParamDefIdx = paramDefIdx; + methodParam.mDelegateParamIdx = 0; + auto invokeMethodInstance = methodParam.GetDelegateParamInvoke(); + for (int delegateParamIdx = 0; delegateParamIdx < tupleType->mFieldInstances.mSize; delegateParamIdx++) + { + auto& fieldInstance = tupleType->mFieldInstances[delegateParamIdx]; + + methodParam.mDelegateParamIdx = delegateParamIdx; + mCurMethodInstance->mParams.Add(methodParam); + + if (!methodInstance->IsSpecializedGenericMethod()) + AddDependency(fieldInstance.mResolvedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ParamOrReturnValue); + } + isValid = true; + addParams = false; + } else if (resolvedParamType->IsGenericParam()) { - auto genericParamInstance = GetGenericParamInstance((BfGenericParamType*)resolvedParamType); - if (genericParamInstance->mTypeConstraint != NULL) + auto genericParamInstance = GetGenericParamInstance((BfGenericParamType*)resolvedParamType, false, BfFailHandleKind_Ignore); + if (genericParamInstance == NULL) + { + // Delegate case with a 'params T'? + mCurMethodInstance->mHadGenericDelegateParams = true; + isValid = true; + addParams = false; + } + else if (genericParamInstance->mTypeConstraint != NULL) { auto typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance(); if ((genericParamInstance->mTypeConstraint->IsArray()) || (genericParamInstance->mTypeConstraint->IsSizedArray())) @@ -24979,9 +25016,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool mCurMethodInstance->mParams.Add(methodParam); isValid = true; } - else if ((genericParamInstance->mTypeConstraint->IsDelegate()) || (genericParamInstance->mTypeConstraint->IsFunction()) || + else if ((genericParamInstance->mTypeConstraint->IsDelegate()) || (genericParamInstance->mTypeConstraint->IsFunction()) || (genericParamInstance->mTypeConstraint->IsTuple()) || ((genericParamInstance != NULL) && (typeInstConstraint != NULL) && - ((typeInstConstraint->IsInstanceOf(mCompiler->mDelegateTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef))))) + ((typeInstConstraint->IsInstanceOf(mCompiler->mDelegateTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mTupleTypeDef))))) { mCurMethodInstance->mHadGenericDelegateParams = true; isValid = true; @@ -25055,10 +25092,22 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool { if (usedParamDefIdx[methodParam.mParamDefIdx] > 1) methodParam.mDelegateParamNameCombine = true; - BfMethodInstance* invokeMethodInstance = methodParam.GetDelegateParamInvoke(); - String paramName = invokeMethodInstance->GetParamName(methodParam.mDelegateParamIdx); - if (usedNames.Contains(paramName)) - methodParam.mDelegateParamNameCombine = true; + + if (methodParam.mResolvedType->IsTuple()) + { + auto tupleType = (BfTupleType*)methodParam.mResolvedType; + auto& fieldInstance = tupleType->mFieldInstances[methodParam.mDelegateParamIdx]; + auto paramName = fieldInstance.GetFieldDef()->mName; + if (!usedNames.Add(paramName)) + methodParam.mDelegateParamNameCombine = true; + } + else + { + BfMethodInstance* invokeMethodInstance = methodParam.GetDelegateParamInvoke(); + String paramName = invokeMethodInstance->GetParamName(methodParam.mDelegateParamIdx); + if (!usedNames.Add(paramName)) + methodParam.mDelegateParamNameCombine = true; + } } } } diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index dc6609b0..8e0f3416 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1617,6 +1617,7 @@ public: public: void FatalError(const StringImpl& error, const char* file = NULL, int line = -1, int column = -1); void FatalError(const StringImpl& error, BfAstNode* refNode); + void FatalError(const StringImpl& error, BfFailHandleKind failHandleKind); void InternalError(const StringImpl& error, BfAstNode* refNode = NULL, const char* file = NULL, int line = -1); void NotImpl(BfAstNode* astNode); void AddMethodReference(const BfMethodRef& methodRef, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None); @@ -1959,7 +1960,7 @@ public: BfType* ResolveGenericType(BfType* unspecializedType, BfTypeVector* typeGenericArguments, BfTypeVector* methodGenericArguments, BfType* selfType, bool allowFail = false); BfType* ResolveSelfType(BfType* type, BfType* selfType); bool IsUnboundGeneric(BfType* type); - BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx); + BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx, BfFailHandleKind failHandleKind = BfFailHandleKind_Normal); BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type, bool checkMixinBind = false, BfFailHandleKind failHandleKind = BfFailHandleKind_Normal); void GetActiveTypeGenericParamInstances(SizedArray& genericParamInstance); BfGenericParamInstance* GetMergedGenericParamData(BfType* type, BfGenericParamFlags& outFlags, BfType*& outTypeConstraint); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index feaf80f0..b985ddb5 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -4209,6 +4209,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy { baseType = ResolveTypeDef(mCompiler->mPointerTTypeDef, BfPopulateType_Data); } + else if (resolvedTypeRef->IsTuple()) + { + baseType = ResolveTypeDef(mCompiler->mTupleTypeDef, BfPopulateType_Data); + } else if ((resolvedTypeRef->IsValueType()) && (typeDef != mCompiler->mValueTypeTypeDef)) { baseType = ResolveTypeDef(mCompiler->mValueTypeTypeDef, BfPopulateType_Data)->ToTypeInstance(); @@ -9565,7 +9569,7 @@ bool BfModule::IsUnboundGeneric(BfType* type) return (genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0; } -BfGenericParamInstance* BfModule::GetGenericTypeParamInstance(int genericParamIdx) +BfGenericParamInstance* BfModule::GetGenericTypeParamInstance(int genericParamIdx, BfFailHandleKind failHandleKind) { // When we're evaluating a method, make sure the params refer back to that method context auto curTypeInstance = mCurTypeInstance; @@ -9576,8 +9580,8 @@ BfGenericParamInstance* BfModule::GetGenericTypeParamInstance(int genericParamId BfTypeInstance* genericTypeInst = curTypeInstance->ToGenericTypeInstance(); if (genericTypeInst == NULL) - { - FatalError("Invalid mCurTypeInstance for GetGenericTypeParamInstance"); + { + FatalError("Invalid mCurTypeInstance for GetGenericTypeParamInstance", failHandleKind); return NULL; } @@ -9756,7 +9760,7 @@ BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* ty return curGenericMethodInstance->mMethodInfoEx->mGenericParams[type->mGenericParamIdx]; } - return GetGenericTypeParamInstance(type->mGenericParamIdx); + return GetGenericTypeParamInstance(type->mGenericParamIdx, failHandleKind); } bool BfModule::ResolveTypeResult_Validate(BfAstNode* typeRef, BfType* resolvedTypeRef) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 0d5aa927..89f1680c 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -698,7 +698,8 @@ BfMethodInstance* BfMethodParam::GetDelegateParamInvoke() auto methodRefType = (BfMethodRefType*)mResolvedType; return methodRefType->mMethodRef; } - + else if (mResolvedType->IsTuple()) + return NULL; BF_ASSERT(mResolvedType->IsDelegate() || mResolvedType->IsFunction()); auto bfModule = BfModule::GetModuleFor(mResolvedType); BfMethodInstance* invokeMethodInstance = bfModule->GetRawMethodInstanceAtIdx(mResolvedType->ToTypeInstance(), 0, "Invoke"); @@ -1166,6 +1167,23 @@ void BfMethodInstance::GetParamName(int paramIdx, StringImpl& name, int& namePre BfParameterDef* paramDef = mMethodDef->mParams[methodParam->mParamDefIdx]; if (methodParam->mDelegateParamIdx != -1) { + if (methodParam->mResolvedType->IsTuple()) + { + auto tupleType = (BfTupleType*)methodParam->mResolvedType; + auto& fieldInstance = tupleType->mFieldInstances[methodParam->mDelegateParamIdx]; + if (methodParam->mDelegateParamNameCombine) + name = paramDef->mName + "__" + fieldInstance.GetFieldDef()->mName; + else + name = fieldInstance.GetFieldDef()->mName; + + if (name == "p__a__a") + { + NOP; + } + + return; + } + BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke(); if (methodParam->mDelegateParamNameCombine) name = paramDef->mName + "__" + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx); @@ -1213,6 +1231,12 @@ BfType* BfMethodInstance::GetParamType(int paramIdx, bool returnUnderlyingParams BfMethodParam* methodParam = &mParams[paramIdx]; if (methodParam->mDelegateParamIdx != -1) { + if (methodParam->mResolvedType->IsTuple()) + { + auto tupleType = (BfTupleType*)methodParam->mResolvedType; + return tupleType->mFieldInstances[methodParam->mDelegateParamIdx].mResolvedType; + } + BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke(); return invokeMethodInstance->GetParamType(methodParam->mDelegateParamIdx, true); } @@ -1247,6 +1271,8 @@ bool BfMethodInstance::GetParamIsSplat(int paramIdx) if (methodParam->mDelegateParamIdx != -1) { BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke(); + if (invokeMethodInstance == NULL) + return false; return invokeMethodInstance->GetParamIsSplat(methodParam->mDelegateParamIdx); } return methodParam->mIsSplat; diff --git a/IDEHelper/Tests/src/Params.bf b/IDEHelper/Tests/src/Params.bf new file mode 100644 index 00000000..8cb1cf68 --- /dev/null +++ b/IDEHelper/Tests/src/Params.bf @@ -0,0 +1,29 @@ +using System; + +namespace Tests; + +class Params +{ + class ClassA where T : Tuple + { + public static int Test(delegate int(char8 a, params T) dlg, params T par) + { + return dlg('A', params par); + } + } + + class ClassB : ClassA<(int a, float b)> + { + + } + + [Test] + public static void TestBasics() + { + int val = ClassB.Test(scope (a, __a, b) => + { + return (.)a + (.)__a + (.)b; + }, 10, 2.3f); + Test.Assert(val == 65+10+2); + } +} \ No newline at end of file