1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Expanding support for params in delegates, params tuple support

This commit is contained in:
Brian Fiete 2025-02-16 11:36:14 -08:00
parent 4b660b2314
commit 421cace017
11 changed files with 203 additions and 59 deletions

View file

@ -0,0 +1,5 @@
namespace System;
struct Tuple
{
}

View file

@ -551,10 +551,12 @@ protected:
if ((mAllocSizeAndFlags & AttrFlags) == StrPtrFlag) if ((mAllocSizeAndFlags & AttrFlags) == StrPtrFlag)
{ {
// It's a reference // It's a reference
char* newPtr = AllocPtr(this->mLength); int allocSize = (int)BF_MAX(GetAllocSize(), this->mLength + 1);
memcpy(newPtr, this->mPtr, this->mLength + 1); char* newPtr = AllocPtr(allocSize);
memcpy(newPtr, this->mPtr, this->mLength);
newPtr[this->mLength] = 0;
this->mPtr = newPtr; this->mPtr = newPtr;
mAllocSizeAndFlags = this->mLength | DynAllocFlag | StrPtrFlag; mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
} }
} }

View file

@ -213,6 +213,11 @@ namespace System
public static extern bool Equals<T>(T val1, T val2); public static extern bool Equals<T>(T val1, T val2);
} }
struct Tuple
{
}
struct Function : int struct Function : int
{ {

View file

@ -478,6 +478,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mTypeTypeDef = NULL; mTypeTypeDef = NULL;
mUnboundAttributeTypeDef = NULL; mUnboundAttributeTypeDef = NULL;
mValueTypeTypeDef = NULL; mValueTypeTypeDef = NULL;
mTupleTypeDef = NULL;
mResultTypeDef = NULL; mResultTypeDef = NULL;
mObsoleteAttributeTypeDef = NULL; mObsoleteAttributeTypeDef = NULL;
mErrorAttributeTypeDef = NULL; mErrorAttributeTypeDef = NULL;
@ -7334,6 +7335,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mTypeTypeDef = _GetRequiredType("System.Type"); mTypeTypeDef = _GetRequiredType("System.Type");
mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute"); mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute");
mValueTypeTypeDef = _GetRequiredType("System.ValueType"); mValueTypeTypeDef = _GetRequiredType("System.ValueType");
mTupleTypeDef = _GetRequiredType("System.Tuple");
mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute"); mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute");
mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute"); mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute");
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute"); mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");

View file

@ -379,6 +379,7 @@ public:
BfTypeDef* mTypeTypeDeclDef; BfTypeDef* mTypeTypeDeclDef;
BfTypeDef* mTypeTypeDef; BfTypeDef* mTypeTypeDef;
BfTypeDef* mValueTypeTypeDef; BfTypeDef* mValueTypeTypeDef;
BfTypeDef* mTupleTypeDef;
BfTypeDef* mResultTypeDef; BfTypeDef* mResultTypeDef;
BfTypeDef* mGCTypeDef; BfTypeDef* mGCTypeDef;
BfTypeDef* mGenericIEnumerableTypeDef; BfTypeDef* mGenericIEnumerableTypeDef;

View file

