- make PClass not inherit from PStruct.

Having these two types related can cause problems with detection in the compiler because for some parts they need quite different handling.
Common handling for the fields has been moved into PSymbolTable but overall redundancy was quite minor as both types share surprisingly little functionality.
This commit is contained in:
Christoph Oelckers 2017-04-12 17:21:13 +02:00
parent 0d7b7d6ab1
commit 96631e8808
12 changed files with 221 additions and 237 deletions

View File

@ -438,17 +438,17 @@ PBasicType::PBasicType(unsigned int size, unsigned int align)
IMPLEMENT_CLASS(PCompoundType, true, false) IMPLEMENT_CLASS(PCompoundType, true, false)
/* PNamedType *************************************************************/ /* PContainerType *************************************************************/
IMPLEMENT_CLASS(PNamedType, true, false) IMPLEMENT_CLASS(PContainerType, true, false)
//========================================================================== //==========================================================================
// //
// PNamedType :: IsMatch // PContainerType :: IsMatch
// //
//========================================================================== //==========================================================================
bool PNamedType::IsMatch(intptr_t id1, intptr_t id2) const bool PContainerType::IsMatch(intptr_t id1, intptr_t id2) const
{ {
const DObject *outer = (const DObject *)id1; const DObject *outer = (const DObject *)id1;
FName name = (ENamedName)(intptr_t)id2; FName name = (ENamedName)(intptr_t)id2;
@ -458,11 +458,11 @@ bool PNamedType::IsMatch(intptr_t id1, intptr_t id2) const
//========================================================================== //==========================================================================
// //
// PNamedType :: GetTypeIDs // PContainerType :: GetTypeIDs
// //
//========================================================================== //==========================================================================
void PNamedType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const void PContainerType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
{ {
id1 = (intptr_t)Outer; id1 = (intptr_t)Outer;
id2 = TypeName; id2 = TypeName;
@ -2280,6 +2280,25 @@ PMap *NewMap(PType *keytype, PType *valuetype)
IMPLEMENT_CLASS(PStruct, false, false) IMPLEMENT_CLASS(PStruct, false, false)
//==========================================================================
//
// WriteFields
//
//==========================================================================
static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields)
{
for (unsigned i = 0; i < fields.Size(); ++i)
{
const PField *field = fields[i];
// Skip fields without or with native serialization
if (!(field->Flags & (VARF_Transient | VARF_Meta)))
{
field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const uint8_t *)addr + field->Offset);
}
}
}
//========================================================================== //==========================================================================
// //
// PStruct - Default Constructor // PStruct - Default Constructor
@ -2299,7 +2318,7 @@ PStruct::PStruct()
//========================================================================== //==========================================================================
PStruct::PStruct(FName name, PTypeBase *outer, bool isnative) PStruct::PStruct(FName name, PTypeBase *outer, bool isnative)
: PNamedType(name, outer) : PContainerType(name, outer)
{ {
mDescriptiveName.Format("%sStruct<%s>", isnative? "Native" : "", name.GetChars()); mDescriptiveName.Format("%sStruct<%s>", isnative? "Native" : "", name.GetChars());
Size = 0; Size = 0;
@ -2365,72 +2384,13 @@ bool PStruct::ReadValue(FSerializer &ar, const char *key, void *addr) const
{ {
if (ar.BeginObject(key)) if (ar.BeginObject(key))
{ {
bool ret = ReadFields(ar, addr); bool ret = Symbols.ReadFields(ar, addr, DescriptiveName());
ar.EndObject(); ar.EndObject();
return ret; return ret;
} }
return false; return false;
} }
//==========================================================================
//
// PStruct :: WriteFields STATIC
//
//==========================================================================
void PStruct::WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields)
{
for (unsigned i = 0; i < fields.Size(); ++i)
{
const PField *field = fields[i];
// Skip fields without or with native serialization
if (!(field->Flags & (VARF_Transient|VARF_Meta)))
{
field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const uint8_t *)addr + field->Offset);
}
}
}
//==========================================================================
//
// PStruct :: ReadFields
//
//==========================================================================
bool PStruct::ReadFields(FSerializer &ar, void *addr) const
{
bool readsomething = false;
bool foundsomething = false;
const char *label;
while ((label = ar.GetKey()))
{
foundsomething = true;
const PSymbol *sym = Symbols.FindSymbol(FName(label, true), true);
if (sym == nullptr)
{
DPrintf(DMSG_ERROR, "Cannot find field %s in %s\n",
label, TypeName.GetChars());
}
else if (!sym->IsKindOf(RUNTIME_CLASS(PField)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n",
label, TypeName.GetChars());
}
else if ((static_cast<const PField *>(sym)->Flags & (VARF_Transient | VARF_Meta)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a serializable field\n",
label, TypeName.GetChars());
}
else
{
readsomething |= static_cast<const PField *>(sym)->Type->ReadValue(ar, nullptr,
(uint8_t *)addr + static_cast<const PField *>(sym)->Offset);
}
}
return readsomething || !foundsomething;
}
//========================================================================== //==========================================================================
// //
// PStruct :: AddField // PStruct :: AddField
@ -2442,25 +2402,8 @@ bool PStruct::ReadFields(FSerializer &ar, void *addr) const
PField *PStruct::AddField(FName name, PType *type, uint32_t flags) PField *PStruct::AddField(FName name, PType *type, uint32_t flags)
{ {
PField *field = new PField(name, type, flags); auto field = Symbols.AddField(name, type, flags, Size, &Align);
if (field != nullptr) Fields.Push(field);
// The new field is added to the end of this struct, alignment permitting.
field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1);
// Enlarge this struct to enclose the new field.
Size = unsigned(field->Offset + type->Size);
// This struct's alignment is the same as the largest alignment of any of
// its fields.
Align = MAX(Align, type->Align);
if (Symbols.AddSymbol(field) == nullptr)
{ // name is already in use
field->Destroy();
return nullptr;
}
Fields.Push(field);
return field; return field;
} }
@ -2699,7 +2642,7 @@ static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void *
key.Format("class:%s", type->TypeName.GetChars()); key.Format("class:%s", type->TypeName.GetChars());
if (ar.BeginObject(key.GetChars())) if (ar.BeginObject(key.GetChars()))
{ {
PStruct::WriteFields(ar, addr, type->Fields); WriteFields(ar, addr, type->Fields);
ar.EndObject(); ar.EndObject();
} }
break; break;
@ -2708,15 +2651,6 @@ static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void *
} }
} }
void PClass::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
if (ar.BeginObject(key))
{
RecurseWriteFields(this, ar, addr);
ar.EndObject();
}
}
// Same as WriteValue, but does not create a new object in the serializer // Same as WriteValue, but does not create a new object in the serializer
// This is so that user variables do not contain unnecessary subblocks. // This is so that user variables do not contain unnecessary subblocks.
void PClass::WriteAllFields(FSerializer &ar, const void *addr) const void PClass::WriteAllFields(FSerializer &ar, const void *addr) const
@ -2726,21 +2660,10 @@ void PClass::WriteAllFields(FSerializer &ar, const void *addr) const
//========================================================================== //==========================================================================
// //
// PClass :: ReadValue // PClass :: ReadAllFields
// //
//========================================================================== //==========================================================================
bool PClass::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
if (ar.BeginObject(key))
{
bool ret = ReadAllFields(ar, addr);
ar.EndObject();
return ret;
}
return true;
}
bool PClass::ReadAllFields(FSerializer &ar, void *addr) const bool PClass::ReadAllFields(FSerializer &ar, void *addr) const
{ {
bool readsomething = false; bool readsomething = false;
@ -2778,7 +2701,7 @@ bool PClass::ReadAllFields(FSerializer &ar, void *addr) const
{ {
if (ar.BeginObject(nullptr)) if (ar.BeginObject(nullptr))
{ {
readsomething |= type->ReadFields(ar, addr); readsomething |= type->Symbols.ReadFields(ar, addr, DescriptiveName());
ar.EndObject(); ar.EndObject();
} }
} }
@ -3358,39 +3281,6 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
return type; return type;
} }
//==========================================================================
//
// PStruct :: AddField
//
// Appends a new metadata field to the end of a struct. Returns either the new field
// or nullptr if a symbol by that name already exists.
//
//==========================================================================
PField *PClass::AddMetaField(FName name, PType *type, uint32_t flags)
{
PField *field = new PField(name, type, flags);
// The new field is added to the end of this struct, alignment permitting.
field->Offset = (MetaSize + (type->Align - 1)) & ~(type->Align - 1);
// Enlarge this struct to enclose the new field.
MetaSize = unsigned(field->Offset + type->Size);
// This struct's alignment is the same as the largest alignment of any of
// its fields.
Align = MAX(Align, type->Align);
if (Symbols.AddSymbol(field) == nullptr)
{ // name is already in use
field->Destroy();
return nullptr;
}
Fields.Push(field);
return field;
}
//========================================================================== //==========================================================================
// //
// PClass :: AddField // PClass :: AddField
@ -3399,10 +3289,11 @@ PField *PClass::AddMetaField(FName name, PType *type, uint32_t flags)
PField *PClass::AddField(FName name, PType *type, uint32_t flags) PField *PClass::AddField(FName name, PType *type, uint32_t flags)
{ {
PField *field;
if (!(flags & VARF_Meta)) if (!(flags & VARF_Meta))
{ {
unsigned oldsize = Size; unsigned oldsize = Size;
PField *field = Super::AddField(name, type, flags); field = Symbols.AddField(name, type, flags, Size);
// Only initialize the defaults if they have already been created. // Only initialize the defaults if they have already been created.
// For ZScript this is not the case, it will first define all fields before // For ZScript this is not the case, it will first define all fields before
@ -3412,23 +3303,42 @@ PField *PClass::AddField(FName name, PType *type, uint32_t flags)
Defaults = (uint8_t *)M_Realloc(Defaults, Size); Defaults = (uint8_t *)M_Realloc(Defaults, Size);
memset(Defaults + oldsize, 0, Size - oldsize); memset(Defaults + oldsize, 0, Size - oldsize);
} }
return field;
} }
else else
{ {
// Same as above, but a different data storage.
unsigned oldsize = MetaSize; unsigned oldsize = MetaSize;
PField *field = AddMetaField(name, type, flags); field = Symbols.AddField(name, type, flags, MetaSize);
// Only initialize the defaults if they have already been created.
// For ZScript this is not the case, it will first define all fields before
// setting up any defaults for any class.
if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr) if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr)
{ {
Meta = (uint8_t *)M_Realloc(Meta, MetaSize); Meta = (uint8_t *)M_Realloc(Meta, MetaSize);
memset(Meta + oldsize, 0, MetaSize - oldsize); memset(Meta + oldsize, 0, MetaSize - oldsize);
} }
return field;
} }
if (field != nullptr) Fields.Push(field);
return field;
}
//==========================================================================
//
// PClass :: AddNativeField
//
// This looks the same as the struct version but that will change later.
//
//==========================================================================
PField *PClass::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue)
{
PField *field = new PField(name, type, flags | VARF_Native | VARF_Transient, address, bitvalue);
if (Symbols.AddSymbol(field) == nullptr)
{ // name is already in use
field->Destroy();
return nullptr;
}
Fields.Push(field);
return field;
} }
//========================================================================== //==========================================================================

View File

@ -216,22 +216,24 @@ class PCompoundType : public PType
DECLARE_ABSTRACT_CLASS(PCompoundType, PType); DECLARE_ABSTRACT_CLASS(PCompoundType, PType);
}; };
class PNamedType : public PCompoundType class PContainerType : public PCompoundType
{ {
DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType); DECLARE_ABSTRACT_CLASS(PContainerType, PCompoundType);
public: public:
PTypeBase *Outer; // object this type is contained within PTypeBase *Outer; // object this type is contained within
FName TypeName; // this type's name FName TypeName; // this type's name
PNamedType() : Outer(NULL) { PContainerType() : Outer(NULL) {
mDescriptiveName = "NamedType"; mDescriptiveName = "NamedType";
} }
PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) { PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {
mDescriptiveName = name.GetChars(); mDescriptiveName = name.GetChars();
} }
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
virtual PField *AddField(FName name, PType *type, uint32_t flags = 0) = 0;
virtual PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0) = 0;
}; };
// Basic types -------------------------------------------------------------- // Basic types --------------------------------------------------------------
@ -537,9 +539,9 @@ protected:
PMap(); PMap();
}; };
class PStruct : public PNamedType class PStruct : public PContainerType
{ {
DECLARE_CLASS(PStruct, PNamedType); DECLARE_CLASS(PStruct, PContainerType);
public: public:
PStruct(FName name, PTypeBase *outer, bool isnative = false); PStruct(FName name, PTypeBase *outer, bool isnative = false);
@ -558,8 +560,6 @@ public:
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override; void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override; void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FSerializer &ar, void *addr) const;
protected: protected:
PStruct(); PStruct();
}; };
@ -588,20 +588,17 @@ enum
TentativeClass = UINT_MAX, TentativeClass = UINT_MAX,
}; };
class PClass : public PStruct class PClass : public PContainerType
{ {
DECLARE_CLASS(PClass, PStruct); DECLARE_CLASS(PClass, PContainerType);
// We unravel _WITH_META here just as we did for PType. // We unravel _WITH_META here just as we did for PType.
protected: protected:
TArray<FTypeAndOffset> MetaInits; TArray<FTypeAndOffset> MetaInits;
void Derive(PClass *newclass, FName name); void Derive(PClass *newclass, FName name);
void InitializeSpecials(void *addr, void *defaults, TArray<FTypeAndOffset> PClass::*Inits); void InitializeSpecials(void *addr, void *defaults, TArray<FTypeAndOffset> PClass::*Inits);
void SetSuper(); void SetSuper();
PField *AddMetaField(FName name, PType *type, uint32_t flags);
public: public:
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
void WriteAllFields(FSerializer &ar, const void *addr) const; void WriteAllFields(FSerializer &ar, const void *addr) const;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
bool ReadAllFields(FSerializer &ar, void *addr) const; bool ReadAllFields(FSerializer &ar, void *addr) const;
void InitializeDefaults(); void InitializeDefaults();
int FindVirtualIndex(FName name, PPrototype *proto); int FindVirtualIndex(FName name, PPrototype *proto);
@ -625,6 +622,7 @@ public:
bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility
TArray<VMFunction*> Virtuals; // virtual function table TArray<VMFunction*> Virtuals; // virtual function table
FName SourceLumpName; FName SourceLumpName;
TArray<PField *> Fields;
void (*ConstructNative)(void *); void (*ConstructNative)(void *);
@ -635,6 +633,8 @@ public:
DObject *CreateNew(); DObject *CreateNew();
PClass *CreateDerivedClass(FName name, unsigned int size); PClass *CreateDerivedClass(FName name, unsigned int size);
PField *AddField(FName name, PType *type, uint32_t flags=0) override; PField *AddField(FName name, PType *type, uint32_t flags=0) override;
PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0) override;
void InitializeActorInfo(); void InitializeActorInfo();
void BuildFlatPointers(); void BuildFlatPointers();
void BuildArrayPointers(); void BuildArrayPointers();

View File

@ -114,7 +114,7 @@ FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret
if (fnc != nullptr) Class = fnc->OwningClass; if (fnc != nullptr) Class = fnc->OwningClass;
} }
FCompileContext::FCompileContext(PNamespace *cg, PStruct *cls, bool fromdecorate) FCompileContext::FCompileContext(PNamespace *cg, PContainerType *cls, bool fromdecorate)
: ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1), CurGlobals(cg)
{ {
} }
@ -200,14 +200,14 @@ FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name)
} }
} }
static PStruct *FindStructType(FName name, FCompileContext &ctx) static PContainerType *FindContainerType(FName name, FCompileContext &ctx)
{ {
auto sym = ctx.Class->Symbols.FindSymbol(name, true); auto sym = ctx.Class->Symbols.FindSymbol(name, true);
if (sym == nullptr) sym = ctx.CurGlobals->Symbols.FindSymbol(name, true); if (sym == nullptr) sym = ctx.CurGlobals->Symbols.FindSymbol(name, true);
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{ {
auto type = static_cast<PSymbolType*>(sym); auto type = static_cast<PSymbolType*>(sym);
return dyn_cast<PStruct>(type->Type); return dyn_cast<PContainerType>(type->Type);
} }
return nullptr; return nullptr;
} }
@ -224,7 +224,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx)
return nullptr; return nullptr;
} }
bool isActor(PStruct *type) bool isActor(PContainerType *type)
{ {
auto cls = dyn_cast<PClass>(type); auto cls = dyn_cast<PClass>(type);
return cls ? cls->IsDescendantOf(RUNTIME_CLASS(AActor)) : false; return cls ? cls->IsDescendantOf(RUNTIME_CLASS(AActor)) : false;
@ -6121,7 +6121,7 @@ foundit:
// //
//========================================================================== //==========================================================================
FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classctx, FxExpression *&object, PStruct *objtype) FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *classctx, FxExpression *&object, PContainerType *objtype)
{ {
PSymbol *sym; PSymbol *sym;
PSymbolTable *symtbl; PSymbolTable *symtbl;
@ -6269,7 +6269,7 @@ FxMemberIdentifier::~FxMemberIdentifier()
FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
{ {
PStruct *ccls = nullptr; PContainerType *ccls = nullptr;
CHECKRESOLVED(); CHECKRESOLVED();
if (Object->ExprType == EFX_Identifier) if (Object->ExprType == EFX_Identifier)
@ -6277,7 +6277,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
auto id = static_cast<FxIdentifier *>(Object)->Identifier; auto id = static_cast<FxIdentifier *>(Object)->Identifier;
// If the left side is a class name for a static member function call it needs to be resolved manually // If the left side is a class name for a static member function call it needs to be resolved manually
// because the resulting value type would cause problems in nearly every other place where identifiers are being used. // because the resulting value type would cause problems in nearly every other place where identifiers are being used.
ccls = FindStructType(id, ctx); ccls = FindContainerType(id, ctx);
if (ccls != nullptr) if (ccls != nullptr)
{ {
static_cast<FxIdentifier *>(Object)->noglobal = true; static_cast<FxIdentifier *>(Object)->noglobal = true;
@ -6398,9 +6398,9 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{ {
auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType; auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType)))
{ {
auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PStruct *>(ptype)); auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PContainerType *>(ptype));
delete this; delete this;
return ret; return ret;
} }
@ -7023,7 +7023,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{ {
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType); PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType);
if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PStruct))) if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PContainerType)))
{ {
ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object"); ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object");
delete this; delete this;
@ -7925,12 +7925,12 @@ FxMemberFunctionCall::~FxMemberFunctionCall()
FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
{ {
PStruct *cls; PContainerType *cls = nullptr;
bool staticonly = false; bool staticonly = false;
bool novirtual = false; bool novirtual = false;
bool isreadonly = false; bool isreadonly = false;
PStruct *ccls = nullptr; PContainerType *ccls = nullptr;
if (ctx.Class == nullptr) if (ctx.Class == nullptr)
{ {
@ -7957,7 +7957,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
// because the resulting value type would cause problems in nearly every other place where identifiers are being used. // because the resulting value type would cause problems in nearly every other place where identifiers are being used.
// [ZZ] substitute ccls for String internal type. // [ZZ] substitute ccls for String internal type.
if (id == NAME_String) ccls = TypeStringStruct; if (id == NAME_String) ccls = TypeStringStruct;
else ccls = FindStructType(id, ctx); else ccls = FindContainerType(id, ctx);
if (ccls != nullptr) static_cast<FxIdentifier *>(Self)->noglobal = true; if (ccls != nullptr) static_cast<FxIdentifier *>(Self)->noglobal = true;
} }
@ -8228,7 +8228,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
{ {
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType; auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType)))
{ {
if (ptype->IsKindOf(RUNTIME_CLASS(PClass)) && MethodName == NAME_GetClass) if (ptype->IsKindOf(RUNTIME_CLASS(PClass)) && MethodName == NAME_GetClass)
{ {
@ -8243,7 +8243,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
} }
cls = static_cast<PStruct *>(ptype); cls = static_cast<PContainerType *>(ptype);
} }
else else
{ {
@ -8825,9 +8825,9 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested. ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr) if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr)
{ {
if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(type)->IsA(RUNTIME_CLASS(PStruct))) if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(type)->PointedType->IsA(RUNTIME_CLASS(PStruct)))
{ {
// trying to pass a struct reference as a struct refg // trying to pass a struct reference as a struct reference. This must preserve the type.
} }
else else
{ {

View File

@ -78,7 +78,7 @@ struct FCompileContext
FxCompoundStatement *Block = nullptr; FxCompoundStatement *Block = nullptr;
PPrototype *ReturnProto; PPrototype *ReturnProto;
PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.)
PStruct *Class; // The type of the owning class. PContainerType *Class; // The type of the owning class.
bool FromDecorate; // DECORATE must silence some warnings and demote some errors. bool FromDecorate; // DECORATE must silence some warnings and demote some errors.
int StateIndex; // index in actor's state table for anonymous functions, otherwise -1 (not used by DECORATE which pre-resolves state indices) int StateIndex; // index in actor's state table for anonymous functions, otherwise -1 (not used by DECORATE which pre-resolves state indices)
int StateCount; // amount of states an anoymous function is being used on (must be 1 for state indices to be allowed.) int StateCount; // amount of states an anoymous function is being used on (must be 1 for state indices to be allowed.)
@ -90,7 +90,7 @@ struct FCompileContext
FString VersionString; FString VersionString;
FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver); FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver);
FCompileContext(PNamespace *spc, PStruct *cls, bool fromdecorate); // only to be used to resolve constants! FCompileContext(PNamespace *spc, PContainerType *cls, bool fromdecorate); // only to be used to resolve constants!
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt);
@ -373,7 +373,7 @@ public:
FxIdentifier(FName i, const FScriptPosition &p); FxIdentifier(FName i, const FScriptPosition &p);
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
FxExpression *ResolveMember(FCompileContext&, PStruct*, FxExpression*&, PStruct*); FxExpression *ResolveMember(FCompileContext&, PContainerType*, FxExpression*&, PContainerType*);
}; };

View File

@ -36,6 +36,8 @@
#include <float.h> #include <float.h>
#include "dobject.h" #include "dobject.h"
#include "i_system.h" #include "i_system.h"
#include "templates.h"
#include "serializer.h"
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -102,7 +104,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray<uint32_t> &argflags, TA
assert(proto->ArgumentTypes.Size() > 0); assert(proto->ArgumentTypes.Size() > 0);
auto selftypeptr = dyn_cast<PPointer>(proto->ArgumentTypes[0]); auto selftypeptr = dyn_cast<PPointer>(proto->ArgumentTypes[0]);
assert(selftypeptr != nullptr); assert(selftypeptr != nullptr);
variant.SelfClass = dyn_cast<PStruct>(selftypeptr->PointedType); variant.SelfClass = dyn_cast<PContainerType>(selftypeptr->PointedType);
assert(variant.SelfClass != nullptr); assert(variant.SelfClass != nullptr);
} }
else else
@ -238,6 +240,78 @@ PSymbol *PSymbolTable::AddSymbol (PSymbol *sym)
// //
//========================================================================== //==========================================================================
PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align)
{
PField *field = new PField(name, type, flags);
// The new field is added to the end of this struct, alignment permitting.
field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1);
// Enlarge this struct to enclose the new field.
Size = unsigned(field->Offset + type->Size);
// This struct's alignment is the same as the largest alignment of any of
// its fields.
if (Align != nullptr)
{
*Align = MAX(*Align, type->Align);
}
if (AddSymbol(field) == nullptr)
{ // name is already in use
field->Destroy();
return nullptr;
}
return field;
}
//==========================================================================
//
// PClass :: ReadFields
//
// This will need some changes later.
//==========================================================================
bool PSymbolTable::ReadFields(FSerializer &ar, void *addr, const char *TypeName) const
{
bool readsomething = false;
bool foundsomething = false;
const char *label;
while ((label = ar.GetKey()))
{
foundsomething = true;
const PSymbol *sym = FindSymbol(FName(label, true), false);
if (sym == nullptr)
{
DPrintf(DMSG_ERROR, "Cannot find field %s in %s\n",
label, TypeName);
}
else if (!sym->IsKindOf(RUNTIME_CLASS(PField)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n",
label, TypeName);
}
else if ((static_cast<const PField *>(sym)->Flags & (VARF_Transient | VARF_Meta)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a serializable field\n",
label, TypeName);
}
else
{
readsomething |= static_cast<const PField *>(sym)->Type->ReadValue(ar, nullptr,
(uint8_t *)addr + static_cast<const PField *>(sym)->Offset);
}
}
return readsomething || !foundsomething;
}
//==========================================================================
//
//
//
//==========================================================================
void PSymbolTable::RemoveSymbol(PSymbol *sym) void PSymbolTable::RemoveSymbol(PSymbol *sym)
{ {
auto mysym = Symbols.CheckKey(sym->SymbolName); auto mysym = Symbols.CheckKey(sym->SymbolName);
@ -387,7 +461,7 @@ void RemoveUnusedSymbols()
{ {
for (PType *ty = TypeTable.TypeHash[i]; ty != nullptr; ty = ty->HashNext) for (PType *ty = TypeTable.TypeHash[i]; ty != nullptr; ty = ty->HashNext)
{ {
if (ty->IsKindOf(RUNTIME_CLASS(PStruct))) if (ty->IsKindOf(RUNTIME_CLASS(PContainerType)))
{ {
auto it = ty->Symbols.GetIterator(); auto it = ty->Symbols.GetIterator();
PSymbolTable::MapType::Pair *pair; PSymbolTable::MapType::Pair *pair;

View File

@ -10,7 +10,7 @@ class VMFunction;
class PType; class PType;
class PPrototype; class PPrototype;
struct ZCC_TreeNode; struct ZCC_TreeNode;
class PStruct; class PContainerType;
// Symbol information ------------------------------------------------------- // Symbol information -------------------------------------------------------
@ -175,15 +175,15 @@ public:
TArray<FName> ArgNames; // we need the names to access them later when the function gets compiled. TArray<FName> ArgNames; // we need the names to access them later when the function gets compiled.
uint32_t Flags; uint32_t Flags;
int UseFlags; int UseFlags;
PStruct *SelfClass; PContainerType *SelfClass;
}; };
TArray<Variant> Variants; TArray<Variant> Variants;
PStruct *OwningClass = nullptr; PContainerType *OwningClass = nullptr;
unsigned AddVariant(PPrototype *proto, TArray<uint32_t> &argflags, TArray<FName> &argnames, VMFunction *impl, int flags, int useflags); unsigned AddVariant(PPrototype *proto, TArray<uint32_t> &argflags, TArray<FName> &argnames, VMFunction *impl, int flags, int useflags);
int GetImplicitArgs(); int GetImplicitArgs();
PFunction(PStruct *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {} PFunction(PContainerType *owner = nullptr, FName name = NAME_None) : PSymbol(name), OwningClass(owner) {}
}; };
// A symbol table ----------------------------------------------------------- // A symbol table -----------------------------------------------------------
@ -215,6 +215,8 @@ struct PSymbolTable
// a symbol with the same name is already in the table. This symbol is // a symbol with the same name is already in the table. This symbol is
// not copied and will be freed when the symbol table is destroyed. // not copied and will be freed when the symbol table is destroyed.
PSymbol *AddSymbol (PSymbol *sym); PSymbol *AddSymbol (PSymbol *sym);
PField *AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align = nullptr);
bool ReadFields(FSerializer &ar, void *addr, const char *TypeName) const;
// Similar to AddSymbol but always succeeds. Returns the symbol that used // Similar to AddSymbol but always succeeds. Returns the symbol that used
// to be in the table with this name, if any. // to be in the table with this name, if any.

View File

@ -101,7 +101,7 @@ FScriptPosition & GetStateSource(FState *state)
// //
//========================================================================== //==========================================================================
void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PStruct *cls, uint32_t funcflags, int useflags) void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PContainerType *cls, uint32_t funcflags, int useflags)
{ {
// Must be called before adding any other arguments. // Must be called before adding any other arguments.
assert(args == nullptr || args->Size() == 0); assert(args == nullptr || args->Size() == 0);
@ -154,7 +154,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<F
// //
//========================================================================== //==========================================================================
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags) PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *returntype, int flags)
{ {
TArray<PType *> rets(1); TArray<PType *> rets(1);
TArray<PType *> args; TArray<PType *> args;
@ -184,7 +184,7 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i
// //
//========================================================================== //==========================================================================
PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error) PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error)
{ {
// Skip ACS_NamedExecuteWithResult. Anything calling this should use the builtin instead. // Skip ACS_NamedExecuteWithResult. Anything calling this should use the builtin instead.
if (name == NAME_ACS_NamedExecuteWithResult) return nullptr; if (name == NAME_ACS_NamedExecuteWithResult) return nullptr;

View File

@ -148,8 +148,8 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass)
// //
//========================================================================== //==========================================================================
AFuncDesc *FindFunction(PStruct *cls, const char * string); AFuncDesc *FindFunction(PContainerType *cls, const char * string);
FieldDesc *FindField(PStruct *cls, const char * string); FieldDesc *FindField(PContainerType *cls, const char * string);
FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, PNamespace *resolvenspc = nullptr); FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, PNamespace *resolvenspc = nullptr);
@ -159,9 +159,9 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray<FxExpression
FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, bool &endswithret); FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Baggage &bag, bool &endswithret);
class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag); class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag);
FName CheckCastKludges(FName in); FName CheckCastKludges(FName in);
void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PStruct *cls, uint32_t funcflags, int useflags); void SetImplicitArgs(TArray<PType *> *args, TArray<uint32_t> *argflags, TArray<FName> *argnames, PContainerType *cls, uint32_t funcflags, int useflags);
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *returntype, int flags);
PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error); PFunction *FindClassMemberFunction(PContainerType *cls, PContainerType *funccls, FName name, FScriptPosition &sc, bool *error);
void CreateDamageFunction(PNamespace *ns, const VersionInfo &ver, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum); void CreateDamageFunction(PNamespace *ns, const VersionInfo &ver, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum);
//========================================================================== //==========================================================================

