mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-11 04:52:21 +02:00
Added '.{ x = 1, y = 2}' initializer expression
This commit is contained in:
parent
b18cdc706c
commit
0692fb44a4
5 changed files with 127 additions and 33 deletions
|
@ -2120,7 +2120,7 @@ class BfInitializerExpression : public BfExpression
|
||||||
public:
|
public:
|
||||||
BF_AST_TYPE(BfInitializerExpression, BfExpression);
|
BF_AST_TYPE(BfInitializerExpression, BfExpression);
|
||||||
|
|
||||||
BfExpression* mTarget;
|
BfAstNode* mTarget;
|
||||||
BfTokenNode* mOpenBrace;
|
BfTokenNode* mOpenBrace;
|
||||||
BfSizedArray<BfExpression*> mValues;
|
BfSizedArray<BfExpression*> mValues;
|
||||||
BfSizedArray<BfTokenNode*> mCommas;
|
BfSizedArray<BfTokenNode*> mCommas;
|
||||||
|
|
|
@ -9240,11 +9240,54 @@ void BfExprEvaluator::Visit(BfSizedArrayCreateExpression* createExpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
||||||
{
|
{
|
||||||
VisitChild(initExpr->mTarget);
|
uint64 unassignedFieldFlags = 0;
|
||||||
|
|
||||||
|
if (auto typeRef = BfNodeDynCast<BfTypeReference>(initExpr->mTarget))
|
||||||
|
{
|
||||||
|
BfType* type = NULL;
|
||||||
|
if (auto typeRef = BfNodeDynCast<BfDotTypeReference>(initExpr->mTarget))
|
||||||
|
{
|
||||||
|
type = mExpectingType;
|
||||||
|
}
|
||||||
|
if (type == NULL)
|
||||||
|
type = mModule->ResolveTypeRef(typeRef);
|
||||||
|
if (type != NULL)
|
||||||
|
{
|
||||||
|
if (type->IsValueType())
|
||||||
|
{
|
||||||
|
if (mReceivingValue != NULL)
|
||||||
|
{
|
||||||
|
mResult = *mReceivingValue;
|
||||||
|
mReceivingValue = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mResult = BfTypedValue(mModule->CreateAlloca(type), type, true);
|
||||||
|
}
|
||||||
|
auto typeInstance = type->ToTypeInstance();
|
||||||
|
if (typeInstance != NULL)
|
||||||
|
unassignedFieldFlags = (1 << typeInstance->mMergedFieldDataCount) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mModule->Fail("Initializer expressions can only be used on value types or allocated values", initExpr->mTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VisitChild(initExpr->mTarget);
|
||||||
if (!mResult)
|
if (!mResult)
|
||||||
mResult = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
|
mResult = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
|
||||||
|
|
||||||
|
BfIRBlock initBlock = BfIRBlock();
|
||||||
|
if (unassignedFieldFlags != 0)
|
||||||
|
{
|
||||||
|
initBlock = mModule->mBfIRBuilder->CreateBlock("initStart", true);
|
||||||
|
mModule->mBfIRBuilder->CreateBr(initBlock);
|
||||||
|
mModule->mBfIRBuilder->SetInsertPoint(initBlock);
|
||||||
|
}
|
||||||
|
|
||||||
BfTypedValue initValue = GetResult(true);
|
BfTypedValue initValue = GetResult(true);
|
||||||
bool isFirstAdd = true;
|
bool isFirstAdd = true;
|
||||||
BfFunctionBindResult addFunctionBindResult;
|
BfFunctionBindResult addFunctionBindResult;
|
||||||
|
@ -9261,10 +9304,21 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
||||||
{
|
{
|
||||||
StringT<128> findName;
|
StringT<128> findName;
|
||||||
identifierNode->ToString(findName);
|
identifierNode->ToString(findName);
|
||||||
|
mResultFieldInstance = NULL;
|
||||||
fieldResult = LookupField(identifierNode, initValue, findName, BfLookupFieldFlag_IsImplicitThis);
|
fieldResult = LookupField(identifierNode, initValue, findName, BfLookupFieldFlag_IsImplicitThis);
|
||||||
if ((fieldResult.mKind == BfTypedValueKind_TempAddr) || (fieldResult.mKind == BfTypedValueKind_RestrictedTempAddr))
|
if ((fieldResult.mKind == BfTypedValueKind_TempAddr) || (fieldResult.mKind == BfTypedValueKind_RestrictedTempAddr))
|
||||||
fieldResult.mKind = BfTypedValueKind_Addr;
|
fieldResult.mKind = BfTypedValueKind_Addr;
|
||||||
|
|
||||||
|
if ((mResultFieldInstance != NULL) && (mResultFieldInstance->mMergedDataIdx != -1))
|
||||||
|
{
|
||||||
|
int resultLocalVarField = 0;
|
||||||
|
int resultLocalVarFieldCount = 0;
|
||||||
|
mResultFieldInstance->GetDataRange(resultLocalVarField, resultLocalVarFieldCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < resultLocalVarFieldCount; i++)
|
||||||
|
unassignedFieldFlags &= ~((int64)1 << (resultLocalVarField - 1 + i));
|
||||||
|
}
|
||||||
|
|
||||||
wasValidInitKind = true;
|
wasValidInitKind = true;
|
||||||
|
|
||||||
if ((fieldResult) || (mPropDef != NULL))
|
if ((fieldResult) || (mPropDef != NULL))
|
||||||
|
@ -9341,6 +9395,15 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unassignedFieldFlags != 0)
|
||||||
|
{
|
||||||
|
auto curBlock = mModule->mBfIRBuilder->GetInsertBlock();
|
||||||
|
mModule->mBfIRBuilder->SetInsertPointAtStart(initBlock);
|
||||||
|
mModule->mBfIRBuilder->CreateMemSet(initValue.mValue, mModule->GetConstValue(0, mModule->GetPrimitiveType(BfTypeCode_Int8)),
|
||||||
|
mModule->GetConstValue(initValue.mType->mSize), initValue.mType->mAlign);
|
||||||
|
mModule->mBfIRBuilder->SetInsertPoint(curBlock);
|
||||||
|
}
|
||||||
|
|
||||||
mResult = initValue;
|
mResult = initValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1692,6 +1692,17 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
else if (endNodeIdx != -1)
|
||||||
|
{
|
||||||
|
if (auto blockNode = BfNodeDynCast<BfBlock>(mVisitorPos.Get(endNodeIdx)))
|
||||||
|
{
|
||||||
|
auto typeRef = CreateTypeRef(mVisitorPos.GetCurrent());
|
||||||
|
if (typeRef)
|
||||||
|
{
|
||||||
|
exprLeft = TryCreateInitializerExpression(typeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exprLeft == NULL)
|
if (exprLeft == NULL)
|
||||||
|
@ -1917,43 +1928,55 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
}
|
}
|
||||||
else if (token == BfToken_Dot) // Abbreviated dot syntax ".EnumVal"
|
else if (token == BfToken_Dot) // Abbreviated dot syntax ".EnumVal"
|
||||||
{
|
{
|
||||||
auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
|
// Initializer ".{ x = 1, y = 2 }"
|
||||||
ReplaceNode(tokenNode, memberReferenceExpr);
|
if (auto blockNode = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext()))
|
||||||
MEMBER_SET(memberReferenceExpr, mDotToken, tokenNode);
|
|
||||||
|
|
||||||
bool handled = false;
|
|
||||||
if (auto nextToken = BfNodeDynCastExact<BfTokenNode>(mVisitorPos.GetNext()))
|
|
||||||
{
|
{
|
||||||
if (nextToken->GetToken() == BfToken_LParen)
|
auto typeRef = CreateTypeRef(mVisitorPos.GetCurrent());
|
||||||
|
if (typeRef)
|
||||||
{
|
{
|
||||||
// It's an unnamed dot ctor
|
exprLeft = TryCreateInitializerExpression(typeRef);
|
||||||
handled = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!handled)
|
|
||||||
{
|
{
|
||||||
auto memberName = ExpectIdentifierAfter(memberReferenceExpr);
|
auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
|
||||||
if (memberName != NULL)
|
ReplaceNode(tokenNode, memberReferenceExpr);
|
||||||
|
MEMBER_SET(memberReferenceExpr, mDotToken, tokenNode);
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
if (auto nextToken = BfNodeDynCastExact<BfTokenNode>(mVisitorPos.GetNext()))
|
||||||
{
|
{
|
||||||
MEMBER_SET(memberReferenceExpr, mMemberName, memberName);
|
if (nextToken->GetToken() == BfToken_LParen)
|
||||||
|
{
|
||||||
|
// It's an unnamed dot ctor
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// We don't set exprLeft here because it's illegal to do ".EnumVal.SomethingElse". That wouldn't make
|
|
||||||
// sense because the abbreviated syntax relies on type inference and the ".SomethingElse" wouldn't be
|
|
||||||
// the right type (whatever it is), AND mostly importantly, it breaks autocomplete when we are typing
|
|
||||||
// "KEnum val = ." above a line that starts with a something like a method call "OtherThing.MethodCall()"
|
|
||||||
// The exception is if we're creating an enum val with a payload
|
|
||||||
|
|
||||||
//auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
|
if (!handled)
|
||||||
//if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_LParen))
|
{
|
||||||
{
|
auto memberName = ExpectIdentifierAfter(memberReferenceExpr);
|
||||||
exprLeft = memberReferenceExpr;
|
if (memberName != NULL)
|
||||||
|
{
|
||||||
|
MEMBER_SET(memberReferenceExpr, mMemberName, memberName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We don't set exprLeft here because it's illegal to do ".EnumVal.SomethingElse". That wouldn't make
|
||||||
|
// sense because the abbreviated syntax relies on type inference and the ".SomethingElse" wouldn't be
|
||||||
|
// the right type (whatever it is), AND mostly importantly, it breaks autocomplete when we are typing
|
||||||
|
// "KEnum val = ." above a line that starts with a something like a method call "OtherThing.MethodCall()"
|
||||||
|
// The exception is if we're creating an enum val with a payload
|
||||||
|
|
||||||
|
//auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
|
||||||
|
//if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_LParen))
|
||||||
|
{
|
||||||
|
exprLeft = memberReferenceExpr;
|
||||||
|
}
|
||||||
|
/*else
|
||||||
|
{
|
||||||
|
return memberReferenceExpr;
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
/*else
|
|
||||||
{
|
|
||||||
return memberReferenceExpr;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
else if (token == BfToken_LBracket)
|
else if (token == BfToken_LBracket)
|
||||||
{
|
{
|
||||||
|
@ -7072,7 +7095,7 @@ BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target,
|
||||||
return invocationExpr;
|
return invocationExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfExpression* target)
|
BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfAstNode* target)
|
||||||
{
|
{
|
||||||
auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
|
auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
|
||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
|
|
|
@ -203,7 +203,7 @@ public:
|
||||||
BfObjectCreateExpression* CreateObjectCreateExpression(BfAstNode* allocNode);
|
BfObjectCreateExpression* CreateObjectCreateExpression(BfAstNode* allocNode);
|
||||||
BfScopedInvocationTarget* CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken);
|
BfScopedInvocationTarget* CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken);
|
||||||
BfInvocationExpression* CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags = CreateExprFlags_None);
|
BfInvocationExpression* CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags = CreateExprFlags_None);
|
||||||
BfInitializerExpression* TryCreateInitializerExpression(BfExpression* target);
|
BfInitializerExpression* TryCreateInitializerExpression(BfAstNode* target);
|
||||||
BfExpression* CreateIndexerExpression(BfExpression* target);
|
BfExpression* CreateIndexerExpression(BfExpression* target);
|
||||||
BfMemberReferenceExpression* CreateMemberReferenceExpression(BfAstNode* target);
|
BfMemberReferenceExpression* CreateMemberReferenceExpression(BfAstNode* target);
|
||||||
BfTupleExpression* CreateTupleExpression(BfTokenNode* newNode, BfExpression* innerExpr = NULL);
|
BfTupleExpression* CreateTupleExpression(BfTokenNode* newNode, BfExpression* innerExpr = NULL);
|
||||||
|
|
|
@ -134,6 +134,14 @@ namespace Tests
|
||||||
sb1.mA = 1;
|
sb1.mA = 1;
|
||||||
sb1.mB = 2;
|
sb1.mB = 2;
|
||||||
Test.Assert(sb0 == sb1);
|
Test.Assert(sb0 == sb1);
|
||||||
|
|
||||||
|
sb0 = StructB { mA = 2 };
|
||||||
|
Test.Assert(sb0.mA == 2);
|
||||||
|
Test.Assert(sb0.mB == 0);
|
||||||
|
|
||||||
|
sb0 = .{ mA = 3, mB = 4 };
|
||||||
|
Test.Assert(sb0.mA == 3);
|
||||||
|
Test.Assert(sb0.mB == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue