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:
parent
f609062c2a
commit
958fc30310
20 changed files with 600 additions and 48 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -223,6 +223,7 @@ BfAutoComplete::BfAutoComplete(BfResolveType resolveType, bool doFuzzyAutoComple
|
|||
BfAutoComplete::~BfAutoComplete()
|
||||
{
|
||||
Clear();
|
||||
RemoveMethodMatchInfo();
|
||||
}
|
||||
|
||||
void BfAutoComplete::SetModule(BfModule* module)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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, ¶ms, &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, ¶ms, &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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
44
IDEHelper/Tests/src/Anonymous.bf
Normal file
44
IDEHelper/Tests/src/Anonymous.bf
Normal 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue