diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 9eeb5d56..0989cd58 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -2574,7 +2574,7 @@ public: BfTokenNode* mCloseParen; BfSizedArray mParams; BfSizedArray mCommas; - BfTokenNode* mFatArrowToken; + BfTokenNode* mFatArrowToken; BfAstNode* mBody; // Either expression or block BfFieldDtorDeclaration* mDtor; }; BF_AST_DECL(BfLambdaBindExpression, BfExpression); @@ -2827,7 +2827,7 @@ public: ASTREF(BfGenericConstraintsDeclaration*) mGenericConstraintsDeclaration; ASTREF(BfAstNode*) mEndSemicolon; ASTREF(BfTokenNode*) mFatArrowToken; - ASTREF(BfAstNode*) mBody; // Either expression or block + ASTREF(BfAstNode*) mBody; // Either expression or block //BfMethodDef* mMethodDef; @@ -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 diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index 43ea9023..b3d5ee51 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -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) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 3757f1f9..2676f8c9 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -13447,7 +13447,7 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr auto methodDecl = methodDef->GetMethodDeclaration(); auto methodDeclBlock = BfNodeDynCast(methodDecl->mBody); if (methodDeclBlock == NULL) - return BfTypedValue(); + return GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_IntPtr)); // Must not have an append alloc at all! BfTypedValue constValue; @@ -17596,7 +17596,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) isExpressionBody = true; } else if (auto propertyDeclaration = methodDef->GetPropertyDeclaration()) - { + { + auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration(); + if ((propertyMethodDeclaration != NULL) && (propertyMethodDeclaration->mFatArrowToken != NULL)) + isExpressionBody = true; if (auto propBodyExpr = BfNodeDynCast(propertyDeclaration->mDefinitionBlock)) { isExpressionBody = true; @@ -17636,42 +17639,45 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } else if (auto expressionBody = BfNodeDynCast(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(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 diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index 521f5d19..a9eecabe 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -2349,9 +2349,12 @@ void BfPrinter::Visit(BfPropertyMethodDeclaration* propertyMethodDeclaration) ExpectSpace(); QueueVisitChild(propertyMethodDeclaration->mMutSpecifier); ExpectSpace(); + QueueVisitChild(propertyMethodDeclaration->mFatArrowToken); + ExpectSpace(); if (auto block = BfNodeDynCast(propertyMethodDeclaration->mBody)) ExpectNewLine(); QueueVisitChild(propertyMethodDeclaration->mBody); + QueueVisitChild(propertyMethodDeclaration->mEndSemicolon); } void BfPrinter::Visit(BfPropertyDeclaration* propertyDeclaration) diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 4dcea2c5..3ebe6b2a 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -6157,17 +6157,36 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf bodyAfterNode = tokenNode; mVisitorPos.MoveNext(); - child = mVisitorPos.GetCurrent(); + child = mVisitorPos.GetNext(); } - auto endSemicolon = BfNodeDynCast(child); - if ((endSemicolon != NULL) && (endSemicolon->GetToken() == BfToken_Semicolon)) + bool handled = false; + BfTokenNode* fatArrowToken = NULL; + BfAstNode* endSemicolon = NULL; + if (tokenNode = BfNodeDynCast(child)) { - body = endSemicolon; - mVisitorPos.MoveNext(); - } + 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(child); - if (accessorBlock == NULL) + if (auto accessorBlock = BfNodeDynCast(child)) + { + body = accessorBlock; + mVisitorPos.MoveNext(); + } + if (body == NULL) { if (child != NULL) { @@ -6185,9 +6208,7 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf mVisitorPos.MoveNext(); } 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(); 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)