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

Allow boxed types to utilize comptime methods

This commit is contained in:
Brian Fiete 2021-12-16 07:28:03 -05:00
parent 8bc5d09787
commit 2932fceae4
7 changed files with 114 additions and 29 deletions

View file

@ -892,6 +892,9 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
return; return;
} }
if ((typeInst->IsBoxed()) && (typeInst->mTypeDef->mEmitParent != NULL))
typeInst->mTypeDef = typeInst->mTypeDef->mEmitParent;
if (mSystem->mWorkspaceConfigChanged) if (mSystem->mWorkspaceConfigChanged)
{ {
typeInst->mTypeOptionsIdx = -2; typeInst->mTypeOptionsIdx = -2;
@ -1061,7 +1064,11 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
{ {
auto emitTypeDef = typeInst->mTypeDef; auto emitTypeDef = typeInst->mTypeDef;
typeInst->mTypeDef = emitTypeDef->mEmitParent; typeInst->mTypeDef = emitTypeDef->mEmitParent;
delete emitTypeDef; BfLogSysM("Type %p queueing delete of typeDef %p, resetting typeDef to %p\n", typeInst, emitTypeDef, typeInst->mTypeDef);
emitTypeDef->mDefState = BfTypeDef::DefState_Deleted;
AutoCrit autoCrit(mSystem->mDataLock);
BF_ASSERT(!mSystem->mTypeDefDeleteQueue.Contains(emitTypeDef));
mSystem->mTypeDefDeleteQueue.push_back(emitTypeDef);
} }
//typeInst->mTypeDef->ClearEmitted(); //typeInst->mTypeDef->ClearEmitted();
@ -1911,12 +1918,19 @@ void BfContext::UpdateRevisedTypes()
auto typeDef = typeInst->mTypeDef; auto typeDef = typeInst->mTypeDef;
if (typeDef->mEmitParent != NULL) if (typeDef->mEmitParent != NULL)
{
if (typeDef->mDefState == BfTypeDef::DefState_Deleted)
{
typeInst->mTypeDef = typeDef->mEmitParent;
}
else
{ {
auto emitTypeDef = typeDef; auto emitTypeDef = typeDef;
typeDef = typeDef->mEmitParent; typeDef = typeDef->mEmitParent;
if (typeDef->mNextRevision != NULL) if (typeDef->mNextRevision != NULL)
emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty; emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty;
} }
}
if (typeDef->mProject->mDisabled) if (typeDef->mProject->mDisabled)
{ {

View file

@ -15286,7 +15286,7 @@ void BfModule::AssertErrorState()
{ {
if (mCurTypeInstance->mTypeFailed) if (mCurTypeInstance->mTypeFailed)
return; return;
if ((mCurTypeInstance->mTypeDef->mSource != NULL) && (mCurTypeInstance->mTypeDef->mSource->mParsingFailed)) if ((mCurTypeInstance->mTypeDef->GetDefinition()->mSource != NULL) && (mCurTypeInstance->mTypeDef->GetDefinition()->mSource->mParsingFailed))
return; return;
} }
if (mCurMethodInstance != NULL) if (mCurMethodInstance != NULL)
@ -19763,11 +19763,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
} }
else else
{ {
BF_ASSERT(!innerMethodInstance.mMethodInstance->mMethodDef->mDeclaringType->IsEmitted());
auto innerMethodDef = innerMethodInstance.mMethodInstance->mMethodDef; auto innerMethodDef = innerMethodInstance.mMethodInstance->mMethodDef;
if (innerType->mTypeDef->IsEmitted())
innerMethodDef = innerType->mTypeDef->mEmitParent->mMethods[innerMethodDef->mIdx];
BF_ASSERT(innerMethodDef == methodDef); BF_ASSERT(innerMethodDef == methodDef);
SizedArray<BfIRValue, 8> innerParams; SizedArray<BfIRValue, 8> innerParams;

View file

@ -2747,7 +2747,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize; resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize;
} }
BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mCeTypeInfo != NULL)); BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mCeTypeInfo != NULL) || (typeInstance->IsBoxed()));
typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size()); typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size());
for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++) for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++)
{ {
@ -3702,6 +3702,15 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (innerType->IsIncomplete()) if (innerType->IsIncomplete())
PopulateType(innerType, BfPopulateType_Data); PopulateType(innerType, BfPopulateType_Data);
auto innerTypeInst = innerType->ToTypeInstance();
if ((innerTypeInst != NULL) && (typeInstance->mTypeDef != innerTypeInst->mTypeDef))
{
// Rebuild with proper typedef (generally from inner type comptime emission)
typeInstance->mTypeDef = innerTypeInst->mTypeDef;
DoPopulateType(resolvedTypeRef, populateType);
return;
}
auto baseType = typeInstance->mBaseType; auto baseType = typeInstance->mBaseType;
dataPos = baseType->mInstSize; dataPos = baseType->mInstSize;
int alignSize = BF_MAX(innerType->mAlign, baseType->mInstAlign); int alignSize = BF_MAX(innerType->mAlign, baseType->mInstAlign);
@ -5667,14 +5676,14 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
else else
{ {
auto matchedMethodDef = matchedMethod->mMethodDef; auto matchedMethodDef = matchedMethod->mMethodDef;
if (matchedMethodDef->mDeclaringType->IsEmitted()) // if (matchedMethodDef->mDeclaringType->IsEmitted())
{ // {
Fail("Boxed interface binding error to emitted method", mCurTypeInstance->mTypeDef->GetRefNode()); // Fail("Boxed interface binding error to emitted method", mCurTypeInstance->mTypeDef->GetRefNode());
continue; // continue;
} // }
//
if (underlyingTypeInstance->mTypeDef->IsEmitted()) // if (underlyingTypeInstance->mTypeDef->IsEmitted())
matchedMethodDef = underlyingTypeInstance->mTypeDef->mEmitParent->mMethods[matchedMethodDef->mIdx]; // matchedMethodDef = underlyingTypeInstance->mTypeDef->mEmitParent->mMethods[matchedMethodDef->mIdx];
if (!matchedMethod->mIsForeignMethodDef) if (!matchedMethod->mIsForeignMethodDef)
{ {

View file

@ -1554,6 +1554,7 @@ BfTypeInstance::~BfTypeInstance()
if ((mTypeDef != NULL) && (mTypeDef->mEmitParent != NULL)) if ((mTypeDef != NULL) && (mTypeDef->mEmitParent != NULL))
{ {
mMethodInstanceGroups.Clear(); mMethodInstanceGroups.Clear();
BfLogSys(mModule->mSystem, "Type %p dtor deleting typeDef %p\n", this, mTypeDef);
delete mTypeDef; delete mTypeDef;
} }
} }
@ -2627,6 +2628,12 @@ void BfTupleType::Finish()
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
BfBoxedType::~BfBoxedType()
{
if (mTypeDef->mEmitParent != NULL)
mTypeDef = mTypeDef->mEmitParent;
}
BfType* BfBoxedType::GetModifiedElementType() BfType* BfBoxedType::GetModifiedElementType()
{ {
if ((mBoxedFlags & BoxedFlags_StructPtr) != 0) if ((mBoxedFlags & BoxedFlags_StructPtr) != 0)

View file

@ -2110,6 +2110,7 @@ public:
mBoxedBaseType = NULL; mBoxedBaseType = NULL;
mBoxedFlags = BoxedFlags_None; mBoxedFlags = BoxedFlags_None;
} }
~BfBoxedType();
virtual bool IsBoxed() override { return true; } virtual bool IsBoxed() override { return true; }

View file

@ -793,11 +793,6 @@ BfTypeDef::~BfTypeDef()
{ {
BfLogSysM("BfTypeDef::~BfTypeDef %p\n", this); BfLogSysM("BfTypeDef::~BfTypeDef %p\n", this);
if ((mHash == -1330357811) && (IsEmitted()))
{
NOP;
}
delete mNextRevision; delete mNextRevision;
FreeMembers(); FreeMembers();
@ -3728,11 +3723,15 @@ void BfSystem::RemoveOldData()
{ {
AutoCrit autoCrit(mDataLock); AutoCrit autoCrit(mDataLock);
for (auto typeDef : mTypeDefDeleteQueue) for (int i = 0; i < (int)mTypeDefDeleteQueue.size(); i++)
{
auto typeDef = mTypeDefDeleteQueue[i];
mTypeDefDeleteQueue[i] = NULL;
BfLogSys(this, "RemoveOldData deleting from mTypeDefDeleteQueue %p\n", typeDef);
delete typeDef; delete typeDef;
}
mTypeDefDeleteQueue.Clear(); mTypeDefDeleteQueue.Clear();
if (!mProjectDeleteQueue.IsEmpty()) if (!mProjectDeleteQueue.IsEmpty())
{ {
for (auto project : mProjectDeleteQueue) for (auto project : mProjectDeleteQueue)

View file

@ -175,6 +175,59 @@ namespace Tests
public float mZ; public float mZ;
} }
class SerializationContext
{
public String mStr = new String() ~ delete _;
public void Serialize<T>(String name, T val) where T : struct
{
mStr.AppendF($"{name} {val}\n");
}
}
interface ISerializable
{
void Serialize(SerializationContext ctx);
}
[AttributeUsage(.Enum | .Struct | .Class, .NotInherited | .ReflectAttribute | .DisallowAllowMultiple)]
struct SerializableAttribute : Attribute, IComptimeTypeApply
{
[Comptime]
public void ApplyToType(Type type)
{
const String SERIALIZE_NAME = "void ISerializable.Serialize(SerializationContext ctx)\n";
String serializeBuffer = new .();
Compiler.Assert(!type.IsUnion);
for (let field in type.GetFields())
{
if (!field.IsInstanceField || field.DeclaringType != type)
continue;
serializeBuffer.AppendF($"\n\tctx.Serialize(\"{field.Name}\", {field.Name});");
}
Compiler.EmitTypeBody(type, scope $"{SERIALIZE_NAME}{{{serializeBuffer}\n}}\n");
}
}
[Serializable]
struct Foo : this(float x, float y), ISerializable
{
}
public class ComponentHandler<T>
where T : struct
{
uint8* data;
protected override void GCMarkMembers()
{
T* ptr = (T*)data;
GC.Mark!((*ptr));
}
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -209,6 +262,12 @@ namespace Tests
4 mY 4 mY
8 mZ 8 mZ
"""); """);
Foo bar = .(10, 2);
ISerializable iSer = bar;
SerializationContext serCtx = scope .();
iSer.Serialize(serCtx);
Test.Assert(serCtx.mStr == "x 10\ny 2\n");
} }
} }
} }