浏览代码

Added '.{ x = 1, y = 2}' initializer expression

Brian Fiete 4 年之前
父节点
当前提交
0692fb44a4

+ 1 - 1
IDEHelper/Compiler/BfAst.h

@@ -2120,7 +2120,7 @@ class BfInitializerExpression : public BfExpression
 public:
 	BF_AST_TYPE(BfInitializerExpression, BfExpression);
 
-	BfExpression* mTarget;
+	BfAstNode* mTarget;
 	BfTokenNode* mOpenBrace;
 	BfSizedArray<BfExpression*> mValues;
 	BfSizedArray<BfTokenNode*> mCommas;

+ 65 - 2
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -9240,11 +9240,54 @@ void BfExprEvaluator::Visit(BfSizedArrayCreateExpression* createExpr)
 }
 
 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)
 		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);	
 	bool isFirstAdd = true;	
 	BfFunctionBindResult addFunctionBindResult;
@@ -9261,10 +9304,21 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
 			{
 				StringT<128> findName;
 				identifierNode->ToString(findName);
+				mResultFieldInstance = NULL;
 				fieldResult = LookupField(identifierNode, initValue, findName, BfLookupFieldFlag_IsImplicitThis);
 				if ((fieldResult.mKind == BfTypedValueKind_TempAddr) || (fieldResult.mKind == BfTypedValueKind_RestrictedTempAddr))
 					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;
 
 				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;
 }
 

+ 52 - 29
IDEHelper/Compiler/BfReducer.cpp

@@ -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)
@@ -1917,43 +1928,55 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
 			}
 			else if (token == BfToken_Dot) // Abbreviated dot syntax ".EnumVal"
 			{
-				auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
-				ReplaceNode(tokenNode, memberReferenceExpr);
-				MEMBER_SET(memberReferenceExpr, mDotToken, tokenNode);
-
-				bool handled = false;
-				if (auto nextToken = BfNodeDynCastExact<BfTokenNode>(mVisitorPos.GetNext()))
+				// Initializer ".{ x = 1, y = 2 }"
+				if (auto blockNode = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext()))
 				{
-					if (nextToken->GetToken() == BfToken_LParen)
+					auto typeRef = CreateTypeRef(mVisitorPos.GetCurrent());
+					if (typeRef)
 					{
-						// It's an unnamed dot ctor
-						handled = true;
+						exprLeft = TryCreateInitializerExpression(typeRef);
 					}
 				}
-
-				if (!handled)
+				else
 				{
-					auto memberName = ExpectIdentifierAfter(memberReferenceExpr);
-					if (memberName != NULL)
+					auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
+					ReplaceNode(tokenNode, memberReferenceExpr);
+					MEMBER_SET(memberReferenceExpr, mDotToken, tokenNode);
+
+					bool handled = false;
+					if (auto nextToken = BfNodeDynCastExact<BfTokenNode>(mVisitorPos.GetNext()))
+					{
+						if (nextToken->GetToken() == BfToken_LParen)
+						{
+							// It's an unnamed dot ctor
+							handled = true;
+						}
+					}
+
+					if (!handled)
 					{
-						MEMBER_SET(memberReferenceExpr, mMemberName, memberName);
+						auto memberName = ExpectIdentifierAfter(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
+					// 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;
+					//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)
 			{
@@ -7072,7 +7095,7 @@ BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target,
 	return invocationExpr;
 }
 
-BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfExpression* target)
+BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfAstNode* target)
 {
 	auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
 	if (block == NULL)

+ 1 - 1
IDEHelper/Compiler/BfReducer.h

@@ -203,7 +203,7 @@ public:
 	BfObjectCreateExpression* CreateObjectCreateExpression(BfAstNode* allocNode);
 	BfScopedInvocationTarget* CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken);
 	BfInvocationExpression* CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags = CreateExprFlags_None);
-	BfInitializerExpression* TryCreateInitializerExpression(BfExpression* target);
+	BfInitializerExpression* TryCreateInitializerExpression(BfAstNode* target);
 	BfExpression* CreateIndexerExpression(BfExpression* target);
 	BfMemberReferenceExpression* CreateMemberReferenceExpression(BfAstNode* target);
 	BfTupleExpression* CreateTupleExpression(BfTokenNode* newNode, BfExpression* innerExpr = NULL);

+ 8 - 0
IDEHelper/Tests/src/Structs.bf

@@ -134,6 +134,14 @@ namespace Tests
 			sb1.mA = 1;
 			sb1.mB = 2;
 			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]