diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 98274328e..b9ad1e57d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -438,17 +438,17 @@ PBasicType::PBasicType(unsigned int size, unsigned int align) 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; 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; id2 = TypeName; @@ -2280,6 +2280,25 @@ PMap *NewMap(PType *keytype, PType *valuetype) IMPLEMENT_CLASS(PStruct, false, false) +//========================================================================== +// +// WriteFields +// +//========================================================================== + +static void WriteFields(FSerializer &ar, const void *addr, const TArray &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 @@ -2299,7 +2318,7 @@ PStruct::PStruct() //========================================================================== PStruct::PStruct(FName name, PTypeBase *outer, bool isnative) -: PNamedType(name, outer) +: PContainerType(name, outer) { mDescriptiveName.Format("%sStruct<%s>", isnative? "Native" : "", name.GetChars()); Size = 0; @@ -2365,72 +2384,13 @@ bool PStruct::ReadValue(FSerializer &ar, const char *key, void *addr) const { if (ar.BeginObject(key)) { - bool ret = ReadFields(ar, addr); + bool ret = Symbols.ReadFields(ar, addr, DescriptiveName()); ar.EndObject(); return ret; } return false; } -//========================================================================== -// -// PStruct :: WriteFields STATIC -// -//========================================================================== - -void PStruct::WriteFields(FSerializer &ar, const void *addr, const TArray &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(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(sym)->Type->ReadValue(ar, nullptr, - (uint8_t *)addr + static_cast(sym)->Offset); - } - } - return readsomething || !foundsomething; -} - //========================================================================== // // 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 *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. - Align = MAX(Align, type->Align); - - if (Symbols.AddSymbol(field) == nullptr) - { // name is already in use - field->Destroy(); - return nullptr; - } - Fields.Push(field); - + auto field = Symbols.AddField(name, type, flags, Size, &Align); + if (field != nullptr) Fields.Push(field); return field; } @@ -2699,7 +2642,7 @@ static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void * key.Format("class:%s", type->TypeName.GetChars()); if (ar.BeginObject(key.GetChars())) { - PStruct::WriteFields(ar, addr, type->Fields); + WriteFields(ar, addr, type->Fields); ar.EndObject(); } 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 // This is so that user variables do not contain unnecessary subblocks. 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 readsomething = false; @@ -2778,7 +2701,7 @@ bool PClass::ReadAllFields(FSerializer &ar, void *addr) const { if (ar.BeginObject(nullptr)) { - readsomething |= type->ReadFields(ar, addr); + readsomething |= type->Symbols.ReadFields(ar, addr, DescriptiveName()); ar.EndObject(); } } @@ -3358,39 +3281,6 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) 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 @@ -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 *field; if (!(flags & VARF_Meta)) { 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. // 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); memset(Defaults + oldsize, 0, Size - oldsize); } - return field; } else { + // Same as above, but a different data storage. 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) { Meta = (uint8_t *)M_Realloc(Meta, MetaSize); 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; } //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index bc5a6bcfd..0b776e503 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -216,22 +216,24 @@ class PCompoundType : public 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: PTypeBase *Outer; // object this type is contained within FName TypeName; // this type's name - PNamedType() : Outer(NULL) { + PContainerType() : Outer(NULL) { mDescriptiveName = "NamedType"; } - PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) { + PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) { mDescriptiveName = name.GetChars(); } virtual bool IsMatch(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 -------------------------------------------------------------- @@ -537,9 +539,9 @@ protected: PMap(); }; -class PStruct : public PNamedType +class PStruct : public PContainerType { - DECLARE_CLASS(PStruct, PNamedType); + DECLARE_CLASS(PStruct, PContainerType); public: PStruct(FName name, PTypeBase *outer, bool isnative = false); @@ -558,8 +560,6 @@ public: void SetDefaultValue(void *base, unsigned offset, TArray *specials) override; void SetPointer(void *base, unsigned offset, TArray *specials) override; - static void WriteFields(FSerializer &ar, const void *addr, const TArray &fields); - bool ReadFields(FSerializer &ar, void *addr) const; protected: PStruct(); }; @@ -588,20 +588,17 @@ enum 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. protected: TArray MetaInits; void Derive(PClass *newclass, FName name); void InitializeSpecials(void *addr, void *defaults, TArray PClass::*Inits); void SetSuper(); - PField *AddMetaField(FName name, PType *type, uint32_t flags); public: - void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; 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; void InitializeDefaults(); int FindVirtualIndex(FName name, PPrototype *proto); @@ -625,6 +622,7 @@ public: bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility TArray Virtuals; // virtual function table FName SourceLumpName; + TArray Fields; void (*ConstructNative)(void *); @@ -635,6 +633,8 @@ public: DObject *CreateNew(); PClass *CreateDerivedClass(FName name, unsigned int size); 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 BuildFlatPointers(); void BuildArrayPointers(); diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 26e15fe14..f54ccf1f8 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -114,7 +114,7 @@ FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret 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) { } @@ -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); if (sym == nullptr) sym = ctx.CurGlobals->Symbols.FindSymbol(name, true); if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) { auto type = static_cast(sym); - return dyn_cast(type->Type); + return dyn_cast(type->Type); } return nullptr; } @@ -224,7 +224,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx) return nullptr; } -bool isActor(PStruct *type) +bool isActor(PContainerType *type) { auto cls = dyn_cast(type); 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; PSymbolTable *symtbl; @@ -6269,7 +6269,7 @@ FxMemberIdentifier::~FxMemberIdentifier() FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) { - PStruct *ccls = nullptr; + PContainerType *ccls = nullptr; CHECKRESOLVED(); if (Object->ExprType == EFX_Identifier) @@ -6277,7 +6277,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) auto id = static_cast(Object)->Identifier; // 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. - ccls = FindStructType(id, ctx); + ccls = FindContainerType(id, ctx); if (ccls != nullptr) { static_cast(Object)->noglobal = true; @@ -6398,9 +6398,9 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { auto ptype = static_cast(Object->ValueType)->PointedType; - if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) + if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType))) { - auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(ptype)); + auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(ptype)); delete this; return ret; } @@ -7023,7 +7023,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { PPointer *ptrtype = dyn_cast(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"); delete this; @@ -7925,12 +7925,12 @@ FxMemberFunctionCall::~FxMemberFunctionCall() FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) { - PStruct *cls; + PContainerType *cls = nullptr; bool staticonly = false; bool novirtual = false; bool isreadonly = false; - PStruct *ccls = nullptr; + PContainerType *ccls = 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. // [ZZ] substitute ccls for String internal type. if (id == NAME_String) ccls = TypeStringStruct; - else ccls = FindStructType(id, ctx); + else ccls = FindContainerType(id, ctx); if (ccls != nullptr) static_cast(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))) { auto ptype = static_cast(Self->ValueType)->PointedType; - if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) + if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType))) { if (ptype->IsKindOf(RUNTIME_CLASS(PClass)) && MethodName == NAME_GetClass) { @@ -8243,7 +8243,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } - cls = static_cast(ptype); + cls = static_cast(ptype); } else { @@ -8825,9 +8825,9 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested. if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr) { - if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast(type)->IsA(RUNTIME_CLASS(PStruct))) + if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast(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 { diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index a6aef7523..35831c958 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -78,7 +78,7 @@ struct FCompileContext FxCompoundStatement *Block = nullptr; PPrototype *ReturnProto; 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. 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.) @@ -90,7 +90,7 @@ struct FCompileContext FString VersionString; 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 *FindInSelfClass(FName identifier, PSymbolTable *&symt); @@ -373,7 +373,7 @@ public: FxIdentifier(FName i, const FScriptPosition &p); FxExpression *Resolve(FCompileContext&); - FxExpression *ResolveMember(FCompileContext&, PStruct*, FxExpression*&, PStruct*); + FxExpression *ResolveMember(FCompileContext&, PContainerType*, FxExpression*&, PContainerType*); }; diff --git a/src/scripting/symbols.cpp b/src/scripting/symbols.cpp index 41ca4a1a8..8b641ac55 100644 --- a/src/scripting/symbols.cpp +++ b/src/scripting/symbols.cpp @@ -36,6 +36,8 @@ #include #include "dobject.h" #include "i_system.h" +#include "templates.h" +#include "serializer.h" // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -102,7 +104,7 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TA assert(proto->ArgumentTypes.Size() > 0); auto selftypeptr = dyn_cast(proto->ArgumentTypes[0]); assert(selftypeptr != nullptr); - variant.SelfClass = dyn_cast(selftypeptr->PointedType); + variant.SelfClass = dyn_cast(selftypeptr->PointedType); assert(variant.SelfClass != nullptr); } 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(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(sym)->Type->ReadValue(ar, nullptr, + (uint8_t *)addr + static_cast(sym)->Offset); + } + } + return readsomething || !foundsomething; +} + +//========================================================================== +// +// +// +//========================================================================== + void PSymbolTable::RemoveSymbol(PSymbol *sym) { auto mysym = Symbols.CheckKey(sym->SymbolName); @@ -387,7 +461,7 @@ void RemoveUnusedSymbols() { 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(); PSymbolTable::MapType::Pair *pair; diff --git a/src/scripting/symbols.h b/src/scripting/symbols.h index 648462168..f21ec749e 100644 --- a/src/scripting/symbols.h +++ b/src/scripting/symbols.h @@ -10,7 +10,7 @@ class VMFunction; class PType; class PPrototype; struct ZCC_TreeNode; -class PStruct; +class PContainerType; // Symbol information ------------------------------------------------------- @@ -175,15 +175,15 @@ public: TArray ArgNames; // we need the names to access them later when the function gets compiled. uint32_t Flags; int UseFlags; - PStruct *SelfClass; + PContainerType *SelfClass; }; TArray Variants; - PStruct *OwningClass = nullptr; + PContainerType *OwningClass = nullptr; unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags, int useflags); 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 ----------------------------------------------------------- @@ -215,6 +215,8 @@ struct PSymbolTable // 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. 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 // to be in the table with this name, if any. diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 0fbac19b9..4eb0098dd 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -101,7 +101,7 @@ FScriptPosition & GetStateSource(FState *state) // //========================================================================== -void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PStruct *cls, uint32_t funcflags, int useflags) +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PContainerType *cls, uint32_t funcflags, int useflags) { // Must be called before adding any other arguments. assert(args == nullptr || args->Size() == 0); @@ -154,7 +154,7 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArray rets(1); TArray 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. if (name == NAME_ACS_NamedExecuteWithResult) return nullptr; diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 7517283cf..d727623b4 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -148,8 +148,8 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass) // //========================================================================== -AFuncDesc *FindFunction(PStruct *cls, const char * string); -FieldDesc *FindField(PStruct *cls, const char * string); +AFuncDesc *FindFunction(PContainerType *cls, const char * string); +FieldDesc *FindField(PContainerType *cls, const char * string); FxExpression *ParseExpression(FScanner &sc, PClassActor *cls, PNamespace *resolvenspc = nullptr); @@ -159,9 +159,9 @@ void ParseFunctionParameters(FScanner &sc, PClassActor *cls, TArray *args, TArray *argflags, TArray *argnames, PStruct *cls, uint32_t funcflags, int useflags); -PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags); -PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error); +void SetImplicitArgs(TArray *args, TArray *argflags, TArray *argnames, PContainerType *cls, uint32_t funcflags, int useflags); +PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *returntype, int flags); +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); //========================================================================== diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index c145fd0f5..fe3a35933 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -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; @@ -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; const char * cname = cls ? cls->TypeName.GetChars() : ""; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 50eb2c396..9ebed3c6b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -75,7 +75,7 @@ const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx) return AST.Strings.Alloc(static_cast(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); FxExpression *ex = new FxIntCast(ConvertNode(node), false); @@ -89,7 +89,7 @@ int ZCCCompiler::IntConstFromNode(ZCC_TreeNode *node, PStruct *cls) return static_cast(ex)->GetValue().GetInt(); } -FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PStruct *cls) +FString ZCCCompiler::StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls) { FCompileContext ctx(OutNamespace, cls, false); FxExpression *ex = new FxStringCast(ConvertNode(node)); @@ -641,7 +641,7 @@ void ZCCCompiler::CreateClassTypes() { 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) { @@ -689,7 +689,7 @@ void ZCCCompiler::CreateClassTypes() 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()); OutNamespace->Symbols.AddSymbol(c->cls->Symbol); 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. for (auto cc : Classes) { - if (cc->Type() == cd->Type()->ParentClass) + if (cc->ClassType() == cd->ClassType()->ParentClass) { cd->TreeNodes.SetParentTable(&cc->TreeNodes); break; @@ -769,7 +769,7 @@ void ZCCCompiler::CreateClassTypes() // //========================================================================== -void ZCCCompiler::CopyConstants(TArray &dest, TArray &Constants, PStruct *cls, PSymbolTable *ot) +void ZCCCompiler::CopyConstants(TArray &dest, TArray &Constants, PContainerType *cls, PSymbolTable *ot) { for (auto c : Constants) { @@ -1155,7 +1155,7 @@ void ZCCCompiler::CompileAllFields() } for (unsigned i = 0; i < Classes.Size(); i++) { - auto type = Classes[i]->Type(); + auto type = Classes[i]->ClassType(); if (type->Size == TentativeClass) { @@ -1167,7 +1167,7 @@ void ZCCCompiler::CompileAllFields() else { // 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) @@ -1175,8 +1175,8 @@ void ZCCCompiler::CompileAllFields() assert(type->MetaSize == 0); AddActorInfo(type); // AActor needs the actor info manually added to its meta data before adding any scripted fields. } - else if (Classes[i]->Type()->ParentClass) - type->MetaSize = Classes[i]->Type()->ParentClass->MetaSize; + else if (Classes[i]->ClassType()->ParentClass) + type->MetaSize = Classes[i]->ClassType()->ParentClass->MetaSize; else type->MetaSize = 0; @@ -1207,7 +1207,7 @@ void ZCCCompiler::CompileAllFields() // //========================================================================== -bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren) +bool ZCCCompiler::CompileFields(PContainerType *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren) { while (Fields.Size() > 0) { @@ -1372,7 +1372,7 @@ void ZCCCompiler::CompileAllProperties() for (auto c : Classes) { 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 indices; @@ -2189,28 +2189,26 @@ void ZCCCompiler::InitDefaults() for (auto c : Classes) { // 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->Type()->ParentClass) + if (c->ClassType()->ParentClass) { - auto ti = static_cast(c->Type()); - FString mename = ti->TypeName.GetChars(); - + auto ti = static_cast(c->ClassType()); ti->InitializeDefaults(); } } else { // 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()); } // 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 { @@ -2295,7 +2293,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool do { 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. type = NewPointer(type); @@ -2749,9 +2747,9 @@ void ZCCCompiler::InitFunctions() for (auto c : Classes) { // 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) { @@ -2847,7 +2845,7 @@ void ZCCCompiler::CompileStates() 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()); continue; @@ -2855,7 +2853,7 @@ void ZCCCompiler::CompileStates() FString statename; // The state builder wants the label as one complete string, not separated into tokens. FStateDefinitions statedef; - statedef.MakeStateDefines(ValidateActor(c->Type()->ParentClass)); + statedef.MakeStateDefines(ValidateActor(c->ClassType()->ParentClass)); int numframes = 0; for (auto s : c->States) @@ -3050,7 +3048,7 @@ void ZCCCompiler::CompileStates() } try { - GetDefaultByType(c->Type())->Finalize(statedef); + GetDefaultByType(c->ClassType())->Finalize(statedef); } 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; // 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. diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 9d54f925b..acfbc6b15 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -41,7 +41,7 @@ struct ZCC_StructWork return strct->NodeName; } - PStruct *Type() + PContainerType *Type() { return strct->Type; } @@ -64,7 +64,7 @@ struct ZCC_ClassWork : public ZCC_StructWork Outer = nullptr; } - PClass *Type() + PClass *ClassType() { return static_cast(strct->Type); } @@ -79,7 +79,7 @@ struct ZCC_PropertyWork struct ZCC_ConstantWork { ZCC_ConstantDef *node; - PStruct *cls; + PContainerType *cls; PSymbolTable *Outputtable; ExpVal constval; }; @@ -94,25 +94,25 @@ public: private: const char * GetStringConst(FxExpression *ex, FCompileContext &ctx); - int IntConstFromNode(ZCC_TreeNode *node, PStruct *cls); - FString StringConstFromNode(ZCC_TreeNode *node, PStruct *cls); + int IntConstFromNode(ZCC_TreeNode *node, PContainerType *cls); + FString StringConstFromNode(ZCC_TreeNode *node, PContainerType *cls); void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer); void CreateStructTypes(); void CreateClassTypes(); - void CopyConstants(TArray &dest, TArray &Constants, PStruct *cls, PSymbolTable *ot); + void CopyConstants(TArray &dest, TArray &Constants, PContainerType *cls, PSymbolTable *ot); void CompileAllConstants(); void AddConstant(ZCC_ConstantWork &constant); bool CompileConstant(ZCC_ConstantWork *def); void CompileArrays(ZCC_StructWork *work); void CompileAllFields(); - bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false); + bool CompileFields(PContainerType *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false); void CompileAllProperties(); bool CompileProperties(PClass *type, TArray &Properties, FName prefix); FString FlagsToString(uint32_t flags); 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); void InitDefaults(); @@ -143,12 +143,12 @@ private: 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); - FxExpression *ConvertAST(PStruct *cclass, ZCC_TreeNode *ast); + FxExpression *ConvertAST(PContainerType *cclass, ZCC_TreeNode *ast); FxExpression *ConvertNode(ZCC_TreeNode *node); FArgumentList &ConvertNodeList(FArgumentList &, ZCC_TreeNode *head); 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; PNamespace *OutNamespace; ZCC_AST &AST; diff --git a/src/scripting/zscript/zcc_parser.h b/src/scripting/zscript/zcc_parser.h index 29c6ec20c..22742ac56 100644 --- a/src/scripting/zscript/zcc_parser.h +++ b/src/scripting/zscript/zcc_parser.h @@ -195,7 +195,7 @@ struct ZCC_Struct : ZCC_NamedNode { VM_UWORD Flags; ZCC_TreeNode *Body; - PStruct *Type; + PContainerType *Type; VersionInfo Version; };