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:
parent
3cc0ba2ed6
commit
5268e103e9
6 changed files with 60 additions and 18 deletions
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue