1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Inline anonymous type declarations

This commit is contained in:
Brian Fiete 2025-01-02 11:42:33 -08:00
parent f609062c2a
commit 958fc30310
20 changed files with 600 additions and 48 deletions

View file

@ -236,6 +236,11 @@ void BfStructuralVisitor::Visit(BfTypeReference* typeRef)
Visit(typeRef->ToBase());
}
void BfStructuralVisitor::Visit(BfInlineTypeReference* typeRef)
{
Visit(typeRef->ToBase());
}
void BfStructuralVisitor::Visit(BfNamedTypeReference* typeRef)
{
Visit(typeRef->ToBase());
@ -1233,14 +1238,21 @@ void BfBlock::SetSize(int wantSize)
//////////////////////////////////////////////////////////////////////////
bool BfTypeDeclaration::IsAnonymous()
{
return (mAnonymousName != NULL);
}
//////////////////////////////////////////////////////////////////////////
bool BfTypeReference::IsNamedTypeReference()
{
return IsA<BfNamedTypeReference>() || IsA<BfDirectStrTypeReference>();
return IsA<BfNamedTypeReference>() || IsA<BfDirectStrTypeReference>() || IsA<BfInlineTypeReference>();
}
bool BfTypeReference::IsTypeDefTypeReference()
{
return IsA<BfNamedTypeReference>() || IsA<BfDirectStrTypeReference>() || IsA<BfDirectTypeDefReference>();
return IsA<BfNamedTypeReference>() || IsA<BfDirectStrTypeReference>() || IsA<BfInlineTypeReference>() || IsA<BfDirectTypeDefReference>();
}
String BfTypeReference::ToCleanAttributeString()
@ -1657,6 +1669,11 @@ bool Beefy::BfTokenIsKeyword(BfToken token)
return (token >= BfToken_Abstract) && (token <= BfToken_Yield);
}
bool Beefy::BfTokenIsTypeDecl(BfToken token)
{
return (token == BfToken_Struct) || (token == BfToken_Class) || (token == BfToken_Interface) || (token == BfToken_Enum);
}
BfBinaryOp Beefy::BfAssignOpToBinaryOp(BfAssignmentOp assignmentOp)
{
switch (assignmentOp)

View file

@ -381,6 +381,7 @@ class BfReturnStatement;
class BfYieldStatement;
class BfUnaryOperatorExpression;
class BfBinaryOperatorExpression;
class BfInlineTypeReference;
class BfArrayTypeRef;
class BfPointerTypeRef;
class BfDotTypeReference;
@ -549,6 +550,7 @@ public:
virtual void Visit(BfInitializerExpression* collectionInitExpr);
virtual void Visit(BfCollectionInitializerExpression* collectionInitExpr);
virtual void Visit(BfTypeReference* typeRef);
virtual void Visit(BfInlineTypeReference* typeRef);
virtual void Visit(BfNamedTypeReference* typeRef);
virtual void Visit(BfQualifiedTypeReference* qualifiedType);
virtual void Visit(BfDotTypeReference* typeRef);
@ -2147,6 +2149,7 @@ public:
ASTREF(BfTokenNode*) mCtorCloseParen;
BfSizedArray<ASTREF(BfExpression*)> mArguments;
BfSizedArray<ASTREF(BfTokenNode*)> mCommas;
bool mIsMultiUse; // For anonymous types and also another use like a field decl
ASTREF(BfAttributeDirective*) mNextAttribute;
@ -2442,10 +2445,15 @@ public:
BfGenericParamsDeclaration* mGenericParams;
BfGenericConstraintsDeclaration* mGenericConstraintsDeclaration;
bool mIgnoreDeclaration;
char* mAnonymousName;
BfTokenNode* mColonToken;
BfSizedArray<ASTREF(BfTypeReference*)> mBaseClasses;
BfSizedArray<ASTREF(BfAstNode*)> mBaseClassCommas;
BfSizedArray<BfTypeDeclaration*> mAnonymousTypes;
bool IsAnonymous();
}; BF_AST_DECL(BfTypeDeclaration, BfAstNode);
class BfTypeAliasDeclaration : public BfTypeDeclaration
@ -2468,6 +2476,14 @@ public:
String ToCleanAttributeString();
}; BF_AST_DECL(BfTypeReference, BfAstNode);
class BfInlineTypeReference : public BfTypeReference
{
public:
BF_AST_TYPE(BfInlineTypeReference, BfTypeReference);
BfTypeDeclaration* mTypeDeclaration;
}; BF_AST_DECL(BfInlineTypeReference, BfTypeReference);
class BfDirectTypeReference : public BfTypeReference
{
public:
@ -3568,6 +3584,7 @@ public:
const char* BfTokenToString(BfToken token);
bool BfTokenIsKeyword(BfToken token);
bool BfTokenIsTypeDecl(BfToken token);
BfBinaryOp BfAssignOpToBinaryOp(BfAssignmentOp assignmentOp);
BfBinaryOp BfGetOppositeBinaryOp(BfBinaryOp origOp);
BfBinaryOp BfGetFlippedBinaryOp(BfBinaryOp origOp);

View file

@ -223,6 +223,7 @@ BfAutoComplete::BfAutoComplete(BfResolveType resolveType, bool doFuzzyAutoComple
BfAutoComplete::~BfAutoComplete()
{
Clear();
RemoveMethodMatchInfo();
}
void BfAutoComplete::SetModule(BfModule* module)

View file

@ -795,10 +795,16 @@ void BfDefBuilder::Visit(BfMethodDeclaration* methodDeclaration)
}
}
void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef)
void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef, bool checkReturnType)
{
while (attributes != NULL)
if (checkReturnType)
{
if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(methodDef->mReturnTypeRef))
ParseAttributes(inlineTypeRef->mTypeDeclaration->mAttributes, methodDef, false);
}
while (attributes != NULL)
{
if (attributes->mAttributeTypeRef != NULL)
{
auto typeRefName = attributes->mAttributeTypeRef->ToCleanAttributeString();
@ -1434,13 +1440,11 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
}
BF_ASSERT(typeDeclaration->GetSourceData() == mCurSource->mSourceData);
if ((typeDeclaration->mTypeNode != NULL) && (typeDeclaration->mNameNode == NULL))
return;
/*if (typeDeclaration->mNameNode != NULL)
OutputDebugStrF("Decl: %s\n", typeDeclaration->mNameNode->ToString().c_str());*/
bool isAnonymous = typeDeclaration->IsAnonymous();
bool isAutoCompleteTempType = false;
if (mResolvePassData != NULL)
{
@ -1511,10 +1515,17 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
}
if (typeDeclaration->mNameNode == NULL)
{
// Global
mCurTypeDef->mName = mSystem->mGlobalsAtom;
mCurTypeDef->mName->Ref();
BF_ASSERT(mCurTypeDef->mSystem != NULL);
if (typeDeclaration->mStaticSpecifier != NULL)
{
// Global
mCurTypeDef->mName = mSystem->mGlobalsAtom;
mCurTypeDef->mName->Ref();
BF_ASSERT(mCurTypeDef->mSystem != NULL);
}
else
{
mCurTypeDef->mName = mSystem->GetAtom(typeDeclaration->mAnonymousName);
}
}
else
{
@ -1527,7 +1538,7 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
BfLogSys(mCurSource->mSystem, "DefBuilder %p %p TypeDecl:%s\n", mCurTypeDef, mCurSource, mCurTypeDef->mName->ToString().mPtr);
mCurTypeDef->mProtection = (outerTypeDef == NULL) ? BfProtection_Public : BfProtection_Private;
mCurTypeDef->mProtection = ((outerTypeDef == NULL) || (isAnonymous)) ? BfProtection_Public : BfProtection_Private;
if (typeDeclaration->mProtectionSpecifier != NULL)
{
if ((outerTypeDef == NULL) &&
@ -1956,6 +1967,11 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
}
}
for (auto& anonTypeDecl : typeDeclaration->mAnonymousTypes)
{
VisitChildNoRef(anonTypeDecl);
}
FinishTypeDef(mCurTypeDef->mTypeCode == BfTypeCode_Enum);
// Map methods into the correct index from previous revision

View file

@ -56,7 +56,7 @@ public:
static void AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, const StringImpl& paramName);
BfTypeDef* ComparePrevTypeDef(BfTypeDef* prevTypeDef, BfTypeDef* checkTypeDef);
void FinishTypeDef(bool wantsToString);
void ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef);
void ParseAttributes(BfAttributeDirective* attributes, BfMethodDef* methodDef, bool checkReturnType = true);
void ParseAttributes(BfAttributeDirective* attributes, BfTypeDef* typeDef);
BfMethodDef* CreateMethodDef(BfMethodDeclaration* methodDecl, BfMethodDef* outerMethodDef = NULL);
BfError* Fail(const StringImpl& errorStr, BfAstNode* refNode);

View file

@ -325,6 +325,13 @@ void BfElementVisitor::Visit(BfTypeReference* typeRef)
Visit(typeRef->ToBase());
}
void BfElementVisitor::Visit(BfInlineTypeReference* typeRef)
{
Visit(typeRef->ToBase());
VisitChild(typeRef->mTypeDeclaration);
}
void BfElementVisitor::Visit(BfNamedTypeReference* typeRef)
{
Visit(typeRef->ToBase());

View file

@ -51,6 +51,7 @@ public:
virtual void Visit(BfInitializerExpression* initExpr);
virtual void Visit(BfCollectionInitializerExpression* collectionInitExpr);
virtual void Visit(BfTypeReference* typeRef);
virtual void Visit(BfInlineTypeReference* typeRef);
virtual void Visit(BfNamedTypeReference* typeRef);
virtual void Visit(BfQualifiedTypeReference* qualifiedType);
virtual void Visit(BfDotTypeReference* typeRef);

View file

@ -2350,7 +2350,7 @@ bool BfModule::TryLocalVariableInit(BfLocalVariable* localVar)
void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
{
BfAstNode* localNameNode = localVar->mNameNode;
if (localVar->mIsThis)
if ((localVar->mIsThis) && (mCurMethodInstance != NULL))
{
localNameNode = mCurMethodInstance->mMethodDef->GetRefNode();
}
@ -12137,7 +12137,7 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
return mBfIRBuilder->CreateConst(constant, constHolder);
}
void BfModule::ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget)
void BfModule::ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget, bool force)
{
if (attrTarget == BfAttributeTargets_SkipValidate)
return;
@ -12149,6 +12149,9 @@ void BfModule::ValidateCustomAttributes(BfCustomAttributes* customAttributes, Bf
if ((customAttribute.mType->mAttributeData->mAttributeTargets & attrTarget) == 0)
{
if ((customAttribute.mIsMultiUse) && (!force))
continue;
Fail(StrFormat("Attribute '%s' is not valid on this declaration type. It is only valid on %s.",
customAttribute.GetRefNode()->ToString().c_str(), GetAttributesTargetListString(customAttribute.mType->mAttributeData->mAttributeTargets).c_str()), customAttribute.mRef->mAttributeTypeRef); // CS0592
}
@ -12222,6 +12225,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
customAttribute.mAwaitingValidation = true;
customAttribute.mDeclaringType = activeTypeDef;
customAttribute.mRef = attributesDirective;
customAttribute.mIsMultiUse = attributesDirective->mIsMultiUse;
if (attributesDirective->mAttrOpenToken != NULL)
targetOverride = (BfAttributeTargets)0;
@ -23430,7 +23434,7 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
auto typeInstance = methodInstance->GetOwner();
if (typeInstance->IsInstanceOf(mCompiler->mValueTypeTypeDef))
return;
return;
BfTypeState typeState(typeInstance);
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
@ -23458,7 +23462,7 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
if ((methodInstance == methodInstance->mMethodInstanceGroup->mDefault) && (methodInstance->mMethodInstanceGroup->mDefaultCustomAttributes != NULL))
{
// Take over prevoiusly-generated custom attributes
// Take over previously-generated custom attributes
methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes = methodInstance->mMethodInstanceGroup->mDefaultCustomAttributes;
methodInstance->mMethodInstanceGroup->mDefaultCustomAttributes = NULL;
}
@ -23479,7 +23483,55 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
}
}
customAttributes = methodInstance->GetCustomAttributes();
if (methodDeclaration != NULL)
{
if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(methodDeclaration->mReturnType))
{
if (inlineTypeRef->mTypeDeclaration->mAttributes != NULL)
{
// Apply multiuse attributes from anonymous return type
auto returnType = ResolveTypeRef(inlineTypeRef);
if ((returnType != NULL) && (returnType->ToTypeInstance()))
{
auto returnTypeInst = returnType->ToTypeInstance();
if ((returnTypeInst->IsAnonymous()) && (returnTypeInst->mCustomAttributes != NULL))
{
bool hasPendingAttributes = false;
for (const auto& customAttribute : returnTypeInst->mCustomAttributes->mAttributes)
{
if (customAttribute.mAwaitingValidation)
{
hasPendingAttributes = true;
break;
}
}
if (hasPendingAttributes)
{
if (methodInstance->GetMethodInfoEx()->mMethodCustomAttributes == NULL)
methodInstance->mMethodInfoEx->mMethodCustomAttributes = new BfMethodCustomAttributes();
if (methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes == NULL)
methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes = new BfCustomAttributes();
for (const auto& customAttribute : returnTypeInst->mCustomAttributes->mAttributes)
{
if (!customAttribute.mAwaitingValidation)
continue;
BfCustomAttribute copiedCustomAttribute = customAttribute;
copiedCustomAttribute.mIsMultiUse = false;
methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes->mAttributes.Add(copiedCustomAttribute);
}
ValidateCustomAttributes(methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes, attrTarget);
}
}
}
}
}
}
customAttributes = methodInstance->GetCustomAttributes();
if (customAttributes == NULL)
{
auto owner = methodInstance->GetOwner();

View file

@ -1676,7 +1676,7 @@ public:
bool HasUnactializedConstant(BfConstant* constant, BfIRConstHolder* constHolder);
BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType);
BfIRValue ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowUnactualized = false);
void ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget);
void ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget, bool force = false);
void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, BfGetCustomAttributesFlags flags = BfGetCustomAttributesFlags_None, BfCaptureInfo* captureInfo = NULL);
BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, BfGetCustomAttributesFlags flags = BfGetCustomAttributesFlags_None, BfCaptureInfo* captureInfo = NULL);
BfCustomAttributes* GetCustomAttributes(BfTypeDef* typeDef);

View file

@ -5077,10 +5077,13 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
// Handled elsewhere
}
else
{
{
SetAndRestoreValue<BfFieldDef*> prevTypeRef(mContext->mCurTypeState->mCurFieldDef, fieldDef);
fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->GetFieldDeclaration()->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
}
fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->GetFieldDeclaration()->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
if (fieldInstance->mCustomAttributes != NULL)
{
for (auto customAttr : fieldInstance->mCustomAttributes->mAttributes)
{
if (TypeToString(customAttr.mType) == "System.ThreadStaticAttribute")
@ -5094,6 +5097,38 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
}
}
if ((fieldInstance->mResolvedType != NULL) && (fieldInstance->mResolvedType->IsTypeInstance()) && (fieldInstance->mResolvedType->ToTypeInstance()->IsAnonymous()))
{
auto fieldTypeInst = fieldInstance->mResolvedType->ToTypeInstance();
if ((fieldTypeInst->IsAnonymous()) && (fieldTypeInst->mCustomAttributes != NULL))
{
bool hasPendingAttributes = false;
for (const auto& customAttribute : fieldTypeInst->mCustomAttributes->mAttributes)
{
if (customAttribute.mAwaitingValidation)
{
hasPendingAttributes = true;
break;
}
}
if (hasPendingAttributes)
{
fieldInstance->mCustomAttributes = new BfCustomAttributes();
for (const auto& customAttribute : fieldTypeInst->mCustomAttributes->mAttributes)
{
if (!customAttribute.mAwaitingValidation)
continue;
BfCustomAttribute copiedCustomAttribute = customAttribute;
copiedCustomAttribute.mIsMultiUse = false;
fieldInstance->mCustomAttributes->mAttributes.Add(copiedCustomAttribute);
}
ValidateCustomAttributes(fieldInstance->mCustomAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
}
}
}
if (resolvedFieldType == NULL)
{
if ((underlyingType != NULL) || (typeInstance->IsPayloadEnum()))
@ -8445,6 +8480,7 @@ BfType* BfModule::ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopu
BfNamedTypeReference* namedTypeRef = NULL;
BfGenericInstanceTypeRef* genericTypeRef = NULL;
BfDirectStrTypeReference* directStrTypeRef = NULL;
BfInlineTypeReference* inlineTypeRef = NULL;
BfIdentifierNode* identifierNode = NULL;
if ((namedTypeRef = BfNodeDynCast<BfNamedTypeReference>(typeRef)))
{
@ -8463,17 +8499,24 @@ BfType* BfModule::ResolveInnerType(BfType* outerType, BfAstNode* typeRef, BfPopu
{
//
}
else if ((inlineTypeRef = BfNodeDynCastExact<BfInlineTypeReference>(typeRef)))
{
//
}
BF_ASSERT((identifierNode != NULL) || (namedTypeRef != NULL) || (directStrTypeRef != NULL));
BF_ASSERT((identifierNode != NULL) || (namedTypeRef != NULL) || (directStrTypeRef != NULL) || (inlineTypeRef != NULL));
auto usedOuterType = outerType;
if (nestedTypeDef == NULL)
{
String tempStr;
StringView findName;
if (namedTypeRef != NULL)
findName = namedTypeRef->mNameNode->ToStringView();
else if (identifierNode != NULL)
findName = identifierNode->ToStringView();
else if (inlineTypeRef != NULL)
findName = inlineTypeRef->mTypeDeclaration->mAnonymousName;
else
findName = directStrTypeRef->mTypeName;
@ -10468,17 +10511,18 @@ BfTypeDef* BfModule::FindTypeDef(BfTypeReference* typeRef, BfTypeInstance* typeI
if (auto elementedType = BfNodeDynCast<BfElementedTypeRef>(typeRef))
return FindTypeDef(elementedType->mElementType, typeInstanceOverride, error);
BF_ASSERT(typeRef->IsA<BfNamedTypeReference>() || typeRef->IsA<BfQualifiedTypeReference>() || typeRef->IsA<BfDirectStrTypeReference>());
BF_ASSERT(typeRef->IsA<BfNamedTypeReference>() || typeRef->IsA<BfQualifiedTypeReference>() || typeRef->IsA<BfDirectStrTypeReference>() || typeRef->IsA<BfInlineTypeReference>());
auto namedTypeRef = BfNodeDynCast<BfNamedTypeReference>(typeRef);
StringView findNameStr;
if (namedTypeRef != NULL)
findNameStr = namedTypeRef->mNameNode->ToStringView();
else
{
auto directStrTypeDef = BfNodeDynCastExact<BfDirectStrTypeReference>(typeRef);
if (directStrTypeDef != NULL)
{
if (auto directStrTypeDef = BfNodeDynCastExact<BfDirectStrTypeReference>(typeRef))
findNameStr = directStrTypeDef->mTypeName;
else if (auto inlineTypeRef = BfNodeDynCastExact<BfInlineTypeReference>(typeRef))
findNameStr = inlineTypeRef->mTypeDeclaration->mAnonymousName;
else
BFMODULE_FATAL(this, "Error?");
}
@ -10943,7 +10987,7 @@ BfType* BfModule::ResolveTypeRef_Ref(BfTypeReference* typeRef, BfPopulateType po
{
Fail("Invalid use of 'var ref'. Generally references are generated with a 'var' declaration with 'ref' applied to the initializer", typeRef);
return NULL;
}
}
if (mNoResolveGenericParams)
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_NoResolveGenericParam);
@ -10989,13 +11033,16 @@ BfType* BfModule::ResolveTypeRef_Ref(BfTypeReference* typeRef, BfPopulateType po
// Check generics first
auto namedTypeRef = BfNodeDynCastExact<BfNamedTypeReference>(typeRef);
auto directStrTypeRef = BfNodeDynCastExact<BfDirectStrTypeReference>(typeRef);
if (((namedTypeRef != NULL) && (namedTypeRef->mNameNode != NULL)) || (directStrTypeRef != NULL))
auto inlineStrTypeRef = BfNodeDynCastExact<BfInlineTypeReference>(typeRef);
if (((namedTypeRef != NULL) && (namedTypeRef->mNameNode != NULL)) || (directStrTypeRef != NULL) || (inlineStrTypeRef != NULL))
{
StringView findName;
if (namedTypeRef != NULL)
findName = namedTypeRef->mNameNode->ToStringView();
else
else if (directStrTypeRef != NULL)
findName = directStrTypeRef->mTypeName;
else
findName = inlineStrTypeRef->mTypeDeclaration->mAnonymousName;
if (findName == "Self")
{
BfType* selfType = mCurTypeInstance;

View file

@ -105,6 +105,38 @@ return 0;
//////////////////////////////////////////////////////////////////////////
static CritSect gParseFileDataCrit;
static Array<int> gFreeIds;
static int gCurFreeId;
int BfParseFileData::GetUniqueId(int idx)
{
AutoCrit autoCrit(gParseFileDataCrit);
while (idx >= mUniqueIDList.size())
{
if (!gFreeIds.IsEmpty())
{
mUniqueIDList.Add(gFreeIds.back());
gFreeIds.pop_back();
}
else
mUniqueIDList.Add(gCurFreeId++);
}
return mUniqueIDList[idx];
}
BfParseFileData::~BfParseFileData()
{
if (!mUniqueIDList.IsEmpty())
{
AutoCrit autoCrit(gParseFileDataCrit);
for (auto id : mUniqueIDList)
gFreeIds.Add(id);
}
}
//////////////////////////////////////////////////////////////////////////
BfParserCache* Beefy::gBfParserCache = NULL;
bool BfParserCache::DataEntry::operator==(const LookupEntry& lookup) const
@ -201,14 +233,39 @@ BfParserData::BfParserData()
mCharIdData = NULL;
mUniqueParser = NULL;
mDidReduce = false;
mParseFileData = NULL;
}
BfParserData::~BfParserData()
{
if (mParseFileData != NULL)
{
BF_ASSERT(mParseFileData->mRefCount >= 0);
mParseFileData->mRefCount--;
if (mParseFileData->mRefCount == 0)
{
delete mParseFileData;
gBfParserCache->mParseFileDataMap.Remove(mFileName);
}
}
delete[] mJumpTable;
delete[] mCharIdData;
}
void BfParserData::InitFileData()
{
BF_ASSERT(mParseFileData == NULL);
BfParseFileData** valuePtr = NULL;
if (gBfParserCache->mParseFileDataMap.TryAdd(mFileName, NULL, &valuePtr))
{
*valuePtr = new BfParseFileData();
}
mParseFileData = *valuePtr;
mParseFileData->mRefCount++;
}
int BfParserData::GetCharIdAtIndex(int findIndex)
{
if (mCharIdData == NULL)
@ -328,7 +385,7 @@ void BfParserData::Deref()
mRefCount--;
BF_ASSERT(mRefCount >= 0);
if (mRefCount == 0)
{
{
AutoCrit autoCrit(gBfParserCache->mCritSect);
BfParserCache::DataEntry dataEntry;
dataEntry.mParserData = this;
@ -413,6 +470,8 @@ BfParser::~BfParser()
}
else if (mParserData->mRefCount == 0)
{
// Just never got added to the cache
delete mParserData;
}
@ -510,6 +569,7 @@ void BfParser::Init(uint64 cacheHash)
mParserData = new BfParserData();
mSourceData = mParserData;
mParserData->mFileName = mFileName;
mParserData->InitFileData();
if (mDataId != -1)
mParserData->mDataId = mDataId;
else

View file

@ -62,6 +62,22 @@ enum MaybeBool
MaybeBool_True = 1,
};
class BfParseFileData
{
public:
Array<int> mUniqueIDList;
int mRefCount;
public:
BfParseFileData()
{
mRefCount = 0;
}
~BfParseFileData();
int GetUniqueId(int idx);
};
class BfParserData : public BfSourceData
{
public:
@ -81,8 +97,9 @@ public:
OwnedVector<String> mStringLiterals;
Dictionary<int, BfParserWarningEnabledChange> mWarningEnabledChanges;
std::set<int> mUnwarns;
BfParseFileData* mParseFileData;
bool mFailed; // Don't cache if there's a warning or an error
bool mDidReduce;
bool mDidReduce;
public:
BfParserData();
@ -94,6 +111,7 @@ public:
return this;
}
void InitFileData();
virtual BfParser* ToParser() override;
int GetCharIdAtIndex(int findIndex);
void GetLineCharAtIdx(int idx, int& line, int& lineChar);
@ -130,6 +148,7 @@ public:
int mRefCount;
BfAstAllocManager mAstAllocManager;
HashSet<DataEntry> mEntries;
Dictionary<String, BfParseFileData*> mParseFileDataMap;
public:
BfParserCache();

View file

@ -47,6 +47,7 @@ BfReducer::BfReducer()
mSystem = NULL;
mResolvePassData = NULL;
mMethodDepth = 0;
mCurUniqueIdx = 0;
mDocumentCheckIdx = 0;
mTypeMemberNodeStart = NULL;
}
@ -403,6 +404,39 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int
mVisitorPos.mReadPos = startNode;
return true;
}
else if ((checkToken == BfToken_Struct) || (checkToken == BfToken_Class) || (checkToken == BfToken_Interface) || (checkToken == BfToken_Enum))
{
checkIdx++;
auto nextNode = mVisitorPos.Get(checkIdx);
if (auto block = BfNodeDynCast<BfBlock>(nextNode))
{
if (outEndNode != NULL)
*outEndNode = checkIdx;
return true;
}
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
{
if (tokenNode->mToken == BfToken_Colon)
{
while (true)
{
checkIdx++;
auto checkNode = mVisitorPos.Get(checkIdx);
if (checkNode == NULL)
return false;
if (auto block = BfNodeDynCast<BfBlock>(checkNode))
{
if (outEndNode != NULL)
*outEndNode = checkIdx;
return true;
}
}
}
}
return false;
}
else
return false;
}
@ -4360,6 +4394,7 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS
ReplaceNode(typeRef, methodDecl);
methodDecl->mDocumentation = FindDocumentation(methodDecl);
methodDecl->mReturnType = typeRef;
CheckMultiuseAttributeTypeRef(methodDecl->mReturnType);
BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDecl->mParams, mAlloc);
BfDeferredAstSizedArray<BfTokenNode*> commas(methodDecl->mCommas, mAlloc);
@ -5105,6 +5140,71 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
if ((createTypeRefFlags & CreateTypeRefFlags_EarlyExit) != 0)
return delegateTypeRef;
}
else if ((BfTokenIsTypeDecl(token)) || (token == BfToken_LBracket))
{
BfAttributeDirective* attributes = NULL;
if (token == BfToken_LBracket)
{
attributes = CreateAttributeDirective(tokenNode);
if (attributes == NULL)
return NULL;
mVisitorPos.MoveNext();
bool isValid = false;
auto nextNode = mVisitorPos.GetCurrent();
tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
if (tokenNode != NULL)
{
token = tokenNode->mToken;
if (BfTokenIsTypeDecl(token))
isValid = true;
}
if (!isValid)
{
AddErrorNode(attributes);
return NULL;
}
}
bool attribsApply = false;
if ((mTypeMemberNodeStart != NULL) && (mTypeMemberNodeStart->mSrcEnd == tokenNode->mTriviaStart))
attribsApply = true;
auto typeDeclNode = CreateTopLevelObject(tokenNode, attributes, attribsApply ? mTypeMemberNodeStart : NULL, true);
if (typeDeclNode == NULL)
{
if (attributes != NULL)
AddErrorNode(attributes);
return NULL;
}
auto typeDecl = BfNodeDynCast<BfTypeDeclaration>(typeDeclNode);
if (typeDecl == NULL)
{
if (attributes != NULL)
AddErrorNode(attributes);
AddErrorNode(typeDeclNode);
return NULL;
}
String name;
auto parserData = typeDecl->GetParserData();
name = "Anon_";
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<BfInlineTypeReference>();
ReplaceNode(typeDecl, typeRef);
typeRef->mTypeDeclaration = typeDecl;
return typeRef;
}
else if ((token == BfToken_Comptype) || (token == BfToken_Decltype))
{
auto declTypeRef = mAlloc->Alloc<BfExprModTypeRef>();
@ -5881,6 +5981,12 @@ BfStatement* BfReducer::CreateAttributedStatement(BfTokenNode* tokenNode, Create
(checkNode->IsA<BfStringInterpolationExpression>()) ||
(checkNode->IsA<BfBlock>()))
{
if (auto varDecl = BfNodeDynCast<BfVariableDeclaration>(checkNode))
{
if (CheckInlineTypeRefAttribute(varDecl->mTypeRef, attrib))
return BfNodeDynCast<BfStatement>(stmt);
}
BfAttributedStatement* attribStmt = mAlloc->Alloc<BfAttributedStatement>();
ReplaceNode(attrib, attribStmt);
attribStmt->mAttributes = attrib;
@ -6169,6 +6275,8 @@ BfFieldDeclaration* BfReducer::CreateFieldDeclaration(BfTokenNode* tokenNode, Bf
MoveNode(fieldDeclaration->mNameNode, fieldDeclaration);
//mVisitorPos.MoveNext();
}
CheckMultiuseAttributeTypeRef(fieldDeclaration->mTypeRef);
BfToken token = tokenNode->GetToken();
if (token == BfToken_AssignEquals)
{
@ -6273,6 +6381,26 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, i
Fail("Invalid target for attributes", memberNode);
return memberNode;
}
memberNode->mTriviaStart = attributes->mTriviaStart;
memberNode->mSrcStart = attributes->mSrcStart;
if (auto fieldDecl = BfNodeDynCast<BfFieldDeclaration>(member))
{
if (CheckInlineTypeRefAttribute(fieldDecl->mTypeRef, attributes))
{
return member;
}
}
if (auto methodDecl = BfNodeDynCast<BfMethodDeclaration>(member))
{
if (CheckInlineTypeRefAttribute(methodDecl->mReturnType, attributes))
{
return member;
}
}
ReplaceNode(attributes, member);
member->mAttributes = attributes;
@ -6291,6 +6419,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, i
if (typeRef == NULL)
return operatorDecl;
MEMBER_SET_CHECKED(operatorDecl, mReturnType, typeRef);
CheckMultiuseAttributeTypeRef(operatorDecl->mReturnType);
operatorDecl->mIsConvOperator = true;
ParseMethod(operatorDecl, &params, &commas);
@ -7061,10 +7190,19 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
}
}
if ((token == BfToken_Struct) || (token == BfToken_Class) || (token == BfToken_Interface) || (token == BfToken_Enum))
{
int endNodeIdx = -1;
if (IsTypeReference(node, BfToken_None, -1, &endNodeIdx))
{
isTypeRef = true;
}
}
if ((token == BfToken_LBracket) && (depth > 0))
{
Fail("Unexpected custom attribute", node);
return NULL;
// The only valid option is an attributed type reference
isTypeRef = true;
}
if (isTypeRef)
@ -7218,6 +7356,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
ReplaceNode(nameIdentifier, methodDeclaration);
methodDeclaration->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
MEMBER_SET(methodDeclaration, mReturnType, typeRef);
CheckMultiuseAttributeTypeRef(methodDeclaration->mReturnType);
MEMBER_SET(methodDeclaration, mExplicitInterface, explicitInterface);
MEMBER_SET(methodDeclaration, mExplicitInterfaceDotToken, explicitInterfaceDot);
return methodDeclaration;
@ -7235,6 +7374,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
BfDeferredAstSizedArray<BfTokenNode*> commas(operatorDecl->mCommas, mAlloc);
ReplaceNode(typeRef, operatorDecl);
operatorDecl->mReturnType = typeRef;
CheckMultiuseAttributeTypeRef(operatorDecl->mReturnType);
mVisitorPos.MoveNext();
MEMBER_SET(operatorDecl, mOperatorToken, nextToken);
@ -7394,6 +7534,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
ReplaceNode(typeRef, propDecl);
propDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
propDecl->mTypeRef = typeRef;
CheckMultiuseAttributeTypeRef(propDecl->mTypeRef);
if (explicitInterface != NULL)
{
@ -7553,6 +7694,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
ReplaceNode(typeRef, fieldDecl);
fieldDecl->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
fieldDecl->mTypeRef = typeRef;
CheckMultiuseAttributeTypeRef(fieldDecl->mTypeRef);
return fieldDecl;
}
}
@ -7584,6 +7726,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
}
methodDeclaration->mReturnType = typeRef;
CheckMultiuseAttributeTypeRef(methodDeclaration->mReturnType);
MEMBER_SET_CHECKED(methodDeclaration, mNameNode, nameIdentifier);
mCurMethodDecl = methodDeclaration;
ParseMethod(methodDeclaration, &params, &commas);
@ -7990,6 +8133,47 @@ BfScopedInvocationTarget* BfReducer::CreateScopedInvocationTarget(BfAstNode*& ta
return scopedInvocationTarget;
}
bool BfReducer::CheckInlineTypeRefAttribute(BfAstNode* typeRef, BfAttributeDirective* attributes)
{
if (attributes == NULL)
return false;
if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(typeRef))
{
auto checkAttribute = attributes;
while (checkAttribute != NULL)
{
checkAttribute->mIsMultiUse = true;
checkAttribute = checkAttribute->mNextAttribute;
}
auto typeDecl = inlineTypeRef->mTypeDeclaration;
typeDecl->mTriviaStart = attributes->mTriviaStart;
typeDecl->mSrcStart = attributes->mSrcStart;
typeDecl->mAttributes = attributes;
if ((typeDecl->mIgnoreDeclaration) && (IsNodeRelevant(typeDecl)))
typeDecl->mIgnoreDeclaration = false;
return true;
}
return false;
}
void BfReducer::CheckMultiuseAttributeTypeRef(BfAstNode* typeRef)
{
if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(typeRef))
{
auto checkAttribute = inlineTypeRef->mTypeDeclaration->mAttributes;
while (checkAttribute != NULL)
{
checkAttribute->mIsMultiUse = true;
checkAttribute = checkAttribute->mNextAttribute;
}
}
}
bool BfReducer::SetProtection(BfAstNode* parentNode, BfAstNode*& protectionNodeRef, BfTokenNode* tokenNode)
{
bool failed = false;
@ -8648,7 +8832,7 @@ BfAstNode* BfReducer::HandleTopLevel(BfBlock* node)
return node;
}
BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode)
BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode, bool isAnonymous)
{
AssertCurrentNode(tokenNode);
@ -8992,9 +9176,12 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
case BfToken_Delegate:
case BfToken_Function:
{
{
auto typeDeclaration = mAlloc->Alloc<BfTypeDeclaration>();
SetAndRestoreValue<BfTypeDeclaration*> prevTypeDecl(mCurTypeDecl, typeDeclaration);
CurTypeState curTypeState(typeDeclaration, mAlloc);
SetAndRestoreValue<CurTypeState*> prevTypeState(mCurTypeState, &curTypeState);
ReplaceNode(tokenNode, typeDeclaration);
typeDeclaration->mDocumentation = FindDocumentation(typeDeclaration);
@ -9006,6 +9193,7 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
auto methodDecl = mAlloc->Alloc<BfMethodDeclaration>();
MEMBER_SET(methodDecl, mReturnType, retType);
CheckMultiuseAttributeTypeRef(methodDecl->mReturnType);
BfDeferredAstSizedArray<BfParameterDeclaration*> params(methodDecl->mParams, mAlloc);
BfDeferredAstSizedArray<BfTokenNode*> commas(methodDecl->mCommas, mAlloc);
methodDecl->mDocumentation = FindDocumentation(methodDecl);
@ -9121,11 +9309,16 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
if ((tokenNode->GetToken() == BfToken_Enum) && (isSimpleEnum))
break;
auto identifierNode = ExpectIdentifierAfter(tokenNode);
if (identifierNode == NULL)
BfIdentifierNode* identifierNode = NULL;
if (!isAnonymous)
{
AddErrorNode(tokenNode);
return NULL;
identifierNode = ExpectIdentifierAfter(tokenNode);
if (identifierNode == NULL)
{
AddErrorNode(tokenNode);
return NULL;
}
}
// We put extra effort in here to continue after failure, since 'return NULL' failure
@ -9138,7 +9331,8 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
typeDeclaration->mTypeNode = tokenNode;
typeDeclaration->mNameNode = identifierNode;
ReplaceNode(tokenNode, typeDeclaration);
MoveNode(identifierNode, typeDeclaration);
if (identifierNode != NULL)
MoveNode(identifierNode, typeDeclaration);
typeDeclaration->mDocumentation = FindDocumentation(mTypeMemberNodeStart);
auto nextNode = mVisitorPos.GetNext();
@ -10645,8 +10839,10 @@ void BfReducer::HandleBlock(BfBlock* block, bool allowEndingExpression)
void BfReducer::HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode)
{
SetAndRestoreValue<BfTypeDeclaration*> prevTypeDecl(mCurTypeDecl, typeDecl);
CurTypeState curTypeState(typeDecl, mAlloc);
SetAndRestoreValue<CurTypeState*> prevTypeState(mCurTypeState, &curTypeState);
SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(BfNodeDynCast<BfBlock>(typeDecl->mDefineNode)));
if (attributes != NULL)
{
MEMBER_SET(typeDecl, mAttributes, attributes);

View file

@ -129,6 +129,39 @@ public:
}
};
struct CurTypeState
{
public:
BfTypeDeclaration* mTypeDeclaration;
BfAstAllocator* mAlloc;
Array<BfTypeDeclaration*> mAnonymousTypeDecls;
public:
CurTypeState()
{
mTypeDeclaration = NULL;
mAlloc = NULL;
}
CurTypeState(BfTypeDeclaration* typeDecl, BfAstAllocator* alloc)
{
mTypeDeclaration = typeDecl;
mAlloc = alloc;
}
~CurTypeState()
{
if ((mTypeDeclaration != NULL) && (mAnonymousTypeDecls.mSize > 0))
{
BF_ASSERT(mTypeDeclaration->mAnonymousTypes.mSize == 0);
mTypeDeclaration->mAnonymousTypes.mSize = (int)mAnonymousTypeDecls.size();
mTypeDeclaration->mAnonymousTypes.mVals = (BfTypeDeclaration**)mAlloc->AllocBytes(mAnonymousTypeDecls.mSize * sizeof(BfTypeDeclaration*), sizeof(BfTypeDeclaration*));
for (int i = 0; i < mAnonymousTypeDecls.mSize; i++)
mTypeDeclaration->mAnonymousTypes.mVals[i] = mAnonymousTypeDecls[i];
}
}
};
public:
BfAstAllocator* mAlloc;
BfSystem* mSystem;
@ -138,10 +171,12 @@ public:
BfAstNode* mTypeMemberNodeStart;
int mClassDepth;
int mMethodDepth;
int mCurUniqueIdx;
BfTypeDeclaration* mCurTypeDecl;
CurTypeState* mCurTypeState;
BfTypeDeclaration* mLastTypeDecl;
BfMethodDeclaration* mCurMethodDecl;
BfAstNode* mLastBlockNode;
BfAstNode* mLastBlockNode;
bool mStmtHasError;
bool mPrevStmtHadError;
bool mCompatMode; // Does C++ compatible parsing
@ -179,7 +214,9 @@ public:
bool IsNodeRelevant(BfAstNode* startNode, BfAstNode* endNode);
void MoveNode(BfAstNode* srcNode, BfAstNode* newOwner);
void ReplaceNode(BfAstNode* prevNode, BfAstNode* newNode);
bool CheckInlineTypeRefAttribute(BfAstNode* typeRef, BfAttributeDirective* attributes);
void CheckMultiuseAttributeTypeRef(BfAstNode* typeRef);
bool SetProtection(BfAstNode* parentNode, BfAstNode*& protectionNodeRef, BfTokenNode* tokenNode);
BfAstNode* CreateAllocNode(BfTokenNode* newNode);
BfAstNode* ReplaceTokenStarter(BfAstNode* astNode, int idx = -1, bool allowIn = false);
@ -238,7 +275,7 @@ public:
BfWhileStatement* CreateWhileStatement(BfAstNode* node);
BfDoStatement* CreateDoStatement(BfAstNode* node);
BfRepeatStatement* CreateRepeatStatement(BfAstNode* node);
BfAstNode* CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode = NULL);
BfAstNode* CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDirective* attributes, BfAstNode* deferredHeadNode = NULL, bool isAnonymous = false);
BfAstNode* HandleTopLevel(BfBlock* node);
BfInlineAsmStatement* CreateInlineAsmStatement(BfAstNode* asmNode);

View file

@ -2450,6 +2450,11 @@ bool BfTypeInstance::GetResultInfo(BfType*& valueType, int& okTagId)
return false;
}
bool BfTypeInstance::IsAnonymous()
{
return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymous());
}
void BfTypeInstance::ReportMemory(MemReporter* memReporter)
{
if (mGenericTypeInfo != NULL)
@ -4249,6 +4254,13 @@ int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHa
}
return nameHash ^ HASH_TAG;
}
// else if (auto inlineTypeRef = BfNodeDynCastExact<BfInlineTypeReference>(typeRef))
// {
// String name;
// inlineTypeRef->mTypeDeclaration->GetAnonymousName(name);
// int nameHash = (int)Hash64(name.c_str(), (int)name.length());
// return nameHash ^ HASH_TAG;
// }
else
{
BF_FATAL("Not handled");
@ -5552,6 +5564,8 @@ String BfTypeUtils::TypeToString(BfAstNode* typeRefNode)
}
if (auto directStrTypeName = BfNodeDynCast<BfDirectStrTypeReference>(typeRef))
return directStrTypeName->mTypeName;
if (auto inlineTypeRef = BfNodeDynCast<BfInlineTypeReference>(typeRef))
return inlineTypeRef->mTypeDeclaration->mAnonymousName;
if (auto tupleTypeRef = BfNodeDynCast<BfTupleTypeRef>(typeRef))
{

View file

@ -2205,6 +2205,7 @@ public:
bool HasBeenInstantiated() { return mHasBeenInstantiated || ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_AssumeInstantiated) != 0); }
bool IncludeAllMethods() { return ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_IncludeAllMethods) != 0); }
bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; }
bool IsAnonymous();
virtual void ReportMemory(MemReporter* memReporter) override;
};
@ -2669,6 +2670,7 @@ public:
Array<BfCustomAttributeSetProperty> mSetProperties;
Array<BfCustomAttributeSetField> mSetField;
bool mAwaitingValidation;
bool mIsMultiUse;
BfAstNode* GetRefNode()
{

View file

@ -662,7 +662,7 @@ void BfSourceClassifier::Visit(BfTypeDeclaration* typeDeclaration)
SetAndRestoreValue<BfAstNode*> prevMember(mCurMember, typeDeclaration);
if (mSkipTypeDeclarations)
if ((mSkipTypeDeclarations) && (!typeDeclaration->IsAnonymous()))
{
if (auto defineBlock = BfNodeDynCast<BfBlock>(typeDeclaration->mDefineNode))
{

View file

@ -1984,6 +1984,8 @@ BfSystem::BfSystem()
gPerfManager = new PerfManager();
//gPerfManager->StartRecording();
mAnonymousAtomCount = 0;
mCurUniqueId = 0;
mAtomUpdateIdx = 0;
mAtomCreateIdx = 0;
mTypeMapVersion = 1;
@ -2094,7 +2096,7 @@ BfSystem::~BfSystem()
typeDef->mHash = typeCode + 1000; \
mSystemTypeDefs[name] = typeDef;
BfAtom* BfSystem::GetAtom(const StringImpl& string)
BfAtom* BfSystem::GetAtom(const StringImpl& string, BfAtom::Kind kind)
{
StringView* stringPtr = NULL;
BfAtom* atom = NULL;
@ -2111,6 +2113,7 @@ BfAtom* BfSystem::GetAtom(const StringImpl& string)
}
#endif
mAtomCreateIdx++;
atom->mKind = kind;
atom->mIsSystemType = false;
atom->mAtomUpdateIdx = ++mAtomUpdateIdx;
atom->mString = *stringPtr;
@ -2121,6 +2124,9 @@ BfAtom* BfSystem::GetAtom(const StringImpl& string)
for (char c : string)
atom->mHash = ((atom->mHash ^ c) << 5) - atom->mHash;
if (kind == BfAtom::Kind_Anon)
mAnonymousAtomCount++;
BfLogSys(this, "Atom Allocated %p %s\n", atom, string.c_str());
return atom;
@ -2152,6 +2158,12 @@ void BfSystem::ReleaseAtom(BfAtom* atom)
{
if (--atom->mRefCount == 0)
{
if (atom->mKind == BfAtom::Kind_Anon)
{
mAnonymousAtomCount--;
BF_ASSERT(mAnonymousAtomCount >= 0);
}
mAtomGraveyard.push_back(atom);
return;
}

View file

@ -48,8 +48,16 @@ typedef HashSet<BfProject*> BfProjectSet;
class BfAtom
{
public:
enum Kind
{
Kind_Normal,
Kind_Anon
};
public:
StringView mString;
Kind mKind;
int mRefCount;
int mPendingDerefCount;
int mHash;
@ -1783,6 +1791,8 @@ public:
Array<BfAtom*> mAtomGraveyard;
uint32 mAtomUpdateIdx;
int32 mTypeMapVersion; // Increment when we add any new types or namespaces
int32 mAnonymousAtomCount;
int32 mCurUniqueId;
OwnedVector<BfMethodDef> mMethodGraveyard;
OwnedVector<BfFieldDef> mFieldGraveyard;
@ -1830,7 +1840,7 @@ public:
BfSystem();
~BfSystem();
BfAtom* GetAtom(const StringImpl& string);
BfAtom* GetAtom(const StringImpl& string, BfAtom::Kind kind = BfAtom::Kind_Normal);
BfAtom* FindAtom(const StringImpl& string); // Doesn't create a ref
BfAtom* FindAtom(const StringView& string); // Doesn't create a ref
void ReleaseAtom(BfAtom* atom);

View file

@ -0,0 +1,44 @@
using System;
namespace Tests;
class Anonymous
{
struct StructA
{
public [Union] struct { public int mX, mY; } mVals;
[CRepr, SkipCall] struct { public int mA, mB; } GetVals()
{
decltype(GetVals()) retVals;
retVals.mA = 1;
retVals.mB = 2;
return retVals;
}
}
struct StructB
{
[Union]
public using struct
{
public int mX;
public int mY;
} mCoords;
}
[Test]
public static void TestBasics()
{
StructA sa = default;
sa.mVals.mX = 123;
Test.Assert(sa.mVals.mY == 123);
var val = sa.[Friend]GetVals();
Test.Assert(val.mA == 0);
Test.Assert(val.mB == 0);
StructB sb = default;
sb.mX = 345;
Test.Assert(sb.mY == 345);
}
}