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

Improved generic param reflection in comptime

This commit is contained in:
Brian Fiete 2022-01-31 15:41:05 -05:00
parent 157d3f90e5
commit 26506efc1e
9 changed files with 143 additions and 19 deletions

View file

@ -490,6 +490,7 @@ namespace System
static extern Type Comptime_GetTypeById(int32 typeId); static extern Type Comptime_GetTypeById(int32 typeId);
static extern Type Comptime_GetTypeByName(StringView name); static extern Type Comptime_GetTypeByName(StringView name);
static extern String Comptime_Type_ToString(int32 typeId);
static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs); static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeId, void* dataPtr); static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeId, void* dataPtr);
static extern int32 Comptime_GetMethodCount(int32 typeId); static extern int32 Comptime_GetMethodCount(int32 typeId);
@ -556,6 +557,12 @@ namespace System
} }
} }
void ComptimeToString(String strBuffer)
{
if (Compiler.IsComptime)
strBuffer.Append(Comptime_Type_ToString((.)mTypeId));
}
public virtual void GetFullName(String strBuffer) public virtual void GetFullName(String strBuffer)
{ {
GetBasicName(strBuffer); GetBasicName(strBuffer);
@ -1285,6 +1292,23 @@ namespace System.Reflection
} }
} }
[Ordered, AlwaysInclude(AssumeInstantiated=true)]
class GenericParamType : Type
{
public override void GetName(String strBuffer)
{
if (Compiler.IsComptime)
this.[Friend]ComptimeToString(strBuffer);
else
strBuffer.Append("$GenericParam");
}
public override void GetFullName(String strBuffer)
{
GetName(strBuffer);
}
}
public enum TypeFlags : uint32 public enum TypeFlags : uint32
{ {
UnspecializedGeneric = 0x0001, UnspecializedGeneric = 0x0001,

View file

@ -482,6 +482,7 @@ namespace System
static extern Type Comptime_GetTypeById(int32 typeId); static extern Type Comptime_GetTypeById(int32 typeId);
static extern Type Comptime_GetTypeByName(StringView name); static extern Type Comptime_GetTypeByName(StringView name);
static extern String Comptime_Type_ToString(int32 typeId);
static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs); static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeId, void* dataPtr); static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeId, void* dataPtr);
static extern int32 Comptime_GetMethodCount(int32 typeId); static extern int32 Comptime_GetMethodCount(int32 typeId);
@ -548,6 +549,12 @@ namespace System
} }
} }
void ComptimeToString(String strBuffer)
{
if (Compiler.IsComptime)
strBuffer.Append(Comptime_Type_ToString((.)mTypeId));
}
public virtual void GetFullName(String strBuffer) public virtual void GetFullName(String strBuffer)
{ {
GetBasicName(strBuffer); GetBasicName(strBuffer);
@ -1261,6 +1268,23 @@ namespace System.Reflection
} }
} }
[Ordered, AlwaysInclude(AssumeInstantiated=true)]
class GenericParamType : Type
{
public override void GetName(String strBuffer)
{
if (Compiler.IsComptime)
this.[Friend]ComptimeToString(strBuffer);
else
strBuffer.Append("$GenericParam");
}
public override void GetFullName(String strBuffer)
{
GetName(strBuffer);
}
}
public enum TypeFlags : uint32 public enum TypeFlags : uint32
{ {
UnspecializedGeneric = 0x0001, UnspecializedGeneric = 0x0001,

View file

@ -439,6 +439,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mPointerTypeDef = NULL; mPointerTypeDef = NULL;
mReflectTypeIdTypeDef = NULL; mReflectTypeIdTypeDef = NULL;
mReflectArrayType = NULL; mReflectArrayType = NULL;
mReflectGenericParamType = NULL;
mReflectFieldDataDef = NULL; mReflectFieldDataDef = NULL;
mReflectFieldSplatDataDef = NULL; mReflectFieldSplatDataDef = NULL;
mReflectMethodDataDef = NULL; mReflectMethodDataDef = NULL;
@ -1345,6 +1346,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType)); reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType)); reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType)); reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectGenericParamType));
SmallVector<BfIRValue, 256> typeDataVector; SmallVector<BfIRValue, 256> typeDataVector;
for (auto type : vdataTypeList) for (auto type : vdataTypeList)
@ -6835,6 +6837,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mPointerTypeDef = _GetRequiredType("System.Pointer", 0); mPointerTypeDef = _GetRequiredType("System.Pointer", 0);
mReflectTypeIdTypeDef = _GetRequiredType("System.Reflection.TypeId"); mReflectTypeIdTypeDef = _GetRequiredType("System.Reflection.TypeId");
mReflectArrayType = _GetRequiredType("System.Reflection.ArrayType"); mReflectArrayType = _GetRequiredType("System.Reflection.ArrayType");
mReflectGenericParamType = _GetRequiredType("System.Reflection.GenericParamType");
mReflectFieldDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldData"); mReflectFieldDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldData");
mReflectFieldSplatDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldSplatData"); mReflectFieldSplatDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldSplatData");
mReflectMethodDataDef = _GetRequiredType("System.Reflection.TypeInstance.MethodData"); mReflectMethodDataDef = _GetRequiredType("System.Reflection.TypeInstance.MethodData");

