mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Added reflection category to distinct build options (wip)
This commit is contained in:
parent
5cb6570e14
commit
037b2ac1e4
15 changed files with 538 additions and 94 deletions
|
@ -64,6 +64,15 @@ namespace IDE
|
||||||
Small,
|
Small,
|
||||||
Big
|
Big
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum AlwaysIncludeKind
|
||||||
|
{
|
||||||
|
NotSet,
|
||||||
|
No,
|
||||||
|
IncludeType,
|
||||||
|
AssumeInstantiated,
|
||||||
|
IncludeAll
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DistinctBuildOptions
|
public class DistinctBuildOptions
|
||||||
|
@ -94,6 +103,20 @@ namespace IDE
|
||||||
public bool? mEmitObjectAccessCheck; // Only valid with mObjectHasDebugFlags
|
public bool? mEmitObjectAccessCheck; // Only valid with mObjectHasDebugFlags
|
||||||
[Reflect]
|
[Reflect]
|
||||||
public int32? mAllocStackTraceDepth;
|
public int32? mAllocStackTraceDepth;
|
||||||
|
[Reflect]
|
||||||
|
public BuildOptions.AlwaysIncludeKind mReflectAlwaysInclude;
|
||||||
|
[Reflect]
|
||||||
|
public bool? mReflectStaticFields;
|
||||||
|
[Reflect]
|
||||||
|
public bool? mReflectNonStaticFields;
|
||||||
|
[Reflect]
|
||||||
|
public bool? mReflectStaticMethods;
|
||||||
|
[Reflect]
|
||||||
|
public bool? mReflectNonStaticMethods;
|
||||||
|
[Reflect]
|
||||||
|
public bool? mReflectConstructors;
|
||||||
|
[Reflect]
|
||||||
|
public String mReflectMethodFilter = new String() ~ delete _;
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
|
@ -111,6 +134,13 @@ namespace IDE
|
||||||
newVal.mEmitDynamicCastCheck = mEmitDynamicCastCheck;
|
newVal.mEmitDynamicCastCheck = mEmitDynamicCastCheck;
|
||||||
newVal.mEmitObjectAccessCheck = mEmitObjectAccessCheck;
|
newVal.mEmitObjectAccessCheck = mEmitObjectAccessCheck;
|
||||||
newVal.mAllocStackTraceDepth = mAllocStackTraceDepth;
|
newVal.mAllocStackTraceDepth = mAllocStackTraceDepth;
|
||||||
|
newVal.mReflectAlwaysInclude = mReflectAlwaysInclude;
|
||||||
|
newVal.mReflectStaticFields = mReflectStaticFields;
|
||||||
|
newVal.mReflectNonStaticFields = mReflectNonStaticFields;
|
||||||
|
newVal.mReflectStaticMethods = mReflectStaticMethods;
|
||||||
|
newVal.mReflectNonStaticMethods = mReflectNonStaticMethods;
|
||||||
|
newVal.mReflectConstructors = mReflectConstructors;
|
||||||
|
newVal.mReflectMethodFilter.Set(mReflectMethodFilter);
|
||||||
return newVal;
|
return newVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +163,20 @@ namespace IDE
|
||||||
mEmitObjectAccessCheck = data.GetBool("EmitObjectAccessCheck");
|
mEmitObjectAccessCheck = data.GetBool("EmitObjectAccessCheck");
|
||||||
if (data.Contains("AllocStackTraceDepth"))
|
if (data.Contains("AllocStackTraceDepth"))
|
||||||
mAllocStackTraceDepth = data.GetInt("AllocStackTraceDepth");
|
mAllocStackTraceDepth = data.GetInt("AllocStackTraceDepth");
|
||||||
|
|
||||||
|
if (data.Contains("ReflectAlwaysInclude"))
|
||||||
|
mReflectAlwaysInclude = data.GetEnum<BuildOptions.AlwaysIncludeKind>("ReflectAlwaysInclude");
|
||||||
|
if (data.Contains("ReflectStaticFields"))
|
||||||
|
mReflectStaticFields = data.GetBool("ReflectStaticFields");
|
||||||
|
if (data.Contains("ReflectNonStaticFields"))
|
||||||
|
mReflectNonStaticFields = data.GetBool("ReflectNonStaticFields");
|
||||||
|
if (data.Contains("ReflectStaticMethods"))
|
||||||
|
mReflectStaticMethods = data.GetBool("ReflectStaticMethods");
|
||||||
|
if (data.Contains("ReflectNonStaticMethods"))
|
||||||
|
mReflectNonStaticMethods = data.GetBool("ReflectNonStaticMethods");
|
||||||
|
if (data.Contains("ReflectConstructors"))
|
||||||
|
mReflectConstructors = data.GetBool("ReflectConstructors");
|
||||||
|
data.GetString("ReflectMethodFilter", mReflectMethodFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Serialize(StructuredData data)
|
public void Serialize(StructuredData data)
|
||||||
|
@ -146,6 +190,13 @@ namespace IDE
|
||||||
data.ConditionalAdd("EmitDynamicCastCheck", mEmitDynamicCastCheck);
|
data.ConditionalAdd("EmitDynamicCastCheck", mEmitDynamicCastCheck);
|
||||||
data.ConditionalAdd("EmitObjectAccessCheck", mEmitObjectAccessCheck);
|
data.ConditionalAdd("EmitObjectAccessCheck", mEmitObjectAccessCheck);
|
||||||
data.ConditionalAdd("AllocStackTraceDepth", mAllocStackTraceDepth);
|
data.ConditionalAdd("AllocStackTraceDepth", mAllocStackTraceDepth);
|
||||||
|
data.ConditionalAdd("ReflectAlwaysInclude", mReflectAlwaysInclude);
|
||||||
|
data.ConditionalAdd("ReflectStaticFields", mReflectStaticFields);
|
||||||
|
data.ConditionalAdd("ReflectNonStaticFields", mReflectNonStaticFields);
|
||||||
|
data.ConditionalAdd("ReflectStaticMethods", mReflectStaticMethods);
|
||||||
|
data.ConditionalAdd("ReflectNonStaticMethods", mReflectNonStaticMethods);
|
||||||
|
data.ConditionalAdd("ReflectConstructors", mReflectConstructors);
|
||||||
|
data.ConditionalAdd("ReflectMethodFilter", mReflectMethodFilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,25 @@ namespace IDE.Compiler
|
||||||
{
|
{
|
||||||
public class BfSystem
|
public class BfSystem
|
||||||
{
|
{
|
||||||
|
enum BfOptionFlags
|
||||||
|
{
|
||||||
|
RuntimeChecks = 1,
|
||||||
|
InitLocalVariables = 2,
|
||||||
|
EmitDynamicCastCheck = 4,
|
||||||
|
EmitObjectAccessCheck = 8,
|
||||||
|
|
||||||
|
ReflectAlwaysIncludeType = 0x10,
|
||||||
|
ReflectAlwaysIncludeAll = 0x20,
|
||||||
|
ReflectAssumeInstantiated = 0x40,
|
||||||
|
ReflectStaticFields = 0x80,
|
||||||
|
ReflectNonStaticFields = 0x100,
|
||||||
|
ReflectStaticMethods = 0x200,
|
||||||
|
ReflectNonStaticMethods = 0x400,
|
||||||
|
ReflectConstructors = 0x800,
|
||||||
|
|
||||||
|
All = 0xFFF
|
||||||
|
};
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void BfSystem_CheckLock(void* bfSystem);
|
static extern void BfSystem_CheckLock(void* bfSystem);
|
||||||
|
|
||||||
|
@ -37,8 +56,8 @@ namespace IDE.Compiler
|
||||||
static extern void BfSystem_ClearTypeOptions(void* bfSystem);
|
static extern void BfSystem_ClearTypeOptions(void* bfSystem);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void BfSystem_AddTypeOptions(void* bfSystem, char8* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 runtimeChecks,
|
static extern void BfSystem_AddTypeOptions(void* bfSystem, char8* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 andFlags, int32 orFlags,
|
||||||
int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth);
|
int32 allocStackTraceDepth, char8* reflectMethodFilter);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern void* BfSystem_CreateParser(void* bfSystem, void* bfProject);
|
static extern void* BfSystem_CreateParser(void* bfSystem, void* bfProject);
|
||||||
|
@ -343,25 +362,52 @@ namespace IDE.Compiler
|
||||||
BfSystem_ClearTypeOptions(mNativeBfSystem);
|
BfSystem_ClearTypeOptions(mNativeBfSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddTypeOptions(String filter, BuildOptions.SIMDSetting? simdSetting, BuildOptions.BfOptimizationLevel? optimizationLevel, BuildOptions.EmitDebugInfo? emitDebugInfo, bool? runtimeChecks,
|
public void AddTypeOptions(String filter, BuildOptions.SIMDSetting? simdSetting, BuildOptions.BfOptimizationLevel? optimizationLevel, BuildOptions.EmitDebugInfo? emitDebugInfo, BfOptionFlags andFlags, BfOptionFlags orFlags, int32? allocStackTraceDepth, String reflectMethodFilter)
|
||||||
bool? initLocalVariables, bool? emitDynamicCastCheck, bool? emitObjectAccessCheck, int32? allocStackTraceDepth)
|
|
||||||
{
|
{
|
||||||
int32 simdSettingInt = (simdSetting == null) ? -1 : (int32)simdSetting.Value;
|
int32 simdSettingInt = (simdSetting == null) ? -1 : (int32)simdSetting.Value;
|
||||||
int32 optimizationLevelInt = (optimizationLevel == null) ? -1 : (int32)optimizationLevel.Value;
|
int32 optimizationLevelInt = (optimizationLevel == null) ? -1 : (int32)optimizationLevel.Value;
|
||||||
int32 emitDebugInfoInt = (emitDebugInfo == null) ? -1 : (int32)emitDebugInfo.Value;
|
int32 emitDebugInfoInt = (emitDebugInfo == null) ? -1 : (int32)emitDebugInfo.Value;
|
||||||
int32 runtimeChecksInt = (runtimeChecks == null) ? -1 : runtimeChecks.Value ? 1 : 0;
|
/*int32 runtimeChecksInt = (runtimeChecks == null) ? -1 : runtimeChecks.Value ? 1 : 0;
|
||||||
int32 initLocalVariablesInt = (initLocalVariables == null) ? -1 : initLocalVariables.Value ? 1 : 0;
|
int32 initLocalVariablesInt = (initLocalVariables == null) ? -1 : initLocalVariables.Value ? 1 : 0;
|
||||||
int32 emitDynamicCastCheckInt = (emitDynamicCastCheck == null) ? -1 : emitDynamicCastCheck.Value ? 1 : 0;
|
int32 emitDynamicCastCheckInt = (emitDynamicCastCheck == null) ? -1 : emitDynamicCastCheck.Value ? 1 : 0;
|
||||||
int32 emitObjectAccessCheckInt = (emitObjectAccessCheck == null) ? -1 : emitObjectAccessCheck.Value ? 1 : 0;
|
int32 emitObjectAccessCheckInt = (emitObjectAccessCheck == null) ? -1 : emitObjectAccessCheck.Value ? 1 : 0;*/
|
||||||
int32 allocStackTraceDepthInt = (allocStackTraceDepth == null) ? -1 : allocStackTraceDepth.Value;
|
int32 allocStackTraceDepthInt = (allocStackTraceDepth == null) ? -1 : allocStackTraceDepth.Value;
|
||||||
BfSystem_AddTypeOptions(mNativeBfSystem, filter, simdSettingInt, optimizationLevelInt, emitDebugInfoInt, runtimeChecksInt,
|
BfSystem_AddTypeOptions(mNativeBfSystem, filter, simdSettingInt, optimizationLevelInt, emitDebugInfoInt, (.)andFlags, (.)orFlags, allocStackTraceDepthInt, reflectMethodFilter);
|
||||||
initLocalVariablesInt, emitDynamicCastCheckInt, emitObjectAccessCheckInt, allocStackTraceDepthInt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddTypeOptions(DistinctBuildOptions typeOption)
|
public void AddTypeOptions(DistinctBuildOptions typeOption)
|
||||||
{
|
{
|
||||||
AddTypeOptions(typeOption.mFilter, typeOption.mBfSIMDSetting, typeOption.mBfOptimizationLevel, typeOption.mEmitDebugInfo, typeOption.mRuntimeChecks,
|
BfOptionFlags andFlags = .All;
|
||||||
typeOption.mInitLocalVariables, typeOption.mEmitDynamicCastCheck, typeOption.mEmitObjectAccessCheck, typeOption.mAllocStackTraceDepth);
|
BfOptionFlags orFlags = 0;
|
||||||
|
|
||||||
|
void SetFlag(bool? val, BfOptionFlags flag)
|
||||||
|
{
|
||||||
|
if (val == false)
|
||||||
|
andFlags &= ~flag;
|
||||||
|
if (val == true)
|
||||||
|
orFlags |= flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (typeOption.mReflectAlwaysInclude)
|
||||||
|
{
|
||||||
|
case .NotSet:
|
||||||
|
case .No:
|
||||||
|
andFlags &= ~(.ReflectAlwaysIncludeType | .ReflectAlwaysIncludeAll | .ReflectAssumeInstantiated);
|
||||||
|
case .IncludeType:
|
||||||
|
orFlags |= .ReflectAssumeInstantiated;
|
||||||
|
case .AssumeInstantiated:
|
||||||
|
orFlags |= .ReflectAssumeInstantiated;
|
||||||
|
case .IncludeAll:
|
||||||
|
orFlags |= .ReflectAlwaysIncludeType | .ReflectAlwaysIncludeAll | .ReflectAssumeInstantiated;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetFlag(typeOption.mReflectStaticFields, .ReflectStaticFields);
|
||||||
|
SetFlag(typeOption.mReflectNonStaticFields, .ReflectNonStaticFields);
|
||||||
|
SetFlag(typeOption.mReflectStaticMethods, .ReflectStaticMethods);
|
||||||
|
SetFlag(typeOption.mReflectNonStaticMethods, .ReflectNonStaticMethods);
|
||||||
|
SetFlag(typeOption.mReflectConstructors, .ReflectConstructors);
|
||||||
|
|
||||||
|
AddTypeOptions(typeOption.mFilter, typeOption.mBfSIMDSetting, typeOption.mBfOptimizationLevel, typeOption.mEmitDebugInfo, andFlags, orFlags, typeOption.mAllocStackTraceDepth, typeOption.mReflectMethodFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(String str)
|
public void Log(String str)
|
||||||
|
|
|
@ -145,6 +145,34 @@ namespace IDE.ui
|
||||||
typeName.Clear(); typeName.Append(optionsName, "mAllocStackTraceDepth");
|
typeName.Clear(); typeName.Append(optionsName, "mAllocStackTraceDepth");
|
||||||
AddPropertiesItem(category, "Alloc Stack Trace Depth", typeName);
|
AddPropertiesItem(category, "Alloc Stack Trace Depth", typeName);
|
||||||
|
|
||||||
|
let (reflectItem, ?) = AddPropertiesItem(category, "Reflect");
|
||||||
|
|
||||||
|
typeName.Clear(); typeName.Append(optionsName, "mReflectAlwaysInclude");
|
||||||
|
AddPropertiesItem(reflectItem, "Always Include", typeName);
|
||||||
|
|
||||||
|
typeName.Clear(); typeName.Append(optionsName, "mReflectStaticFields");
|
||||||
|
AddPropertiesItem(reflectItem, "Static Fields", typeName,
|
||||||
|
scope String[] { "No", "Yes" });
|
||||||
|
|
||||||
|
typeName.Clear(); typeName.Append(optionsName, "mReflectNonStaticFields");
|
||||||
|
AddPropertiesItem(reflectItem, "Non-Static Fields", typeName,
|
||||||
|
scope String[] { "No", "Yes" });
|
||||||
|
|
||||||
|
typeName.Clear(); typeName.Append(optionsName, "mReflectStaticMethods");
|
||||||
|
AddPropertiesItem(reflectItem, "Static Methods", typeName,
|
||||||
|
scope String[] { "No", "Yes" });
|
||||||
|
|
||||||
|
typeName.Clear(); typeName.Append(optionsName, "mReflectNonStaticMethods");
|
||||||
|
AddPropertiesItem(reflectItem, "Non-Static Methods", typeName,
|
||||||
|
scope String[] { "No", "Yes" });
|
||||||
|
|
||||||
|
typeName.Clear(); typeName.Append(optionsName, "mReflectConstructors");
|
||||||
|
AddPropertiesItem(reflectItem, "Constructors", typeName,
|
||||||
|
scope String[] { "No", "Yes" });
|
||||||
|
|
||||||
|
typeName.Clear(); typeName.Append(optionsName, "mReflectMethodFilter");
|
||||||
|
AddPropertiesItem(reflectItem, "Method Filter", typeName);
|
||||||
|
|
||||||
category.Open(true, true);
|
category.Open(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5906,8 +5906,13 @@ void BfCompiler::CompileReified()
|
||||||
if (typeDef->mIsPartial)
|
if (typeDef->mIsPartial)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
auto scratchModule = mContext->mScratchModule;
|
||||||
bool isAlwaysInclude = (typeDef->mIsAlwaysInclude) || (typeDef->mProject->mAlwaysIncludeAll);
|
bool isAlwaysInclude = (typeDef->mIsAlwaysInclude) || (typeDef->mProject->mAlwaysIncludeAll);
|
||||||
|
|
||||||
|
auto typeOptions = scratchModule->GetTypeOptions(typeDef);
|
||||||
|
if (typeOptions != NULL)
|
||||||
|
typeOptions->Apply(isAlwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);
|
||||||
|
|
||||||
if (typeDef->mProject->IsTestProject())
|
if (typeDef->mProject->IsTestProject())
|
||||||
{
|
{
|
||||||
for (auto methodDef : typeDef->mMethods)
|
for (auto methodDef : typeDef->mMethods)
|
||||||
|
@ -5922,8 +5927,7 @@ void BfCompiler::CompileReified()
|
||||||
//TODO: Just because the type is required doesn't mean we want to reify it. Why did we have that check?
|
//TODO: Just because the type is required doesn't mean we want to reify it. Why did we have that check?
|
||||||
if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!isAlwaysInclude))
|
if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!isAlwaysInclude))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto scratchModule = mContext->mScratchModule;
|
|
||||||
scratchModule->ResolveTypeDef(typeDef, BfPopulateType_Full);
|
scratchModule->ResolveTypeDef(typeDef, BfPopulateType_Full);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6396,7 +6400,15 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
||||||
|
|
||||||
for (auto typeDef : mSystem->mTypeDefs)
|
for (auto typeDef : mSystem->mTypeDefs)
|
||||||
{
|
{
|
||||||
if ((typeDef->mIsAlwaysInclude) && (!typeDef->mIsPartial))
|
if (typeDef->mIsPartial)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool isAlwaysInclude = (typeDef->mIsAlwaysInclude) || (typeDef->mProject->mAlwaysIncludeAll);
|
||||||
|
auto typeOptions = mContext->mScratchModule->GetTypeOptions(typeDef);
|
||||||
|
if (typeOptions != NULL)
|
||||||
|
isAlwaysInclude = typeOptions->Apply(isAlwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);
|
||||||
|
|
||||||
|
if (isAlwaysInclude)
|
||||||
{
|
{
|
||||||
auto requiredType = mContext->mScratchModule->ResolveTypeDef(typeDef);
|
auto requiredType = mContext->mScratchModule->ResolveTypeDef(typeDef);
|
||||||
if (requiredType != NULL)
|
if (requiredType != NULL)
|
||||||
|
|
|
@ -1896,10 +1896,14 @@ void BfContext::UpdateRevisedTypes()
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mSIMDSetting);
|
workspaceConfigHashCtx.Mixin(typeOptions.mSIMDSetting);
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mOptimizationLevel);
|
workspaceConfigHashCtx.Mixin(typeOptions.mOptimizationLevel);
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mEmitDebugInfo);
|
workspaceConfigHashCtx.Mixin(typeOptions.mEmitDebugInfo);
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mRuntimeChecks);
|
workspaceConfigHashCtx.Mixin(typeOptions.mAndFlags);
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mInitLocalVariables);
|
workspaceConfigHashCtx.Mixin(typeOptions.mOrFlags);
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mEmitDynamicCastCheck);
|
workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodFilters.size());
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mEmitObjectAccessCheck);
|
for (auto& filter : typeOptions.mReflectMethodFilters)
|
||||||
|
workspaceConfigHashCtx.MixinStr(filter);
|
||||||
|
workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodAttributeFilters.size());
|
||||||
|
for (auto& filter : typeOptions.mReflectMethodAttributeFilters)
|
||||||
|
workspaceConfigHashCtx.MixinStr(filter);
|
||||||
workspaceConfigHashCtx.Mixin(typeOptions.mAllocStackTraceDepth);
|
workspaceConfigHashCtx.Mixin(typeOptions.mAllocStackTraceDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2629,7 +2633,10 @@ void BfContext::TryUnreifyModules()
|
||||||
bool isRequired = false;
|
bool isRequired = false;
|
||||||
for (auto typeInst : module->mOwnedTypeInstances)
|
for (auto typeInst : module->mOwnedTypeInstances)
|
||||||
{
|
{
|
||||||
if ((typeInst->mTypeDef->mIsAlwaysInclude) || (typeInst->mTypeDef->IsGlobalsContainer()))
|
if (typeInst->mTypeDef->IsGlobalsContainer())
|
||||||
|
isRequired = true;
|
||||||
|
|
||||||
|
if (typeInst->IsAlwaysInclude())
|
||||||
isRequired = true;
|
isRequired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3341,7 +3341,7 @@ BfCheckedKind BfModule::GetDefaultCheckedKind()
|
||||||
bool runtimeChecks = mCompiler->mOptions.mRuntimeChecks;
|
bool runtimeChecks = mCompiler->mOptions.mRuntimeChecks;
|
||||||
auto typeOptions = GetTypeOptions();
|
auto typeOptions = GetTypeOptions();
|
||||||
if (typeOptions != NULL)
|
if (typeOptions != NULL)
|
||||||
runtimeChecks = BfTypeOptions::Apply(runtimeChecks, typeOptions->mRuntimeChecks);
|
runtimeChecks = typeOptions->Apply(runtimeChecks, BfOptionFlags_RuntimeChecks);
|
||||||
return runtimeChecks ? BfCheckedKind_Checked : BfCheckedKind_Unchecked;
|
return runtimeChecks ? BfCheckedKind_Checked : BfCheckedKind_Unchecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4738,6 +4738,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
||||||
typeFlags |= BfTypeFlags_Union;
|
typeFlags |= BfTypeFlags_Union;
|
||||||
if (type->IsDelegate())
|
if (type->IsDelegate())
|
||||||
typeFlags |= BfTypeFlags_Delegate;
|
typeFlags |= BfTypeFlags_Delegate;
|
||||||
|
if (type->IsFunction())
|
||||||
|
typeFlags |= BfTypeFlags_Function;
|
||||||
if (type->WantsGCMarking())
|
if (type->WantsGCMarking())
|
||||||
typeFlags |= BfTypeFlags_WantsMarking;
|
typeFlags |= BfTypeFlags_WantsMarking;
|
||||||
|
|
||||||
|
@ -4839,7 +4841,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
||||||
// Reserve position
|
// Reserve position
|
||||||
mTypeDataRefs[typeInstance] = BfIRValue();
|
mTypeDataRefs[typeInstance] = BfIRValue();
|
||||||
|
|
||||||
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
|
if (typeInstance->IsReified())
|
||||||
|
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
|
||||||
|
|
||||||
BfTypeDef* typeDef = typeInstance->mTypeDef;
|
BfTypeDef* typeDef = typeInstance->mTypeDef;
|
||||||
StringT<128> mangledName;
|
StringT<128> mangledName;
|
||||||
|
@ -6198,12 +6201,14 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
||||||
if ((typeInstance->IsTypedPrimitive()) || (typeInstance->IsBoxed()))
|
if ((typeInstance->IsTypedPrimitive()) || (typeInstance->IsBoxed()))
|
||||||
{
|
{
|
||||||
underlyingType = typeInstance->GetUnderlyingType()->mTypeId;
|
underlyingType = typeInstance->GetUnderlyingType()->mTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int outerTypeId = 0;
|
int outerTypeId = 0;
|
||||||
auto outerType = mContext->mUnreifiedModule->GetOuterType(typeInstance);
|
auto outerType = mContext->mUnreifiedModule->GetOuterType(typeInstance);
|
||||||
if (outerType != NULL)
|
if (outerType != NULL)
|
||||||
|
{
|
||||||
outerTypeId = outerType->mTypeId;
|
outerTypeId = outerType->mTypeId;
|
||||||
|
}
|
||||||
|
|
||||||
BfIRValue customAttrDataPtr;
|
BfIRValue customAttrDataPtr;
|
||||||
if (customAttrs.size() > 0)
|
if (customAttrs.size() > 0)
|
||||||
|
@ -8753,7 +8758,7 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
|
||||||
bool emitObjectAccessCheck = mCompiler->mOptions.mEmitObjectAccessCheck;
|
bool emitObjectAccessCheck = mCompiler->mOptions.mEmitObjectAccessCheck;
|
||||||
auto typeOptions = GetTypeOptions();
|
auto typeOptions = GetTypeOptions();
|
||||||
if (typeOptions != NULL)
|
if (typeOptions != NULL)
|
||||||
emitObjectAccessCheck = BfTypeOptions::Apply(emitObjectAccessCheck, typeOptions->mEmitObjectAccessCheck);
|
emitObjectAccessCheck = typeOptions->Apply(emitObjectAccessCheck, BfOptionFlags_EmitObjectAccessCheck);
|
||||||
if (!emitObjectAccessCheck)
|
if (!emitObjectAccessCheck)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -8875,7 +8880,7 @@ void BfModule::EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool al
|
||||||
bool emitDynamicCastCheck = mCompiler->mOptions.mEmitDynamicCastCheck;
|
bool emitDynamicCastCheck = mCompiler->mOptions.mEmitDynamicCastCheck;
|
||||||
auto typeOptions = GetTypeOptions();
|
auto typeOptions = GetTypeOptions();
|
||||||
if (typeOptions != NULL)
|
if (typeOptions != NULL)
|
||||||
emitDynamicCastCheck = BfTypeOptions::Apply(emitDynamicCastCheck, typeOptions->mEmitDynamicCastCheck);
|
emitDynamicCastCheck = typeOptions->Apply(emitDynamicCastCheck, BfOptionFlags_EmitDynamicCastCheck);
|
||||||
|
|
||||||
if (emitDynamicCastCheck)
|
if (emitDynamicCastCheck)
|
||||||
{
|
{
|
||||||
|
@ -12715,7 +12720,7 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo
|
||||||
bool initLocalVariables = mCompiler->mOptions.mInitLocalVariables;
|
bool initLocalVariables = mCompiler->mOptions.mInitLocalVariables;
|
||||||
auto typeOptions = GetTypeOptions();
|
auto typeOptions = GetTypeOptions();
|
||||||
if (typeOptions != NULL)
|
if (typeOptions != NULL)
|
||||||
initLocalVariables = BfTypeOptions::Apply(initLocalVariables, typeOptions->mInitLocalVariables);
|
initLocalVariables = typeOptions->Apply(initLocalVariables, BfOptionFlags_InitLocalVariables);
|
||||||
// Local variable inits are implicitly handled in the Beef Backend
|
// Local variable inits are implicitly handled in the Beef Backend
|
||||||
if ((initLocalVariables) && (!IsTargetingBeefBackend()))
|
if ((initLocalVariables) && (!IsTargetingBeefBackend()))
|
||||||
{
|
{
|
||||||
|
@ -18448,6 +18453,7 @@ BfMethodDef* BfModule::GetLocalMethodDef(BfLocalMethod* localMethod)
|
||||||
if (methodDeclaration != NULL)
|
if (methodDeclaration != NULL)
|
||||||
{
|
{
|
||||||
BfDefBuilder defBuilder(mCompiler->mSystem);
|
BfDefBuilder defBuilder(mCompiler->mSystem);
|
||||||
|
defBuilder.mCurSource = localMethod->mMethodDeclaration->GetParser();
|
||||||
defBuilder.mPassInstance = mCompiler->mPassInstance;
|
defBuilder.mPassInstance = mCompiler->mPassInstance;
|
||||||
defBuilder.mCurTypeDef = mCurMethodInstance->mMethodDef->mDeclaringType;
|
defBuilder.mCurTypeDef = mCurMethodInstance->mMethodDef->mDeclaringType;
|
||||||
|
|
||||||
|
|
|
@ -1603,6 +1603,7 @@ public:
|
||||||
void MarkDerivedDirty(BfTypeInstance* typeInst);
|
void MarkDerivedDirty(BfTypeInstance* typeInst);
|
||||||
void CheckAddFailType();
|
void CheckAddFailType();
|
||||||
bool PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
bool PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
||||||
|
BfTypeOptions* GetTypeOptions(BfTypeDef* typeDef);
|
||||||
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();
|
||||||
|
|
|
@ -1234,6 +1234,245 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfTypeOptions* BfModule::GetTypeOptions(BfTypeDef* typeDef)
|
||||||
|
{
|
||||||
|
if (mContext->mSystem->mTypeOptions.size() == 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<int> matchedIndices;
|
||||||
|
|
||||||
|
if (!mCompiler->mAttributeTypeOptionMap.IsEmpty())
|
||||||
|
{
|
||||||
|
auto customAttributes = typeDef->mTypeDeclaration->mAttributes;
|
||||||
|
|
||||||
|
while (customAttributes != NULL)
|
||||||
|
{
|
||||||
|
if (!mCompiler->mAttributeTypeOptionMap.IsEmpty())
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
|
||||||
|
|
||||||
|
auto typeRef = customAttributes->mAttributeTypeRef;
|
||||||
|
|
||||||
|
// StringT<128> attrName;
|
||||||
|
// for (auto& customAttrs : customAttributes->mAttributeTypeRef)
|
||||||
|
// {
|
||||||
|
// attrName.Clear();
|
||||||
|
// customAttrs.mType->mTypeDef->mFullName.ToString(attrName);
|
||||||
|
// Array<int>* arrPtr;
|
||||||
|
// if (mCompiler->mAttributeTypeOptionMap.TryGetValue(attrName, &arrPtr))
|
||||||
|
// {
|
||||||
|
// for (auto optionsIdx : *arrPtr)
|
||||||
|
// {
|
||||||
|
// matchedIndices.Add(optionsIdx);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
customAttributes = customAttributes->mNextAttribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int typeOptionsCount = (int)mContext->mSystem->mTypeOptions.size();
|
||||||
|
|
||||||
|
auto _CheckTypeName = [&](const StringImpl& typeName)
|
||||||
|
{
|
||||||
|
for (int optionIdx = 0; optionIdx < (int)mContext->mSystem->mTypeOptions.size(); optionIdx++)
|
||||||
|
{
|
||||||
|
auto& typeOptions = mContext->mSystem->mTypeOptions[optionIdx];
|
||||||
|
|
||||||
|
bool matched = false;
|
||||||
|
for (auto& filter : typeOptions.mTypeFilters)
|
||||||
|
{
|
||||||
|
int filterIdx = 0;
|
||||||
|
int typeNameIdx = 0;
|
||||||
|
|
||||||
|
const char* filterPtr = filter.c_str();
|
||||||
|
const char* namePtr = typeName.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched)
|
||||||
|
matchedIndices.push_back(optionIdx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// if (typeInstance->IsTypedPrimitive())
|
||||||
|
// {
|
||||||
|
// auto underlyingType = typeInstance->GetUnderlyingType();
|
||||||
|
// if (underlyingType != NULL)
|
||||||
|
// {
|
||||||
|
// String typeName = TypeToString(underlyingType);
|
||||||
|
// _CheckTypeName(typeName);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // Can this only happen for functions that are being extended?
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if ((!typeInstance->IsBoxed()) && (typeInstance->mTypeDef == mCompiler->mPointerTTypeDef))
|
||||||
|
// {
|
||||||
|
// BF_ASSERT(typeInstance->IsGenericTypeInstance());
|
||||||
|
// auto innerType = typeInstance->mGenericTypeInfo->mTypeGenericArguments[0];
|
||||||
|
// auto ptrType = CreatePointerType(innerType);
|
||||||
|
// String typeName = TypeToString(ptrType);
|
||||||
|
// _CheckTypeName(typeName);
|
||||||
|
// }
|
||||||
|
|
||||||
|
String typeName = BfTypeUtils::TypeToString(typeDef);
|
||||||
|
_CheckTypeName(typeName);
|
||||||
|
|
||||||
|
int matchedIdx = -1;
|
||||||
|
if (matchedIndices.size() == 1)
|
||||||
|
{
|
||||||
|
matchedIdx = matchedIndices[0];
|
||||||
|
}
|
||||||
|
else if (matchedIndices.size() > 1)
|
||||||
|
{
|
||||||
|
// Try to find a merged typeoptions with these indices
|
||||||
|
for (int mergedIdx = 0; mergedIdx < (int)mContext->mSystem->mMergedTypeOptions.size(); mergedIdx++)
|
||||||
|
{
|
||||||
|
auto& typeOptions = mContext->mSystem->mMergedTypeOptions[mergedIdx];
|
||||||
|
if (typeOptions.mMatchedIndices == matchedIndices)
|
||||||
|
{
|
||||||
|
matchedIdx = typeOptionsCount + mergedIdx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise make one...
|
||||||
|
if (matchedIdx == -1)
|
||||||
|
{
|
||||||
|
auto& first = mContext->mSystem->mTypeOptions[matchedIndices[0]];
|
||||||
|
BfTypeOptions mergedTypeOptions;
|
||||||
|
mergedTypeOptions.mSIMDSetting = first.mSIMDSetting;
|
||||||
|
mergedTypeOptions.mOptimizationLevel = first.mOptimizationLevel;
|
||||||
|
mergedTypeOptions.mEmitDebugInfo = first.mEmitDebugInfo;
|
||||||
|
mergedTypeOptions.mAndFlags = first.mAndFlags;
|
||||||
|
mergedTypeOptions.mOrFlags = first.mOrFlags;
|
||||||
|
mergedTypeOptions.mAllocStackTraceDepth = first.mAllocStackTraceDepth;
|
||||||
|
mergedTypeOptions.mReflectMethodFilters = first.mReflectMethodFilters;
|
||||||
|
mergedTypeOptions.mReflectMethodAttributeFilters = first.mReflectMethodAttributeFilters;
|
||||||
|
|
||||||
|
mergedTypeOptions.mMatchedIndices = matchedIndices;
|
||||||
|
for (int idx = 1; idx < (int)matchedIndices.size(); idx++)
|
||||||
|
{
|
||||||
|
auto& typeOptions = mContext->mSystem->mTypeOptions[matchedIndices[idx]];
|
||||||
|
if (typeOptions.mSIMDSetting != -1)
|
||||||
|
mergedTypeOptions.mSIMDSetting = typeOptions.mSIMDSetting;
|
||||||
|
if (typeOptions.mOptimizationLevel != -1)
|
||||||
|
mergedTypeOptions.mOptimizationLevel = typeOptions.mOptimizationLevel;
|
||||||
|
if (typeOptions.mEmitDebugInfo != -1)
|
||||||
|
mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo;
|
||||||
|
|
||||||
|
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags | typeOptions.mOrFlags);
|
||||||
|
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | typeOptions.mOrFlags);
|
||||||
|
|
||||||
|
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags & typeOptions.mAndFlags);
|
||||||
|
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & typeOptions.mAndFlags);
|
||||||
|
|
||||||
|
if (typeOptions.mAllocStackTraceDepth != -1)
|
||||||
|
mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth;
|
||||||
|
for (auto filter : typeOptions.mReflectMethodFilters)
|
||||||
|
mergedTypeOptions.mReflectMethodFilters.Add(filter);
|
||||||
|
for (auto filter : typeOptions.mReflectMethodAttributeFilters)
|
||||||
|
mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter);
|
||||||
|
}
|
||||||
|
matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size();
|
||||||
|
mContext->mSystem->mMergedTypeOptions.push_back(mergedTypeOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mSystem->GetTypeOptions( matchedIdx);
|
||||||
|
}
|
||||||
|
|
||||||
int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName)
|
int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName)
|
||||||
{
|
{
|
||||||
if (mContext->mSystem->mTypeOptions.size() == 0)
|
if (mContext->mSystem->mTypeOptions.size() == 0)
|
||||||
|
@ -1379,14 +1618,14 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matched)
|
if (matched)
|
||||||
matchedIndices.push_back(optionIdx);
|
matchedIndices.push_back(optionIdx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeInstance->IsTypedPrimitive())
|
if (typeInstance->IsTypedPrimitive())
|
||||||
{
|
{
|
||||||
auto underlyingType = typeInstance->GetUnderlyingType();
|
auto underlyingType = typeInstance->GetUnderlyingType();
|
||||||
if (underlyingType != NULL)
|
if (underlyingType != NULL)
|
||||||
{
|
{
|
||||||
String typeName = TypeToString(underlyingType);
|
String typeName = TypeToString(underlyingType);
|
||||||
_CheckTypeName(typeName);
|
_CheckTypeName(typeName);
|
||||||
|
@ -1407,7 +1646,7 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
|
||||||
}
|
}
|
||||||
|
|
||||||
String typeName = TypeToString(typeInstance);
|
String typeName = TypeToString(typeInstance);
|
||||||
_CheckTypeName(typeName);
|
_CheckTypeName(typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
int matchedIdx = -1;
|
int matchedIdx = -1;
|
||||||
|
@ -1436,11 +1675,11 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
|
||||||
mergedTypeOptions.mSIMDSetting = first.mSIMDSetting;
|
mergedTypeOptions.mSIMDSetting = first.mSIMDSetting;
|
||||||
mergedTypeOptions.mOptimizationLevel = first.mOptimizationLevel;
|
mergedTypeOptions.mOptimizationLevel = first.mOptimizationLevel;
|
||||||
mergedTypeOptions.mEmitDebugInfo = first.mEmitDebugInfo;
|
mergedTypeOptions.mEmitDebugInfo = first.mEmitDebugInfo;
|
||||||
mergedTypeOptions.mRuntimeChecks = first.mRuntimeChecks;
|
mergedTypeOptions.mAndFlags = first.mAndFlags;
|
||||||
mergedTypeOptions.mInitLocalVariables = first.mInitLocalVariables;
|
mergedTypeOptions.mOrFlags = first.mOrFlags;
|
||||||
mergedTypeOptions.mEmitDynamicCastCheck = first.mEmitDynamicCastCheck;
|
mergedTypeOptions.mAllocStackTraceDepth = first.mAllocStackTraceDepth;
|
||||||
mergedTypeOptions.mEmitObjectAccessCheck = first.mEmitObjectAccessCheck;
|
mergedTypeOptions.mReflectMethodFilters = first.mReflectMethodFilters;
|
||||||
mergedTypeOptions.mAllocStackTraceDepth = first.mAllocStackTraceDepth;
|
mergedTypeOptions.mReflectMethodAttributeFilters = first.mReflectMethodAttributeFilters;
|
||||||
|
|
||||||
mergedTypeOptions.mMatchedIndices = matchedIndices;
|
mergedTypeOptions.mMatchedIndices = matchedIndices;
|
||||||
for (int idx = 1; idx < (int)matchedIndices.size(); idx++)
|
for (int idx = 1; idx < (int)matchedIndices.size(); idx++)
|
||||||
|
@ -1452,16 +1691,19 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
|
||||||
mergedTypeOptions.mOptimizationLevel = typeOptions.mOptimizationLevel;
|
mergedTypeOptions.mOptimizationLevel = typeOptions.mOptimizationLevel;
|
||||||
if (typeOptions.mEmitDebugInfo != -1)
|
if (typeOptions.mEmitDebugInfo != -1)
|
||||||
mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo;
|
mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo;
|
||||||
if (typeOptions.mRuntimeChecks != BfOptionalBool_NotSet)
|
|
||||||
mergedTypeOptions.mRuntimeChecks = typeOptions.mRuntimeChecks;
|
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags | typeOptions.mOrFlags);
|
||||||
if (typeOptions.mInitLocalVariables != BfOptionalBool_NotSet)
|
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | typeOptions.mOrFlags);
|
||||||
mergedTypeOptions.mInitLocalVariables = typeOptions.mInitLocalVariables;
|
|
||||||
if (typeOptions.mEmitDynamicCastCheck != BfOptionalBool_NotSet)
|
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags & typeOptions.mAndFlags);
|
||||||
mergedTypeOptions.mEmitDynamicCastCheck = typeOptions.mEmitDynamicCastCheck;
|
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & typeOptions.mAndFlags);
|
||||||
if (typeOptions.mEmitObjectAccessCheck != BfOptionalBool_NotSet)
|
|
||||||
mergedTypeOptions.mEmitObjectAccessCheck = typeOptions.mEmitObjectAccessCheck;
|
|
||||||
if (typeOptions.mAllocStackTraceDepth != -1)
|
if (typeOptions.mAllocStackTraceDepth != -1)
|
||||||
mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth;
|
mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth;
|
||||||
|
for (auto filter : typeOptions.mReflectMethodFilters)
|
||||||
|
mergedTypeOptions.mReflectMethodFilters.Add(filter);
|
||||||
|
for (auto filter : typeOptions.mReflectMethodAttributeFilters)
|
||||||
|
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);
|
||||||
|
@ -1880,6 +2122,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
{
|
{
|
||||||
BfTypeReference* mTypeRef;
|
BfTypeReference* mTypeRef;
|
||||||
BfTypeInstance* mGenericType;
|
BfTypeInstance* mGenericType;
|
||||||
|
bool mIgnoreErrors;
|
||||||
};
|
};
|
||||||
Array<_DeferredValidate> deferredTypeValidateList;
|
Array<_DeferredValidate> deferredTypeValidateList;
|
||||||
|
|
||||||
|
@ -1930,7 +2173,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
{
|
{
|
||||||
// Specialized type variations don't need to validate their constraints
|
// Specialized type variations don't need to validate their constraints
|
||||||
if (!typeInstance->IsUnspecializedTypeVariation())
|
if (!typeInstance->IsUnspecializedTypeVariation())
|
||||||
deferredTypeValidateList.Add({ checkTypeRef, genericTypeInst });
|
deferredTypeValidateList.Add({ checkTypeRef, genericTypeInst, false });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto checkTypeInst = checkType->ToTypeInstance();
|
auto checkTypeInst = checkType->ToTypeInstance();
|
||||||
|
@ -2077,8 +2320,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
{
|
{
|
||||||
if ((genericTypeInst->IsSpecializedType()) && (!genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints) && (!typeInstance->IsBoxed()))
|
if ((genericTypeInst->IsSpecializedType()) && (!genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints) && (!typeInstance->IsBoxed()))
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, true);
|
deferredTypeValidateList.Add({ NULL, genericTypeInst, true });
|
||||||
ValidateGenericConstraints(NULL, genericTypeInst, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2086,15 +2328,14 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
{
|
{
|
||||||
BfType* outerType = GetOuterType(typeInstance);
|
BfType* outerType = GetOuterType(typeInstance);
|
||||||
if (outerType != NULL)
|
if (outerType != NULL)
|
||||||
|
{
|
||||||
|
PopulateType(outerType, BfPopulateType_BaseType);
|
||||||
AddDependency(outerType, typeInstance, BfDependencyMap::DependencyFlag_OuterType);
|
AddDependency(outerType, typeInstance, BfDependencyMap::DependencyFlag_OuterType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((baseTypeInst != NULL) && (typeInstance->mBaseType == NULL))
|
if ((baseTypeInst != NULL) && (typeInstance->mBaseType == NULL))
|
||||||
{
|
{
|
||||||
//curFieldDataIdx = 1;
|
|
||||||
// if (!typeInstance->mTypeFailed)
|
|
||||||
// PopulateType(baseTypeInst, BfPopulateType_Data);
|
|
||||||
|
|
||||||
if (typeInstance->mTypeFailed)
|
if (typeInstance->mTypeFailed)
|
||||||
{
|
{
|
||||||
if (baseTypeInst->IsDataIncomplete())
|
if (baseTypeInst->IsDataIncomplete())
|
||||||
|
@ -2217,6 +2458,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
|
|
||||||
for (auto& validateEntry : deferredTypeValidateList)
|
for (auto& validateEntry : deferredTypeValidateList)
|
||||||
{
|
{
|
||||||
|
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, mIgnoreErrors | validateEntry.mIgnoreErrors);
|
||||||
ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
|
ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8564,6 +8806,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
resolvedEntry->mValue = delegateType;
|
resolvedEntry->mValue = delegateType;
|
||||||
|
|
||||||
AddDependency(directTypeRef->mType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
AddDependency(directTypeRef->mType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
||||||
|
if (delegateInfo->mFunctionThisType != NULL)
|
||||||
|
AddDependency(delegateInfo->mFunctionThisType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
||||||
for (auto paramType : paramTypes)
|
for (auto paramType : paramTypes)
|
||||||
AddDependency(paramType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
AddDependency(paramType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
|
||||||
|
|
||||||
|
|
|
@ -6936,7 +6936,7 @@ BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target,
|
||||||
return invocationExpr;
|
return invocationExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfInitializerExpression * BfReducer::TryCreateInitializerExpression(BfExpression* target)
|
BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfExpression* target)
|
||||||
{
|
{
|
||||||
auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
|
auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
|
||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
|
|
|
@ -1909,6 +1909,17 @@ void BfTypeInstance::GenerateProjectsReferenced()
|
||||||
BfTypeUtils::GetProjectList(genericArgType, &mGenericTypeInfo->mProjectsReferenced, 0);
|
BfTypeUtils::GetProjectList(genericArgType, &mGenericTypeInfo->mProjectsReferenced, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfTypeInstance::IsAlwaysInclude()
|
||||||
|
{
|
||||||
|
bool alwaysInclude = mTypeDef->mIsAlwaysInclude || mTypeDef->mProject->mAlwaysIncludeAll;
|
||||||
|
if (mTypeOptionsIdx > 0)
|
||||||
|
{
|
||||||
|
auto typeOptions = mModule->mSystem->GetTypeOptions(mTypeOptionsIdx);
|
||||||
|
typeOptions->Apply(alwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);
|
||||||
|
}
|
||||||
|
return alwaysInclude;
|
||||||
|
}
|
||||||
|
|
||||||
bool BfTypeInstance::IsSpecializedByAutoCompleteMethod()
|
bool BfTypeInstance::IsSpecializedByAutoCompleteMethod()
|
||||||
{
|
{
|
||||||
if (mGenericTypeInfo == NULL)
|
if (mGenericTypeInfo == NULL)
|
||||||
|
|
|
@ -1878,6 +1878,7 @@ public:
|
||||||
bool GetResultInfo(BfType*& valueType, int& okTagId);
|
bool GetResultInfo(BfType*& valueType, int& okTagId);
|
||||||
BfGenericTypeInfo::GenericParamsVector* GetGenericParamsVector(BfTypeDef* declaringTypeDef);
|
BfGenericTypeInfo::GenericParamsVector* GetGenericParamsVector(BfTypeDef* declaringTypeDef);
|
||||||
void GenerateProjectsReferenced();
|
void GenerateProjectsReferenced();
|
||||||
|
bool IsAlwaysInclude();
|
||||||
|
|
||||||
virtual void ReportMemory(MemReporter* memReporter) override;
|
virtual void ReportMemory(MemReporter* memReporter) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6412,7 +6412,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
||||||
bool boundsCheck = mCompiler->mOptions.mRuntimeChecks;
|
bool boundsCheck = mCompiler->mOptions.mRuntimeChecks;
|
||||||
auto typeOptions = GetTypeOptions();
|
auto typeOptions = GetTypeOptions();
|
||||||
if (typeOptions != NULL)
|
if (typeOptions != NULL)
|
||||||
boundsCheck = BfTypeOptions::Apply(boundsCheck, typeOptions->mRuntimeChecks);
|
boundsCheck = typeOptions->Apply(boundsCheck, BfOptionFlags_RuntimeChecks);
|
||||||
|
|
||||||
BfMethodMatcher methodMatcher(forEachStmt->mVariableName, this, "get__", argValues.mResolvedArgs, NULL);
|
BfMethodMatcher methodMatcher(forEachStmt->mVariableName, this, "get__", argValues.mResolvedArgs, NULL);
|
||||||
methodMatcher.mMethodType = BfMethodType_PropertyGetter;
|
methodMatcher.mMethodType = BfMethodType_PropertyGetter;
|
||||||
|
|
|
@ -3617,51 +3617,57 @@ BF_EXPORT void BF_CALLTYPE BfSystem_ClearTypeOptions(BfSystem* bfSystem)
|
||||||
bfSystem->mTypeOptions.Clear();
|
bfSystem->mTypeOptions.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_EXPORT void BF_CALLTYPE BfSystem_AddTypeOptions(BfSystem* bfSystem, char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 runtimeChecks,
|
BF_EXPORT void BF_CALLTYPE BfSystem_AddTypeOptions(BfSystem* bfSystem, char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 andFlags, int32 orFlags, int32 allocStackTraceDepth, char* reflectMethodFilter)
|
||||||
int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth)
|
|
||||||
{
|
{
|
||||||
AutoCrit autoCrit(bfSystem->mDataLock);
|
AutoCrit autoCrit(bfSystem->mDataLock);
|
||||||
BfTypeOptions typeOptions;
|
BfTypeOptions typeOptions;
|
||||||
|
|
||||||
String filterStr = filter;
|
auto _ParseFilters = [&](char* filter, Array<String>& filters, Array<String>& attributeFilters)
|
||||||
int idx = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
int semiIdx = (int)filterStr.IndexOf(';', idx);
|
String filterStr = filter;
|
||||||
String newFilter;
|
int idx = 0;
|
||||||
if (semiIdx == -1)
|
while (true)
|
||||||
newFilter = filterStr.Substring(idx);
|
|
||||||
else
|
|
||||||
newFilter = filterStr.Substring(idx, semiIdx - idx);
|
|
||||||
newFilter.Trim();
|
|
||||||
if (!newFilter.IsEmpty())
|
|
||||||
{
|
{
|
||||||
if (newFilter.StartsWith('['))
|
int semiIdx = (int)filterStr.IndexOf(';', idx);
|
||||||
{
|
String newFilter;
|
||||||
newFilter.Remove(0);
|
if (semiIdx == -1)
|
||||||
if (newFilter.EndsWith(']'))
|
newFilter = filterStr.Substring(idx);
|
||||||
newFilter.Remove(newFilter.length() - 1);
|
|
||||||
newFilter.Trim();
|
|
||||||
typeOptions.mAttributeFilters.Add(newFilter);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
typeOptions.mTypeFilters.Add(newFilter);
|
newFilter = filterStr.Substring(idx, semiIdx - idx);
|
||||||
}
|
newFilter.Trim();
|
||||||
|
if (!newFilter.IsEmpty())
|
||||||
|
{
|
||||||
|
if (newFilter.StartsWith('['))
|
||||||
|
{
|
||||||
|
newFilter.Remove(0);
|
||||||
|
if (newFilter.EndsWith(']'))
|
||||||
|
newFilter.Remove(newFilter.length() - 1);
|
||||||
|
newFilter.Trim();
|
||||||
|
attributeFilters.Add(newFilter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
filters.Add(newFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semiIdx == -1)
|
||||||
|
break;
|
||||||
|
idx = semiIdx + 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_ParseFilters(filter, typeOptions.mTypeFilters, typeOptions.mAttributeFilters);
|
||||||
|
|
||||||
if (semiIdx == -1)
|
|
||||||
break;
|
|
||||||
idx = semiIdx + 1;
|
|
||||||
}
|
|
||||||
if ((typeOptions.mTypeFilters.IsEmpty()) && (typeOptions.mAttributeFilters.IsEmpty()))
|
if ((typeOptions.mTypeFilters.IsEmpty()) && (typeOptions.mAttributeFilters.IsEmpty()))
|
||||||
return;
|
return;
|
||||||
typeOptions.mSIMDSetting = simdSetting;
|
typeOptions.mSIMDSetting = simdSetting;
|
||||||
typeOptions.mOptimizationLevel = optimizationLevel;
|
typeOptions.mOptimizationLevel = optimizationLevel;
|
||||||
typeOptions.mEmitDebugInfo = emitDebugInfo;
|
typeOptions.mEmitDebugInfo = emitDebugInfo;
|
||||||
typeOptions.mRuntimeChecks = (BfOptionalBool)runtimeChecks;
|
typeOptions.mAndFlags = (BfOptionFlags)andFlags;
|
||||||
typeOptions.mInitLocalVariables = (BfOptionalBool)initLocalVariables;
|
typeOptions.mOrFlags = (BfOptionFlags)orFlags;
|
||||||
typeOptions.mEmitDynamicCastCheck = (BfOptionalBool)emitDynamicCastCheck;
|
|
||||||
typeOptions.mEmitObjectAccessCheck = (BfOptionalBool)emitObjectAccessCheck;
|
|
||||||
typeOptions.mAllocStackTraceDepth = allocStackTraceDepth;
|
typeOptions.mAllocStackTraceDepth = allocStackTraceDepth;
|
||||||
|
|
||||||
|
_ParseFilters(reflectMethodFilter, typeOptions.mReflectMethodFilters, typeOptions.mReflectMethodAttributeFilters);
|
||||||
|
|
||||||
bfSystem->mTypeOptions.push_back(typeOptions);
|
bfSystem->mTypeOptions.push_back(typeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,8 @@ enum BfTypeFlags
|
||||||
//
|
//
|
||||||
BfTypeFlags_WantsMarking = 0x8000,
|
BfTypeFlags_WantsMarking = 0x8000,
|
||||||
BfTypeFlags_Delegate = 0x10000,
|
BfTypeFlags_Delegate = 0x10000,
|
||||||
BfTypeFlags_HasDestructor = 0x20000,
|
BfTypeFlags_Function = 0x20000,
|
||||||
|
BfTypeFlags_HasDestructor = 0x40000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfObjectFlags : uint8
|
enum BfObjectFlags : uint8
|
||||||
|
@ -1267,11 +1268,23 @@ public:
|
||||||
void WriteErrorSummary();
|
void WriteErrorSummary();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfOptionalBool
|
enum BfOptionFlags
|
||||||
{
|
{
|
||||||
BfOptionalBool_NotSet = -1,
|
BfOptionFlags_None = 0,
|
||||||
BfOptionalBool_False = 0,
|
BfOptionFlags_RuntimeChecks = 1,
|
||||||
BfOptionalBool_True = 1
|
BfOptionFlags_InitLocalVariables = 2,
|
||||||
|
BfOptionFlags_EmitDynamicCastCheck = 4,
|
||||||
|
BfOptionFlags_EmitObjectAccessCheck = 8,
|
||||||
|
|
||||||
|
BfOptionFlags_ReflectAlwaysIncludeType = 0x10,
|
||||||
|
BfOptionFlags_ReflectAlwaysIncludeAll = 0x20,
|
||||||
|
BfOptionFlags_ReflectAssumeInstantiated = 0x40,
|
||||||
|
BfOptionFlags_ReflectStaticFields = 0x80,
|
||||||
|
BfOptionFlags_ReflectNonStaticFields = 0x100,
|
||||||
|
BfOptionFlags_ReflectStaticMethods = 0x200,
|
||||||
|
BfOptionFlags_ReflectNonStaticMethods = 0x400,
|
||||||
|
BfOptionFlags_ReflectConstructors = 0x800,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfTypeOptions
|
class BfTypeOptions
|
||||||
|
@ -1283,10 +1296,10 @@ public:
|
||||||
int mSIMDSetting;
|
int mSIMDSetting;
|
||||||
int mOptimizationLevel;
|
int mOptimizationLevel;
|
||||||
int mEmitDebugInfo;
|
int mEmitDebugInfo;
|
||||||
BfOptionalBool mRuntimeChecks;
|
BfOptionFlags mAndFlags;
|
||||||
BfOptionalBool mInitLocalVariables;
|
BfOptionFlags mOrFlags;
|
||||||
BfOptionalBool mEmitDynamicCastCheck;
|
Array<String> mReflectMethodFilters;
|
||||||
BfOptionalBool mEmitObjectAccessCheck;
|
Array<String> mReflectMethodAttributeFilters;
|
||||||
int mAllocStackTraceDepth;
|
int mAllocStackTraceDepth;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1295,13 +1308,14 @@ public:
|
||||||
if (applyVal != -1)
|
if (applyVal != -1)
|
||||||
return applyVal;
|
return applyVal;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Apply(bool val, BfOptionalBool applyVal)
|
bool Apply(bool val, BfOptionFlags flags)
|
||||||
{
|
{
|
||||||
if (applyVal != BfOptionalBool_NotSet)
|
if (val)
|
||||||
return applyVal == BfOptionalBool_True;
|
return (mAndFlags & flags) != 0;
|
||||||
return val;
|
else
|
||||||
|
return (mOrFlags & flags) != 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,20 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Singleton<T> where T : Singleton<T>
|
||||||
|
{
|
||||||
|
public static T mInstance;
|
||||||
|
|
||||||
|
protected this()
|
||||||
|
{
|
||||||
|
mInstance = (T)this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassC : Singleton<ClassC>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void DoDispose<T>(mut T val) where T : IDisposable
|
static void DoDispose<T>(mut T val) where T : IDisposable
|
||||||
{
|
{
|
||||||
val.Dispose();
|
val.Dispose();
|
||||||
|
@ -119,6 +133,9 @@ namespace Tests
|
||||||
Test.Assert(MethodA("") == 1);
|
Test.Assert(MethodA("") == 1);
|
||||||
Test.Assert(MethodA(1.2f) == 2);
|
Test.Assert(MethodA(1.2f) == 2);
|
||||||
Test.Assert(MethodA(TypeCode.Boolean) == 3);
|
Test.Assert(MethodA(TypeCode.Boolean) == 3);
|
||||||
|
|
||||||
|
ClassC cc = scope .();
|
||||||
|
Test.Assert(ClassC.mInstance == cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue