1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Added reflect method filters

This commit is contained in:
Brian Fiete 2020-07-14 08:27:25 -07:00
parent f566daacea
commit f9c0f2a311
9 changed files with 204 additions and 112 deletions

View file

@ -1900,10 +1900,18 @@ void BfContext::UpdateRevisedTypes()
workspaceConfigHashCtx.Mixin(typeOptions.mOrFlags); workspaceConfigHashCtx.Mixin(typeOptions.mOrFlags);
workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodFilters.size()); workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodFilters.size());
for (auto& filter : typeOptions.mReflectMethodFilters) for (auto& filter : typeOptions.mReflectMethodFilters)
workspaceConfigHashCtx.MixinStr(filter); {
workspaceConfigHashCtx.MixinStr(filter.mFilter);
workspaceConfigHashCtx.Mixin(filter.mAndFlags);
workspaceConfigHashCtx.Mixin(filter.mOrFlags);
}
workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodAttributeFilters.size()); workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodAttributeFilters.size());
for (auto& filter : typeOptions.mReflectMethodAttributeFilters) for (auto& filter : typeOptions.mReflectMethodAttributeFilters)
workspaceConfigHashCtx.MixinStr(filter); {
workspaceConfigHashCtx.MixinStr(filter.mFilter);
workspaceConfigHashCtx.Mixin(filter.mAndFlags);
workspaceConfigHashCtx.Mixin(filter.mOrFlags);
}
workspaceConfigHashCtx.Mixin(typeOptions.mAllocStackTraceDepth); workspaceConfigHashCtx.Mixin(typeOptions.mAllocStackTraceDepth);
} }

View file

@ -6932,7 +6932,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
// If we call "GetType" on a value type, statically determine the type rather than boxing and then dispatching // If we call "GetType" on a value type, statically determine the type rather than boxing and then dispatching
if ((methodDef) && (target) && (curTypeInst == mModule->mContext->mBfObjectType) && if ((methodDef) && (target) && (curTypeInst == mModule->mContext->mBfObjectType) &&
(methodDef->mName == "GetType") && (target.mType->IsValueType())) (methodDef->mName == "GetType") && (target.mType->IsValueType()) && (argValues.mArguments->IsEmpty()))
{ {
BfType* targetType = target.mType; BfType* targetType = target.mType;
if (origTarget) if (origTarget)

View file

@ -6042,19 +6042,9 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if ((methodDef->mIsStatic) && ((methodReflectKind & ReflectKind_StaticMethods) != 0)) if ((methodDef->mIsStatic) && ((methodReflectKind & ReflectKind_StaticMethods) != 0))
includeMethod = true; includeMethod = true;
if (methodDef->mMethodType == BfMethodType_Ctor) if ((!includeMethod) && (typeOptions != NULL))
{ includeMethod = ApplyTypeOptionMethodFilters(includeMethod, methodDef, typeOptions);
if (typeOptions != NULL)
includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectConstructors);
}
else
{
if ((!methodDef->mIsStatic) && (typeOptions != NULL))
includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectNonStaticMethods);
if ((methodDef->mIsStatic) && (typeOptions != NULL))
includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectStaticMethods);
}
if (!includeMethod) if (!includeMethod)
continue; continue;

View file

@ -1604,7 +1604,7 @@ public:
void CheckAddFailType(); void CheckAddFailType();
bool PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data); bool PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
BfTypeOptions* GetTypeOptions(BfTypeDef* typeDef); BfTypeOptions* GetTypeOptions(BfTypeDef* typeDef);
bool CheckTypeOptionMethodFilters(BfMethodDef* methodDef, BfTypeOptions* typeOptions); bool ApplyTypeOptionMethodFilters(bool includeMethod, BfMethodDef* methodDef, BfTypeOptions* typeOptions);
int GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName); int GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName);
void SetTypeOptions(BfTypeInstance* typeInstance); void SetTypeOptions(BfTypeInstance* typeInstance);
BfModuleOptions GetModuleOptions(); BfModuleOptions GetModuleOptions();

View file

@ -1452,18 +1452,34 @@ BfTypeOptions* BfModule::GetTypeOptions(BfTypeDef* typeDef)
if (typeOptions.mEmitDebugInfo != -1) if (typeOptions.mEmitDebugInfo != -1)
mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo; mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo;
if (typeOptions.mReflectMethodFilters.IsEmpty())
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags | typeOptions.mOrFlags); mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags | typeOptions.mOrFlags);
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | typeOptions.mOrFlags); mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | typeOptions.mOrFlags);
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags & typeOptions.mAndFlags); mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags & typeOptions.mAndFlags);
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & typeOptions.mAndFlags); mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & typeOptions.mAndFlags);
if (mergedTypeOptions.HasReflectMethodFilters())
{
// If merging filter has non-default method flags but no filter then we need to append it as a filtered modification
if ((!typeOptions.HasReflectMethodFilters()) &&
(((typeOptions.mAndFlags & BfOptionFlags_Reflect_MethodMask) != BfOptionFlags_Reflect_MethodMask) ||
((typeOptions.mOrFlags & BfOptionFlags_Reflect_MethodMask) != 0)))
{
mergedTypeOptions.mReflectMethodFilters.Add({"*", typeOptions.mAndFlags, typeOptions.mOrFlags});
}
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | BfOptionFlags_Reflect_MethodMask);
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & ~BfOptionFlags_Reflect_MethodMask);
}
if (typeOptions.mAllocStackTraceDepth != -1) if (typeOptions.mAllocStackTraceDepth != -1)
mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth; mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth;
for (auto filter : typeOptions.mReflectMethodFilters) for (auto filter : typeOptions.mReflectMethodFilters)
mergedTypeOptions.mReflectMethodFilters.Add(filter); mergedTypeOptions.mReflectMethodFilters.Add(filter);
for (auto filter : typeOptions.mReflectMethodAttributeFilters) for (auto filter : typeOptions.mReflectMethodAttributeFilters)
mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter); mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter);
} }
matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size(); matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size();
mContext->mSystem->mMergedTypeOptions.push_back(mergedTypeOptions); mContext->mSystem->mMergedTypeOptions.push_back(mergedTypeOptions);
@ -1473,9 +1489,36 @@ BfTypeOptions* BfModule::GetTypeOptions(BfTypeDef* typeDef)
return mSystem->GetTypeOptions( matchedIdx); return mSystem->GetTypeOptions( matchedIdx);
} }
bool BfModule::CheckTypeOptionMethodFilters(BfMethodDef* methodDef, BfTypeOptions * typeOptions) bool BfModule::ApplyTypeOptionMethodFilters(bool includeMethod, BfMethodDef* methodDef, BfTypeOptions* typeOptions)
{ {
return true; BfOptionFlags findFlag = BfOptionFlags_None;
if (methodDef->mMethodType == BfMethodType_Ctor)
findFlag = BfOptionFlags_ReflectConstructors;
else if (methodDef->mIsStatic)
findFlag = BfOptionFlags_ReflectStaticMethods;
else
findFlag = BfOptionFlags_ReflectNonStaticMethods;
if ((typeOptions->mAndFlags & findFlag) == 0)
includeMethod = false;
if ((typeOptions->mOrFlags & findFlag) != 0)
includeMethod = true;
if (!typeOptions->mReflectMethodFilters.IsEmpty())
{
for (auto& filter : typeOptions->mReflectMethodFilters)
{
if (BfCheckWildcard(filter.mFilter, methodDef->mName))
{
if ((filter.mAndFlags & findFlag) == 0)
includeMethod = false;
if ((filter.mAndFlags | findFlag) != 0)
includeMethod = true;
}
}
}
return includeMethod;
} }
int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName) int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName)
@ -1533,92 +1576,10 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
int filterIdx = 0; int filterIdx = 0;
int typeNameIdx = 0; int typeNameIdx = 0;
const char* filterPtr = filter.c_str(); if (BfCheckWildcard(filter, typeName))
const char* namePtr = typeName.c_str();
char prevFilterC = 0;
while (true)
{ {
char filterC; matched = true;
while (true) break;
{
filterC = *(filterPtr++);
if (filterC != ' ')
break;
}
char nameC;
while (true)
{
nameC = *(namePtr++);
if (nameC != ' ')
break;
}
if ((filterC == 0) || (nameC == 0))
{
matched = (filterC == 0) && (nameC == 0);
break;
}
bool doWildcard = false;
if (nameC != filterC)
{
if (filterC == '*')
doWildcard = true;
else if (((filterC == ',') || (filterC == '>')) &&
((prevFilterC == '<') || (prevFilterC == ',')))
{
doWildcard = true;
filterPtr--;
}
if (!doWildcard)
{
matched = false;
break;
}
}
if (doWildcard)
{
int openDepth = 0;
const char* startNamePtr = namePtr;
while (true)
{
nameC = *(namePtr++);
if (nameC == 0)
{
namePtr--;
if (openDepth != 0)
matched = false;
break;
}
if ((nameC == '>') && (openDepth == 0))
{
namePtr--;
break;
}
if (nameC == '<')
openDepth++;
else if (nameC == '>')
openDepth--;
else if ((nameC == ',') && (openDepth == 0))
{
namePtr--;
break;
}
}
if (!matched)
break;
}
prevFilterC = filterC;
} }
} }
@ -1705,9 +1666,9 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
if (typeOptions.mAllocStackTraceDepth != -1) if (typeOptions.mAllocStackTraceDepth != -1)
mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth; mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth;
for (auto filter : typeOptions.mReflectMethodFilters) for (auto& filter : typeOptions.mReflectMethodFilters)
mergedTypeOptions.mReflectMethodFilters.Add(filter); mergedTypeOptions.mReflectMethodFilters.Add(filter);
for (auto filter : typeOptions.mReflectMethodAttributeFilters) for (auto& filter : typeOptions.mReflectMethodAttributeFilters)
mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter); mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter);
} }
matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size(); matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size();
@ -2537,8 +2498,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx); auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
if (typeOptions != NULL) if (typeOptions != NULL)
{ {
typeInstance->mIncludeAllMethods = typeOptions->Apply(typeInstance->mIncludeAllMethods, BfOptionFlags_ReflectAlwaysIncludeAll);
typeInstance->mHasBeenInstantiated = typeOptions->Apply(typeInstance->mHasBeenInstantiated, BfOptionFlags_ReflectAssumeInstantiated); typeInstance->mHasBeenInstantiated = typeOptions->Apply(typeInstance->mHasBeenInstantiated, BfOptionFlags_ReflectAssumeInstantiated);
} }
} }
@ -3896,6 +3856,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
isFailedType = true; isFailedType = true;
} }
bool typeOptionsIncludeAll = false;
if (typeOptions != NULL)
typeOptionsIncludeAll = typeOptions->Apply(typeOptionsIncludeAll, BfOptionFlags_ReflectAlwaysIncludeAll);
// Generate all methods. Pass 1 // Generate all methods. Pass 1
for (auto methodDef : typeDef->mMethods) for (auto methodDef : typeDef->mMethods)
{ {
@ -3997,6 +3961,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
} }
if (typeInstance->mIncludeAllMethods) if (typeInstance->mIncludeAllMethods)
implRequired = true; implRequired = true;
if ((typeOptionsIncludeAll) && (ApplyTypeOptionMethodFilters(true, methodDef, typeOptions)))
implRequired = true;
// if ((typeOptions != NULL) && (CheckTypeOptionMethodFilters(typeOptions, methodDef))) // if ((typeOptions != NULL) && (CheckTypeOptionMethodFilters(typeOptions, methodDef)))
// implRequired = true; // implRequired = true;

View file

@ -3666,7 +3666,21 @@ BF_EXPORT void BF_CALLTYPE BfSystem_AddTypeOptions(BfSystem* bfSystem, char* fil
typeOptions.mOrFlags = (BfOptionFlags)orFlags; typeOptions.mOrFlags = (BfOptionFlags)orFlags;
typeOptions.mAllocStackTraceDepth = allocStackTraceDepth; typeOptions.mAllocStackTraceDepth = allocStackTraceDepth;
_ParseFilters(reflectMethodFilter, typeOptions.mReflectMethodFilters, typeOptions.mReflectMethodAttributeFilters); Array<String> methodReflectFilters;
Array<String> methodReflectAttributeFilters;
_ParseFilters(reflectMethodFilter, methodReflectFilters, methodReflectAttributeFilters);
// When we have method filters we want to apply those to the methods for when we merge options
if ((!methodReflectFilters.IsEmpty()) || (!methodReflectAttributeFilters.IsEmpty()))
{
for (auto& filter : methodReflectFilters)
typeOptions.mReflectMethodFilters.Add({ filter, (BfOptionFlags)andFlags, (BfOptionFlags)orFlags });
for (auto& filter : methodReflectAttributeFilters)
typeOptions.mReflectMethodAttributeFilters.Add({ filter, (BfOptionFlags)andFlags, (BfOptionFlags)orFlags });
typeOptions.mAndFlags = (BfOptionFlags)(typeOptions.mAndFlags | BfOptionFlags_Reflect_MethodMask);
typeOptions.mOrFlags = (BfOptionFlags)(typeOptions.mOrFlags & ~BfOptionFlags_Reflect_MethodMask);
}
bfSystem->mTypeOptions.push_back(typeOptions); bfSystem->mTypeOptions.push_back(typeOptions);
} }

View file

@ -1285,10 +1285,21 @@ enum BfOptionFlags
BfOptionFlags_ReflectNonStaticMethods = 0x400, BfOptionFlags_ReflectNonStaticMethods = 0x400,
BfOptionFlags_ReflectConstructors = 0x800, BfOptionFlags_ReflectConstructors = 0x800,
BfOptionFlags_Reflect_MethodMask = BfOptionFlags_ReflectStaticMethods | BfOptionFlags_ReflectNonStaticMethods | BfOptionFlags_ReflectConstructors,
BfOptionFlags_Mask = 0xFFF
}; };
class BfTypeOptions class BfTypeOptions
{ {
public:
struct MethodFilter
{
String mFilter;
BfOptionFlags mOrFlags;
BfOptionFlags mAndFlags;
};
public: public:
Array<String> mTypeFilters; Array<String> mTypeFilters;
Array<String> mAttributeFilters; Array<String> mAttributeFilters;
@ -1298,8 +1309,8 @@ public:
int mEmitDebugInfo; int mEmitDebugInfo;
BfOptionFlags mAndFlags; BfOptionFlags mAndFlags;
BfOptionFlags mOrFlags; BfOptionFlags mOrFlags;
Array<String> mReflectMethodFilters; Array<MethodFilter> mReflectMethodFilters;
Array<String> mReflectMethodAttributeFilters; Array<MethodFilter> mReflectMethodAttributeFilters;
int mAllocStackTraceDepth; int mAllocStackTraceDepth;
public: public:
@ -1317,6 +1328,11 @@ public:
else else
return (mOrFlags & flags) != 0; return (mOrFlags & flags) != 0;
} }
bool HasReflectMethodFilters()
{
return !mReflectMethodFilters.IsEmpty() || !mReflectMethodAttributeFilters.IsEmpty();
}
}; };
class BfSystem class BfSystem

View file

@ -60,3 +60,97 @@ uint64 stouln(const char* str, int len)
} }
return val; return val;
} }
bool Beefy::BfCheckWildcard(const StringImpl& wildcard, const StringImpl& checkStr)
{
bool matched = true;
const char* filterPtr = wildcard.c_str();
const char* namePtr = checkStr.c_str();
char prevFilterC = 0;
while (true)
{
char filterC;
while (true)
{
filterC = *(filterPtr++);
if (filterC != ' ')
break;
}
char nameC;
while (true)
{
nameC = *(namePtr++);
if (nameC != ' ')
break;
}
if ((filterC == 0) || (nameC == 0))
{
matched = (filterC == 0) && (nameC == 0);
break;
}
bool doWildcard = false;
if (nameC != filterC)
{
if (filterC == '*')
doWildcard = true;
else if (((filterC == ',') || (filterC == '>')) &&
((prevFilterC == '<') || (prevFilterC == ',')))
{
doWildcard = true;
filterPtr--;
}
if (!doWildcard)
{
matched = false;
break;
}
}
if (doWildcard)
{
int openDepth = 0;
const char* startNamePtr = namePtr;
while (true)
{
nameC = *(namePtr++);
if (nameC == 0)
{
namePtr--;
if (openDepth != 0)
matched = false;
break;
}
if ((nameC == '>') && (openDepth == 0))
{
namePtr--;
break;
}
if (nameC == '<')
openDepth++;
else if (nameC == '>')
openDepth--;
else if ((nameC == ',') && (openDepth == 0))
{
namePtr--;
break;
}
}
if (!matched)
break;
}
prevFilterC = filterC;
}
return matched;
}

View file

@ -276,6 +276,8 @@ T* ZeroedAlloc()
return new (ZeroedAlloc(sizeof(T))) T(); return new (ZeroedAlloc(sizeof(T))) T();
}*/ }*/
bool BfCheckWildcard(const StringImpl& wildcard, const StringImpl& checkStr);
template <typename T> template <typename T>
T* PlaceNew(void* addr) T* PlaceNew(void* addr)
{ {