View file

@ -398,6 +398,7 @@ public:
BfTypeDef* mPointerTypeDef; BfTypeDef* mPointerTypeDef;
BfTypeDef* mReflectTypeIdTypeDef; BfTypeDef* mReflectTypeIdTypeDef;
BfTypeDef* mReflectArrayType; BfTypeDef* mReflectArrayType;
BfTypeDef* mReflectGenericParamType;
BfTypeDef* mReflectFieldDataDef; BfTypeDef* mReflectFieldDataDef;
BfTypeDef* mReflectFieldSplatDataDef; BfTypeDef* mReflectFieldSplatDataDef;
BfTypeDef* mReflectMethodDataDef; BfTypeDef* mReflectMethodDataDef;

View file

@ -10593,15 +10593,8 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr)
return; return;
} }
if ((type->IsGenericParam()) && (!mModule->mIsComptimeModule))
{
mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(typeType)), typeType);
}
else
{
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
mResult = BfTypedValue(mModule->CreateTypeDataRef(type), typeType); mResult = BfTypedValue(mModule->CreateTypeDataRef(type), typeType);
}
} }
bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifierNode* propName) bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifierNode* propName)

View file

@ -5396,12 +5396,14 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
typeDataSource = ResolveTypeDef(mCompiler->mReflectSizedArrayType)->ToTypeInstance(); typeDataSource = ResolveTypeDef(mCompiler->mReflectSizedArrayType)->ToTypeInstance();
else if (type->IsConstExprValue()) else if (type->IsConstExprValue())
typeDataSource = ResolveTypeDef(mCompiler->mReflectConstExprType)->ToTypeInstance(); typeDataSource = ResolveTypeDef(mCompiler->mReflectConstExprType)->ToTypeInstance();
else if (type->IsGenericParam())
{
typeFlags |= BfTypeFlags_GenericParam;
typeDataSource = ResolveTypeDef(mCompiler->mReflectGenericParamType)->ToTypeInstance();
}
else else
typeDataSource = mContext->mBfTypeType; typeDataSource = mContext->mBfTypeType;
if (type->IsGenericParam())
typeFlags |= BfTypeFlags_GenericParam;
if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type)) if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type))
{ {
CreateTypeData(typeDataSource, usedStringIdMap, false, true, needsTypeNames, true); CreateTypeData(typeDataSource, usedStringIdMap, false, true, needsTypeNames, true);
@ -5636,6 +5638,22 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize); mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType)); typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
} }
else if (type->IsGenericParam())
{
auto genericParamType = (BfGenericParamType*)type;
SizedArray<BfIRValue, 3> genericParamTypeDataParms =
{
typeData
};
auto reflectGenericParamType = ResolveTypeDef(mCompiler->mReflectGenericParamType)->ToTypeInstance();
FixConstValueParams(reflectGenericParamType, genericParamTypeDataParms);
auto genericParamTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectGenericParamType, BfIRPopulateType_Full), genericParamTypeDataParms);
typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectGenericParamType), true,
BfIRLinkageType_External, genericParamTypeData, typeDataName);
mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
}
else else
{ {
typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(mContext->mBfTypeType), true, typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(mContext->mBfTypeType), true,

View file

@ -2913,6 +2913,9 @@ CeContext::CeContext()
mCurFrame = NULL; mCurFrame = NULL;
mCurModule = NULL; mCurModule = NULL;
mCurMethodInstance = NULL; mCurMethodInstance = NULL;
mCallerMethodInstance = NULL;
mCallerTypeInstance = NULL;
mCallerActiveTypeDef = NULL;
mCurExpectingType = NULL; mCurExpectingType = NULL;
mCurEmitContext = NULL; mCurEmitContext = NULL;
} }
@ -2983,18 +2986,20 @@ BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str)
err += " "; err += " ";
} }
auto contextMethodInstance = mCurModule->mCurMethodInstance; auto contextMethodInstance = mCallerMethodInstance;
auto contextTypeInstance = mCallerTypeInstance;
if (stackIdx > 1) if (stackIdx > 1)
{ {
auto func = mCallStack[stackIdx - 1].mFunction; auto func = mCallStack[stackIdx - 1].mFunction;
contextMethodInstance = func->mCeFunctionInfo->mMethodInstance; contextMethodInstance = func->mCeFunctionInfo->mMethodInstance;
contextTypeInstance = contextMethodInstance->GetOwner();
} }
err += StrFormat("in comptime "); err += StrFormat("in comptime ");
// //
{ {
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, (contextMethodInstance != NULL) ? contextMethodInstance->GetOwner() : NULL); SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, contextTypeInstance);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, contextMethodInstance); SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, contextMethodInstance);
if (ceFunction->mMethodInstance != NULL) if (ceFunction->mMethodInstance != NULL)
@ -3033,7 +3038,7 @@ BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str)
void CeContext::FixProjectRelativePath(StringImpl& path) void CeContext::FixProjectRelativePath(StringImpl& path)
{ {
BfProject* activeProject = NULL; BfProject* activeProject = NULL;
auto activeTypeDef = mCurModule->GetActiveTypeDef(); auto activeTypeDef = mCallerActiveTypeDef;
if (activeTypeDef != NULL) if (activeTypeDef != NULL)
activeProject = activeTypeDef->mProject; activeProject = activeTypeDef->mProject;
if (activeProject != NULL) if (activeProject != NULL)
@ -4064,8 +4069,14 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc); SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module); SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance); SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);
SetAndRestoreValue<BfMethodInstance*> prevCallerMethodInstance(mCallerMethodInstance, module->mCurMethodInstance);
SetAndRestoreValue<BfTypeInstance*> prevCallerTypeInstance(mCallerTypeInstance, module->mCurTypeInstance);
SetAndRestoreValue<BfTypeDef*> prevCallerActiveTypeDef(mCallerActiveTypeDef, module->GetActiveTypeDef());
SetAndRestoreValue<BfType*> prevExpectingType(mCurExpectingType, expectingType); SetAndRestoreValue<BfType*> prevExpectingType(mCurExpectingType, expectingType);
SetAndRestoreValue<BfMethodInstance*> moduleCurMethodInstance(module->mCurMethodInstance, methodInstance);
SetAndRestoreValue<BfTypeInstance*> moduleCurTypeInstance(module->mCurTypeInstance, methodInstance->GetOwner());
SetAndRestoreValue<int> prevCurExecuteId(mCurModule->mCompiler->mCurCEExecuteId, mCeMachine->mExecuteId); SetAndRestoreValue<int> prevCurExecuteId(mCurModule->mCompiler->mCurCEExecuteId, mCeMachine->mExecuteId);
// Reentrancy may occur as methods need defining // Reentrancy may occur as methods need defining
@ -4854,6 +4865,23 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
_FixVariables(); _FixVariables();
CeSetAddrVal(stackPtr + 0, reflectType, ptrSize); CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
} }
else if (checkFunction->mFunctionKind == CeFunctionKind_Type_ToString)
{
int32 typeId = *(int32*)((uint8*)stackPtr + ptrSize);
BfType* type = GetBfType(typeId);
bool success = false;
if (type == NULL)
{
_Fail("Invalid type");
return false;
}
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
CeSetAddrVal(stackPtr + 0, GetString(mCeMachine->mCeModule->TypeToString(type)), ptrSize);
_FixVariables();
}
else if (checkFunction->mFunctionKind == CeFunctionKind_Type_GetCustomAttribute) else if (checkFunction->mFunctionKind == CeFunctionKind_Type_GetCustomAttribute)
{ {
int32 typeId = *(int32*)((uint8*)stackPtr + 1); int32 typeId = *(int32*)((uint8*)stackPtr + 1);
@ -7786,6 +7814,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
{ {
ceFunction->mFunctionKind = CeFunctionKind_GetReflectSpecializedType; ceFunction->mFunctionKind = CeFunctionKind_GetReflectSpecializedType;
} }
else if (methodDef->mName == "Comptime_Type_ToString")
{
ceFunction->mFunctionKind = CeFunctionKind_Type_ToString;
}
else if (methodDef->mName == "Comptime_Type_GetCustomAttribute") else if (methodDef->mName == "Comptime_Type_GetCustomAttribute")
{ {
ceFunction->mFunctionKind = CeFunctionKind_Type_GetCustomAttribute; ceFunction->mFunctionKind = CeFunctionKind_Type_GetCustomAttribute;

View file

@ -324,6 +324,7 @@ enum CeFunctionKind
CeFunctionKind_GetReflectTypeById, CeFunctionKind_GetReflectTypeById,
CeFunctionKind_GetReflectTypeByName, CeFunctionKind_GetReflectTypeByName,
CeFunctionKind_GetReflectSpecializedType, CeFunctionKind_GetReflectSpecializedType,
CeFunctionKind_Type_ToString,
CeFunctionKind_Type_GetCustomAttribute, CeFunctionKind_Type_GetCustomAttribute,
CeFunctionKind_GetMethodCount, CeFunctionKind_GetMethodCount,
CeFunctionKind_GetMethod, CeFunctionKind_GetMethod,
@ -867,6 +868,9 @@ public:
Dictionary<int, CeInternalData*> mInternalDataMap; Dictionary<int, CeInternalData*> mInternalDataMap;
int mCurHandleId; int mCurHandleId;
BfMethodInstance* mCallerMethodInstance;
BfTypeInstance* mCallerTypeInstance;
BfTypeDef* mCallerActiveTypeDef;
BfMethodInstance* mCurMethodInstance; BfMethodInstance* mCurMethodInstance;
BfType* mCurExpectingType; BfType* mCurExpectingType;
BfAstNode* mCurTargetSrc; BfAstNode* mCurTargetSrc;

View file

@ -405,6 +405,25 @@ namespace Tests
} }
} }
public struct GetTupleField<TTuple, C> where C : const int
{
public typealias Type = comptype(GetTupleFieldType(typeof(TTuple), C));
[Comptime]
private static Type GetTupleFieldType(Type type, int index)
{
if (type.IsGenericParam)
{
Compiler.Assert(type.IsGenericParam);
String tName = type.GetFullName(.. scope .());
Compiler.Assert(tName == "TTuple");
return typeof(var);
}
Compiler.Assert(type.IsTuple);
return type.GetField(index).Get().FieldType;
}
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -468,6 +487,12 @@ namespace Tests
++idx; ++idx;
} }
Test.Assert(idx == 2); Test.Assert(idx == 2);
var tuple = ((int16)1, 2.3f);
GetTupleField<decltype(tuple), const 0>.Type tupType0;
GetTupleField<decltype(tuple), const 1>.Type tupType1;
Test.Assert(typeof(decltype(tupType0)) == typeof(int16));
Test.Assert(typeof(decltype(tupType1)) == typeof(float));
} }
} }
} }