diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 2313e8bd..473f1379 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -1243,6 +1243,11 @@ bool BfTypeDeclaration::IsAnonymous() return (mAnonymousName != NULL); } +bool BfTypeDeclaration::IsAnonymousInitializerType() +{ + return (mAnonymousName != NULL) && (mTypeNode == NULL); +} + ////////////////////////////////////////////////////////////////////////// bool BfTypeReference::IsNamedTypeReference() diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 5b24e794..1411422a 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -358,6 +358,7 @@ class BfAttributedIdentifierNode; class BfQualifiedNameNode; class BfNamespaceDeclaration; class BfTypeDeclaration; +class BfInitializerTypeDeclaration; class BfTypeAliasDeclaration; class BfMethodDeclaration; class BfOperatorDeclaration; @@ -1809,6 +1810,7 @@ public: ASTREF(BfTokenNode*) mCloseBrace; //BfDebugArray mChildArr; BfSizedArray mChildArr; + int mParserBlockId; public: using BfAstNode::Init; @@ -2282,6 +2284,7 @@ public: BfAstNode* mTarget; BfTokenNode* mOpenBrace; + BfInlineTypeReference* mInlineTypeRef; BfSizedArray mValues; BfSizedArray mCommas; BfTokenNode* mCloseBrace; @@ -2453,9 +2456,16 @@ public: BfSizedArray mAnonymousTypes; bool IsAnonymous(); + bool IsAnonymousInitializerType(); }; BF_AST_DECL(BfTypeDeclaration, BfAstNode); +class BfInitializerTypeDeclaration : public BfTypeDeclaration +{ +public: + BF_AST_TYPE(BfInitializerTypeDeclaration, BfTypeDeclaration); +}; BF_AST_DECL(BfInitializerTypeDeclaration, BfTypeDeclaration); + class BfTypeAliasDeclaration : public BfTypeDeclaration { public: @@ -2965,6 +2975,14 @@ public: BfSizedArray mCommas; }; BF_AST_DECL(BfObjectCreateExpression, BfMethodBoundExpression); +class BfExtendExpression : public BfExpression +{ +public: + BF_AST_TYPE(BfExtendExpression, BfExpression); + BfAstNode* mTarget; + BfTypeDeclaration* mTypeDecl; +}; BF_AST_DECL(BfExtendExpression, BfExpression); + class BfBoxExpression : public BfExpression { public: diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 8a5f4902..3ea8e3ec 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -2759,7 +2759,7 @@ bool BfAutoComplete::GetMethodInfo(BfMethodInstance* methodInst, StringImpl* sho return false; } -void BfAutoComplete::AddOverrides(const StringImpl& filter) +void BfAutoComplete::AddOverrides(const StringImpl& filter, bool forceAll) { if (!mIsAutoComplete) return; @@ -2780,7 +2780,7 @@ void BfAutoComplete::AddOverrides(const StringImpl& filter) if (curType == mModule->mCurTypeInstance) { // The "normal" case, and only case for types without extensions - if (methodDef->mDeclaringType == activeTypeDef) + if ((methodDef->mDeclaringType == activeTypeDef) && (!forceAll)) continue; if ((methodDef->mDeclaringType->IsExtension()) && (methodDef->mDeclaringType->mProject == activeTypeDef->mProject)) @@ -2812,7 +2812,7 @@ void BfAutoComplete::AddOverrides(const StringImpl& filter) (methodDef->mMethodType != BfMethodType_PropertySetter)) continue; - if ((methodInst->mVirtualTableIdx >= 0) && (methodInst->mVirtualTableIdx < mModule->mCurTypeInstance->mVirtualMethodTable.size())) + if ((methodInst->mVirtualTableIdx >= 0) && (methodInst->mVirtualTableIdx < mModule->mCurTypeInstance->mVirtualMethodTable.size()) && (!forceAll)) { auto& vEntry = mModule->mCurTypeInstance->mVirtualMethodTable[methodInst->mVirtualTableIdx]; if (vEntry.mImplementingMethod.mTypeInstance == mModule->mCurTypeInstance) diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index 7e6132dc..1009ef65 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -236,7 +236,7 @@ public: void AddExtensionMethods(BfTypeInstance* targetType, BfTypeInstance* extensionContainer, const StringImpl& filter, bool allowProtected, bool allowPrivate); void AddTopLevelNamespaces(BfAstNode* identifierNode); void AddTopLevelTypes(BfAstNode* identifierNode, bool onlyAttribute = false); - void AddOverrides(const StringImpl& filter); + void AddOverrides(const StringImpl& filter, bool forceAll = false); void AddCtorPassthroughs(); void UpdateReplaceData(); void AddTypeInstanceEntry(BfTypeInstance* typeInst); diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 7cf6ae6e..a0b18358 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -4442,7 +4442,7 @@ void BfCompiler::ProcessAutocompleteTempType() { auto checkTypeDef = *actualTypeDefItr; if ((!checkTypeDef->mIsPartial) /*&& (checkTypeDef->mTypeCode != BfTypeCode_Extension)*/ && - ((checkTypeDef->mTypeCode == tempTypeDef->mTypeCode) || (tempTypeDef->mTypeCode == BfTypeCode_Extension))) + ((checkTypeDef->mTypeCode == tempTypeDef->mTypeCode) || (tempTypeDef->mTypeCode == BfTypeCode_Extension) || (tempTypeDef->mTypeCode == BfTypeCode_Inferred))) { if ((checkTypeDef->NameEquals(tempTypeDef)) && (checkTypeDef->mIsCombinedPartial) && (checkTypeDef->mGenericParamDefs.size() == tempTypeDef->mGenericParamDefs.size()) && @@ -4831,8 +4831,8 @@ void BfCompiler::ProcessAutocompleteTempType() { for (auto baseType : checkTypeDef->mBaseTypes) { - autoComplete->CheckTypeRef(baseType, false); - module->ResolveTypeRef(baseType); + autoComplete->CheckTypeRef(BfNodeDynCast(baseType), false); + module->ResolveTypeRef_Ref(baseType, BfPopulateType_Identity); } checkTypeDef = checkTypeDef->mOuterType; } @@ -5055,6 +5055,9 @@ void BfCompiler::ProcessAutocompleteTempType() BfType* BfCompiler::CheckSymbolReferenceTypeRef(BfModule* module, BfTypeReference* typeRef) { + if (typeRef == NULL) + return NULL; + //auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration, //(BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue | BfResolveTypeRefFlag_AllowGenericTypeParamConstValue)); auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowRef); @@ -5271,7 +5274,7 @@ void BfCompiler::GetSymbolReferences() SetAndRestoreValue prevTypeState(module->mContext->mCurTypeState, &typeState); for (auto baseTypeRef : checkTypeDef->mBaseTypes) - CheckSymbolReferenceTypeRef(module, baseTypeRef); + CheckSymbolReferenceTypeRef(module, BfNodeDynCast(baseTypeRef)); for (auto genericParam : checkTypeDef->mGenericParamDefs) { @@ -5343,7 +5346,7 @@ void BfCompiler::GetSymbolReferences() if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type) { for (auto baseTypeRef : typeDef->mBaseTypes) - CheckSymbolReferenceTypeRef(module, baseTypeRef); + CheckSymbolReferenceTypeRef(module, BfNodeDynCast(baseTypeRef)); } BfTypeState typeState; diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 5a54851a..d1a97a0e 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -1293,7 +1293,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild typeInst->mHasStaticInitMethod = false; typeInst->mHasStaticMarkMethod = false; typeInst->mHasStaticDtorMethod = false; - typeInst->mHasTLSFindMethod = false; + typeInst->mHasTLSFindMethod = false; typeInst->mBaseType = NULL; delete typeInst->mCustomAttributes; typeInst->mCustomAttributes = NULL; diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index 911387d6..fc662dfc 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -166,6 +166,7 @@ public: ResolveKind mResolveKind; BfAstNode* mCurVarInitializer; int mArrayInitializerSize; + BfTypeInstance* mInitializerBaseType; public: BfTypeState() @@ -185,6 +186,7 @@ public: mCurVarInitializer = NULL; mArrayInitializerSize = -1; mResolveKind = ResolveKind_None; + mInitializerBaseType = NULL; } BfTypeState(BfType* type, BfTypeState* prevState = NULL) @@ -203,6 +205,7 @@ public: mCurVarInitializer = NULL; mArrayInitializerSize = -1; mResolveKind = ResolveKind_None; + mInitializerBaseType = NULL; } }; diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index c0e7a8d8..330565c0 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -1508,7 +1508,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) mCurTypeDef->mProject = mCurSource->mProject; mCurTypeDef->mNamespace = mNamespace; mSystem->AddNamespaceUsage(mCurTypeDef->mNamespace, mCurTypeDef->mProject); - if (typeDeclaration->mTypeNode == NULL) + if ((typeDeclaration->mTypeNode == NULL) && (!isAnonymous)) { mCurTypeDef->mIsPartial = true; mCurTypeDef->mIsExplicitPartial = true; @@ -1750,7 +1750,11 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) if (typeDeclaration->mTypeNode != NULL) typeToken = typeDeclaration->mTypeNode->GetToken(); - if (typeDeclaration->mTypeNode == NULL) + if (typeDeclaration->IsAnonymousInitializerType()) + { + mCurTypeDef->mTypeCode = BfTypeCode_Inferred; + } + else if (typeDeclaration->mTypeNode == NULL) { // Globals mCurTypeDef->mTypeCode = BfTypeCode_Struct; @@ -1852,6 +1856,9 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) (checkTypeDef->mIsFunction == mCurTypeDef->mIsFunction) && (checkTypeDef->mOuterType == actualOuterTypeDef); + if ((mCurTypeDef->mTypeCode == BfTypeCode_Inferred) && (checkTypeDef->mTypeDeclaration->IsAnonymousInitializerType())) + isCompatible = true; + if (isCompatible) { if (prevRevisionTypeDef == NULL) @@ -1977,7 +1984,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) // Map methods into the correct index from previous revision if (prevRevisionTypeDef != NULL) { - BF_ASSERT(mCurTypeDef->mTypeCode == prevRevisionTypeDef->mTypeCode); + BF_ASSERT((mCurTypeDef->mTypeCode == prevRevisionTypeDef->mTypeCode) || (mCurTypeDef->mTypeCode == BfTypeCode_Inferred)); if (mCurTypeDef->mFullHash == prevRevisionTypeDef->mFullHash) { @@ -2280,7 +2287,8 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) needsDynamicCastMethod = false; } - if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic) && (ctorClear == NULL)) + if (((mCurTypeDef->mTypeCode == BfTypeCode_Object) || (mCurTypeDef->mTypeCode == BfTypeCode_Inferred)) && + (!mCurTypeDef->mIsStatic) && (ctorClear == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "", mIsComptime); methodDef->mIsMutating = true; @@ -2299,7 +2307,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) if ((needsStaticInit) && (staticCtor == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, "", mIsComptime); - } + } bool makeCtorPrivate = hasCtor; diff --git a/IDEHelper/Compiler/BfElementVisitor.cpp b/IDEHelper/Compiler/BfElementVisitor.cpp index 7bd8ec07..305739a3 100644 --- a/IDEHelper/Compiler/BfElementVisitor.cpp +++ b/IDEHelper/Compiler/BfElementVisitor.cpp @@ -301,6 +301,7 @@ void BfElementVisitor::Visit(BfInitializerExpression* initExpr) VisitChild(initExpr->mTarget); VisitChild(initExpr->mOpenBrace); + VisitChild(initExpr->mInlineTypeRef); for (auto& val : initExpr->mValues) VisitChild(val); for (auto& val : initExpr->mCommas) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 7750ff16..ba6f66cd 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -4184,7 +4184,7 @@ void BfExprEvaluator::Visit(BfStringInterpolationExpression* stringInterpolation // { SetAndRestoreValue prevFlags(mBfEvalExprFlags, (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_NoAutoComplete)); - CreateObject(NULL, stringInterpolationExpression->mAllocNode, stringType); + CreateObject(NULL, stringInterpolationExpression->mAllocNode, stringType, NULL); } BfTypedValue newString = mResult; BF_ASSERT(newString); @@ -8159,6 +8159,9 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu } } + if (refNode == NULL) + refNode = methodInstance->GetOwner()->mTypeDef->GetRefNode(); + if ((autoComplete != NULL) && (prevNode != NULL)) autoComplete->CheckEmptyStart(prevNode, wantType); @@ -10128,6 +10131,8 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp if (resolvedTypeInstance != NULL) { + auto origTypeInstance = resolvedTypeInstance; + if ((mBfEvalExprFlags & BfEvalExprFlags_AppendFieldInitializer) == 0) { if ((!resolvedTypeInstance->IsStruct()) && (!resolvedTypeInstance->IsTypedPrimitive())) @@ -10173,10 +10178,12 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp structInst = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedTypeInstance, true); } + bool doBind = false; + mResultLocalVar = NULL; mResultFieldInstance = NULL; mResultLocalVarRefNode = NULL; - auto result = MatchConstructor(targetSrc, methodBoundExpr, structInst, resolvedTypeInstance, argValues, false, BfMethodGenericArguments(), resolvedTypeInstance->IsObject()); + BfTypedValue result = MatchConstructor(targetSrc, methodBoundExpr, structInst, resolvedTypeInstance, argValues, false, BfMethodGenericArguments(), resolvedTypeInstance->IsObject()); if ((result) && (!result.mType->IsVoid())) return result; mModule->ValidateAllocation(resolvedTypeInstance, targetSrc); @@ -11297,7 +11304,7 @@ void BfExprEvaluator::LookupQualifiedStaticField(BfQualifiedNameNode* nameNode, { BfType* type = NULL; { - type = mModule->ResolveTypeRef(nameNode->mLeft, NULL, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef); + type = mModule->ResolveTypeRef(nameNode->mLeft, NULL, BfPopulateType_Data, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_IgnoreLookupError)); mModule->CheckTypeRefFixit(nameNode->mLeft); } if (type != NULL) @@ -11690,6 +11697,10 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr) } } } + else if (auto objCreateExpr = BfNodeDynCast(initExpr->mTarget)) + { + CreateObject(objCreateExpr, objCreateExpr->mNewNode, NULL, initExpr->mInlineTypeRef); + } else VisitChild(initExpr->mTarget); if (!mResult) @@ -11789,6 +11800,37 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr) } else { + BfBlock* block = BfNodeDynCast(elementExpr); + bool handled = false; + + BfScopeData newScope; + + if (block != NULL) + { + newScope.mInnerIsConditional = true; + newScope.mCloseNode = block; + if (block->mCloseBrace != NULL) + newScope.mCloseNode = block->mCloseBrace; + mModule->mCurMethodState->AddScope(&newScope); + mModule->NewScopeState(); + + BfLocalVariable* localDef = new BfLocalVariable(); + localDef->mName = "_"; + localDef->mResolvedType = initValue.mType; + localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional; + if (initValue.IsAddr()) + { + localDef->mAddr = initValue.mValue; + } + else + { + localDef->mValue = initValue.mValue; + localDef->mIsSplat = initValue.IsSplat(); + } + if (!localDef->mResolvedType->IsVar()) + mModule->AddLocalVariableDef(localDef, true, true); + } + auto autoComplete = GetAutoComplete(); if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(elementExpr))) { @@ -11804,13 +11846,26 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr) } } - BfExprEvaluator exprEvaluator(mModule); - SizedArray argExprs; - argExprs.push_back(elementExpr); - BfSizedArray sizedArgExprs(argExprs); - BfResolvedArgs argValues(&sizedArgExprs); - exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval); - exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, BfMethodGenericArguments()); + if ((block != NULL) && (!block->IsExpression())) + { + mModule->VisitCodeBlock(block); + } + else + { + BfExprEvaluator exprEvaluator(mModule); + SizedArray argExprs; + argExprs.push_back(elementExpr); + BfSizedArray sizedArgExprs(argExprs); + BfResolvedArgs argValues(&sizedArgExprs); + exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval); + exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, BfMethodGenericArguments()); + } + + if (block != NULL) + { + mModule->RestoreScopeState(); + handled = true; + } wasValidInitKind = true; } @@ -11821,6 +11876,53 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr) } } + if (initExpr->mValues.IsEmpty()) + { + // When we are first typing out 'override', we + if (initExpr->mInlineTypeRef != NULL) + { + if (auto defineBlock = BfNodeDynCast(initExpr->mInlineTypeRef->mTypeDeclaration->mDefineNode)) + { + if (defineBlock->mChildArr.mSize == 1) + { + auto lastNode = defineBlock->mChildArr[0]; + if (lastNode->Equals("override")) + { + auto autoComplete = mModule->mCompiler->GetAutoComplete(); + if (autoComplete != NULL) + { + int cursorIdx = autoComplete->GetCursorIdx(lastNode); + if ((autoComplete->IsAutocompleteNode(lastNode, 1)) && (cursorIdx == lastNode->GetSrcEnd())) + { + auto typeInst = initValue.mType->ToTypeInstance(); + if (typeInst != NULL) + { + SetAndRestoreValue prevTypeInst(mModule->mCurTypeInstance, typeInst); + SetAndRestoreValue prevMethodInst(mModule->mCurMethodInstance, NULL); + autoComplete->AddOverrides("", true); + autoComplete->mInsertStartIdx = lastNode->mSrcStart; + autoComplete->mInsertEndIdx = lastNode->mSrcEnd; + } + } + } + } + } + } + } + } + else + { + auto lastNode = initExpr->mValues.back(); + if (auto lastIdentifier = BfNodeDynCast(lastNode)) + { + auto autoComplete = mModule->mCompiler->GetAutoComplete(); + if (autoComplete != NULL) + { + autoComplete->CheckIdentifier(lastIdentifier, false, false); + } + } + } + if (unassignedFieldFlags != 0) { auto curBlock = mModule->mBfIRBuilder->GetInsertBlock(); @@ -15500,17 +15602,17 @@ void BfExprEvaluator::CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode* void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr) { - CreateObject(objCreateExpr, objCreateExpr->mNewNode, NULL); + CreateObject(objCreateExpr, objCreateExpr->mNewNode, NULL, NULL); } -void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* wantAllocType) -{ +void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* wantAllocType, BfInlineTypeReference* inlineTypeRef) +{ auto autoComplete = GetAutoComplete(); if ((autoComplete != NULL) && (objCreateExpr != NULL) && (objCreateExpr->mTypeRef != NULL)) { autoComplete->CheckTypeRef(objCreateExpr->mTypeRef, false, true); } - + if ((autoComplete != NULL) && (objCreateExpr != NULL) && (objCreateExpr->mOpenToken != NULL) && (objCreateExpr->mCloseToken != NULL) && (objCreateExpr->mOpenToken->mToken == BfToken_LBrace) && (autoComplete->CheckFixit(objCreateExpr->mOpenToken))) { @@ -15744,6 +15846,16 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs resolvedTypeRef = unresolvedTypeRef; } + if (inlineTypeRef != NULL) + { + auto inlineType = mModule->ResolveTypeRef(inlineTypeRef); + if (inlineType != NULL) + { + unresolvedTypeRef = inlineType; + resolvedTypeRef = inlineType; + } + } + if (resolvedTypeRef == NULL) { unresolvedTypeRef = mModule->GetPrimitiveType(BfTypeCode_Var); @@ -16346,7 +16458,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs BfAstNode* refNode = objCreateExpr->mTypeRef; if ((objCreateExpr->mCtorExplicit != NULL) && (objCreateExpr->mCtorExplicit->mThisToken != NULL)) refNode = objCreateExpr->mCtorExplicit->mThisToken; - MatchConstructor(refNode, objCreateExpr, emtpyThis, typeInstance, argValues, false, methodGenericArguments, true); + auto checkTypeInst = typeInstance; + if (checkTypeInst->IsAnonymousInitializerType()) + checkTypeInst = checkTypeInst->mBaseType; + MatchConstructor(refNode, objCreateExpr, emtpyThis, checkTypeInst, argValues, false, methodGenericArguments, true); if ((wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo)) { if (autoComplete->mMethodMatchInfo != NULL) @@ -16360,7 +16475,11 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs auto refNode = allocNode; if (objCreateExpr != NULL) refNode = objCreateExpr->mTypeRef; - MatchConstructor(refNode, objCreateExpr, emtpyThis, typeInstance, argValues, false, methodGenericArguments, true); + + auto checkTypeInst = typeInstance; + if (checkTypeInst->IsAnonymousInitializerType()) + checkTypeInst = checkTypeInst->mBaseType; + MatchConstructor(refNode, objCreateExpr, emtpyThis, checkTypeInst, argValues, false, methodGenericArguments, true); } if (objCreateExpr != NULL) mModule->ValidateAllocation(typeInstance, objCreateExpr->mTypeRef); @@ -16471,10 +16590,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs } else if (bindResult.mFunc) { - if (typeInstance->IsObject()) + bool hasRealtimeLeakCheck = (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!IsComptime()); + if ((typeInstance->IsObject()) || (typeInstance->IsAnonymousInitializerType())) { - bool hasRealtimeLeakCheck = (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!IsComptime()); - bool wantsCtorClear = true; if (hasRealtimeLeakCheck) { @@ -16497,7 +16615,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs CreateCall(objCreateExpr, ctorClear.mMethodInstance, ctorClear.mFunc, false, irArgs); } } + } + if (typeInstance->IsObject()) + { if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (hasRealtimeLeakCheck)) { BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers"); @@ -16560,23 +16681,56 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs } } + auto origThisTypedValue = mResult; + auto thisTypedValue = mResult; + if (inlineTypeRef != NULL) + { + BfType* wantType = bindResult.mMethodInstance->GetOwner(); + if (thisTypedValue.mType->IsPointer()) + wantType = mModule->CreatePointerType(wantType); + thisTypedValue = mModule->Cast(allocNode, thisTypedValue, wantType); + } + if ((bindResult.mMethodInstance->mMethodDef->mHasAppend) && (mResult.mType->IsObject())) { BF_ASSERT(bindResult.mIRArgs[0].IsFake()); auto typeInst = mResult.mType->ToTypeInstance(); - auto intPtrType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); - auto thisVal = mResult; + auto intPtrType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); BfIRValue intPtrVal = mModule->CreateAlloca(intPtrType); - auto intPtrThisVal = mModule->mBfIRBuilder->CreatePtrToInt(thisVal.mValue, (intPtrType->mSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64); + auto intPtrThisVal = mModule->mBfIRBuilder->CreatePtrToInt(thisTypedValue.mValue, (intPtrType->mSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64); auto curValPtr = mModule->mBfIRBuilder->CreateAdd(intPtrThisVal, mModule->GetConstValue(typeInst->mInstSize, intPtrType)); mModule->mBfIRBuilder->CreateStore(curValPtr, intPtrVal); bindResult.mIRArgs[0] = intPtrVal; } if (!typeInstance->IsValuelessType()) - bindResult.mIRArgs.Insert(0, mResult.mValue); + bindResult.mIRArgs.Insert(0, thisTypedValue.mValue); auto result = CreateCall(objCreateExpr, bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs); if ((result) && (!result.mType->IsVoid())) mResult = result; + + if (origThisTypedValue.mType != thisTypedValue.mType) + { + auto origThisType = origThisTypedValue.mType; + if (origThisType->IsPointer()) + origThisType = origThisType->GetUnderlyingType(); + auto origThisTypeInst = origThisType->ToTypeInstance(); + if (origThisTypeInst != NULL) + { + BF_ASSERT(origThisTypeInst->IsAnonymousInitializerType()); + + auto ctorMethod = mModule->GetMethodByName(origThisTypeInst, "__BfCtor", 0); + if (!ctorMethod) + { + mModule->AssertErrorState(); + } + else if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) == 0) + { + SizedArray irArgs; + irArgs.push_back(origThisTypedValue.mValue); + CreateCall(objCreateExpr, ctorMethod.mMethodInstance, ctorMethod.mFunc, false, irArgs); + } + } + } } } @@ -19114,6 +19268,11 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m } void BfExprEvaluator::Visit(BfInvocationExpression* invocationExpr) +{ + DoInvocation(invocationExpr); +} + +void BfExprEvaluator::DoInvocation(BfInvocationExpression* invocationExpr) { BfAutoParentNodeEntry autoParentNodeEntry(mModule, invocationExpr); diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 1899a489..63c6e88d 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -506,6 +506,7 @@ public: BfModuleMethodInstance GetSelectedMethod(BfMethodMatcher& methodMatcher); bool CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail); bool HasVariableDeclaration(BfAstNode* checkNode); + void DoInvocation(BfInvocationExpression* invocationExpr); void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray& args, const BfMethodGenericArguments& methodGenericArgs, BfTypedValue* outCascadeValue = NULL); int GetMixinVariable(); void CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* typeInstance, const StringImpl& methodName, BfMethodMatcher& methodMatcher, BfMethodType methodType); @@ -538,7 +539,7 @@ public: void InitializedSizedArray(BfSizedArrayType* sizedArrayType, BfTokenNode* openToken, const BfSizedArray& values, const BfSizedArray& commas, BfTokenNode* closeToken, BfTypedValue* receivingValue = NULL); void CheckDotToken(BfTokenNode* tokenNode); void DoMemberReference(BfMemberReferenceExpression* memberRefExpr, BfTypedValue* outCascadeValue); - void CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* allocType); + void CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* allocType, BfInlineTypeReference* inlineTypeRef); void HandleIndexerExpression(BfIndexerExpression* indexerExpr, BfTypedValue target); ////////////////////////////////////////////////////////////////////////// diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index 03d69c3c..57924a93 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -118,7 +118,8 @@ enum BfTypeCode : uint8 BfTypeCode_Int64X2, BfTypeCode_Int64X3, BfTypeCode_Int64X4, - BfTypeCode_Length + BfTypeCode_Length, + BfTypeCode_Inferred }; enum BfConstType diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index e02c5a08..60a46d97 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -18194,7 +18194,7 @@ void BfModule::EmitCtorBody(bool& skipBody) auto methodDeclaration = methodDef->mMethodDeclaration; auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration; auto typeDef = mCurTypeInstance->mTypeDef; - + BfCustomAttributes* customAttributes = NULL; defer(delete customAttributes); BfInvocationExpression* ctorInvocation = NULL; @@ -18230,7 +18230,7 @@ void BfModule::EmitCtorBody(bool& skipBody) } // Zero out memory for default ctor - if ((methodDeclaration == NULL) && (mCurTypeInstance->IsStruct()) && (methodInstance->mChainType != BfMethodChainType_ChainMember) && + if ((methodDeclaration == NULL) && (mCurTypeInstance->IsStruct()) && (!mCurTypeInstance->IsAnonymousInitializerType()) && (methodInstance->mChainType != BfMethodChainType_ChainMember) && (!mCurMethodState->mLocals.IsEmpty())) { if (mCurTypeInstance->IsTypedPrimitive()) @@ -18593,6 +18593,8 @@ void BfModule::EmitCtorBody(bool& skipBody) targetRefNode = ctorDeclaration->mInitializer; if (auto invocationExpr = BfNodeDynCast(targetRefNode)) targetRefNode = invocationExpr->mTarget; + if (targetRefNode == NULL) + targetRefNode = mCurTypeInstance->mTypeDef->GetRefNode(); if (baseCtorNode != NULL) { @@ -18687,7 +18689,7 @@ void BfModule::EmitCtorBody(bool& skipBody) targetType = mCurTypeInstance->mBaseType; if (ctorDeclaration != NULL) targetRefNode = ctorDeclaration->mThisToken; - else if (typeDef->mTypeDeclaration != NULL) + else if ((typeDef->mTypeDeclaration != NULL) && (typeDef->mTypeDeclaration->mNameNode != NULL)) targetRefNode = typeDef->mTypeDeclaration->mNameNode; } } @@ -18717,7 +18719,7 @@ void BfModule::EmitCtorBody(bool& skipBody) } auto autoComplete = mCompiler->GetAutoComplete(); - if (targetType != NULL) + if ((targetType != NULL) && (!mCurTypeInstance->IsAnonymousInitializerType())) { BfAstNode* refNode = methodDeclaration; if (refNode == NULL) @@ -20615,7 +20617,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup, if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed())) { if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(methodDef->mBody)) + { + SetAndRestoreValue prevSkipAnonTypes(sourceClassifier->mSkipAnonymousTypes, true); sourceClassifier->VisitChildNoRef(methodDef->mBody); + } } } @@ -21727,13 +21732,13 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup, mCurMethodState->mLeftBlockUncond = true; } else if (methodDef->mMethodType == BfMethodType_CtorClear) - { + { SetIllegalSrcPos(); mBfIRBuilder->ClearDebugLocation(); PopulateType(mCurTypeInstance, BfPopulateType_Data); auto thisVal = GetThis(); int prevSize = 0; - if (mContext->mBfObjectType != NULL) + if ((mContext->mBfObjectType != NULL) && (mCurTypeInstance->IsObject())) { prevSize = mContext->mBfObjectType->mInstSize; PopulateType(mContext->mBfObjectType); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index a2c2b310..17c5e110 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1981,6 +1981,7 @@ public: BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, bool resolveGenericParam = true); BfType* ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags& resolveFlags); BfType* ResolveTypeRef_Ref(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags& resolveFlags); + BfType* ResolveTypeRef_Ref(BfAstNode* astNode, BfPopulateType populateType); BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0); BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 57ad962a..5df85405 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -1660,6 +1660,7 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType case BfTypeCode_Interface: case BfTypeCode_Enum: case BfTypeCode_TypeAlias: + case BfTypeCode_Inferred: // Implemented below break; case BfTypeCode_Extension: @@ -4179,6 +4180,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy { baseType = ResolveTypeDef(mCompiler->mValueTypeTypeDef, BfPopulateType_Data)->ToTypeInstance(); } + else if (typeDef->mTypeCode == BfTypeCode_Inferred) + baseType = mContext->mBfObjectType; if (baseType != NULL) defaultBaseTypeInst = baseType->ToTypeInstance(); @@ -4193,7 +4196,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy bool wantPopulateInterfaces = false; - BfTypeReference* baseTypeRef = NULL; + BfAstNode* baseTypeRef = NULL; if ((typeDef->mIsDelegate) && (!typeInstance->IsClosure())) { if (mCompiler->mDelegateTypeDef == NULL) @@ -4229,7 +4232,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy SetAndRestoreValue prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType); bool populateBase = !typeInstance->mTypeFailed; - BfType* checkType = checkType = ResolveTypeRef(checkTypeRef, BfPopulateType_Declaration); + BfType* checkType = checkType = ResolveTypeRef_Ref(checkTypeRef, BfPopulateType_Declaration); if ((checkType != NULL) && (!checkType->IsInterface()) && (populateBase)) { @@ -4415,6 +4418,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (baseType != NULL) { baseTypeInst = baseType->ToTypeInstance(); + if ((baseTypeInst != NULL) && (typeDef->mTypeCode == BfTypeCode_Inferred)) + typeDef->mTypeCode = baseTypeInst->mTypeDef->mTypeCode; } if (typeInstance->mBaseType != NULL) @@ -12967,6 +12972,9 @@ BfType* BfModule::ResolveTypeRef_Ref(BfAstNode* astNode, const BfSizedArray(astNode)) return ResolveTypeRef_Ref(typeRef, populateType, resolveFlags, 0); + if (astNode->IsTemporary()) + return ResolveTypeRef((BfTypeReference*)astNode, populateType, resolveFlags); + if ((resolveFlags & BfResolveTypeRefFlag_AllowImplicitConstExpr) != 0) { if (auto expr = BfNodeDynCast(astNode)) @@ -12993,6 +13001,12 @@ BfType* BfModule::ResolveTypeRef_Ref(BfAstNode* astNode, const BfSizedArray= mUniqueIDList.size()) + + int* valuePtr = NULL; + if (mUniqueIDList.TryAdd(idx, NULL, &valuePtr)) { if (!gFreeIds.IsEmpty()) { - mUniqueIDList.Add(gFreeIds.back()); + *valuePtr = gFreeIds.back(); gFreeIds.pop_back(); } else - mUniqueIDList.Add(gCurFreeId++); - } - return mUniqueIDList[idx]; + *valuePtr = gCurFreeId++; + } + return *valuePtr; } BfParseFileData::~BfParseFileData() @@ -130,8 +132,8 @@ BfParseFileData::~BfParseFileData() if (!mUniqueIDList.IsEmpty()) { AutoCrit autoCrit(gParseFileDataCrit); - for (auto id : mUniqueIDList) - gFreeIds.Add(id); + for (auto kv : mUniqueIDList) + gFreeIds.Add(kv.mValue); } } @@ -442,6 +444,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem mTriviaStart = 0; mParsingFailed = false; mInAsmBlock = false; + mCurBlockId = 0; mPreprocessorIgnoredSectionNode = NULL; mPreprocessorIgnoreDepth = 0; mAddedDependsDefines = false; @@ -856,7 +859,10 @@ BfBlock* BfParser::ParseInlineBlock(int spaceIdx, int endIdx) if (startNode == NULL) startNode = childNode; if (block == NULL) + { block = mAlloc->Alloc(); + block->mParserBlockId = ++mCurBlockId; + } block->Add(childNode); childArr.push_back(childNode); //block->mChildArr.Add(childNode, &mAlloc); @@ -3644,6 +3650,7 @@ void BfParser::ParseBlock(BfBlock* astNode, int depth, bool isInterpolate) else*/ { genBlock = mAlloc->Alloc(); + genBlock->mParserBlockId = ++mCurBlockId; genBlock->mOpenBrace = (BfTokenNode*)CreateNode(); newBlock = genBlock; } diff --git a/IDEHelper/Compiler/BfParser.h b/IDEHelper/Compiler/BfParser.h index c01f9cd2..5974d00f 100644 --- a/IDEHelper/Compiler/BfParser.h +++ b/IDEHelper/Compiler/BfParser.h @@ -65,7 +65,7 @@ enum MaybeBool class BfParseFileData { public: - Array mUniqueIDList; + Dictionary mUniqueIDList; int mRefCount; public: @@ -198,6 +198,7 @@ public: int mLineStart; int mLineNum; bool mInAsmBlock; + int mCurBlockId; BfParserFlag mParserFlags; int mCursorIdx; diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index ceee732d..ef6599ee 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -46,8 +46,7 @@ BfReducer::BfReducer() mAssertCurrentNodeIdx = 0; mSystem = NULL; mResolvePassData = NULL; - mMethodDepth = 0; - mCurUniqueIdx = 0; + mMethodDepth = 0; mDocumentCheckIdx = 0; mTypeMemberNodeStart = NULL; } @@ -110,6 +109,20 @@ bool BfReducer::IsNodeRelevant(BfAstNode* astNode) return false; } +bool BfReducer::IsCursorInside(BfAstNode* astNode) +{ + BfParser* bfParser = astNode->GetSourceData()->ToParser(); + if (bfParser == NULL) + return false; + int cursorPos = bfParser->mCursorIdx; + if (cursorPos == -1) + return false; + if (astNode->Contains(cursorPos, 1, 0)) + return true; + BF_ASSERT(bfParser->mParserData->mRefCount == -1); + return false; +} + bool BfReducer::IsNodeRelevant(BfAstNode* startNode, BfAstNode* endNode) { if (startNode == NULL) @@ -971,7 +984,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int // Ignore } else if ((checkNode->IsA()) || (checkNode->IsA())) - { + { // Identifier is always allowed in tuple (parenDepth == 0), because it's potentially the field name // (successToken == BfToken_RParen) infers we are already checking inside parentheses, such as // when we see a potential cast expression @@ -988,11 +1001,11 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int hadUnexpectedIdentifier = true; } -// if (checkNode->Equals("tag")) -// { -// // Keep looking for tag name -// } -// else + // if (checkNode->Equals("tag")) + // { + // // Keep looking for tag name + // } + // else { hadIdentifier = true; identifierExpected = false; @@ -1052,13 +1065,13 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int if ((retryNode != -1) && (successToken == BfToken_None)) { - int newEndNode = -1; - if (IsTypeReference(checkNode, successToken, retryNode, &retryNode, &newEndNode, couldBeExpr, isGenericType, isTuple)) - { - if (outEndNode != NULL) - *outEndNode = newEndNode; - return true; - } + int newEndNode = -1; + if (IsTypeReference(checkNode, successToken, retryNode, &retryNode, &newEndNode, couldBeExpr, isGenericType, isTuple)) + { + if (outEndNode != NULL) + *outEndNode = newEndNode; + return true; + } } return false; } @@ -1582,9 +1595,9 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat { BfExpression* result = NULL; if (!stackHelper.Execute([&]() - { - result = CreateExpression(node, createExprFlags); - })) + { + result = CreateExpression(node, createExprFlags); + })) { Fail("Expression too complex to parse", node); } @@ -1837,6 +1850,45 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat exprLeft = TryCreateInitializerExpression(typeRef); } } + + if (auto tokenNode = BfNodeDynCast(mVisitorPos.Get(endNodeIdx))) + { + if (tokenNode->mToken == BfToken_LParen) + { + int openCount = 1; + int checkIdx = endNodeIdx + 1; + while (true) + { + auto checkNode = mVisitorPos.Get(checkIdx); + if (checkNode == NULL) + break; + if (auto checkTokenNode = BfNodeDynCast(checkNode)) + { + if (checkTokenNode->mToken == BfToken_LParen) + openCount++; + if (checkTokenNode->mToken == BfToken_RParen) + { + openCount--; + if (openCount == 0) + break; + } + } + checkIdx++; + } + + if (auto blockNode = BfNodeDynCast(mVisitorPos.Get(checkIdx + 1))) + { + // If we have 'A() { ... }', that can either be an invocation with an initializer block or a + // create expression with an inline type declaration + initializer block + if (InitializerBlockHasInlineTypeDecl(blockNode)) + { + exprLeft = CreateObjectCreateExpression(NULL, exprLeft); + if (auto initExpr = TryCreateInitializerExpression(exprLeft)) + exprLeft = initExpr; + } + } + } + } } } @@ -1849,7 +1901,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat auto nextNode = mVisitorPos.GetNext(); if ((nextNode != NULL) && ((token == BfToken_Checked) || - (token == BfToken_Unchecked))) + (token == BfToken_Unchecked))) { mVisitorPos.MoveNext(); auto nextExpr = CreateExpression(nextNode); @@ -1858,9 +1910,9 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat return nextExpr; } else if ((token == BfToken_New) || - (token == BfToken_Scope) || + (token == BfToken_Scope) || (token == BfToken_Append)) - { + { auto allocNode = CreateAllocNode(tokenNode); bool isDelegateBind = false; @@ -2088,7 +2140,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat return caseExpr; } else if (token == BfToken_Dot) // Abbreviated dot syntax ".EnumVal" - { + { bool handled = false; if (auto nextTokenNode = BfNodeDynCast(mVisitorPos.GetNext())) { @@ -2097,11 +2149,11 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat auto invocationExpr = CreateObjectCreateExpression(NULL, tokenNode); if (invocationExpr == NULL) return exprLeft; - exprLeft = invocationExpr; + exprLeft = invocationExpr; handled = true; } } - + if (auto blockNode = BfNodeDynCast(mVisitorPos.GetNext())) { // Initializer ".{ x = 1, y = 2 }" @@ -2425,8 +2477,8 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat bool isTypeRef = IsTypeReference(mVisitorPos.GetCurrent(), BfToken_RParen, -1, &outEndNode); mVisitorPos.mReadPos--; - if ((isTypeRef) && (outEndNode > 0)) - { + if ((isTypeRef) && (outEndNode > 0)) + { if (auto tokenNode = BfNodeDynCast(mVisitorPos.Get(outEndNode - 1))) { if ((tokenNode->mToken == BfToken_RChevron) || (tokenNode->mToken == BfToken_RDblChevron)) @@ -2436,7 +2488,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat MEMBER_SET_CHECKED(nameOfExpr, mTarget, typeRef); } } - } + } if (nameOfExpr->mTarget == NULL) { @@ -4628,7 +4680,7 @@ bool BfReducer::IsTerminatingExpression(BfAstNode* node) case BfToken_AllocType: case BfToken_Append: case BfToken_Default: - case BfToken_Is: + case BfToken_Is: case BfToken_Scope: case BfToken_New: case BfToken_RetType: @@ -4744,7 +4796,7 @@ BfAstNode* BfReducer::CreateStatement(BfAstNode* node, CreateStmtFlags createStm { Fail("Statement too complex to parse", node); } - return result; + return result; } } @@ -5149,7 +5201,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF if (attributes == NULL) return NULL; mVisitorPos.MoveNext(); - bool isValid = false; + bool isValid = false; auto nextNode = mVisitorPos.GetCurrent(); tokenNode = BfNodeDynCast(nextNode); @@ -5186,25 +5238,13 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF return NULL; } - String name; - auto parserData = typeDecl->GetParserData(); - name = "_Anon_"; + InitAnonymousType(typeDecl); - auto parseFileData = parserData->mParseFileData; - int uniqueId = parseFileData->GetUniqueId(mCurUniqueIdx++); - name += StrFormat("%d", uniqueId); - - int len = (int)name.length() + 1; - typeDecl->mAnonymousName = (char*)mAlloc->AllocBytes(len); - memcpy(typeDecl->mAnonymousName, name.c_str(), len); - - if (mCurTypeState != NULL) - mCurTypeState->mAnonymousTypeDecls.Add(typeDecl); auto typeRef = mAlloc->Alloc(); ReplaceNode(typeDecl, typeRef); typeRef->mTypeDeclaration = typeDecl; return typeRef; - } + } else if ((token == BfToken_Comptype) || (token == BfToken_Decltype)) { auto declTypeRef = mAlloc->Alloc(); @@ -5297,18 +5337,18 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF BfTypeReference* typeRef = BfNodeDynCast(firstNode); if (typeRef == NULL) { -// if (identifierNode->Equals("tag")) -// { -// auto rightIdentifer = ExpectIdentifierAfter(identifierNode); -// if (rightIdentifer != NULL) -// { -// auto tagTypeRef = mAlloc->Alloc(); -// ReplaceNode(identifierNode, tagTypeRef); -// tagTypeRef->mTagNode = identifierNode; -// MEMBER_SET(tagTypeRef, mNameNode, rightIdentifer); -// return tagTypeRef; -// } -// } + // if (identifierNode->Equals("tag")) + // { + // auto rightIdentifer = ExpectIdentifierAfter(identifierNode); + // if (rightIdentifer != NULL) + // { + // auto tagTypeRef = mAlloc->Alloc(); + // ReplaceNode(identifierNode, tagTypeRef); + // tagTypeRef->mTagNode = identifierNode; + // MEMBER_SET(tagTypeRef, mNameNode, rightIdentifer); + // return tagTypeRef; + // } + // } typeRef = DoCreateNamedTypeRef(identifierNode); } @@ -5365,7 +5405,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF { auto rightIdentifer = ExpectIdentifierAfter(qualifiedTypeRef); if (rightIdentifer == NULL) - return qualifiedTypeRef; + return qualifiedTypeRef; auto namedTypeRef = mAlloc->Alloc(); namedTypeRef->mNameNode = rightIdentifer; @@ -5568,7 +5608,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF token = tokenNode->GetToken(); if ((tokenNode != NULL) && ((token == BfToken_Const) || - (token == BfToken_Ref) || + (token == BfToken_Ref) || (token == BfToken_Mut) || (token == BfToken_LParen) || (token == BfToken_Delegate) || @@ -5772,8 +5812,8 @@ BfIdentifierNode* BfReducer::CompactQualifiedName(BfAstNode* leftNode) auto prevNodeToken = BfNodeDynCast(prevNode); if ((prevNodeToken != NULL) && ((prevNodeToken->GetToken() == BfToken_Dot) || - (prevNodeToken->GetToken() == BfToken_QuestionDot) || - (prevNodeToken->GetToken() == BfToken_Arrow))) + (prevNodeToken->GetToken() == BfToken_QuestionDot) || + (prevNodeToken->GetToken() == BfToken_Arrow))) return leftIdentifier; mVisitorPos.MoveNext(); // past . @@ -5975,11 +6015,11 @@ BfStatement* BfReducer::CreateAttributedStatement(BfTokenNode* tokenNode, Create if (auto exprStatement = BfNodeDynCast(checkNode)) checkNode = exprStatement->mExpression; - if ((checkNode->IsA()) || - (checkNode->IsA()) || - (checkNode->IsA()) || + if ((checkNode->IsA()) || + (checkNode->IsA()) || + (checkNode->IsA()) || (checkNode->IsA()) || - (checkNode->IsA())) + (checkNode->IsA())) { if (auto varDecl = BfNodeDynCast(checkNode)) { @@ -6129,7 +6169,7 @@ BfTokenNode* BfReducer::ReadArguments(BfAstNode* parentNode, BfAstNode* afterNod ReplaceNode(identifierNode, namedExpr); MEMBER_SET(namedExpr, mNameNode, identifierNode); MEMBER_SET(namedExpr, mColonToken, nextNextToken) - mVisitorPos.MoveNext(); + mVisitorPos.MoveNext(); mVisitorPos.MoveNext(); auto innerExpr = CreateExpressionAfter(namedExpr, CreateExprFlags_AllowVariableDecl); @@ -6381,7 +6421,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, i Fail("Invalid target for attributes", memberNode); return memberNode; } - + memberNode->mTriviaStart = attributes->mTriviaStart; memberNode->mSrcStart = attributes->mSrcStart; @@ -6400,7 +6440,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, i return member; } } - + ReplaceNode(attributes, member); member->mAttributes = attributes; @@ -6893,13 +6933,13 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, i if (token == BfToken_Extern) { if ((fieldDecl->mExternSpecifier != NULL) && (fieldDecl->mExternSpecifier->mToken == BfToken_Append)) - { - Fail("Extern cannot be used with 'append' specified", tokenNode); - } - else if (fieldDecl->mExternSpecifier != NULL) - { + { + Fail("Extern cannot be used with 'append' specified", tokenNode); + } + else if (fieldDecl->mExternSpecifier != NULL) + { Fail("Extern already specified", tokenNode); - } + } MEMBER_SET(fieldDecl, mExternSpecifier, tokenNode); handled = true; @@ -7167,9 +7207,9 @@ void BfReducer::ReadPropertyBlock(BfPropertyDeclaration* propertyDeclaration, Bf BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int depth, BfAstNode* deferredHeadNode) { -// SetAndRestoreValue prevTypeMemberNodeStart(mTypeMemberNodeStart, node, false); -// if (depth == 0) -// prevTypeMemberNodeStart.Set(); + // SetAndRestoreValue prevTypeMemberNodeStart(mTypeMemberNodeStart, node, false); + // if (depth == 0) + // prevTypeMemberNodeStart.Set(); if (mCurTypeDecl != NULL) AssertCurrentNode(node); @@ -7196,7 +7236,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept if (IsTypeReference(node, BfToken_None, -1, &endNodeIdx)) { isTypeRef = true; - } + } } if ((token == BfToken_LBracket) && (depth > 0)) @@ -7821,11 +7861,16 @@ BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target, } BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfAstNode* target) -{ +{ auto block = BfNodeDynCast(mVisitorPos.GetNext()); if (block == NULL) return NULL; + bool allowInitializerStatement = false; + auto objectCreateExpr = BfNodeDynCast(target); + if (objectCreateExpr != NULL) + allowInitializerStatement = true; + mVisitorPos.MoveNext(); auto initializerExpr = mAlloc->Alloc(); @@ -7840,12 +7885,43 @@ BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfAstNode* ta BfDeferredAstNodeSizedArray values(initializerExpr, initializerExpr->mValues, mAlloc); BfDeferredAstNodeSizedArray commas(initializerExpr, initializerExpr->mCommas, mAlloc); + int initializerStartIdx = 0; + int minTypeDeclEnd = 0; + BfAstNode* nextNode = NULL; while (!isDone) { BfAstNode* node = mVisitorPos.GetCurrent(); + if (node == NULL) + break; initializerExpr->mSrcEnd = node->mSrcEnd; + if ((values.IsEmpty()) && (initializerExpr->mInlineTypeRef == NULL)) + { + if ((allowInitializerStatement) && (!IsInitializerStatement(node))) + { + auto typeDecl = mAlloc->Alloc(); + ReplaceNode(node, typeDecl); + block->mOpenBrace = NULL; + MEMBER_SET(typeDecl, mDefineNode, block); + InitAnonymousType(typeDecl); + HandleTypeDeclaration(typeDecl, NULL, NULL, true); + initializerStartIdx = mVisitorPos.mWritePos; + auto typeRef = mAlloc->Alloc(); + ReplaceNode(typeDecl, typeRef); + typeRef->mTypeDeclaration = typeDecl; + MEMBER_SET(initializerExpr, mInlineTypeRef, typeRef); + + if (objectCreateExpr != NULL) + { + BfDeferredAstSizedArray baseClasses(typeDecl->mBaseClasses, mAlloc); + baseClasses.Add(objectCreateExpr->mTypeRef); + } + + continue; + } + } + auto expr = CreateExpression(node, BfReducer::CreateExprFlags_AllowAnonymousIndexer); isDone = !mVisitorPos.MoveNext(); if (expr != NULL) @@ -7878,6 +7954,24 @@ BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfAstNode* ta mVisitorPos.Trim(); + if (initializerExpr->mInlineTypeRef != NULL) + { + auto typeDecl = initializerExpr->mInlineTypeRef->mTypeDeclaration; + + if (initializerStartIdx != 0) + { + block->SetSize(initializerStartIdx); + int srcEnd = block->mSrcEnd; + if (initializerStartIdx > 0) + srcEnd = block->mChildArr[initializerStartIdx - 1]->mSrcEnd; + block->mSrcEnd = srcEnd; + typeDecl->mSrcEnd = srcEnd; + } + + typeDecl->mSrcEnd = BF_MAX(typeDecl->mSrcEnd, minTypeDeclEnd); + initializerExpr->mInlineTypeRef->mSrcEnd = typeDecl->mSrcEnd; + } + if (block->mCloseBrace != NULL) MEMBER_SET(initializerExpr, mCloseBrace, block->mCloseBrace); @@ -7938,7 +8032,7 @@ BfLambdaBindExpression* BfReducer::CreateLambdaBindExpression(BfAstNode* allocNo if (auto tokenNode = BfNodeDynCast(nextNode)) isRParen = tokenNode->GetToken() == BfToken_RParen; if (!isRParen) - { + { auto nameIdentifier = ExpectIdentifierAfter(lambdaBindExpr, "parameter name"); if (nameIdentifier == NULL) return lambdaBindExpr; @@ -8036,7 +8130,7 @@ BfCollectionInitializerExpression* BfReducer::CreateCollectionInitializerExpress return arrayInitializerExpression; } -BfCollectionInitializerExpression * BfReducer::CreateCollectionInitializerExpression(BfTokenNode* openToken) +BfCollectionInitializerExpression* BfReducer::CreateCollectionInitializerExpression(BfTokenNode* openToken) { auto arrayInitializerExpression = mAlloc->Alloc(); BfDeferredAstSizedArray values(arrayInitializerExpression->mValues, mAlloc); @@ -8133,6 +8227,26 @@ BfScopedInvocationTarget* BfReducer::CreateScopedInvocationTarget(BfAstNode*& ta return scopedInvocationTarget; } +void BfReducer::InitAnonymousType(BfTypeDeclaration* typeDecl) +{ + auto block = BfNodeDynCast(typeDecl->mDefineNode); + + String name; + auto parserData = typeDecl->GetParserData(); + name = "_Anon_"; + + auto parseFileData = parserData->mParseFileData; + int uniqueId = parseFileData->GetUniqueId(block->mParserBlockId); + name += StrFormat("%d", uniqueId); + + int len = (int)name.length() + 1; + typeDecl->mAnonymousName = (char*)mAlloc->AllocBytes(len); + memcpy(typeDecl->mAnonymousName, name.c_str(), len); + + if (mCurTypeState != NULL) + mCurTypeState->mAnonymousTypeDecls.Add(typeDecl); +} + bool BfReducer::CheckInlineTypeRefAttribute(BfAstNode* typeRef, BfAttributeDirective* attributes) { if (attributes == NULL) @@ -8147,7 +8261,7 @@ bool BfReducer::CheckInlineTypeRefAttribute(BfAstNode* typeRef, BfAttributeDirec checkAttribute = checkAttribute->mNextAttribute; } - auto typeDecl = inlineTypeRef->mTypeDeclaration; + auto typeDecl = inlineTypeRef->mTypeDeclaration; typeDecl->mTriviaStart = attributes->mTriviaStart; typeDecl->mSrcStart = attributes->mSrcStart; typeDecl->mAttributes = attributes; @@ -8171,7 +8285,7 @@ void BfReducer::CheckMultiuseAttributeTypeRef(BfAstNode* typeRef) checkAttribute->mIsMultiUse = true; checkAttribute = checkAttribute->mNextAttribute; } - } + } } bool BfReducer::SetProtection(BfAstNode* parentNode, BfAstNode*& protectionNodeRef, BfTokenNode* tokenNode) @@ -8410,16 +8524,6 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all BfTokenNode* tokenNode; - // Why did we want this syntax? - // if (tokenNode = BfNodeDynCast(mVisitorPos.GetNext())) - // { - // if (tokenNode->GetToken() == BfToken_Star) - // { - // MEMBER_SET(objectCreateExpr, mStarToken, tokenNode); - // mVisitorPos.MoveNext(); - // } - // } - if (typeRef == NULL) typeRef = CreateTypeRefAfter(objectCreateExpr); if (typeRef == NULL) @@ -8487,7 +8591,7 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all if ((nextToken != NULL) && (nextToken->mToken == BfToken_Dot) && (nextNextToken != NULL) && (nextNextToken->mToken == BfToken_This)) { - auto ctorExplicitNode = mAlloc->Alloc(); + auto ctorExplicitNode = mAlloc->Alloc(); ReplaceNode(nextToken, ctorExplicitNode); ctorExplicitNode->mDotToken = nextToken; MEMBER_SET(ctorExplicitNode, mThisToken, nextNextToken); @@ -8499,7 +8603,7 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all { auto ctorExplicitNode = mAlloc->Alloc(); ReplaceNode(nextToken, ctorExplicitNode); - ctorExplicitNode->mThisToken = nextToken; + ctorExplicitNode->mThisToken = nextToken; mVisitorPos.MoveNext(); MEMBER_SET(objectCreateExpr, mCtorExplicit, ctorExplicitNode); } @@ -8626,7 +8730,7 @@ BfMemberReferenceExpression* BfReducer::CreateMemberReferenceExpression(BfAstNod if (tokenNode->GetToken() == BfToken_This) { mVisitorPos.MoveNext(); - MEMBER_SET(memberReferenceExpr, mMemberName, tokenNode); + MEMBER_SET(memberReferenceExpr, mMemberName, tokenNode); } } @@ -9176,11 +9280,11 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi case BfToken_Delegate: case BfToken_Function: - { + { auto typeDeclaration = mAlloc->Alloc(); - + SetAndRestoreValue prevTypeDecl(mCurTypeDecl, typeDeclaration); - CurTypeState curTypeState(typeDeclaration, mAlloc); + CurTypeState curTypeState(typeDeclaration, mAlloc); SetAndRestoreValue prevTypeState(mCurTypeState, &curTypeState); ReplaceNode(tokenNode, typeDeclaration); @@ -9743,7 +9847,7 @@ BfTokenNode* BfReducer::BreakQuestionLBracket(BfTokenNode* tokenNode) return firstToken; } -BfCommentNode * BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode* defNodeEnd, bool checkDocAfter) +BfCommentNode* BfReducer::FindDocumentation(BfAstNode* defNodeHead, BfAstNode* defNodeEnd, bool checkDocAfter) { if (defNodeEnd == NULL) defNodeEnd = defNodeHead; @@ -10554,55 +10658,55 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration( bool isDone = false; for (int constraintIdx = 0; !isDone; constraintIdx++) { -// if (auto nextToken = BfNodeDynCast(mVisitorPos.GetNext())) -// { -// if (nextToken->mToken == BfToken_LParen) -// { -// BfGenericConstraintExpression* genericConstraint = mAlloc->Alloc(); -// ReplaceNode(tokenNode, genericConstraint); -// genericConstraint->mWhereToken = tokenNode; -// constraintsDeclaration->mHasExpressions = true; -// -// genericConstraintsArr.push_back(genericConstraint); -// -// auto expr = CreateExpressionAfter(genericConstraint, CreateExprFlags_EarlyExit); -// if (expr == NULL) -// break; -// -// MEMBER_SET(genericConstraint, mExpression, expr); -// -// BfTokenNode* nextWhereToken = NULL; -// if (auto checkToken = BfNodeDynCast(mVisitorPos.GetNext())) -// { -// if (checkToken->mToken != BfToken_Where) -// nextWhereToken = checkToken; -// } -// -// auto nextNode = mVisitorPos.GetNext(); -// if (BfNodeDynCast(nextNode)) -// break; -// -// bool handled = false; -// if (auto tokenNode = BfNodeDynCast(nextNode)) -// { -// if (tokenNode->mToken == BfToken_FatArrow) -// break; -// } -// -// tokenNode = ExpectTokenAfter(genericConstraint, BfToken_LBrace, BfToken_Where, BfToken_Semicolon); -// if (tokenNode == NULL) -// break; -// -// BfToken token = tokenNode->GetToken(); -// if (token != BfToken_Where) -// { -// mVisitorPos.mReadPos--; -// break; -// } -// -// continue; -// } -// } + // if (auto nextToken = BfNodeDynCast(mVisitorPos.GetNext())) + // { + // if (nextToken->mToken == BfToken_LParen) + // { + // BfGenericConstraintExpression* genericConstraint = mAlloc->Alloc(); + // ReplaceNode(tokenNode, genericConstraint); + // genericConstraint->mWhereToken = tokenNode; + // constraintsDeclaration->mHasExpressions = true; + // + // genericConstraintsArr.push_back(genericConstraint); + // + // auto expr = CreateExpressionAfter(genericConstraint, CreateExprFlags_EarlyExit); + // if (expr == NULL) + // break; + // + // MEMBER_SET(genericConstraint, mExpression, expr); + // + // BfTokenNode* nextWhereToken = NULL; + // if (auto checkToken = BfNodeDynCast(mVisitorPos.GetNext())) + // { + // if (checkToken->mToken != BfToken_Where) + // nextWhereToken = checkToken; + // } + // + // auto nextNode = mVisitorPos.GetNext(); + // if (BfNodeDynCast(nextNode)) + // break; + // + // bool handled = false; + // if (auto tokenNode = BfNodeDynCast(nextNode)) + // { + // if (tokenNode->mToken == BfToken_FatArrow) + // break; + // } + // + // tokenNode = ExpectTokenAfter(genericConstraint, BfToken_LBrace, BfToken_Where, BfToken_Semicolon); + // if (tokenNode == NULL) + // break; + // + // BfToken token = tokenNode->GetToken(); + // if (token != BfToken_Where) + // { + // mVisitorPos.mReadPos--; + // break; + // } + // + // continue; + // } + // } BfGenericConstraint* genericConstraint = mAlloc->Alloc(); BfDeferredAstSizedArray constraintTypes(genericConstraint->mConstraintTypes, mAlloc); @@ -10840,19 +10944,131 @@ void BfReducer::HandleBlock(BfBlock* block, bool allowEndingExpression) mVisitorPos.Trim(); } -void BfReducer::HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode) +bool BfReducer::IsInitializerStatement(int checkIdx) +{ + SetAndRestoreValue prevReadPos(mVisitorPos.mReadPos); + + int nodeCount = 0; + while (true) + { + mVisitorPos.mReadPos = checkIdx; + auto checkNode = mVisitorPos.GetCurrent(); + if (checkNode == NULL) + return false; + + if (auto checkToken = BfNodeDynCast(checkNode)) + { + switch (checkToken->mToken) + { + case BfToken_Dot: + if (nodeCount == 0) + return true; + break; + case BfToken_Public: + case BfToken_Private: + case BfToken_Internal: + case BfToken_Protected: + case BfToken_This: + case BfToken_LBracket: + case BfToken_Semicolon: + case BfToken_Case: + case BfToken_Const: + case BfToken_Static: + case BfToken_TypeAlias: + case BfToken_Mixin: + case BfToken_Class: + case BfToken_Struct: + case BfToken_Enum: + case BfToken_Interface: + case BfToken_Override: + return false; + case BfToken_AssignEquals: + if (nodeCount > 0) + return true; + break; + case BfToken_Comma: + if (nodeCount == 0) + return false; + else + return true; + } + } + else if (auto literalExpr = BfNodeDynCast(checkNode)) + { + return true; + } + else if (auto block = BfNodeDynCast(checkNode)) + { + if (nodeCount == 0) + return true; + } + + int endNode = -1; + bool coundBeExpr = false; + if (IsTypeReference(checkNode, BfToken_None, -1, &endNode, &coundBeExpr)) + { + auto nextNode = mVisitorPos.Get(endNode); + if (nextNode == NULL) + { + // At end + return true; + } + + if (BfNodeIsA(nextNode)) + return false; + + if (auto nextToken = BfNodeDynCast(nextNode)) + { + switch (nextToken->mToken) + { + case BfToken_This: + return false; + } + } + + nodeCount++; + checkIdx = BF_MAX(checkIdx + 1, endNode); + continue; + } + + nodeCount++; + checkIdx++; + } + + return false; +} + +bool BfReducer::IsInitializerStatement(BfAstNode* node) +{ + AssertCurrentNode(node); + return IsInitializerStatement(mVisitorPos.mReadPos); +} + +bool BfReducer::InitializerBlockHasInlineTypeDecl(BfBlock* block) +{ + if (block->mChildArr.mSize == 0) + return false; + + SetAndRestoreValue prevVisitorPos(mVisitorPos, BfVisitorPos(block)); + return !IsInitializerStatement(0); +} + +void BfReducer::HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode, bool findInitializer) { SetAndRestoreValue prevTypeDecl(mCurTypeDecl, typeDecl); CurTypeState curTypeState(typeDecl, mAlloc); SetAndRestoreValue prevTypeState(mCurTypeState, &curTypeState); SetAndRestoreValue prevVisitorPos(mVisitorPos, BfVisitorPos(BfNodeDynCast(typeDecl->mDefineNode))); - + + if (findInitializer) + prevVisitorPos.CancelRestore(); + if (attributes != NULL) { MEMBER_SET(typeDecl, mAttributes, attributes); } - if ((!IsNodeRelevant(deferredHeadNode, typeDecl)) && (!typeDecl->IsTemporary())) + if ((!IsNodeRelevant(deferredHeadNode, typeDecl)) && (!typeDecl->IsTemporary()) && (!findInitializer)) { typeDecl->mIgnoreDeclaration = true; return; @@ -10874,6 +11090,13 @@ void BfReducer::HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDi BfAstNode* typeMember = BfNodeDynCast(node); if (typeMember == NULL) { + if (findInitializer) + { + bool isInitializerStatement = IsInitializerStatement(node); + if (isInitializerStatement) + return; + } + SetAndRestoreValue prevTypeMemberNodeStart(mTypeMemberNodeStart, node); typeMember = ReadTypeMember(node); } @@ -10926,439 +11149,439 @@ BfInlineAsmStatement* BfReducer::CreateInlineAsmStatement(BfAstNode* asmNode) { auto processInstrNodes = [&](const Array& nodes) -> BfInlineAsmInstruction* - { - int nodeCount = (int)nodes.size(); - int curNodeIdx = 0; - - auto instNode = mAlloc->Alloc(); - //instNode->mSource = asmStatement->mSource; - int srcStart = nodes.front()->GetSrcStart(); - int srcEnd = nodes.back()->GetSrcEnd(); - instNode->Init(srcStart, srcStart, srcEnd); - - auto replaceWithLower = [](String& s) { - std::transform(s.begin(), s.end(), s.begin(), ::tolower); - }; + int nodeCount = (int)nodes.size(); + int curNodeIdx = 0; - auto readIdent = [&](String& outStr, bool forceLowerCase, const StringImpl& errorExpectation, bool peekOnly) -> bool - { - if (curNodeIdx >= nodeCount) - { - if (!peekOnly) - Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode); - return false; - } - BfAstNode* curNode = nodes[curNodeIdx]; - if (!peekOnly) - ++curNodeIdx; - if (!BfNodeDynCast(curNode)) - { - if (!peekOnly) - Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode); - return false; - } + auto instNode = mAlloc->Alloc(); + //instNode->mSource = asmStatement->mSource; + int srcStart = nodes.front()->GetSrcStart(); + int srcEnd = nodes.back()->GetSrcEnd(); + instNode->Init(srcStart, srcStart, srcEnd); - outStr = NodeToString(curNode); - if (forceLowerCase) - replaceWithLower(outStr); - return true; - }; - auto readToken = [&](BfToken tokenType, const StringImpl& errorExpectation, bool peekOnly) -> bool - { - if (curNodeIdx >= nodeCount) - { - if (!peekOnly) - Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode); - return false; - } - BfAstNode* curNode = nodes[curNodeIdx]; - if (!peekOnly) - ++curNodeIdx; - auto tokenNode = BfNodeDynCast(curNode); - if (!tokenNode || tokenNode->GetToken() != tokenType) - { - if (!peekOnly) - Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode); - return false; - } - - return true; - }; - auto readInteger = [&](int& outInt, const StringImpl& errorExpectation, bool peekOnly, int& outAdvanceTokenCount) -> bool - { - int origCurNodeIdx = curNodeIdx; - outAdvanceTokenCount = 0; - - bool negate = false; - if (readToken(BfToken_Minus, "", true)) - { - ++curNodeIdx; - ++outAdvanceTokenCount; - negate = true; - } - - if (curNodeIdx >= nodeCount) - { - if (!peekOnly) - Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode); - else - curNodeIdx = origCurNodeIdx; - - return false; - } - - BfAstNode* curNode = nodes[curNodeIdx]; - ++curNodeIdx; - ++outAdvanceTokenCount; - auto litNode = BfNodeDynCast(curNode); - if (!litNode || litNode->mValue.mTypeCode != BfTypeCode_Int32) - { - if (!peekOnly) - Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode); - else - curNodeIdx = origCurNodeIdx; - - return false; - } - - outInt = litNode->mValue.mInt32; - if (negate) - outInt = -outInt; - if (peekOnly) - curNodeIdx = origCurNodeIdx; - - return true; - }; - - auto readArgMemPrimaryExpr = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool - { - String primaryIdent; - int primaryInt; - int advanceTokenCount = 0; - - if (readIdent(primaryIdent, false, "", true)) - { - outArg.mMemFlags = BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; - outArg.mReg = primaryIdent; - ++curNodeIdx; - return true; - } - else if (readInteger(primaryInt, "", true, advanceTokenCount)) - { - outArg.mMemFlags = BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp; - outArg.mInt = primaryInt; - curNodeIdx += advanceTokenCount; - return true; - } - else - { - Fail(StrFormat("Found \"%s\", expected integer or identifier", NodeToString(nodes[curNodeIdx]).c_str()), instNode); - return false; - } - }; - std::function readArgMemMulExpr = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool - { - BfInlineAsmInstruction::AsmArg exprArgLeft, exprArgRight; - - if (!readArgMemPrimaryExpr(exprArgLeft)) - return false; - - if (!readToken(BfToken_Star, "", true)) - { - outArg = exprArgLeft; - return true; - } - - ++curNodeIdx; - if (!readArgMemMulExpr(exprArgRight)) - return false; - - bool leftIdent = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; - bool rightIdent = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; - if (leftIdent && rightIdent) - { - Fail(StrFormat("Memory expressions can only scale by an integer", NodeToString(nodes[curNodeIdx]).c_str()), instNode); - return false; - } - else if (leftIdent || rightIdent) - { - if (leftIdent) + auto replaceWithLower = [](String& s) { - outArg = exprArgLeft; - outArg.mAdjRegScalar = exprArgRight.mInt; - } - else + std::transform(s.begin(), s.end(), s.begin(), ::tolower); + }; + + auto readIdent = [&](String& outStr, bool forceLowerCase, const StringImpl& errorExpectation, bool peekOnly) -> bool { - outArg = exprArgRight; - outArg.mAdjRegScalar = exprArgLeft.mInt; - } - - outArg.mMemFlags &= ~BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; - outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg; - outArg.mAdjReg = outArg.mReg; - outArg.mReg.clear(); - } - else - { - outArg = exprArgLeft; - outArg.mInt = exprArgLeft.mInt * exprArgRight.mInt; - } - - return true; - }; - std::function readArgMemAddExpr = [&](BfInlineAsmInstruction::AsmArg& outArg, bool subtractLeft) -> bool // can't use 'auto' here since it's recursive - { - BfInlineAsmInstruction::AsmArg exprArgLeft, exprArgRight; - - if (!readArgMemMulExpr(exprArgLeft)) - return false; - - if (subtractLeft) - { - if (exprArgLeft.mMemFlags != BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) - { - Fail("Memory expressions can only subtract by an integer", instNode); - return false; - } - - exprArgLeft.mInt = -exprArgLeft.mInt; - } - - bool subtract = false; - if (!readToken(BfToken_Plus, "", true)) - { - if (!readToken(BfToken_Minus, "", true)) - { - outArg = exprArgLeft; - return true; - } - else - subtract = true; - } - - ++curNodeIdx; - if (!readArgMemAddExpr(exprArgRight, subtract)) - return false; - - bool leftScaling = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg) != 0; - bool rightScaling = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg) != 0; - if (leftScaling && rightScaling) - { - Fail("Memory expressions can only have one scaling register and one non-scaling register", instNode); - return false; - } - BfInlineAsmInstruction::AsmArg* scaledArg = leftScaling ? &exprArgLeft : (rightScaling ? &exprArgRight : nullptr); - - if (scaledArg) - { - BfInlineAsmInstruction::AsmArg* otherArg = leftScaling ? &exprArgRight : &exprArgLeft; - - outArg = *scaledArg; - outArg.mMemFlags |= otherArg->mMemFlags; - if (otherArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) - { - if (scaledArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) + if (curNodeIdx >= nodeCount) { - Fail("Memory expressions can involve at most two registers", instNode); + if (!peekOnly) + Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode); + return false; + } + BfAstNode* curNode = nodes[curNodeIdx]; + if (!peekOnly) + ++curNodeIdx; + if (!BfNodeDynCast(curNode)) + { + if (!peekOnly) + Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode); return false; } - outArg.mReg = otherArg->mReg; - } - if (otherArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) - { - outArg.mInt += otherArg->mInt; - } - } - else - { - outArg.mInt = 0; - if (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) - { - outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp; - outArg.mInt += exprArgLeft.mInt; - } - if (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) - { - outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp; - outArg.mInt += exprArgRight.mInt; - } - bool leftIdent = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; - bool rightIdent = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; + outStr = NodeToString(curNode); + if (forceLowerCase) + replaceWithLower(outStr); + return true; + }; + auto readToken = [&](BfToken tokenType, const StringImpl& errorExpectation, bool peekOnly) -> bool + { + if (curNodeIdx >= nodeCount) + { + if (!peekOnly) + Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode); + return false; + } + BfAstNode* curNode = nodes[curNodeIdx]; + if (!peekOnly) + ++curNodeIdx; + auto tokenNode = BfNodeDynCast(curNode); + if (!tokenNode || tokenNode->GetToken() != tokenType) + { + if (!peekOnly) + Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode); + return false; + } - if (leftIdent && rightIdent) + return true; + }; + auto readInteger = [&](int& outInt, const StringImpl& errorExpectation, bool peekOnly, int& outAdvanceTokenCount) -> bool { - outArg.mMemFlags |= (BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg | BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg); - outArg.mReg = exprArgLeft.mReg; - outArg.mAdjReg = exprArgRight.mReg; - outArg.mAdjRegScalar = 1; - } - else if (leftIdent) - { - outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; - outArg.mReg = exprArgLeft.mReg; - } - else if (rightIdent) - { - outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; - outArg.mReg = exprArgRight.mReg; - } - } + int origCurNodeIdx = curNodeIdx; + outAdvanceTokenCount = 0; - return true; - }; + bool negate = false; + if (readToken(BfToken_Minus, "", true)) + { + ++curNodeIdx; + ++outAdvanceTokenCount; + negate = true; + } - auto parseArg = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool - { - bool keepGoing = true; - while (keepGoing) - { - keepGoing = false; + if (curNodeIdx >= nodeCount) + { + if (!peekOnly) + Fail(StrFormat("Expected %s", errorExpectation.c_str()), instNode); + else + curNodeIdx = origCurNodeIdx; - int peekInt; - String peekStr; - int advanceTokenCount; - if (readInteger(peekInt, "", true, advanceTokenCount)) - { - outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_Immediate; - outArg.mInt = peekInt; - curNodeIdx += advanceTokenCount; - } - else if (readIdent(peekStr, false, "", true)) - { + return false; + } + + BfAstNode* curNode = nodes[curNodeIdx]; ++curNodeIdx; - String s(peekStr); - replaceWithLower(s); + ++outAdvanceTokenCount; + auto litNode = BfNodeDynCast(curNode); + if (!litNode || litNode->mValue.mTypeCode != BfTypeCode_Int32) + { + if (!peekOnly) + Fail(StrFormat("Found \"%s\", expected %s", NodeToString(curNode).c_str(), errorExpectation.c_str()), instNode); + else + curNodeIdx = origCurNodeIdx; - String tempIdent; + return false; + } - if ((s == "cs" || s == "ds" || s == "es" || s == "fs" || s == "gs" || s == "ss") && readToken(BfToken_Colon, "", true)) + outInt = litNode->mValue.mInt32; + if (negate) + outInt = -outInt; + if (peekOnly) + curNodeIdx = origCurNodeIdx; + + return true; + }; + + auto readArgMemPrimaryExpr = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool + { + String primaryIdent; + int primaryInt; + int advanceTokenCount = 0; + + if (readIdent(primaryIdent, false, "", true)) { + outArg.mMemFlags = BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; + outArg.mReg = primaryIdent; ++curNodeIdx; - outArg.mSegPrefix = s; - keepGoing = true; + return true; } - else if (s == "st" && readToken(BfToken_LParen, "", true)) + else if (readInteger(primaryInt, "", true, advanceTokenCount)) { - ++curNodeIdx; - outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_FloatReg; - if (!readInteger(peekInt, "integer floating-point register number", false, advanceTokenCount)) - return false; - outArg.mInt = peekInt; - if (!readToken(BfToken_RParen, "')'", false)) - return false; - } - else if ((s == "byte" || s == "word" || s == "dword" || s == "qword" || s == "xword" || s == "xmmword" || s == "opaque") && readIdent(tempIdent, true, "", true)) - { - if (tempIdent != "ptr") - { - Fail(StrFormat("Found \"%s\", expected \"ptr\"", NodeToString(nodes[curNodeIdx]).c_str()), instNode); - return false; - } - ++curNodeIdx; - outArg.mSizePrefix = s; - keepGoing = true; + outArg.mMemFlags = BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp; + outArg.mInt = primaryInt; + curNodeIdx += advanceTokenCount; + return true; } else { - outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_IntReg; - outArg.mReg = peekStr; + Fail(StrFormat("Found \"%s\", expected integer or identifier", NodeToString(nodes[curNodeIdx]).c_str()), instNode); + return false; } - } - else if (readToken(BfToken_LBracket, "", true)) + }; + std::function readArgMemMulExpr = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool { - ++curNodeIdx; + BfInlineAsmInstruction::AsmArg exprArgLeft, exprArgRight; - BfInlineAsmInstruction::AsmArg exprArgLeft; - if (!readArgMemAddExpr(exprArgLeft, false)) + if (!readArgMemPrimaryExpr(exprArgLeft)) return false; - if (!readToken(BfToken_RBracket, "']'", false)) - return false; - if (readToken(BfToken_Dot, "", true)) + + if (!readToken(BfToken_Star, "", true)) { - ++curNodeIdx; - if (!readIdent(outArg.mMemberSuffix, false, "struct member suffix identifier", false)) + outArg = exprArgLeft; + return true; + } + + ++curNodeIdx; + if (!readArgMemMulExpr(exprArgRight)) + return false; + + bool leftIdent = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; + bool rightIdent = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; + if (leftIdent && rightIdent) + { + Fail(StrFormat("Memory expressions can only scale by an integer", NodeToString(nodes[curNodeIdx]).c_str()), instNode); + return false; + } + else if (leftIdent || rightIdent) + { + if (leftIdent) + { + outArg = exprArgLeft; + outArg.mAdjRegScalar = exprArgRight.mInt; + } + else + { + outArg = exprArgRight; + outArg.mAdjRegScalar = exprArgLeft.mInt; + } + + outArg.mMemFlags &= ~BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; + outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg; + outArg.mAdjReg = outArg.mReg; + outArg.mReg.clear(); + } + else + { + outArg = exprArgLeft; + outArg.mInt = exprArgLeft.mInt * exprArgRight.mInt; + } + + return true; + }; + std::function readArgMemAddExpr = [&](BfInlineAsmInstruction::AsmArg& outArg, bool subtractLeft) -> bool // can't use 'auto' here since it's recursive + { + BfInlineAsmInstruction::AsmArg exprArgLeft, exprArgRight; + + if (!readArgMemMulExpr(exprArgLeft)) + return false; + + if (subtractLeft) + { + if (exprArgLeft.mMemFlags != BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) + { + Fail("Memory expressions can only subtract by an integer", instNode); + return false; + } + + exprArgLeft.mInt = -exprArgLeft.mInt; + } + + bool subtract = false; + if (!readToken(BfToken_Plus, "", true)) + { + if (!readToken(BfToken_Minus, "", true)) + { + outArg = exprArgLeft; + return true; + } + else + subtract = true; + } + + ++curNodeIdx; + if (!readArgMemAddExpr(exprArgRight, subtract)) + return false; + + bool leftScaling = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg) != 0; + bool rightScaling = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg) != 0; + if (leftScaling && rightScaling) + { + Fail("Memory expressions can only have one scaling register and one non-scaling register", instNode); + return false; + } + BfInlineAsmInstruction::AsmArg* scaledArg = leftScaling ? &exprArgLeft : (rightScaling ? &exprArgRight : nullptr); + + if (scaledArg) + { + BfInlineAsmInstruction::AsmArg* otherArg = leftScaling ? &exprArgRight : &exprArgLeft; + + outArg = *scaledArg; + outArg.mMemFlags |= otherArg->mMemFlags; + if (otherArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) + { + if (scaledArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) + { + Fail("Memory expressions can involve at most two registers", instNode); + return false; + } + outArg.mReg = otherArg->mReg; + } + if (otherArg->mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) + { + outArg.mInt += otherArg->mInt; + } + } + else + { + outArg.mInt = 0; + if (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) + { + outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp; + outArg.mInt += exprArgLeft.mInt; + } + if (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp) + { + outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_ImmediateDisp; + outArg.mInt += exprArgRight.mInt; + } + + bool leftIdent = (exprArgLeft.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; + bool rightIdent = (exprArgRight.mMemFlags & BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg) != 0; + + if (leftIdent && rightIdent) + { + outArg.mMemFlags |= (BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg | BfInlineAsmInstruction::AsmArg::ARGMEMF_AdjReg); + outArg.mReg = exprArgLeft.mReg; + outArg.mAdjReg = exprArgRight.mReg; + outArg.mAdjRegScalar = 1; + } + else if (leftIdent) + { + outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; + outArg.mReg = exprArgLeft.mReg; + } + else if (rightIdent) + { + outArg.mMemFlags |= BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg; + outArg.mReg = exprArgRight.mReg; + } + } + + return true; + }; + + auto parseArg = [&](BfInlineAsmInstruction::AsmArg& outArg) -> bool + { + bool keepGoing = true; + while (keepGoing) + { + keepGoing = false; + + int peekInt; + String peekStr; + int advanceTokenCount; + if (readInteger(peekInt, "", true, advanceTokenCount)) + { + outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_Immediate; + outArg.mInt = peekInt; + curNodeIdx += advanceTokenCount; + } + else if (readIdent(peekStr, false, "", true)) + { + ++curNodeIdx; + String s(peekStr); + replaceWithLower(s); + + String tempIdent; + + if ((s == "cs" || s == "ds" || s == "es" || s == "fs" || s == "gs" || s == "ss") && readToken(BfToken_Colon, "", true)) + { + ++curNodeIdx; + outArg.mSegPrefix = s; + keepGoing = true; + } + else if (s == "st" && readToken(BfToken_LParen, "", true)) + { + ++curNodeIdx; + outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_FloatReg; + if (!readInteger(peekInt, "integer floating-point register number", false, advanceTokenCount)) + return false; + outArg.mInt = peekInt; + if (!readToken(BfToken_RParen, "')'", false)) + return false; + } + else if ((s == "byte" || s == "word" || s == "dword" || s == "qword" || s == "xword" || s == "xmmword" || s == "opaque") && readIdent(tempIdent, true, "", true)) + { + if (tempIdent != "ptr") + { + Fail(StrFormat("Found \"%s\", expected \"ptr\"", NodeToString(nodes[curNodeIdx]).c_str()), instNode); + return false; + } + ++curNodeIdx; + outArg.mSizePrefix = s; + keepGoing = true; + } + else + { + outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_IntReg; + outArg.mReg = peekStr; + } + } + else if (readToken(BfToken_LBracket, "", true)) + { + ++curNodeIdx; + + BfInlineAsmInstruction::AsmArg exprArgLeft; + if (!readArgMemAddExpr(exprArgLeft, false)) + return false; + if (!readToken(BfToken_RBracket, "']'", false)) + return false; + if (readToken(BfToken_Dot, "", true)) + { + ++curNodeIdx; + if (!readIdent(outArg.mMemberSuffix, false, "struct member suffix identifier", false)) + return false; + } + + outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_Memory; + outArg.mMemFlags = exprArgLeft.mMemFlags; + //outArg.mSegPrefix = already_set_leave_me_alone; + //outArg.mSizePrefix = already_set_leave_me_alone; + outArg.mInt = exprArgLeft.mInt; + outArg.mReg = exprArgLeft.mReg; + outArg.mAdjReg = exprArgLeft.mAdjReg; + outArg.mAdjRegScalar = exprArgLeft.mAdjRegScalar; + //outArg.mMemberSuffix = already_set_leave_me_alone; + + return true; + } + else return false; } - outArg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_Memory; - outArg.mMemFlags = exprArgLeft.mMemFlags; - //outArg.mSegPrefix = already_set_leave_me_alone; - //outArg.mSizePrefix = already_set_leave_me_alone; - outArg.mInt = exprArgLeft.mInt; - outArg.mReg = exprArgLeft.mReg; - outArg.mAdjReg = exprArgLeft.mAdjReg; - outArg.mAdjRegScalar = exprArgLeft.mAdjRegScalar; - //outArg.mMemberSuffix = already_set_leave_me_alone; - return true; - } - else - return false; + }; + + BfInlineAsmInstruction::AsmInst& outInst = instNode->mAsmInst; + + // instruction / instruction prefix / label + String opStr; + if (!readIdent(opStr, false, "instruction, instruction prefix, or label", false)) + return nullptr; + + if (readToken(BfToken_Colon, "", true)) + { + ++curNodeIdx; + outInst.mLabel = opStr; + if (curNodeIdx >= nodeCount) + return instNode; + + if (!readIdent(opStr, false, "instruction or instruction prefix", false)) + return nullptr; } - return true; + replaceWithLower(opStr); + + // check for instruction prefix(s) + while (opStr == "lock" || opStr == "rep" || opStr == "repe" || opStr == "repne" || opStr == "repz" || opStr == "repnz") + { + if (curNodeIdx >= nodeCount) // in case prefix is listed like a separate instruction + break; + outInst.mOpPrefixes.push_back(opStr); + + if (!readIdent(opStr, true, "instruction or instruction prefix", false)) + return nullptr; + } + + outInst.mOpCode = opStr; + + BfInlineAsmInstruction::AsmArg asmArg; + while (parseArg(asmArg)) + { + outInst.mArgs.push_back(asmArg); + asmArg = BfInlineAsmInstruction::AsmArg(); + + if (!readToken(BfToken_Comma, "", true)) + break; + ++curNodeIdx; + } + + if (curNodeIdx < nodeCount) + return (BfInlineAsmInstruction*)Fail(StrFormat("Found unexpected \"%s\"", NodeToString(nodes[curNodeIdx]).c_str()), instNode); + + //String testStr = outInst.ToString(); + + int unusedLineChar = 0; + auto bfParser = instNode->GetSourceData()->ToParserData(); + if (bfParser != NULL) + bfParser->GetLineCharAtIdx(instNode->GetSrcStart(), outInst.mDebugLine, unusedLineChar); + //return (BfInlineAsmInstruction*)Fail(StrFormat("Line %d\n", outInst.mDebugLine), instNode); + + return instNode; }; - BfInlineAsmInstruction::AsmInst& outInst = instNode->mAsmInst; - - // instruction / instruction prefix / label - String opStr; - if (!readIdent(opStr, false, "instruction, instruction prefix, or label", false)) - return nullptr; - - if (readToken(BfToken_Colon, "", true)) - { - ++curNodeIdx; - outInst.mLabel = opStr; - if (curNodeIdx >= nodeCount) - return instNode; - - if (!readIdent(opStr, false, "instruction or instruction prefix", false)) - return nullptr; - } - - replaceWithLower(opStr); - - // check for instruction prefix(s) - while (opStr == "lock" || opStr == "rep" || opStr == "repe" || opStr == "repne" || opStr == "repz" || opStr == "repnz") - { - if (curNodeIdx >= nodeCount) // in case prefix is listed like a separate instruction - break; - outInst.mOpPrefixes.push_back(opStr); - - if (!readIdent(opStr, true, "instruction or instruction prefix", false)) - return nullptr; - } - - outInst.mOpCode = opStr; - - BfInlineAsmInstruction::AsmArg asmArg; - while (parseArg(asmArg)) - { - outInst.mArgs.push_back(asmArg); - asmArg = BfInlineAsmInstruction::AsmArg(); - - if (!readToken(BfToken_Comma, "", true)) - break; - ++curNodeIdx; - } - - if (curNodeIdx < nodeCount) - return (BfInlineAsmInstruction*)Fail(StrFormat("Found unexpected \"%s\"", NodeToString(nodes[curNodeIdx]).c_str()), instNode); - - //String testStr = outInst.ToString(); - - int unusedLineChar = 0; - auto bfParser = instNode->GetSourceData()->ToParserData(); - if (bfParser != NULL) - bfParser->GetLineCharAtIdx(instNode->GetSrcStart(), outInst.mDebugLine, unusedLineChar); - //return (BfInlineAsmInstruction*)Fail(StrFormat("Line %d\n", outInst.mDebugLine), instNode); - - return instNode; - }; - // split nodes by newlines into individual instructions, skipping empty lines Array instrNodes; @@ -11397,7 +11620,7 @@ BfInlineAsmStatement* BfReducer::CreateInlineAsmStatement(BfAstNode* asmNode) instrNodes.Clear(); } - for (auto & instNode : dstInstructions) + for (auto& instNode : dstInstructions) MoveNode(instNode, asmStatement); asmStatement->mInstructions = std::move(dstInstructions); } diff --git a/IDEHelper/Compiler/BfReducer.h b/IDEHelper/Compiler/BfReducer.h index 6bdd6f2c..3e74d6f4 100644 --- a/IDEHelper/Compiler/BfReducer.h +++ b/IDEHelper/Compiler/BfReducer.h @@ -170,8 +170,7 @@ public: BfResolvePassData* mResolvePassData; BfAstNode* mTypeMemberNodeStart; int mClassDepth; - int mMethodDepth; - int mCurUniqueIdx; + int mMethodDepth; BfTypeDeclaration* mCurTypeDecl; CurTypeState* mCurTypeState; BfTypeDeclaration* mLastTypeDecl; @@ -211,10 +210,12 @@ public: void AssertCurrentNode(BfAstNode* node); bool IsNodeRelevant(BfAstNode* astNode); + bool IsCursorInside(BfAstNode* astNode); bool IsNodeRelevant(BfAstNode* startNode, BfAstNode* endNode); void MoveNode(BfAstNode* srcNode, BfAstNode* newOwner); void ReplaceNode(BfAstNode* prevNode, BfAstNode* newNode); + void InitAnonymousType(BfTypeDeclaration* typeDecl); bool CheckInlineTypeRefAttribute(BfAstNode* typeRef, BfAttributeDirective* attributes); void CheckMultiuseAttributeTypeRef(BfAstNode* typeRef); bool SetProtection(BfAstNode* parentNode, BfAstNode*& protectionNodeRef, BfTokenNode* tokenNode); @@ -280,7 +281,10 @@ public: BfInlineAsmStatement* CreateInlineAsmStatement(BfAstNode* asmNode); void HandleBlock(BfBlock* block, bool allowEndingExpression = false); - void HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode = NULL); + bool IsInitializerStatement(int checkIdx); + bool IsInitializerStatement(BfAstNode* node); + bool InitializerBlockHasInlineTypeDecl(BfBlock* block); + void HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode = NULL, bool findInitializer = false); public: BfReducer(); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 82dca438..0a5781b4 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -2455,6 +2455,11 @@ bool BfTypeInstance::IsAnonymous() return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymous()); } +bool BfTypeInstance::IsAnonymousInitializerType() +{ + return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymousInitializerType()); +} + void BfTypeInstance::ReportMemory(MemReporter* memReporter) { if (mGenericTypeInfo != NULL) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index ac92cdfc..8b37ad1f 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -2206,6 +2206,7 @@ public: bool IncludeAllMethods() { return ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_IncludeAllMethods) != 0); } bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; } bool IsAnonymous(); + bool IsAnonymousInitializerType(); virtual void ReportMemory(MemReporter* memReporter) override; }; diff --git a/IDEHelper/Compiler/BfSourceClassifier.cpp b/IDEHelper/Compiler/BfSourceClassifier.cpp index c1055929..635d4d78 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.cpp +++ b/IDEHelper/Compiler/BfSourceClassifier.cpp @@ -18,6 +18,7 @@ BfSourceClassifier::BfSourceClassifier(BfParser* bfParser, CharData* charData) mPrevNode = NULL; mCurMember = NULL; mCurLocalMethodDeclaration = NULL; + mSkipAnonymousTypes = false; } void BfSourceClassifier::ModifyFlags(BfAstNode* node, uint8 andFlags, uint8 orFlags) @@ -657,6 +658,9 @@ void BfSourceClassifier::Visit(BfPropertyDeclaration* propertyDeclaration) void BfSourceClassifier::Visit(BfTypeDeclaration* typeDeclaration) { + if ((mSkipAnonymousTypes) && (typeDeclaration->IsAnonymous())) + return; + if (typeDeclaration->mIgnoreDeclaration) return; diff --git a/IDEHelper/Compiler/BfSourceClassifier.h b/IDEHelper/Compiler/BfSourceClassifier.h index ae0a9af9..e3bb0c35 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.h +++ b/IDEHelper/Compiler/BfSourceClassifier.h @@ -69,6 +69,7 @@ public: bool mSkipAttributes; bool mIsSideChannel; bool mPreserveFlags; + bool mSkipAnonymousTypes; uint8 mClassifierPassId; BfAstNode* mPrevNode; BfAstNode* mCurMember; diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index a54211bc..6ca6ea91 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -3044,7 +3044,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) typeDef->mProtection = nextTypeDef->mProtection; - BF_ASSERT(typeDef->mTypeCode == nextTypeDef->mTypeCode); + BF_ASSERT((typeDef->mTypeCode == nextTypeDef->mTypeCode) || (nextTypeDef->mTypeCode == BfTypeCode_Inferred)); typeDef->mTypeCode = nextTypeDef->mTypeCode; typeDef->mShow = nextTypeDef->mShow; diff --git a/IDEHelper/Tests/src/Anonymous.bf b/IDEHelper/Tests/src/Anonymous.bf index 21332362..4f74dcd7 100644 --- a/IDEHelper/Tests/src/Anonymous.bf +++ b/IDEHelper/Tests/src/Anonymous.bf @@ -30,6 +30,21 @@ class Anonymous } mCoords; } + struct StructC + { + public int mA; + + public this(int a) + { + mA = a; + } + } + + class ClassA + { + public int Val = 123; + } + [Test] public static void TestBasics() { @@ -47,5 +62,28 @@ class Anonymous StructB sb = default; sb.mX = 345; Test.Assert(sb.mY == 345); + + var sc = StructC(456) + { + public int mB = 567; + + { + _.mB += 1000; + }, + mB += 10000 + }; + Test.Assert(sc.mA == 456); + Test.Assert(sc.mB == 11567); + + var ca = scope ClassA() + { + public override void ToString(String strBuffer) + { + strBuffer.Append("ClassA override"); + } + }; + + var str = ca.ToString(.. scope .()); + Test.Assert(str == "ClassA override"); } } \ No newline at end of file