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

Added expression bodies for properties

This commit is contained in:
Brian Fiete 2019-09-30 12:24:02 -07:00
parent 69e3bf94f7
commit 85648cda63
8 changed files with 102 additions and 54 deletions

View file

@ -576,6 +576,11 @@ void BfStructuralVisitor::Visit(BfPropertyMethodDeclaration* propertyMethodDecla
Visit(propertyMethodDeclaration->ToBase());
}
void BfStructuralVisitor::Visit(BfPropertyBodyExpression* propertyBodyExpression)
{
Visit(propertyBodyExpression->ToBase());
}
void BfStructuralVisitor::Visit(BfPropertyDeclaration* propertyDeclaration)
{
Visit(propertyDeclaration->ToBase());

View file

@ -322,6 +322,7 @@ class BfQualifiedTypeReference;
class BfUsingDirective;
class BfUsingStaticDirective;
class BfPropertyMethodDeclaration;
class BfPropertyBodyExpression;
class BfPropertyDeclaration;
class BfIndexerDeclaration;
class BfPreprocesorIgnoredSectionNode;
@ -500,6 +501,7 @@ public:
virtual void Visit(BfMethodDeclaration* methodDeclaration);
virtual void Visit(BfOperatorDeclaration* operatorDeclaration);
virtual void Visit(BfPropertyMethodDeclaration* propertyMethodDeclaration);
virtual void Visit(BfPropertyBodyExpression* propertyBodyExpression);
virtual void Visit(BfPropertyDeclaration* propertyDeclaration);
virtual void Visit(BfIndexerDeclaration* indexerDeclaration);
virtual void Visit(BfFieldDeclaration* fieldDeclaration);
@ -2900,6 +2902,13 @@ public:
BfAstNode* mBody;
}; BF_AST_DECL(BfPropertyMethodDeclaration, BfAstNode);
class BfPropertyBodyExpression : public BfAstNode
{
public:
BF_AST_TYPE(BfPropertyBodyExpression, BfAstNode);
BfTokenNode* mFatTokenArrow;
}; BF_AST_DECL(BfPropertyBodyExpression, BfAstNode);
class BfPropertyDeclaration : public BfFieldDeclaration
{
public:
@ -2908,7 +2917,7 @@ public:
BfTokenNode* mVirtualSpecifier; // either 'virtual', 'override', or 'abstract'
BfTypeReference* mExplicitInterface;
BfTokenNode* mExplicitInterfaceDotToken;
BfBlock* mDefinitionBlock;
BfAstNode* mDefinitionBlock;
BfSizedArray<BfPropertyMethodDeclaration*> mMethods;

View file

@ -848,7 +848,9 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration)
}
String methodName;
if ((methodDeclaration != NULL) && (methodDeclaration->mNameNode != NULL))
if (auto propExprBody = BfNodeDynCast<BfPropertyBodyExpression>(propertyDeclaration->mDefinitionBlock))
methodName = "get";
else if ((methodDeclaration != NULL) && (methodDeclaration->mNameNode != NULL))
methodName = methodDeclaration->mNameNode->ToString();
if (methodName == "get")

View file

@ -1022,6 +1022,13 @@ void BfElementVisitor::Visit(BfPropertyMethodDeclaration* propertyDeclaration)
VisitChild(propertyDeclaration->mBody);
}
void BfElementVisitor::Visit(BfPropertyBodyExpression* propertyBodyExpression)
{
Visit(propertyBodyExpression->ToBase());
VisitChild(propertyBodyExpression->mFatTokenArrow);
}
void BfElementVisitor::Visit(BfPropertyDeclaration* propertyDeclaration)
{
Visit(propertyDeclaration->ToBase());
@ -1035,14 +1042,19 @@ void BfElementVisitor::Visit(BfPropertyDeclaration* propertyDeclaration)
VisitChild(propertyDeclaration->mExplicitInterface);
VisitChild(propertyDeclaration->mExplicitInterfaceDotToken);
if (propertyDeclaration->mDefinitionBlock != NULL)
VisitChild(propertyDeclaration->mDefinitionBlock->mOpenBrace);
for (auto& method : propertyDeclaration->mMethods)
VisitChild(method);
if (propertyDeclaration->mDefinitionBlock != NULL)
VisitChild(propertyDeclaration->mDefinitionBlock->mCloseBrace);
if (auto block = BfNodeDynCast<BfBlock>(propertyDeclaration->mDefinitionBlock))
{
VisitChild(block->mOpenBrace);
for (auto& method : propertyDeclaration->mMethods)
VisitChild(method);
VisitChild(block->mCloseBrace);
}
else
{
VisitChild(propertyDeclaration->mDefinitionBlock);
for (auto& method : propertyDeclaration->mMethods)
VisitChild(method);
}
}
void BfElementVisitor::Visit(BfIndexerDeclaration* indexerDeclaration)

View file

@ -116,6 +116,7 @@ public:
virtual void Visit(BfMethodDeclaration* methodDeclaration);
virtual void Visit(BfOperatorDeclaration* operatorDeclaration);
virtual void Visit(BfPropertyMethodDeclaration* propertyDeclaration);
virtual void Visit(BfPropertyBodyExpression* propertyBodyExpression);
virtual void Visit(BfPropertyDeclaration* propertyDeclaration);
virtual void Visit(BfIndexerDeclaration* indexerDeclaration);
virtual void Visit(BfFieldDeclaration* fieldDeclaration);

View file

