mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Enhanced expression-body support
This commit is contained in:
parent
a94d76ac5d
commit
6af96d8f6d
5 changed files with 91 additions and 46 deletions
|
@ -2916,7 +2916,9 @@ public:
|
|||
BfTokenNode* mProtectionSpecifier;
|
||||
BfTokenNode* mMutSpecifier;
|
||||
BfIdentifierNode* mNameNode;
|
||||
BfTokenNode* mFatArrowToken;
|
||||
BfAstNode* mBody;
|
||||
BfAstNode* mEndSemicolon;
|
||||
}; BF_AST_DECL(BfPropertyMethodDeclaration, BfAstNode);
|
||||
|
||||
class BfPropertyBodyExpression : public BfAstNode
|
||||
|
|
|
@ -1012,7 +1012,9 @@ void BfElementVisitor::Visit(BfPropertyMethodDeclaration* propertyDeclaration)
|
|||
VisitChild(propertyDeclaration->mProtectionSpecifier);
|
||||
VisitChild(propertyDeclaration->mNameNode);
|
||||
VisitChild(propertyDeclaration->mMutSpecifier);
|
||||
VisitChild(propertyDeclaration->mFatArrowToken);
|
||||
VisitChild(propertyDeclaration->mBody);
|
||||
VisitChild(propertyDeclaration->mEndSemicolon);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfPropertyBodyExpression* propertyBodyExpression)
|
||||
|
|
|
@ -13447,7 +13447,7 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr
|
|||
auto methodDecl = methodDef->GetMethodDeclaration();
|
||||
auto methodDeclBlock = BfNodeDynCast<BfBlock>(methodDecl->mBody);
|
||||
if (methodDeclBlock == NULL)
|
||||
return BfTypedValue();
|
||||
return GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_IntPtr)); // Must not have an append alloc at all!
|
||||
|
||||
BfTypedValue constValue;
|
||||
|
||||
|
@ -17597,6 +17597,9 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
}
|
||||
else if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
|
||||
{
|
||||
auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration();
|
||||
if ((propertyMethodDeclaration != NULL) && (propertyMethodDeclaration->mFatArrowToken != NULL))
|
||||
isExpressionBody = true;
|
||||
if (auto propBodyExpr = BfNodeDynCast<BfPropertyBodyExpression>(propertyDeclaration->mDefinitionBlock))
|
||||
{
|
||||
isExpressionBody = true;
|
||||
|
@ -17636,42 +17639,45 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
}
|
||||
else if (auto expressionBody = BfNodeDynCast<BfExpression>(methodDef->mBody))
|
||||
{
|
||||
if ((methodDef->mMethodType != BfMethodType_Normal) && (propertyDeclaration == NULL))
|
||||
{
|
||||
BF_ASSERT(methodDeclaration->mFatArrowToken != NULL);
|
||||
Fail("Only normal methods can have expression bodies", methodDeclaration->mFatArrowToken);
|
||||
}
|
||||
// if ((methodDef->mMethodType != BfMethodType_Normal) && (propertyDeclaration == NULL))
|
||||
// {
|
||||
// BF_ASSERT(methodDeclaration->mFatArrowToken != NULL);
|
||||
// Fail("Only normal methods can have expression bodies", methodDeclaration->mFatArrowToken);
|
||||
// }
|
||||
|
||||
auto expectingType = mCurMethodInstance->mReturnType;
|
||||
// What was this error for?
|
||||
// if ((expectingType->IsVoid()) && (IsInSpecializedSection()))
|
||||
// {
|
||||
// Warn(0, "Using a 'void' return with an expression-bodied method isn't needed. Consider removing '=>' token", methodDeclaration->mFatArrowToken);
|
||||
// }
|
||||
|
||||
//TODO: Why did we have all this stuff for handling void?
|
||||
// if (expectingType->IsVoid())
|
||||
// {
|
||||
// bool wasReturnGenericParam = false;
|
||||
// if ((mCurMethodState->mClosureState != NULL) && (mCurMethodState->mClosureState->mReturnType != NULL))
|
||||
// {
|
||||
// wasReturnGenericParam = mCurMethodState->mClosureState->mReturnType->IsGenericParam();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// auto unspecializedMethodInstance = GetUnspecializedMethodInstance(mCurMethodInstance);
|
||||
// if ((unspecializedMethodInstance != NULL) && (unspecializedMethodInstance->mReturnType->IsGenericParam()))
|
||||
// wasReturnGenericParam = true;
|
||||
// }
|
||||
//
|
||||
// // If we the void return was from a generic specialization, allow us to return a void result,
|
||||
// // otherwise treat expression as though it must be a statement
|
||||
// bool isStatement = expressionBody->VerifyIsStatement(mCompiler->mPassInstance, wasReturnGenericParam);
|
||||
// if (isStatement)
|
||||
// expectingType = NULL;
|
||||
// }
|
||||
BfEvalExprFlags exprEvalFlags = BfEvalExprFlags_None;
|
||||
if (expectingType->IsVoid())
|
||||
{
|
||||
exprEvalFlags = BfEvalExprFlags_NoCast;
|
||||
|
||||
bool wasReturnGenericParam = false;
|
||||
if ((mCurMethodState->mClosureState != NULL) && (mCurMethodState->mClosureState->mReturnType != NULL))
|
||||
{
|
||||
wasReturnGenericParam = mCurMethodState->mClosureState->mReturnType->IsGenericParam();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto unspecializedMethodInstance = GetUnspecializedMethodInstance(mCurMethodInstance);
|
||||
if ((unspecializedMethodInstance != NULL) && (unspecializedMethodInstance->mReturnType->IsGenericParam()))
|
||||
wasReturnGenericParam = true;
|
||||
}
|
||||
|
||||
// If we the void return was from a generic specialization, allow us to return a void result,
|
||||
// otherwise treat expression as though it must be a statement
|
||||
bool isStatement = expressionBody->VerifyIsStatement(mCompiler->mPassInstance, wasReturnGenericParam);
|
||||
if (isStatement)
|
||||
expectingType = NULL;
|
||||
}
|
||||
|
||||
UpdateSrcPos(expressionBody);
|
||||
auto retVal = CreateValueFromExpression(expressionBody, expectingType);
|
||||
auto retVal = CreateValueFromExpression(expressionBody, expectingType, exprEvalFlags);
|
||||
if ((retVal) && (expectingType != NULL))
|
||||
{
|
||||
mCurMethodState->mHadReturn = true;
|
||||
|
@ -20881,7 +20887,13 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
|
|||
{
|
||||
auto propertyMethodDecl = methodDef->GetPropertyMethodDeclaration();
|
||||
|
||||
Fail(StrFormat("Property '%s' %s accessor not defined in interface '%s'", propertyDecl->mNameNode->ToString().c_str(),
|
||||
String name;
|
||||
if (auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propertyDecl))
|
||||
name = "this[]";
|
||||
else if (propertyDecl->mNameNode != NULL)
|
||||
propertyDecl->mNameNode->ToString(name);
|
||||
|
||||
Fail(StrFormat("Property '%s' %s accessor not defined in interface '%s'", name.c_str(),
|
||||
(methodDef->mMethodType == BfMethodType_PropertyGetter) ? "get" : "set", TypeToString(ifaceInst).c_str()), methodDef->GetRefNode(), true);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -2349,9 +2349,12 @@ void BfPrinter::Visit(BfPropertyMethodDeclaration* propertyMethodDeclaration)
|
|||
ExpectSpace();
|
||||
QueueVisitChild(propertyMethodDeclaration->mMutSpecifier);
|
||||
ExpectSpace();
|
||||
QueueVisitChild(propertyMethodDeclaration->mFatArrowToken);
|
||||
ExpectSpace();
|
||||
if (auto block = BfNodeDynCast<BfBlock>(propertyMethodDeclaration->mBody))
|
||||
ExpectNewLine();
|
||||
QueueVisitChild(propertyMethodDeclaration->mBody);
|
||||
QueueVisitChild(propertyMethodDeclaration->mEndSemicolon);
|
||||
}
|
||||
|
||||
void BfPrinter::Visit(BfPropertyDeclaration* propertyDeclaration)
|
||||
|
|
|
@ -6157,17 +6157,36 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf
|
|||
bodyAfterNode = tokenNode;
|
||||
|
||||
mVisitorPos.MoveNext();
|
||||
child = mVisitorPos.GetCurrent();
|
||||
child = mVisitorPos.GetNext();
|
||||
}
|
||||
|
||||
auto endSemicolon = BfNodeDynCast<BfTokenNode>(child);
|
||||
if ((endSemicolon != NULL) && (endSemicolon->GetToken() == BfToken_Semicolon))
|
||||
bool handled = false;
|
||||
BfTokenNode* fatArrowToken = NULL;
|
||||
BfAstNode* endSemicolon = NULL;
|
||||
if (tokenNode = BfNodeDynCast<BfTokenNode>(child))
|
||||
{
|
||||
body = endSemicolon;
|
||||
if ((tokenNode->GetToken() == BfToken_Semicolon))
|
||||
{
|
||||
handled = true;
|
||||
endSemicolon = tokenNode;
|
||||
mVisitorPos.MoveNext();
|
||||
}
|
||||
else if (tokenNode->mToken == BfToken_FatArrow)
|
||||
{
|
||||
handled = true;
|
||||
fatArrowToken = tokenNode;
|
||||
mVisitorPos.MoveNext();
|
||||
|
||||
if (body == NULL)
|
||||
auto expr = CreateExpressionAfter(tokenNode);
|
||||
if (expr != NULL)
|
||||
{
|
||||
body = expr;
|
||||
endSemicolon = ExpectTokenAfter(expr, BfToken_Semicolon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
if (bodyAfterNode != NULL)
|
||||
{
|
||||
|
@ -6175,8 +6194,12 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf
|
|||
}
|
||||
else
|
||||
{
|
||||
auto accessorBlock = BfNodeDynCast<BfBlock>(child);
|
||||
if (accessorBlock == NULL)
|
||||
if (auto accessorBlock = BfNodeDynCast<BfBlock>(child))
|
||||
{
|
||||
body = accessorBlock;
|
||||
mVisitorPos.MoveNext();
|
||||
}
|
||||
if (body == NULL)
|
||||
{
|
||||
if (child != NULL)
|
||||
{
|
||||
|
@ -6186,8 +6209,6 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf
|
|||
}
|
||||
continue;
|
||||
}
|
||||
body = accessorBlock;
|
||||
mVisitorPos.MoveNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6200,7 +6221,7 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf
|
|||
}
|
||||
}
|
||||
|
||||
if (body == NULL)
|
||||
if ((body == NULL) && (!handled))
|
||||
{
|
||||
if (protectionSpecifier != NULL)
|
||||
AddErrorNode(protectionSpecifier);
|
||||
|
@ -6213,6 +6234,11 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf
|
|||
|
||||
auto method = mAlloc->Alloc<BfPropertyMethodDeclaration>();
|
||||
method->mPropertyDeclaration = propertyDeclaration;
|
||||
|
||||
if (fatArrowToken != NULL)
|
||||
MEMBER_SET(method, mFatArrowToken, fatArrowToken);
|
||||
if (endSemicolon != NULL)
|
||||
MEMBER_SET(method, mEndSemicolon, endSemicolon);
|
||||
if (protectionSpecifier != NULL)
|
||||
MEMBER_SET(method, mProtectionSpecifier, protectionSpecifier);
|
||||
if (accessorIdentifier != NULL)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue