From 40b0d78d166dcf30f1bd93dd00dfab9c400acd5a Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 27 Nov 2021 09:05:23 -0800 Subject: [PATCH] Allow ref property setter specifier --- IDEHelper/Compiler/BfAst.h | 1 + IDEHelper/Compiler/BfDefBuilder.cpp | 15 +++++++++++---- IDEHelper/Compiler/BfElementVisitor.cpp | 3 ++- IDEHelper/Compiler/BfExprEvaluator.cpp | 5 ++++- IDEHelper/Compiler/BfPrinter.cpp | 2 ++ IDEHelper/Compiler/BfReducer.cpp | 21 ++++++++++++++++++--- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index df9e8ebb..62a34a59 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -3099,6 +3099,7 @@ public: BfPropertyDeclaration* mPropertyDeclaration; BfAttributeDirective* mAttributes; BfAstNode* mProtectionSpecifier; + BfTokenNode* mSetRefSpecifier; BfTokenNode* mMutSpecifier; BfIdentifierNode* mNameNode; BfTokenNode* mFatArrowToken; diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index 6dafe761..febe5418 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -1078,12 +1078,19 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration) if (BfNodeDynCast(methodDeclaration->mBody) != NULL) methodDef->mIsMutating = true; // Don't require "set mut;", just "set;" - auto paramDef = new BfParameterDef(); + auto paramDef = new BfParameterDef(); paramDef->mName = "value"; - if (auto refTypeRef = BfNodeDynCast(propertyDeclaration->mTypeRef)) - paramDef->mTypeRef = refTypeRef->mElementType; + paramDef->mTypeRef = propertyDeclaration->mTypeRef; + if (auto refTypeRef = BfNodeDynCast(propertyDeclaration->mTypeRef)) + { + if (methodDeclaration->mSetRefSpecifier == NULL) + paramDef->mTypeRef = refTypeRef->mElementType; + } else - paramDef->mTypeRef = propertyDeclaration->mTypeRef; + { + if (methodDeclaration->mSetRefSpecifier != NULL) + Fail("Property setter 'ref' can only be used with a 'ref' property type", methodDeclaration->mSetRefSpecifier); + } methodDef->mParams.Insert(0, paramDef); propertyDef->mMethods.Add(methodDef); } diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index 5deb47ad..0805ee67 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -1050,8 +1050,9 @@ void BfElementVisitor::Visit(BfPropertyMethodDeclaration* propertyDeclaration) VisitChild(propertyDeclaration->mAttributes); VisitChild(propertyDeclaration->mProtectionSpecifier); VisitChild(propertyDeclaration->mNameNode); + VisitChild(propertyDeclaration->mSetRefSpecifier); VisitChild(propertyDeclaration->mMutSpecifier); - VisitChild(propertyDeclaration->mFatArrowToken); + VisitChild(propertyDeclaration->mFatArrowToken); VisitChild(propertyDeclaration->mBody); VisitChild(propertyDeclaration->mEndSemicolon); } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index a6bc7b70..b559e47d 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -18128,7 +18128,10 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool mModule->AssertErrorState(); return; } - convVal = mModule->CreateValueFromExpression(assignExpr->mRight, wantType, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_PendingPropSet)); + BfEvalExprFlags exprFlags = (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_PendingPropSet); + if (wantType->IsRef()) + exprFlags = (BfEvalExprFlags)(exprFlags | BfEvalExprFlags_AllowRefExpr); + convVal = mModule->CreateValueFromExpression(assignExpr->mRight, wantType, exprFlags); } if (!convVal) { diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index 8a772451..eba25d73 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -2545,6 +2545,8 @@ void BfPrinter::Visit(BfPropertyMethodDeclaration* propertyMethodDeclaration) ExpectSpace(); QueueVisitChild(propertyMethodDeclaration->mNameNode); ExpectSpace(); + QueueVisitChild(propertyMethodDeclaration->mSetRefSpecifier); + ExpectSpace(); QueueVisitChild(propertyMethodDeclaration->mMutSpecifier); ExpectSpace(); QueueVisitChild(propertyMethodDeclaration->mFatArrowToken); diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 0636ee63..7b56b520 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -6392,6 +6392,7 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf String accessorName; BfTokenNode* mutSpecifier = NULL; + BfTokenNode* refSpecifier = NULL; while (true) { @@ -6459,8 +6460,18 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf BfAstNode* bodyAfterNode = accessorIdentifier; BfAstNode* body = NULL; - + auto tokenNode = BfNodeDynCast(child); + if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Ref) && (accessorName == "set")) + { + refSpecifier = tokenNode; + bodyAfterNode = tokenNode; + + mVisitorPos.MoveNext(); + child = mVisitorPos.GetNext(); + tokenNode = BfNodeDynCast(child); + } + if ((tokenNode != NULL) && (tokenNode->GetToken() == BfToken_Mut)) { if (mutSpecifier != NULL) @@ -6472,8 +6483,8 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf mVisitorPos.MoveNext(); child = mVisitorPos.GetNext(); - } - + } + bool handled = false; BfTokenNode* fatArrowToken = NULL; BfAstNode* endSemicolon = NULL; @@ -6543,6 +6554,8 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf AddErrorNode(accessorIdentifier); if (mutSpecifier != NULL) AddErrorNode(mutSpecifier); + if (refSpecifier != NULL) + AddErrorNode(refSpecifier); continue; } @@ -6561,6 +6574,8 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf { MEMBER_SET(method, mBody, body); } + if (refSpecifier != NULL) + MEMBER_SET(method, mSetRefSpecifier, refSpecifier); if (mutSpecifier != NULL) MEMBER_SET(method, mMutSpecifier, mutSpecifier); // if ((accessorBlock != NULL) && (IsNodeRelevant(propertyDeclaration)))