@ -16973,9 +16973,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
if (methodDeclaration->mFatArrowToken != NULL)
isExpressionBody = true;
}
else if (methodDef->GetPropertyDeclaration() != NULL)
else if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
{
//
if (auto propBodyExpr = BfNodeDynCast<BfPropertyBodyExpression>(propertyDeclaration->mDefinitionBlock))
{
isExpressionBody = true;
}
}
else
{
@ -17011,7 +17014,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
}
else if (auto expressionBody = BfNodeDynCast<BfExpression>(methodDef->mBody))
{
if (methodDef->mMethodType != BfMethodType_Normal)
if ((methodDef->mMethodType != BfMethodType_Normal) && (propertyDeclaration == NULL))
{
BF_ASSERT(methodDeclaration->mFatArrowToken != NULL);
Fail("Only normal methods can have expression bodies", methodDeclaration->mFatArrowToken);
@ -19961,7 +19964,12 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
overrideToken = methodDeclaration->mVirtualSpecifier;
if (overrideToken != NULL)
{
Fail("No suitable method found to override", overrideToken, true);
if ((propertyDeclaration != NULL) && (propertyDeclaration->mNameNode != NULL) &&
((methodDef->mMethodType == BfMethodType_PropertyGetter) || (methodDef->mMethodType == BfMethodType_PropertySetter)))
Fail(StrFormat("No suitable method found to override for '%s.%s'",
propertyDeclaration->mNameNode->ToString().c_str(), (methodDef->mMethodType == BfMethodType_PropertyGetter) ? "get" : "set"), overrideToken, true);
else
Fail("No suitable method found to override", overrideToken, true);
}
return usedMethod;

View file

@ -2070,17 +2070,25 @@ void BfPrinter::Visit(BfPropertyDeclaration* propertyDeclaration)
ExpectSpace();
QueueVisitChild(propertyDeclaration->mInitializer);
bool doInlineBlock = false;
if (propertyDeclaration->mDefinitionBlock != NULL)
DoBlockOpen(propertyDeclaration->mDefinitionBlock, true, &doInlineBlock);
for (auto method : propertyDeclaration->mMethods)
if (auto block = BfNodeDynCast<BfBlock>(propertyDeclaration->mDefinitionBlock))
{
Visit(method);
bool doInlineBlock = false;
DoBlockOpen(block, true, &doInlineBlock);
for (auto method : propertyDeclaration->mMethods)
{
Visit(method);
}
DoBlockClose(block, true, doInlineBlock);
}
else
{
QueueVisitChild(propertyDeclaration->mDefinitionBlock);
ExpectSpace();
for (auto method : propertyDeclaration->mMethods)
{
QueueVisitChild(method->mBody);
}
}
if (propertyDeclaration->mDefinitionBlock != NULL)
DoBlockClose(propertyDeclaration->mDefinitionBlock, true, doInlineBlock);
//QueueVisitChild(propertyDeclaration->mTrailingSemicolon);

View file

@ -6606,39 +6606,19 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth)
nextNode = mVisitorPos.Get(blockAfterIdx);
auto block = BfNodeDynCast<BfBlock>(nextNode);
auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
bool isExprBodyProp = (tokenNode != NULL) && (tokenNode->mToken == BfToken_FatArrow);
// Property.
// If we don't have a token afterwards then still treat it as a property for autocomplete purposes
if (((block != NULL) || (tokenNode == NULL)) && (typeRef != NULL))
if ((typeRef != NULL) &&
((block != NULL) || (tokenNode == NULL) || (isExprBodyProp)))
{
//mVisitorPos.mReadPos = blockAfterIdx;
if (propertyDeclaration == NULL)
{
if (block == NULL)
if ((block == NULL) && (!isExprBodyProp))
{
//// Actually treat it as a method
//auto methodDecl = mAlloc->Alloc<BfMethodDeclaration>();
//ReplaceNode(typeRef, methodDecl);
//methodDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
//methodDecl->mReturnType = typeRef;
//if (explicitInterface != NULL)
//{
// MEMBER_SET(methodDecl, mExplicitInterface, explicitInterface);
// MEMBER_SET(methodDecl, mExplicitInterfaceDotToken, explicitInterfaceDot);
//}
//// Don't set the name identifier, this could be bogus
////mVisitorPos.mReadPos--;
//
//// WHY did we want to not set this?
//// If we don't, then typing a new method name will end up treating the name node as a typeRef
//// which can autocomplete incorrectly
//MEMBER_SET(methodDecl, mNameNode, nameIdentifier);
//return methodDecl;
auto propDecl = mAlloc->Alloc<BfPropertyDeclaration>();
ReplaceNode(typeRef, propDecl);
propDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
@ -6684,6 +6664,29 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth)
MEMBER_SET(propertyDeclaration, mDefinitionBlock, block);
ReadPropertyBlock(propertyDeclaration, block);
}
else if (isExprBodyProp)
{
BfDeferredAstSizedArray<BfPropertyMethodDeclaration*> methods(propertyDeclaration->mMethods, mAlloc);
auto propertyBodyExpr = mAlloc->Alloc<BfPropertyBodyExpression>();
ReplaceNode(tokenNode, propertyBodyExpr);
MEMBER_SET(propertyBodyExpr, mFatTokenArrow, tokenNode);
auto method = mAlloc->Alloc<BfPropertyMethodDeclaration>();
method->mPropertyDeclaration = propertyDeclaration;
method->mNameNode = propertyDeclaration->mNameNode;
auto expr = CreateExpressionAfter(tokenNode);
if (expr != NULL)
{
MEMBER_SET(method, mBody, expr);
propertyDeclaration->SetSrcEnd(expr->GetSrcEnd());
}
methods.Add(method);
MEMBER_SET(propertyDeclaration, mDefinitionBlock, propertyBodyExpr);
}
return propertyDeclaration;
}