From 0d7b7d6ab197ffdfb2f3c0c48db06a8d27bf4ab6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 12 Apr 2017 15:12:41 +0200 Subject: [PATCH] - merged PStruct and PNativeStruct. There were exactly 4 places in the code that checked for the difference, this is better done with a flag. --- src/dobjtype.cpp | 57 +++++---------------------- src/dobjtype.h | 19 +++------ src/menu/menudef.cpp | 4 +- src/scripting/backend/codegen.cpp | 4 +- src/scripting/backend/codegen.h | 1 + src/scripting/thingdef_data.cpp | 24 +++++------ src/scripting/zscript/zcc_compile.cpp | 13 ++++-- 7 files changed, 40 insertions(+), 82 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 1f327b9c1..98274328e 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -348,8 +348,8 @@ void PType::StaticInit() TypeVoidPtr = NewPointer(TypeVoid, false); TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. - TypeStringStruct = NewNativeStruct("Stringstruct", nullptr); - TypeFont = NewPointer(NewNativeStruct("Font", nullptr)); + TypeStringStruct = NewStruct("Stringstruct", nullptr, true); + TypeFont = NewPointer(NewStruct("Font", nullptr, true)); #ifdef __BIG_ENDIAN__ TypeColorStruct->AddField(NAME_a, TypeUInt8); TypeColorStruct->AddField(NAME_r, TypeUInt8); @@ -1521,7 +1521,7 @@ IMPLEMENT_CLASS(PStatePointer, false, false) PStatePointer::PStatePointer() { mDescriptiveName = "Pointer"; - PointedType = NewNativeStruct(NAME_State, nullptr); + PointedType = NewStruct(NAME_State, nullptr, true); IsConst = true; } @@ -2190,7 +2190,7 @@ PDynArray *NewDynArray(PType *type) break; } - auto backing = NewNativeStruct(backingname, nullptr); + auto backing = NewStruct(backingname, nullptr, true); atype = new PDynArray(type, backing); TypeTable.AddType(atype, RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, bucket); } @@ -2298,12 +2298,12 @@ PStruct::PStruct() // //========================================================================== -PStruct::PStruct(FName name, PTypeBase *outer) +PStruct::PStruct(FName name, PTypeBase *outer, bool isnative) : PNamedType(name, outer) { - mDescriptiveName.Format("Struct<%s>", name.GetChars()); + mDescriptiveName.Format("%sStruct<%s>", isnative? "Native" : "", name.GetChars()); Size = 0; - HasNativeFields = false; + isNative = isnative; } //========================================================================== @@ -2483,7 +2483,6 @@ PField *PStruct::AddNativeField(FName name, PType *type, size_t address, uint32_ return nullptr; } Fields.Push(field); - HasNativeFields = true; return field; } @@ -2495,57 +2494,19 @@ PField *PStruct::AddNativeField(FName name, PType *type, size_t address, uint32_ // //========================================================================== -PStruct *NewStruct(FName name, PTypeBase *outer) +PStruct *NewStruct(FName name, PTypeBase *outer, bool native) { size_t bucket; if (outer == nullptr) outer = Namespaces.GlobalNamespace; PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket); if (stype == nullptr) { - stype = new PStruct(name, outer); + stype = new PStruct(name, outer, native); TypeTable.AddType(stype, RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, bucket); } return static_cast(stype); } -/* PNativeStruct ****************************************************************/ - -IMPLEMENT_CLASS(PNativeStruct, false, false) - -//========================================================================== -// -// PNativeStruct - Parameterized Constructor -// -//========================================================================== - -PNativeStruct::PNativeStruct(FName name, PTypeBase *outer) - : PStruct(name, outer) -{ - mDescriptiveName.Format("NativeStruct<%s>", name.GetChars()); - Size = 0; - HasNativeFields = true; -} - -//========================================================================== -// -// NewNativeStruct -// Returns a PNativeStruct for the given name and container, making sure not to -// create duplicates. -// -//========================================================================== - -PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer) -{ - size_t bucket; - if (outer == nullptr) outer = Namespaces.GlobalNamespace; - PType *stype = TypeTable.FindType(RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, &bucket); - if (stype == nullptr) - { - stype = new PNativeStruct(name, outer); - TypeTable.AddType(stype, RUNTIME_CLASS(PNativeStruct), (intptr_t)outer, (intptr_t)name, bucket); - } - return static_cast(stype); -} /* PField *****************************************************************/ diff --git a/src/dobjtype.h b/src/dobjtype.h index c1b93e595..bc5a6bcfd 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -542,10 +542,10 @@ class PStruct : public PNamedType DECLARE_CLASS(PStruct, PNamedType); public: - PStruct(FName name, PTypeBase *outer); + PStruct(FName name, PTypeBase *outer, bool isnative = false); TArray Fields; - bool HasNativeFields; + bool isNative; // Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it. VMFunction *mConstructor = nullptr; VMFunction *mDestructor = nullptr; @@ -564,14 +564,6 @@ protected: PStruct(); }; -// a native struct will always be abstract and cannot be instantiated. All variables are references. -class PNativeStruct : public PStruct -{ - DECLARE_CLASS(PNativeStruct, PStruct); -public: - PNativeStruct(FName name = NAME_None, PTypeBase *outer = nullptr); -}; - class PPrototype : public PCompoundType { DECLARE_CLASS(PPrototype, PCompoundType); @@ -596,9 +588,9 @@ enum TentativeClass = UINT_MAX, }; -class PClass : public PNativeStruct +class PClass : public PStruct { - DECLARE_CLASS(PClass, PNativeStruct); + DECLARE_CLASS(PClass, PStruct); // We unravel _WITH_META here just as we did for PType. protected: TArray MetaInits; @@ -730,8 +722,7 @@ PDynArray *NewDynArray(PType *type); PPointer *NewPointer(PType *type, bool isconst = false); PClassPointer *NewClassPointer(PClass *restrict); PEnum *NewEnum(FName name, PTypeBase *outer); -PStruct *NewStruct(FName name, PTypeBase *outer); -PNativeStruct *NewNativeStruct(FName name, PTypeBase *outer); +PStruct *NewStruct(FName name, PTypeBase *outer, bool native = false); PPrototype *NewPrototype(const TArray &rettypes, const TArray &argtypes); // Built-in types ----------------------------------------------------------- diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 458a89502..490f8ec65 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -384,7 +384,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) params.Push(desc); start = 2; } - auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr)); + auto TypeCVar = NewPointer(NewStruct("CVar", nullptr, true)); // Note that this array may not be reallocated so its initial size must be the maximum possible elements. TArray strings(args.Size()); @@ -753,7 +753,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) TArray params; params.Push(0); - auto TypeCVar = NewPointer(NewNativeStruct("CVar", nullptr)); + auto TypeCVar = NewPointer(NewStruct("CVar", nullptr, true)); // Note that this array may not be reallocated so its initial size must be the maximum possible elements. TArray strings(args.Size()); diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index a87e249a8..26e15fe14 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -1772,7 +1772,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) if (fromtype->IsDescendantOf(totype)) goto basereturn; } } - else if (basex->ValueType->IsA(RUNTIME_CLASS(PNativeStruct)) && ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType == basex->ValueType) + else if (basex->IsNativeStruct() && ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType == basex->ValueType) { bool writable; basex->RequestAddress(ctx, &writable); @@ -2493,7 +2493,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) } // Both types are the same so this is ok. } - else if (Right->ValueType->IsA(RUNTIME_CLASS(PNativeStruct)) && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(Base->ValueType)->PointedType == Right->ValueType) + else if (Right->IsNativeStruct() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(Base->ValueType)->PointedType == Right->ValueType) { // allow conversion of native structs to pointers of the same type. This is necessary to assign elements from global arrays like players, sectors, etc. to local pointers. // For all other types this is not needed. Structs are not assignable and classes can only exist as references. diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index f1a322d7a..a6aef7523 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -337,6 +337,7 @@ public: bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); } bool IsResizableArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PStaticArray))); } // can only exist in pointer form. bool IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); } + bool IsNativeStruct() const { return (ValueType->IsA(RUNTIME_CLASS(PStruct)) && static_cast(ValueType)->isNative); } virtual ExpEmit Emit(VMFunctionBuilder *build); void EmitStatement(VMFunctionBuilder *build); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 7c5608211..c145fd0f5 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -777,11 +777,11 @@ static int fieldcmp(const void * a, const void * b) void InitThingdef() { // Some native types need size and serialization information added before the scripts get compiled. - auto secplanestruct = NewNativeStruct("Secplane", nullptr); + auto secplanestruct = NewStruct("Secplane", nullptr, true); secplanestruct->Size = sizeof(secplane_t); secplanestruct->Align = alignof(secplane_t); - auto sectorstruct = NewNativeStruct("Sector", nullptr); + auto sectorstruct = NewStruct("Sector", nullptr, true); sectorstruct->Size = sizeof(sector_t); sectorstruct->Align = alignof(sector_t); NewPointer(sectorstruct, false)->InstallHandlers( @@ -796,7 +796,7 @@ void InitThingdef() } ); - auto linestruct = NewNativeStruct("Line", nullptr); + auto linestruct = NewStruct("Line", nullptr, true); linestruct->Size = sizeof(line_t); linestruct->Align = alignof(line_t); NewPointer(linestruct, false)->InstallHandlers( @@ -811,7 +811,7 @@ void InitThingdef() } ); - auto sidestruct = NewNativeStruct("Side", nullptr); + auto sidestruct = NewStruct("Side", nullptr, true); sidestruct->Size = sizeof(side_t); sidestruct->Align = alignof(side_t); NewPointer(sidestruct, false)->InstallHandlers( @@ -826,7 +826,7 @@ void InitThingdef() } ); - auto vertstruct = NewNativeStruct("Vertex", nullptr); + auto vertstruct = NewStruct("Vertex", nullptr, true); vertstruct->Size = sizeof(vertex_t); vertstruct->Align = alignof(vertex_t); NewPointer(vertstruct, false)->InstallHandlers( @@ -841,23 +841,23 @@ void InitThingdef() } ); - auto sectorportalstruct = NewNativeStruct("SectorPortal", nullptr); + auto sectorportalstruct = NewStruct("SectorPortal", nullptr, true); sectorportalstruct->Size = sizeof(FSectorPortal); sectorportalstruct->Align = alignof(FSectorPortal); - auto playerclassstruct = NewNativeStruct("PlayerClass", nullptr); + auto playerclassstruct = NewStruct("PlayerClass", nullptr, true); playerclassstruct->Size = sizeof(FPlayerClass); playerclassstruct->Align = alignof(FPlayerClass); - auto playerskinstruct = NewNativeStruct("PlayerSkin", nullptr); + auto playerskinstruct = NewStruct("PlayerSkin", nullptr, true); playerskinstruct->Size = sizeof(FPlayerSkin); playerskinstruct->Align = alignof(FPlayerSkin); - auto teamstruct = NewNativeStruct("Team", nullptr); + auto teamstruct = NewStruct("Team", nullptr, true); teamstruct->Size = sizeof(FTeam); teamstruct->Align = alignof(FTeam); - PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); + PStruct *pstruct = NewStruct("PlayerInfo", nullptr, true); pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); NewPointer(pstruct, false)->InstallHandlers( @@ -872,7 +872,7 @@ void InitThingdef() } ); - auto fontstruct = NewNativeStruct("FFont", nullptr); + auto fontstruct = NewStruct("FFont", nullptr, true); fontstruct->Size = sizeof(FFont); fontstruct->Align = alignof(FFont); NewPointer(fontstruct, false)->InstallHandlers( @@ -887,7 +887,7 @@ void InitThingdef() } ); - auto wbplayerstruct = NewNativeStruct("WBPlayerStruct", nullptr); + auto wbplayerstruct = NewStruct("WBPlayerStruct", nullptr, true); wbplayerstruct->Size = sizeof(wbplayerstruct_t); wbplayerstruct->Align = alignof(wbplayerstruct_t); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index be7ff8182..50eb2c396 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -513,7 +513,7 @@ void ZCCCompiler::CreateStructTypes() } else if (s->strct->Flags & ZCC_Native) { - s->strct->Type = NewNativeStruct(s->NodeName(), outer); + s->strct->Type = NewStruct(s->NodeName(), outer, true); } else { @@ -1315,7 +1315,8 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel Error(field, "The member variable '%s.%s' has not been exported from the executable.", type == nullptr? "" : type->TypeName.GetChars(), FName(name->Name).GetChars()); } // For native structs a size check cannot be done because they normally have no size. But for a native reference they are still fine. - else if (thisfieldtype->Size != ~0u && fd->FieldSize != ~0u && thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0 && !thisfieldtype->IsA(RUNTIME_CLASS(PNativeStruct))) + else if (thisfieldtype->Size != ~0u && fd->FieldSize != ~0u && thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0 && + (!thisfieldtype->IsA(RUNTIME_CLASS(PStruct)) || !static_cast(thisfieldtype)->isNative)) { Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type == nullptr ? "" : type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size); } @@ -1702,10 +1703,14 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo { if (!nativetype) return TypeSInt32; // hack this to an integer until we can resolve the enum mess. } - if (ptype->IsKindOf(RUNTIME_CLASS(PNativeStruct))) // native structs and classes cannot be instantiated, they always get used as reference. + else if (ptype->IsKindOf(RUNTIME_CLASS(PClass))) // classes cannot be instantiated at all, they always get used as references. + { + return NewPointer(ptype, type->isconst); + } + else if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)) && static_cast(ptype)->isNative) // native structs and classes cannot be instantiated, they always get used as reference. { if (!nativetype) return NewPointer(ptype, type->isconst); - if (!ptype->IsKindOf(RUNTIME_CLASS(PClass))) return ptype; // instantiation of native structs. Only for internal use. + return ptype; // instantiation of native structs. Only for internal use. } if (!nativetype) return ptype; }