@ -14741,30 +14741,19 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
if (invokeMethodInstance != NULL) 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()) if (paramIdx < (int)lambdaBindExpr->mParams.size())
{ {
localVar->mName = lambdaBindExpr->mParams[paramIdx]->ToString(); localVar->mName = lambdaBindExpr->mParams[paramIdx]->ToString();
localVar->mNameNode = lambdaBindExpr->mParams[paramIdx]; localVar->mNameNode = lambdaBindExpr->mParams[paramIdx];
paramDef->mParamDeclaration->mNameNode = lambdaBindExpr->mParams[paramIdx];
} }
else else
{ {
mModule->AssertErrorState(); mModule->AssertErrorState();
localVar->mName = invokeParamDef->mName; localVar->mName = invokeMethodInstance->GetParamName(paramIdx);
paramDef->mParamDeclaration->mNameNode = NULL;
} }
paramDef->mName = localVar->mName;
methodDef->mParams.push_back(paramDef);
localVar->mResolvedType = invokeMethodInstance->GetParamType(paramIdx); localVar->mResolvedType = invokeMethodInstance->GetParamType(paramIdx);
mModule->PopulateType(localVar->mResolvedType); mModule->PopulateType(localVar->mResolvedType);
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional; localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
@ -14775,13 +14764,39 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
mModule->DoAddLocalVariable(localVar); mModule->DoAddLocalVariable(localVar);
if (autoComplete != NULL)
autoComplete->CheckLocalDef(BfNodeDynCast<BfIdentifierNode>(paramDef->mParamDeclaration->mNameNode), methodState.mLocals.back());
auto resolvePassData = mModule->mCompiler->mResolvePassData; auto resolvePassData = mModule->mCompiler->mResolvePassData;
if (resolvePassData != NULL) if (resolvePassData != NULL)
resolvePassData->HandleLocalReference(BfNodeDynCast<BfIdentifierNode>(paramDef->mParamDeclaration->mNameNode), mModule->mCurTypeInstance->mTypeDef, resolvePassData->HandleLocalReference(BfNodeDynCast<BfIdentifierNode>(localVar->mNameNode), mModule->mCurTypeInstance->mTypeDef,
mModule->mCurMethodInstance->mMethodDef, localVar->mLocalVarId); 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<BfIdentifierNode>(paramDef->mParamDeclaration->mNameNode), methodState.mLocals.back());
}
} }
bool isAutocomplete = mModule->mCompiler->IsAutocomplete(); bool isAutocomplete = mModule->mCompiler->IsAutocomplete();
@ -24091,12 +24106,17 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp
rightTypedValueExpr.mRefNode = opToken; rightTypedValueExpr.mRefNode = opToken;
auto valueTypeEmpty = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mBaseType->mBaseType), {}); auto valueTypeEmpty = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mBaseType->mBaseType), {});
SizedArray<BfIRValue, 8> tupleEmptyMembers;
tupleEmptyMembers.Add(valueTypeEmpty);
auto tupleTypeEmpty = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(mModule->ResolveTypeDef(mModule->mCompiler->mTupleTypeDef)), tupleEmptyMembers);
SizedArray<BfIRValue, 8> enumMembers; SizedArray<BfIRValue, 8> enumMembers;
enumMembers.Add(valueTypeEmpty); enumMembers.Add(valueTypeEmpty);
auto enumValue = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mBaseType), enumMembers); auto enumValue = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mBaseType), enumMembers);
SizedArray<BfIRValue, 8> tupleMembers; SizedArray<BfIRValue, 8> tupleMembers;
tupleMembers.Add(valueTypeEmpty); tupleMembers.Add(tupleTypeEmpty);
tupleMembers.Add(mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1)); tupleMembers.Add(mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1));
auto tupleValue = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mFieldInstances[0].mResolvedType), tupleMembers); auto tupleValue = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(indexType->mFieldInstances[0].mResolvedType), tupleMembers);

View file

@ -3617,25 +3617,22 @@ void BfModule::FatalError(const StringImpl& error, const char* file, int line, i
BfpSystem_FatalError(fullError.c_str(), "FATAL MODULE ERROR"); 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) if (failHandleKind == BfFailHandleKind_Normal)
{
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); FatalError(error);
else if (failHandleKind == BfFailHandleKind_Soft)
InternalError(error);
} }
void BfModule::InternalError(const StringImpl& error, BfAstNode* refNode, const char* file, int line) 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; String fullError = error;
if (file != NULL) 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); fullError += StrFormat("\nSource Location: %s:%d", mCurFilePosition.mFileInstance->mParser->mFileName.c_str(), mCurFilePosition.mCurLine + 1);
Fail(String("INTERNAL ERROR: ") + fullError, refNode); Fail(String("INTERNAL ERROR: ") + fullError, refNode);
isInside = false;
} }
void BfModule::NotImpl(BfAstNode* astNode) void BfModule::NotImpl(BfAstNode* astNode)
@ -16018,6 +16017,8 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo
void BfModule::DoAddLocalVariable(BfLocalVariable* localVar) void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
{ {
BF_ASSERT(localVar->mResolvedType != NULL);
while (localVar->mName.StartsWith('@')) while (localVar->mName.StartsWith('@'))
{ {
localVar->mNamePrefixCount++; localVar->mNamePrefixCount++;
@ -17064,7 +17065,7 @@ void BfModule::AssertErrorState()
if (mCompiler->mPassInstance->HasFailed()) if (mCompiler->mPassInstance->HasFailed())
return; 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() void BfModule::AssertParseErrorState()
@ -20008,14 +20009,17 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
{ {
if (compositeVariableIdx == -1) if (compositeVariableIdx == -1)
{ {
compositeVariableIdx = (int)mCurMethodState->mLocals.size();
BfLocalVariable* localVar = new BfLocalVariable();
auto paramInst = &methodInstance->mParams[paramIdx]; auto paramInst = &methodInstance->mParams[paramIdx];
auto paramDef = methodDef->mParams[paramInst->mParamDefIdx]; auto paramDef = methodDef->mParams[paramInst->mParamDefIdx];
compositeVariableIdx = (int)mCurMethodState->mLocals.size();
BfLocalVariable* localVar = new BfLocalVariable();
localVar->mName = paramDef->mName; localVar->mName = paramDef->mName;
localVar->mNamePrefixCount = paramDef->mNamePrefixCount; localVar->mNamePrefixCount = paramDef->mNamePrefixCount;
if (paramDef->mTypeRef != NULL)
localVar->mResolvedType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam); localVar->mResolvedType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam);
if (localVar->mResolvedType == NULL)
localVar->mResolvedType = GetPrimitiveType(BfTypeCode_None);
localVar->mCompositeCount = 0; localVar->mCompositeCount = 0;
DoAddLocalVariable(localVar); DoAddLocalVariable(localVar);
} }
@ -20064,9 +20068,9 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
if (genericParamInstance->mTypeConstraint != NULL) if (genericParamInstance->mTypeConstraint != NULL)
{ {
auto typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance(); 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 != 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(); BfLocalVariable* localVar = new BfLocalVariable();
localVar->mName = paramDef->mName; localVar->mName = paramDef->mName;
@ -24965,10 +24969,43 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
isValid = true; isValid = true;
addParams = false; 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()) else if (resolvedParamType->IsGenericParam())
{ {
auto genericParamInstance = GetGenericParamInstance((BfGenericParamType*)resolvedParamType); auto genericParamInstance = GetGenericParamInstance((BfGenericParamType*)resolvedParamType, false, BfFailHandleKind_Ignore);
if (genericParamInstance->mTypeConstraint != NULL) 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(); auto typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance();
if ((genericParamInstance->mTypeConstraint->IsArray()) || (genericParamInstance->mTypeConstraint->IsSizedArray())) if ((genericParamInstance->mTypeConstraint->IsArray()) || (genericParamInstance->mTypeConstraint->IsSizedArray()))
@ -24979,9 +25016,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
mCurMethodInstance->mParams.Add(methodParam); mCurMethodInstance->mParams.Add(methodParam);
isValid = true; 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) && ((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; mCurMethodInstance->mHadGenericDelegateParams = true;
isValid = true; isValid = true;
@ -25055,13 +25092,25 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{ {
if (usedParamDefIdx[methodParam.mParamDefIdx] > 1) if (usedParamDefIdx[methodParam.mParamDefIdx] > 1)
methodParam.mDelegateParamNameCombine = true; 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(); BfMethodInstance* invokeMethodInstance = methodParam.GetDelegateParamInvoke();
String paramName = invokeMethodInstance->GetParamName(methodParam.mDelegateParamIdx); String paramName = invokeMethodInstance->GetParamName(methodParam.mDelegateParamIdx);
if (usedNames.Contains(paramName)) if (!usedNames.Add(paramName))
methodParam.mDelegateParamNameCombine = true; methodParam.mDelegateParamNameCombine = true;
} }
} }
} }
}
int argIdx = 0; int argIdx = 0;
resolveModule->PopulateType(methodInstance->mReturnType, BfPopulateType_Data); resolveModule->PopulateType(methodInstance->mReturnType, BfPopulateType_Data);

View file

@ -1617,6 +1617,7 @@ public:
public: public:
void FatalError(const StringImpl& error, const char* file = NULL, int line = -1, int column = -1); 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, 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 InternalError(const StringImpl& error, BfAstNode* refNode = NULL, const char* file = NULL, int line = -1);
void NotImpl(BfAstNode* astNode); void NotImpl(BfAstNode* astNode);
void AddMethodReference(const BfMethodRef& methodRef, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None); 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* ResolveGenericType(BfType* unspecializedType, BfTypeVector* typeGenericArguments, BfTypeVector* methodGenericArguments, BfType* selfType, bool allowFail = false);
BfType* ResolveSelfType(BfType* type, BfType* selfType); BfType* ResolveSelfType(BfType* type, BfType* selfType);
bool IsUnboundGeneric(BfType* type); 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); BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type, bool checkMixinBind = false, BfFailHandleKind failHandleKind = BfFailHandleKind_Normal);
void GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInstance*, 4>& genericParamInstance); void GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInstance*, 4>& genericParamInstance);
BfGenericParamInstance* GetMergedGenericParamData(BfType* type, BfGenericParamFlags& outFlags, BfType*& outTypeConstraint); BfGenericParamInstance* GetMergedGenericParamData(BfType* type, BfGenericParamFlags& outFlags, BfType*& outTypeConstraint);

View file

@ -4209,6 +4209,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
baseType = ResolveTypeDef(mCompiler->mPointerTTypeDef, BfPopulateType_Data); baseType = ResolveTypeDef(mCompiler->mPointerTTypeDef, BfPopulateType_Data);
} }
else if (resolvedTypeRef->IsTuple())
{
baseType = ResolveTypeDef(mCompiler->mTupleTypeDef, BfPopulateType_Data);
}
else if ((resolvedTypeRef->IsValueType()) && (typeDef != mCompiler->mValueTypeTypeDef)) else if ((resolvedTypeRef->IsValueType()) && (typeDef != mCompiler->mValueTypeTypeDef))
{ {
baseType = ResolveTypeDef(mCompiler->mValueTypeTypeDef, BfPopulateType_Data)->ToTypeInstance(); baseType = ResolveTypeDef(mCompiler->mValueTypeTypeDef, BfPopulateType_Data)->ToTypeInstance();
@ -9565,7 +9569,7 @@ bool BfModule::IsUnboundGeneric(BfType* type)
return (genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0; 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 // When we're evaluating a method, make sure the params refer back to that method context
auto curTypeInstance = mCurTypeInstance; auto curTypeInstance = mCurTypeInstance;
@ -9577,7 +9581,7 @@ BfGenericParamInstance* BfModule::GetGenericTypeParamInstance(int genericParamId
if (genericTypeInst == NULL) if (genericTypeInst == NULL)
{ {
FatalError("Invalid mCurTypeInstance for GetGenericTypeParamInstance"); FatalError("Invalid mCurTypeInstance for GetGenericTypeParamInstance", failHandleKind);
return NULL; return NULL;
} }
@ -9756,7 +9760,7 @@ BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* ty
return curGenericMethodInstance->mMethodInfoEx->mGenericParams[type->mGenericParamIdx]; return curGenericMethodInstance->mMethodInfoEx->mGenericParams[type->mGenericParamIdx];
} }
return GetGenericTypeParamInstance(type->mGenericParamIdx); return GetGenericTypeParamInstance(type->mGenericParamIdx, failHandleKind);
} }
bool BfModule::ResolveTypeResult_Validate(BfAstNode* typeRef, BfType* resolvedTypeRef) bool BfModule::ResolveTypeResult_Validate(BfAstNode* typeRef, BfType* resolvedTypeRef)

View file

@ -698,7 +698,8 @@ BfMethodInstance* BfMethodParam::GetDelegateParamInvoke()
auto methodRefType = (BfMethodRefType*)mResolvedType; auto methodRefType = (BfMethodRefType*)mResolvedType;
return methodRefType->mMethodRef; return methodRefType->mMethodRef;
} }
else if (mResolvedType->IsTuple())
return NULL;
BF_ASSERT(mResolvedType->IsDelegate() || mResolvedType->IsFunction()); BF_ASSERT(mResolvedType->IsDelegate() || mResolvedType->IsFunction());
auto bfModule = BfModule::GetModuleFor(mResolvedType); auto bfModule = BfModule::GetModuleFor(mResolvedType);
BfMethodInstance* invokeMethodInstance = bfModule->GetRawMethodInstanceAtIdx(mResolvedType->ToTypeInstance(), 0, "Invoke"); 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]; BfParameterDef* paramDef = mMethodDef->mParams[methodParam->mParamDefIdx];
if (methodParam->mDelegateParamIdx != -1) 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(); BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke();
if (methodParam->mDelegateParamNameCombine) if (methodParam->mDelegateParamNameCombine)
name = paramDef->mName + "__" + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx); name = paramDef->mName + "__" + invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx);
@ -1213,6 +1231,12 @@ BfType* BfMethodInstance::GetParamType(int paramIdx, bool returnUnderlyingParams
BfMethodParam* methodParam = &mParams[paramIdx]; BfMethodParam* methodParam = &mParams[paramIdx];
if (methodParam->mDelegateParamIdx != -1) if (methodParam->mDelegateParamIdx != -1)
{ {
if (methodParam->mResolvedType->IsTuple())
{
auto tupleType = (BfTupleType*)methodParam->mResolvedType;
return tupleType->mFieldInstances[methodParam->mDelegateParamIdx].mResolvedType;
}
BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke(); BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke();
return invokeMethodInstance->GetParamType(methodParam->mDelegateParamIdx, true); return invokeMethodInstance->GetParamType(methodParam->mDelegateParamIdx, true);
} }
@ -1247,6 +1271,8 @@ bool BfMethodInstance::GetParamIsSplat(int paramIdx)
if (methodParam->mDelegateParamIdx != -1) if (methodParam->mDelegateParamIdx != -1)
{ {
BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke(); BfMethodInstance* invokeMethodInstance = methodParam->GetDelegateParamInvoke();
if (invokeMethodInstance == NULL)
return false;
return invokeMethodInstance->GetParamIsSplat(methodParam->mDelegateParamIdx); return invokeMethodInstance->GetParamIsSplat(methodParam->mDelegateParamIdx);
} }
return methodParam->mIsSplat; return methodParam->mIsSplat;

View file

@ -0,0 +1,29 @@
using System;
namespace Tests;
class Params
{
class ClassA<T> 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);
}
}