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