1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-14 14:24:10 +02:00

Allow mixins and expression blocks to end in a ref expression

This commit is contained in:
Brian Fiete 2022-06-15 06:45:53 -07:00
parent 3cc0ba2ed6
commit 5268e103e9
6 changed files with 60 additions and 18 deletions

View file

@ -3402,6 +3402,7 @@ void BfExprEvaluator::Visit(BfBlock* blockExpr)
} }
mModule->VisitEmbeddedStatement(blockExpr, this, BfNodeIsA<BfUnscopedBlock>(blockExpr) ? BfEmbeddedStatementFlags_Unscoped : BfEmbeddedStatementFlags_None); mModule->VisitEmbeddedStatement(blockExpr, this, BfNodeIsA<BfUnscopedBlock>(blockExpr) ? BfEmbeddedStatementFlags_Unscoped : BfEmbeddedStatementFlags_None);
mResult = mModule->SanitizeAddr(mResult);
} }
bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail) bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail)
@ -17164,6 +17165,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
if (!exprNode->IsA<BfBlock>()) if (!exprNode->IsA<BfBlock>())
{ {
// Mixin expression result // Mixin expression result
SetAndRestoreValue<BfEvalExprFlags> prevFlags(mBfEvalExprFlags, (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_AllowRefExpr));
mModule->UpdateSrcPos(exprNode); mModule->UpdateSrcPos(exprNode);
VisitChild(exprNode); VisitChild(exprNode);
FinishExpressionResult(); FinishExpressionResult();
@ -17187,6 +17189,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
} }
mResult = mModule->LoadValue(mResult); mResult = mModule->LoadValue(mResult);
mResult = mModule->SanitizeAddr(mResult);
int localIdx = startLocalIdx; int localIdx = startLocalIdx;
@ -19497,7 +19500,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
} }
ResolveGenericType(); ResolveGenericType();
auto ptr = mResult; auto ptr = mModule->RemoveRef(mResult);
mResult = BfTypedValue(); mResult = BfTypedValue();
if (mPropDef != NULL) if (mPropDef != NULL)
@ -21569,8 +21572,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
if (!mResult) if (!mResult)
return; return;
if (mResult.mType->IsRef()) mResult = mModule->RemoveRef(mResult);
mResult.mType = mResult.mType->GetUnderlyingType();
if (mResult.mType->IsVar()) if (mResult.mType->IsVar())
{ {

View file

@ -8791,13 +8791,26 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator,
{ {
// Only allow a 'ref' type if we have an explicit 'ref' operator // Only allow a 'ref' type if we have an explicit 'ref' operator
bool allowRef = false; bool allowRef = false;
BfExpression* checkExpr = expr; BfAstNode* checkExpr = expr;
while (auto parenExpr = BfNodeDynCast<BfParenthesizedExpression>(checkExpr))
checkExpr = parenExpr->mExpression; while (checkExpr != NULL)
if (auto unaryOp = BfNodeDynCast<BfUnaryOperatorExpression>(checkExpr))
{ {
if ((unaryOp->mOp == BfUnaryOp_Ref) || (unaryOp->mOp == BfUnaryOp_Mut)) if (auto parenExpr = BfNodeDynCast<BfParenthesizedExpression>(checkExpr))
allowRef = true; checkExpr = parenExpr->mExpression;
else if (auto unaryOp = BfNodeDynCast<BfUnaryOperatorExpression>(checkExpr))
{
if ((unaryOp->mOp == BfUnaryOp_Ref) || (unaryOp->mOp == BfUnaryOp_Mut))
allowRef = true;
break;
}
if (auto block = BfNodeDynCast<BfBlock>(checkExpr))
{
if (block->mChildArr.mSize == 0)
break;
checkExpr = block->mChildArr.back();
}
else
break;
} }
if (!allowRef) if (!allowRef)
typedVal = RemoveRef(typedVal); typedVal = RemoveRef(typedVal);
@ -12480,6 +12493,23 @@ BfTypedValue BfModule::RemoveRef(BfTypedValue typedValue)
return typedValue; return typedValue;
} }
BfTypedValue BfModule::SanitizeAddr(BfTypedValue typedValue)
{
if (!typedValue)
return typedValue;
if (typedValue.mType->IsRef())
{
typedValue = LoadValue(typedValue);
auto copiedVal = BfTypedValue(CreateAlloca(typedValue.mType), typedValue.mType, true);
mBfIRBuilder->CreateStore(typedValue.mValue, copiedVal.mValue);
return copiedVal;
}
return typedValue;
}
BfTypedValue BfModule::ToRef(BfTypedValue typedValue, BfRefType* refType) BfTypedValue BfModule::ToRef(BfTypedValue typedValue, BfRefType* refType)
{ {
if (refType == NULL) if (refType == NULL)

View file

@ -1700,6 +1700,7 @@ public:
void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull); void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull);
void CheckStaticAccess(BfTypeInstance* typeInstance); void CheckStaticAccess(BfTypeInstance* typeInstance);
BfTypedValue RemoveRef(BfTypedValue typedValue); BfTypedValue RemoveRef(BfTypedValue typedValue);
BfTypedValue SanitizeAddr(BfTypedValue typedValue);
BfTypedValue ToRef(BfTypedValue typedValue, BfRefType* refType = NULL); BfTypedValue ToRef(BfTypedValue typedValue, BfRefType* refType = NULL);
BfTypedValue LoadOrAggregateValue(BfTypedValue typedValue); BfTypedValue LoadOrAggregateValue(BfTypedValue typedValue);
BfTypedValue LoadValue(BfTypedValue typedValue, BfAstNode* refNode = NULL, bool isVolatile = false); BfTypedValue LoadValue(BfTypedValue typedValue, BfAstNode* refNode = NULL, bool isVolatile = false);

View file

@ -4427,15 +4427,10 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS
(unaryOperatorExpr->mOp == BfUnaryOp_Decrement) || (unaryOperatorExpr->mOp == BfUnaryOp_Decrement) ||
(unaryOperatorExpr->mOp == BfUnaryOp_PostDecrement); (unaryOperatorExpr->mOp == BfUnaryOp_PostDecrement);
if ((unaryOperatorExpr->mOp == BfUnaryOp_Ref) || (unaryOperatorExpr->mOp == BfUnaryOp_Mut) || (unaryOperatorExpr->mOp == BfUnaryOp_Out)) if (unaryOperatorExpr->mOp == BfUnaryOp_Out)
{ {
if (unaryOperatorExpr->mOp == BfUnaryOp_Ref) unaryOperatorExpr->mOp = BfUnaryOp_Ref;
Fail("Cannot use 'ref' in this context", unaryOperatorExpr); Fail("Cannot use 'out' in this context", unaryOperatorExpr);
else if (unaryOperatorExpr->mOp == BfUnaryOp_Mut)
Fail("Cannot use 'mut' in this context", unaryOperatorExpr);
else
Fail("Cannot use 'out' in this context", unaryOperatorExpr);
return NULL;
} }
} }

View file

@ -3538,7 +3538,7 @@ void BfModule::VisitCodeBlock(BfBlock* block)
else if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope)) else if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope))
{ {
// Only in mixin definition - result ignored // Only in mixin definition - result ignored
CreateValueFromExpression(expr); CreateValueFromExpression(expr, NULL, BfEvalExprFlags_AllowRefExpr);
break; break;
} }
else else

View file

@ -73,6 +73,12 @@ namespace Tests
total + 100 total + 100
} }
static mixin GetRef(var a)
{
a += 1000;
ref a
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -125,6 +131,14 @@ namespace Tests
AppendAndNullify!(str0); AppendAndNullify!(str0);
Test.Assert(str0 == null); Test.Assert(str0 == null);
Test.Assert(str1 == "AB"); Test.Assert(str1 == "AB");
int b = 12;
GetRef!(b) += 200;
Test.Assert(b == 1212);
var c = { ref b };
c = 99;
Test.Assert(b == 99);
} }
} }