View File

@ -667,7 +667,7 @@ static int CompareClassNames(const Desc& a, const Desc& b)
// //
//========================================================================== //==========================================================================
AFuncDesc *FindFunction(PStruct *cls, const char * string) AFuncDesc *FindFunction(PContainerType *cls, const char * string)
{ {
int min = 0, max = AFTable.Size() - 1; int min = 0, max = AFTable.Size() - 1;
@ -698,7 +698,7 @@ AFuncDesc *FindFunction(PStruct *cls, const char * string)
// //
//========================================================================== //==========================================================================
FieldDesc *FindField(PStruct *cls, const char * string) FieldDesc *FindField(PContainerType *cls, const char * string)
{ {
int min = 0, max = FieldTable.Size() - 1; int min = 0, max = FieldTable.Size() - 1;
const char * cname = cls ? cls->TypeName.GetChars() : ""; const char * cname = cls ? cls->TypeName.GetChars() : "";

View File

@ -75,7 +75,7 @@ const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx)
return AST.Strings.Alloc(static_cast<FxConstant*>(ex)->GetValue().GetString())->GetChars(); return AST.Strings.Alloc(static_cast<FxConstant*>(ex)->GetValue().GetString())->GetChars();
} }
int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls) int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls)
{ {
FCompileContext ctx(OutNamespace, cls, false); FCompileContext ctx(OutNamespace, cls, false);
FxExpression *ex = new FxIntCast(ConvertNode(node), false); FxExpression *ex = new FxIntCast(ConvertNode(node), false);
@ -89,7 +89,7 @@ int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls)
return static_cast<FxConstant*>(ex)->GetValue().GetInt(); return static_cast<FxConstant*>(ex)->GetValue().GetInt();
} }
FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PStruct *cls) FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls)
{ {
FCompileContext ctx(OutNamespace, cls, false); FCompileContext ctx(OutNamespace, cls, false);
FxExpression *ex = new FxStringCast(ConvertNode(node)); FxExpression *ex = new FxStringCast(ConvertNode(node));
@ -641,7 +641,7 @@ void ZCCCompiler::CreateClassTypes()
{ {
Error(c->cls, "Class name %s already exists", c->NodeName().GetChars()); Error(c->cls, "Class name %s already exists", c->NodeName().GetChars());
} }
else DPrintf(DMSG_SPAMMY, "Created class %s with parent %s\n", c->Type()->TypeName.GetChars(), c->Type()->ParentClass->TypeName.GetChars()); else DPrintf(DMSG_SPAMMY, "Created class %s with parent %s\n", c->Type()->TypeName.GetChars(), c->ClassType()->ParentClass->TypeName.GetChars());
} }
catch (CRecoverableError &err) catch (CRecoverableError &err)
{ {
@ -689,7 +689,7 @@ void ZCCCompiler::CreateClassTypes()
c->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ObjectFlags, FScopeBarrier::Side_Play); c->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ObjectFlags, FScopeBarrier::Side_Play);
} }
c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.) c->ClassType()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.)
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
OutNamespace->Symbols.AddSymbol(c->cls->Symbol); OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
Classes.Push(c); Classes.Push(c);
@ -746,7 +746,7 @@ void ZCCCompiler::CreateClassTypes()
// Link the tree node tables. We only can do this after we know the class relations. // Link the tree node tables. We only can do this after we know the class relations.
for (auto cc : Classes) for (auto cc : Classes)
{ {
if (cc->Type() == cd->Type()->ParentClass) if (cc->ClassType() == cd->ClassType()->ParentClass)
{ {
cd->TreeNodes.SetParentTable(&cc->TreeNodes); cd->TreeNodes.SetParentTable(&cc->TreeNodes);
break; break;
@ -769,7 +769,7 @@ void ZCCCompiler::CreateClassTypes()
// //
//========================================================================== //==========================================================================
void ZCCCompiler::CopyConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PStruct *cls, PSymbolTable *ot) void ZCCCompiler::CopyConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PContainerType *cls, PSymbolTable *ot)
{ {
for (auto c : Constants) for (auto c : Constants)
{ {
@ -1155,7 +1155,7 @@ void ZCCCompiler::CompileAllFields()
} }
for (unsigned i = 0; i < Classes.Size(); i++) for (unsigned i = 0; i < Classes.Size(); i++)
{ {
auto type = Classes[i]->Type(); auto type = Classes[i]->ClassType();
if (type->Size == TentativeClass) if (type->Size == TentativeClass)
{ {
@ -1167,7 +1167,7 @@ void ZCCCompiler::CompileAllFields()
else else
{ {
// Inherit the size of the parent class // Inherit the size of the parent class
type->Size = Classes[i]->Type()->ParentClass->Size; type->Size = Classes[i]->ClassType()->ParentClass->Size;
} }
} }
if (type->TypeName == NAME_Actor) if (type->TypeName == NAME_Actor)
@ -1175,8 +1175,8 @@ void ZCCCompiler::CompileAllFields()
assert(type->MetaSize == 0); assert(type->MetaSize == 0);
AddActorInfo(type); // AActor needs the actor info manually added to its meta data before adding any scripted fields. AddActorInfo(type); // AActor needs the actor info manually added to its meta data before adding any scripted fields.
} }
else if (Classes[i]->Type()->ParentClass) else if (Classes[i]->ClassType()->ParentClass)
type->MetaSize = Classes[i]->Type()->ParentClass->MetaSize; type->MetaSize = Classes[i]->ClassType()->ParentClass->MetaSize;
else else
type->MetaSize = 0; type->MetaSize = 0;
@ -1207,7 +1207,7 @@ void ZCCCompiler::CompileAllFields()
// //
//========================================================================== //==========================================================================
bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren) bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren)
{ {
while (Fields.Size() > 0) while (Fields.Size() > 0)
{ {
@ -1372,7 +1372,7 @@ void ZCCCompiler::CompileAllProperties()
for (auto c : Classes) for (auto c : Classes)
{ {
if (c->Properties.Size() > 0) if (c->Properties.Size() > 0)
CompileProperties(c->Type(), c->Properties, c->Type()->TypeName); CompileProperties(c->ClassType(), c->Properties, c->Type()->TypeName);
} }
} }
@ -1727,7 +1727,7 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo
// //
//========================================================================== //==========================================================================
PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PStruct *cls) PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls)
{ {
TArray<ZCC_Expression *> indices; TArray<ZCC_Expression *> indices;
@ -2189,28 +2189,26 @@ void ZCCCompiler::InitDefaults()
for (auto c : Classes) for (auto c : Classes)
{ {
// This may be removed if the conditions change, but right now only subclasses of Actor can define a Default block. // This may be removed if the conditions change, but right now only subclasses of Actor can define a Default block.
if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor))) if (!c->ClassType()->IsDescendantOf(RUNTIME_CLASS(AActor)))
{ {
if (c->Defaults.Size()) Error(c->cls, "%s: Non-actor classes may not have defaults", c->Type()->TypeName.GetChars()); if (c->Defaults.Size()) Error(c->cls, "%s: Non-actor classes may not have defaults", c->Type()->TypeName.GetChars());
if (c->Type()->ParentClass) if (c->ClassType()->ParentClass)
{ {
auto ti = static_cast<PClassActor *>(c->Type()); auto ti = static_cast<PClassActor *>(c->ClassType());
FString mename = ti->TypeName.GetChars();
ti->InitializeDefaults(); ti->InitializeDefaults();
} }
} }
else else
{ {
// This should never happen. // This should never happen.
if (c->Type()->Defaults != nullptr) if (c->ClassType()->Defaults != nullptr)
{ {
Error(c->cls, "%s already has defaults", c->Type()->TypeName.GetChars()); Error(c->cls, "%s already has defaults", c->Type()->TypeName.GetChars());
} }
// This can only occur if a native parent is not initialized. In all other cases the sorting of the class list should prevent this from ever happening. // This can only occur if a native parent is not initialized. In all other cases the sorting of the class list should prevent this from ever happening.
else if (c->Type()->ParentClass->Defaults == nullptr && c->Type() != RUNTIME_CLASS(AActor)) else if (c->ClassType()->ParentClass->Defaults == nullptr && c->ClassType() != RUNTIME_CLASS(AActor))
{ {
Error(c->cls, "Parent class %s of %s is not initialized", c->Type()->ParentClass->TypeName.GetChars(), c->Type()->TypeName.GetChars()); Error(c->cls, "Parent class %s of %s is not initialized", c->ClassType()->ParentClass->TypeName.GetChars(), c->ClassType()->TypeName.GetChars());
} }
else else
{ {
@ -2295,7 +2293,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
do do
{ {
auto type = DetermineType(c->Type(), f, f->Name, t, false, false); auto type = DetermineType(c->Type(), f, f->Name, t, false, false);
if (type->IsKindOf(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) if (type->IsKindOf(RUNTIME_CLASS(PContainerType)) && type != TypeVector2 && type != TypeVector3)
{ {
// structs and classes only get passed by pointer. // structs and classes only get passed by pointer.
type = NewPointer(type); type = NewPointer(type);
@ -2749,9 +2747,9 @@ void ZCCCompiler::InitFunctions()
for (auto c : Classes) for (auto c : Classes)
{ {
// cannot be done earlier because it requires the parent class to be processed by this code, too. // cannot be done earlier because it requires the parent class to be processed by this code, too.
if (c->Type()->ParentClass != nullptr) if (c->ClassType()->ParentClass != nullptr)
{ {
c->Type()->Virtuals = c->Type()->ParentClass->Virtuals; c->ClassType()->Virtuals = c->ClassType()->ParentClass->Virtuals;
} }
for (auto f : c->Functions) for (auto f : c->Functions)
{ {
@ -2847,7 +2845,7 @@ void ZCCCompiler::CompileStates()
for (auto c : Classes) for (auto c : Classes)
{ {
if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor))) if (!c->ClassType()->IsDescendantOf(RUNTIME_CLASS(AActor)))
{ {
if (c->States.Size()) Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars()); if (c->States.Size()) Error(c->cls, "%s: States can only be defined for actors.", c->Type()->TypeName.GetChars());
continue; continue;
@ -2855,7 +2853,7 @@ void ZCCCompiler::CompileStates()
FString statename; // The state builder wants the label as one complete string, not separated into tokens. FString statename; // The state builder wants the label as one complete string, not separated into tokens.
FStateDefinitions statedef; FStateDefinitions statedef;
statedef.MakeStateDefines(ValidateActor(c->Type()->ParentClass)); statedef.MakeStateDefines(ValidateActor(c->ClassType()->ParentClass));
int numframes = 0; int numframes = 0;
for (auto s : c->States) for (auto s : c->States)
@ -3050,7 +3048,7 @@ void ZCCCompiler::CompileStates()
} }
try try
{ {
GetDefaultByType(c->Type())->Finalize(statedef); GetDefaultByType(c->ClassType())->Finalize(statedef);
} }
catch (CRecoverableError &err) catch (CRecoverableError &err)
{ {
@ -3065,7 +3063,7 @@ void ZCCCompiler::CompileStates()
// //
//========================================================================== //==========================================================================
FxExpression *ZCCCompiler::ConvertAST(PStruct *cls, ZCC_TreeNode *ast) FxExpression *ZCCCompiler::ConvertAST(PContainerType *cls, ZCC_TreeNode *ast)
{ {
ConvertClass = cls; ConvertClass = cls;
// there are two possibilities here: either a single function call or a compound statement. For a compound statement we also need to check if the last thing added was a return. // there are two possibilities here: either a single function call or a compound statement. For a compound statement we also need to check if the last thing added was a return.

View File

@ -41,7 +41,7 @@ struct ZCC_StructWork
return strct->NodeName; return strct->NodeName;
} }
PStruct *Type() PContainerType *Type()
{ {
return strct->Type; return strct->Type;
} }
@ -64,7 +64,7 @@ struct ZCC_ClassWork : public ZCC_StructWork
Outer = nullptr; Outer = nullptr;
} }
PClass *Type() PClass *ClassType()
{ {
return static_cast<PClass *>(strct->Type); return static_cast<PClass *>(strct->Type);
} }
@ -79,7 +79,7 @@ struct ZCC_PropertyWork
struct ZCC_ConstantWork struct ZCC_ConstantWork
{ {
ZCC_ConstantDef *node; ZCC_ConstantDef *node;
PStruct *cls; PContainerType *cls;
PSymbolTable *Outputtable; PSymbolTable *Outputtable;
ExpVal constval; ExpVal constval;
}; };
@ -94,25 +94,25 @@ public:
private: private:
const char * GetStringConst(FxExpression *ex, FCompileContext &ctx); const char * GetStringConst(FxExpression *ex, FCompileContext &ctx);
int IntConstFromNode(ZCC_TreeNode *node, PStruct *cls); int IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls);
FString StringConstFromNode(ZCC_TreeNode *node, PStruct *cls); FString StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls);
void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode);
void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer); void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer);
void CreateStructTypes(); void CreateStructTypes();
void CreateClassTypes(); void CreateClassTypes();
void CopyConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PStruct *cls, PSymbolTable *ot); void CopyConstants(TArray<ZCC_ConstantWork> &dest, TArray<ZCC_ConstantDef*> &Constants, PContainerType *cls, PSymbolTable *ot);
void CompileAllConstants(); void CompileAllConstants();
void AddConstant(ZCC_ConstantWork &constant); void AddConstant(ZCC_ConstantWork &constant);
bool CompileConstant(ZCC_ConstantWork *def); bool CompileConstant(ZCC_ConstantWork *def);
void CompileArrays(ZCC_StructWork *work); void CompileArrays(ZCC_StructWork *work);
void CompileAllFields(); void CompileAllFields();
bool CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false); bool CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false);
void CompileAllProperties(); void CompileAllProperties();
bool CompileProperties(PClass *type, TArray<ZCC_Property *> &Properties, FName prefix); bool CompileProperties(PClass *type, TArray<ZCC_Property *> &Properties, FName prefix);
FString FlagsToString(uint32_t flags); FString FlagsToString(uint32_t flags);
PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember);
PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PStruct *cls); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls);
PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym, bool nativetype);
void InitDefaults(); void InitDefaults();
@ -143,12 +143,12 @@ private:
void Error(ZCC_TreeNode *node, const char *msg, ...) GCCPRINTF(3,4); void Error(ZCC_TreeNode *node, const char *msg, ...) GCCPRINTF(3,4);
void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr); void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr);
FxExpression *ConvertAST(PStruct *cclass, ZCC_TreeNode *ast); FxExpression *ConvertAST(PContainerType *cclass, ZCC_TreeNode *ast);
FxExpression *ConvertNode(ZCC_TreeNode *node); FxExpression *ConvertNode(ZCC_TreeNode *node);
FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head); FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head);
DObject *Outer; DObject *Outer;
PStruct *ConvertClass; // class type to be used when resoving symbols while converting an AST PContainerType *ConvertClass; // class type to be used when resoving symbols while converting an AST
PSymbolTable *GlobalTreeNodes; PSymbolTable *GlobalTreeNodes;
PNamespace *OutNamespace; PNamespace *OutNamespace;
ZCC_AST &AST; ZCC_AST &AST;

View File

@ -195,7 +195,7 @@ struct ZCC_Struct : ZCC_NamedNode
{ {
VM_UWORD Flags; VM_UWORD Flags;
ZCC_TreeNode *Body; ZCC_TreeNode *Body;
PStruct *Type; PContainerType *Type;
VersionInfo Version; VersionInfo Version;
}; };