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:
parent
8bc5d09787
commit
2932fceae4
7 changed files with 114 additions and 29 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue