1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00

Added '?' capture, reworked '&' capture, allow 'this' capture

This commit is contained in:
Brian Fiete 2023-03-17 08:38:45 -07:00
parent 7ab6800f40
commit 7f695596b8
5 changed files with 70 additions and 22 deletions

View file

@ -14383,7 +14383,10 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
autoComplete->CheckLocalRef(captureEntry.mNameNode, localVar); autoComplete->CheckLocalRef(captureEntry.mNameNode, localVar);
if (((mModule->mCurMethodState->mClosureState == NULL) || (mModule->mCurMethodState->mClosureState->mCapturing)) && if (((mModule->mCurMethodState->mClosureState == NULL) || (mModule->mCurMethodState->mClosureState->mCapturing)) &&
(mModule->mCompiler->mResolvePassData != NULL) && (mModule->mCurMethodInstance != NULL)) (mModule->mCompiler->mResolvePassData != NULL) && (mModule->mCurMethodInstance != NULL))
mModule->mCompiler->mResolvePassData->HandleLocalReference(captureEntry.mNameNode, localVar->mNameNode, mModule->mCurTypeInstance->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVar->mLocalVarId); {
if (auto captureIdentifierNode = BfNodeDynCast<BfIdentifierNode>(captureEntry.mNameNode))
mModule->mCompiler->mResolvePassData->HandleLocalReference(captureIdentifierNode, localVar->mNameNode, mModule->mCurTypeInstance->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVar->mLocalVarId);
}
localVar->mNotCaptured = false; localVar->mNotCaptured = false;
localVar = localVar->mShadowedLocal; localVar = localVar->mShadowedLocal;
@ -14470,7 +14473,7 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
prevIgnoreWrites.Restore(); prevIgnoreWrites.Restore();
mModule->mBfIRBuilder->RestoreDebugLocation(); mModule->mBfIRBuilder->RestoreDebugLocation();
auto _GetCaptureType = [&](const StringImpl& str) auto _GetCaptureType = [&](const StringImpl& str, BfCaptureInfo::Entry** captureInfo = NULL)
{ {
if (allocTarget.mCaptureInfo->mCaptures.IsEmpty()) if (allocTarget.mCaptureInfo->mCaptures.IsEmpty())
return BfCaptureType_Copy; return BfCaptureType_Copy;
@ -14479,6 +14482,9 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
{ {
if ((captureEntry.mNameNode == NULL) || (captureEntry.mNameNode->Equals(str))) if ((captureEntry.mNameNode == NULL) || (captureEntry.mNameNode->Equals(str)))
{ {
if (captureInfo != NULL)
*captureInfo = &captureEntry;
captureEntry.mUsed = true; captureEntry.mUsed = true;
return captureEntry.mCaptureType; return captureEntry.mCaptureType;
} }
@ -14519,7 +14525,9 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
auto capturedType = outerLocal->mResolvedType; auto capturedType = outerLocal->mResolvedType;
bool captureByRef = false; bool captureByRef = false;
auto captureType = _GetCaptureType(localVar->mName); BfCaptureInfo::Entry* captureInfoEntry = NULL;
auto captureType = _GetCaptureType(localVar->mName, &captureInfoEntry);
if (captureType == BfCaptureType_None) if (captureType == BfCaptureType_None)
{ {
continue; continue;
@ -14529,18 +14537,33 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
{ {
if (captureType == BfCaptureType_Reference) if (captureType == BfCaptureType_Reference)
{ {
if (outerLocal->mIsThis) if ((localVar->mIsThis) && (!localVar->mResolvedType->IsValueType()))
{ {
if ((outerLocal->mResolvedType->IsValueType()) && (mModule->mCurMethodInstance->mMethodDef->HasNoThisSplat())) // Just ignore attempting to capture referencetype 'this' by reference
}
else
captureByRef = true; captureByRef = true;
} }
else if ((!localVar->mIsReadOnly) && (localVar->mWrittenToId >= closureState.mCaptureStartAccessId)) else if (captureType == BfCaptureType_Auto)
{
if (localVar->mWrittenToId >= closureState.mCaptureStartAccessId)
captureByRef = true; captureByRef = true;
else if ((outerLocal->mResolvedType->mSize > 8) ||
((localVar->mIsThis) && (outerLocal->mResolvedType->IsValueType())))
{
// Capture "large" values by reference
captureByRef = true;
}
} }
} }
else else
{ {
if ((captureType != BfCaptureType_Reference) || (localVar->mWrittenToId < closureState.mCaptureStartAccessId)) bool allowRef = false;
if (captureType == BfCaptureType_Reference)
allowRef = true;
else if (captureType == BfCaptureType_Auto)
allowRef = localVar->mWrittenToId < closureState.mCaptureStartAccessId;
if (!allowRef)
{ {
capturedType = ((BfRefType*)capturedType)->mElementType; capturedType = ((BfRefType*)capturedType)->mElementType;
} }
@ -14551,7 +14574,7 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
capturedType = mModule->CreateRefType(capturedType); capturedType = mModule->CreateRefType(capturedType);
} }
if (captureType == BfCaptureType_Reference) if (captureType != BfCaptureType_Copy)
capturedEntry.mExplicitlyByReference = true; capturedEntry.mExplicitlyByReference = true;
capturedEntry.mType = capturedType; capturedEntry.mType = capturedType;
capturedEntry.mNameNode = outerLocal->mNameNode; capturedEntry.mNameNode = outerLocal->mNameNode;
@ -14626,16 +14649,16 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
BfClosureCapturedEntry capturedEntry; BfClosureCapturedEntry capturedEntry;
capturedEntry.mName = fieldDef->mName; capturedEntry.mName = fieldDef->mName;
capturedEntry.mType = copyField->mResolvedType; capturedEntry.mType = copyField->mResolvedType;
if ((captureType == BfCaptureType_Reference) && (capturedEntry.mType->IsRef())) if ((captureType != BfCaptureType_Copy) && (capturedEntry.mType->IsRef()))
{ {
capturedEntry.mExplicitlyByReference = true; capturedEntry.mExplicitlyByReference = true;
} }
else if ((captureType != BfCaptureType_Reference) && (capturedEntry.mType->IsRef())) else if ((captureType == BfCaptureType_Copy) && (capturedEntry.mType->IsRef()))
{ {
auto refType = (BfRefType*)capturedEntry.mType; auto refType = (BfRefType*)capturedEntry.mType;
capturedEntry.mType = refType->mElementType; capturedEntry.mType = refType->mElementType;
} }
else if ((captureType == BfCaptureType_Reference) && (!capturedEntry.mType->IsRef()) && (!fieldDef->mIsReadOnly)) else if ((captureType != BfCaptureType_Copy) && (!capturedEntry.mType->IsRef()) && (!fieldDef->mIsReadOnly))
{ {
capturedEntry.mType = mModule->CreateRefType(capturedEntry.mType); capturedEntry.mType = mModule->CreateRefType(capturedEntry.mType);
} }
@ -15109,10 +15132,7 @@ void BfExprEvaluator::Visit(BfLambdaBindExpression* lambdaBindExpr)
if (!fieldInstance->mResolvedType->IsRef()) if (!fieldInstance->mResolvedType->IsRef())
capturedTypedVal = mModule->LoadOrAggregateValue(capturedTypedVal); capturedTypedVal = mModule->LoadOrAggregateValue(capturedTypedVal);
else if (!capturedTypedVal.IsAddr()) else if (!capturedTypedVal.IsAddr())
{ capturedTypedVal = mModule->MakeAddressable(capturedTypedVal, false, true);
mModule->Fail(StrFormat("Unable to capture '%s' by reference", capturedEntry.mName.c_str()), lambdaBindExpr);
break;
}
capturedValue = capturedTypedVal.mValue; capturedValue = capturedTypedVal.mValue;
if (capturedValue) if (capturedValue)

View file

@ -11925,10 +11925,21 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
} }
BfCaptureInfo::Entry captureEntry; BfCaptureInfo::Entry captureEntry;
captureEntry.mCaptureType = (tokenNode->mToken == BfToken_Ampersand) ? BfCaptureType_Reference : BfCaptureType_Copy; captureEntry.mRefNode = tokenNode;
captureEntry.mCaptureType = BfCaptureType_Copy;
if (tokenNode->mToken == BfToken_Ampersand)
captureEntry.mCaptureType = BfCaptureType_Reference;
if (tokenNode->mToken == BfToken_Question)
captureEntry.mCaptureType = BfCaptureType_Auto;
if (!attributesDirective->mArguments.IsEmpty()) if (!attributesDirective->mArguments.IsEmpty())
{ {
captureEntry.mNameNode = BfNodeDynCast<BfIdentifierNode>(attributesDirective->mArguments[0]); if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(attributesDirective->mArguments[0]))
captureEntry.mNameNode = identifierNode;
else if (auto thisExpr = BfNodeDynCast<BfThisExpression>(attributesDirective->mArguments[0]))
{
captureEntry.mNameNode = thisExpr;
}
if ((captureEntry.mNameNode != NULL) && (autoComplete != NULL)) if ((captureEntry.mNameNode != NULL) && (autoComplete != NULL))
autoComplete->CheckIdentifier(captureEntry.mNameNode); autoComplete->CheckIdentifier(captureEntry.mNameNode);
} }

View file

@ -627,12 +627,14 @@ public:
{ {
BfCaptureType mCaptureType; BfCaptureType mCaptureType;
bool mUsed; bool mUsed;
BfIdentifierNode* mNameNode; BfAstNode* mRefNode;
BfAstNode* mNameNode;
Entry() Entry()
{ {
mCaptureType = BfCaptureType_Copy; mCaptureType = BfCaptureType_Copy;
mUsed = false; mUsed = false;
mRefNode = NULL;
mNameNode = NULL; mNameNode = NULL;
} }
}; };

View file

@ -5624,16 +5624,30 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
MEMBER_SET(attributeTargetSpecifier, mColonToken, tokenNode); MEMBER_SET(attributeTargetSpecifier, mColonToken, tokenNode);
attributeDirective->SetSrcEnd(attributeDirective->mAttributeTargetSpecifier->GetSrcEnd()); attributeDirective->SetSrcEnd(attributeDirective->mAttributeTargetSpecifier->GetSrcEnd());
} }
else if ((tokenNode->mToken == BfToken_Ampersand) || (tokenNode->mToken == BfToken_AssignEquals)) else if ((tokenNode->mToken == BfToken_Ampersand) || (tokenNode->mToken == BfToken_AssignEquals) || (tokenNode->mToken == BfToken_Question))
{ {
MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, tokenNode); MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, tokenNode);
mVisitorPos.MoveNext(); mVisitorPos.MoveNext();
isHandled = true; isHandled = true;
nextNode = mVisitorPos.GetNext(); nextNode = mVisitorPos.GetNext();
BfExpression* nameNode = NULL;
if (auto identiferNode = BfNodeDynCast<BfIdentifierNode>(nextNode)) if (auto identiferNode = BfNodeDynCast<BfIdentifierNode>(nextNode))
nameNode = identiferNode;
else if (auto nextToken = BfNodeDynCast<BfTokenNode>(nextNode))
{ {
attributeDirective->SetSrcEnd(identiferNode->GetSrcEnd()); if (nextToken->mToken == BfToken_This)
arguments.push_back(identiferNode); {
auto thisExpr = mAlloc->Alloc<BfThisExpression>();
ReplaceNode(nextToken, thisExpr);
nameNode = thisExpr;
}
}
if (nameNode != NULL)
{
attributeDirective->SetSrcEnd(nameNode->GetSrcEnd());
arguments.push_back(nameNode);
mVisitorPos.MoveNext(); mVisitorPos.MoveNext();
nextNode = mVisitorPos.GetNext(); nextNode = mVisitorPos.GetNext();
} }

View file

@ -2312,6 +2312,7 @@ public:
enum BfCaptureType enum BfCaptureType
{ {
BfCaptureType_None, BfCaptureType_None,
BfCaptureType_Auto,
BfCaptureType_Copy, BfCaptureType_Copy,
BfCaptureType_Reference, BfCaptureType_Reference,
}; };