diff --git a/src/d_player.h b/src/d_player.h index dc5f6cd540..79a0cb5284 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -235,7 +235,7 @@ enum // The VM cannot deal with this as an invalid pointer because it performs a read barrier on every object pointer read. // This doesn't have to point to a valid weapon, though, because WP_NOCHANGE is never dereferenced, but it must point to a valid object // and the class descriptor just works fine for that. -#define WP_NOCHANGE ((AWeapon*)RUNTIME_CLASS_CASTLESS(AWeapon)) +extern AWeapon *WP_NOCHANGE; #define MAXPLAYERNAME 15 diff --git a/src/dobject.h b/src/dobject.h index b4db0386a7..0108e1378f 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -377,6 +377,8 @@ static inline void GC::WriteBarrier(DObject *pointed) } } +#include "memarena.h" +extern FMemArena ClassDataAllocator; #include "symbols.h" #include "dobjtype.h" diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 35a30c1366..5779b3903c 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -367,8 +367,6 @@ static void MarkRoot() } Mark(SectorMarker); Mark(interpolator.Head); - // Mark global symbols - Namespaces.MarkSymbols(); // Mark bot stuff. Mark(bglobal.firstthing); Mark(bglobal.body1); diff --git a/src/dobjgc.h b/src/dobjgc.h index 608a05224d..269dffc155 100644 --- a/src/dobjgc.h +++ b/src/dobjgc.h @@ -25,9 +25,6 @@ enum EObjectFlags OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk) OF_Spawned = 1 << 12, // Thinker was spawned at all (some thinkers get deleted before spawning) OF_Released = 1 << 13, // Object was released from the GC system and should not be processed by GC function - OF_Abstract = 1 << 14, // Marks a class that cannot be created with new() function at all - OF_UI = 1 << 15, // Marks a class that defaults to VARF_UI for it's fields/methods - OF_Play = 1 << 16, // Marks a class that defaults to VARF_Play for it's fields/methods }; template class TObjPtr; diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 117180d750..62a810969a 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -74,6 +74,12 @@ TArray PClass::FunctionPtrList; bool PClass::bShutdown; bool PClass::bVMOperational; +// Originally this was just a bogus pointer, but with the VM performing a read barrier on every object pointer write +// that does not work anymore. WP_NOCHANGE needs to point to a vaild object to work as intended. +// This Object does not need to be garbage collected, though, but it needs to provide the proper structure so that the +// GC can process it. +AWeapon *WP_NOCHANGE; +DEFINE_GLOBAL(WP_NOCHANGE); // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -205,7 +211,6 @@ void PClass::StaticInit () { atterm (StaticShutdown); - StaticBootstrap(); Namespaces.GlobalNamespace = Namespaces.NewNamespace(0); FAutoSegIterator probe(CRegHead, CRegTail); @@ -219,6 +224,10 @@ void PClass::StaticInit () // I'm not sure if this is really necessary to maintain any sort of sync. qsort(&AllClasses[0], AllClasses.Size(), sizeof(AllClasses[0]), cregcmp); + // WP_NOCHANGE must point to a valid object, although it does not need to be a weapon. + // A simple DObject is enough to give the GC the ability to deal with it, if subjected to it. + WP_NOCHANGE = (AWeapon*)new DObject; + WP_NOCHANGE->Release(); } //========================================================================== @@ -231,6 +240,12 @@ void PClass::StaticInit () void PClass::StaticShutdown () { + if (WP_NOCHANGE != nullptr) + { + WP_NOCHANGE->ObjectFlags |= OF_YesReallyDelete; + delete WP_NOCHANGE; + } + // delete all variables containing pointers to script functions. for (auto p : FunctionPtrList) { @@ -265,6 +280,7 @@ void PClass::StaticShutdown () ClassDataAllocator.FreeAllBlocks(); AllClasses.Clear(); PClassActor::AllActorClasses.Clear(); + ClassMap.Clear(); FAutoSegIterator probe(CRegHead, CRegTail); @@ -276,16 +292,6 @@ void PClass::StaticShutdown () } -//========================================================================== -// -// PClass :: StaticBootstrap STATIC -// -//========================================================================== - -void PClass::StaticBootstrap() -{ -} - //========================================================================== // // PClass Constructor @@ -363,7 +369,6 @@ void ClassReg::SetupClass(PClass *cls) cls->Size = SizeOf; cls->Pointers = Pointers; cls->ConstructNative = ConstructNative; - //cls->mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars()); } //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index 24cd43451f..22d44a2348 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -5,8 +5,6 @@ #error You must #include "dobject.h" to get dobjtype.h #endif -#include "memarena.h" - typedef std::pair FTypeAndOffset; #if 0 @@ -28,8 +26,6 @@ class VMFunction; class PClassType; struct FNamespaceManager; -extern FMemArena ClassDataAllocator; - enum { TentativeClass = UINT_MAX, @@ -52,7 +48,6 @@ public: static void StaticInit(); static void StaticShutdown(); - static void StaticBootstrap(); // Per-class information ------------------------------------- PClass *ParentClass = nullptr; // the class this class derives from diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 5144cf56e3..35dd6505c6 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -714,10 +714,6 @@ class DThinkerIterator : public DObject, public FThinkerIterator { DECLARE_ABSTRACT_CLASS(DThinkerIterator, DObject) - DThinkerIterator() - { - } - public: DThinkerIterator(PClass *cls, int statnum = MAX_STATNUM + 1) : FThinkerIterator(cls, statnum) diff --git a/src/info.cpp b/src/info.cpp index c6072afca3..4619b75856 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -75,12 +75,11 @@ cycle_t ActionCycles; // //========================================================================== -class PActorInfo : public PBasicType +class PActorInfo : public PCompoundType { - DECLARE_CLASS(PActorInfo, PBasicType); public: PActorInfo() - :PBasicType(sizeof(FActorInfo), alignof(FActorInfo)) + :PCompoundType(sizeof(FActorInfo), alignof(FActorInfo)) { } @@ -113,12 +112,10 @@ public: }; -IMPLEMENT_CLASS(PActorInfo, false, false) - void AddActorInfo(PClass *cls) { auto type = new PActorInfo; - TypeTable.AddType(type); + TypeTable.AddType(type, NAME_Actor); cls->AddField("*", type, VARF_Meta); } diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 5a2f189746..8c80325c08 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -424,7 +424,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) } params.Push(f.GetIndex()); } - else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) + else if (args[i]->isIntCompatible()) { char *endp; int v = (int)strtoll(sc.String, &endp, 0); @@ -441,7 +441,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) if (args[i] == TypeBool) v = !!v; params.Push(v); } - else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat))) + else if (args[i]->isFloat()) { char *endp; double v = strtod(sc.String, &endp); @@ -775,7 +775,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) { params.Push(V_GetColor(nullptr, sc)); } - else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) + else if (args[i]->isIntCompatible()) { char *endp; int v = (int)strtoll(sc.String, &endp, 0); @@ -794,7 +794,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc) if (args[i] == TypeBool) v = !!v; params.Push(v); } - else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat))) + else if (args[i]->isFloat()) { char *endp; double v = strtod(sc.String, &endp); diff --git a/src/namedef.h b/src/namedef.h index 4346844fc9..18075976d7 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -7,7 +7,6 @@ xx(Super) xx(Object) xx(Actor) xx(Class) -xx(ClassClass) xx(Untranslated) @@ -904,3 +903,12 @@ xx(Player8) xx(PlayerChunk) xx(RestrictedToPlayerClass) xx(ForbiddenToPlayerClass) + +xx(Prototype) +xx(Void) +xx(Label) +xx(Pointer) +xx(Enum) +xx(StaticArray) +xx(DynArray) +xx(Struct) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 55dfdd8e67..b510ee45fe 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5015,7 +5015,6 @@ int DLevelScript::LineFromID(int id) bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *&type, bool readonly) { PField *var = dyn_cast(self->GetClass()->FindSymbol(varname, true)); - PArray *arraytype; if (var == NULL || (!readonly && (var->Flags & VARF_Native))) { @@ -5023,9 +5022,9 @@ bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType * } type = var->Type; uint8_t *baddr = reinterpret_cast(self) + var->Offset; - arraytype = dyn_cast(type); - if (arraytype != NULL) + if (type->isArray()) { + PArray *arraytype = static_cast(type); // unwrap contained type type = arraytype->ElementType; // offset by index (if in bounds) @@ -5040,12 +5039,11 @@ bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType * return false; } addr = baddr; - // We don't want Int subclasses like Name or Color to be accessible, - // but we do want to support Float subclasses like Fixed. - if (!type->IsA(RUNTIME_CLASS(PInt)) && !type->IsKindOf(RUNTIME_CLASS(PFloat))) + // We don't want Int subclasses like Name or Color to be accessible here. + if (!type->isInt() && !type->isFloat()) { // For reading, we also support Name and String types. - if (readonly && (type->IsA(RUNTIME_CLASS(PName)) || type->IsA(RUNTIME_CLASS(PString)))) + if (readonly && (type == TypeName || type == TypeString)) { return true; } @@ -5061,7 +5059,7 @@ static void SetUserVariable(AActor *self, FName varname, int index, int value) if (GetVarAddrType(self, varname, index, addr, type, false)) { - if (!type->IsKindOf(RUNTIME_CLASS(PFloat))) + if (!type->isFloat()) { type->SetValue(addr, value); } @@ -5079,15 +5077,15 @@ static int GetUserVariable(AActor *self, FName varname, int index) if (GetVarAddrType(self, varname, index, addr, type, true)) { - if (type->IsKindOf(RUNTIME_CLASS(PFloat))) + if (type->isFloat()) { return DoubleToACS(type->GetValueFloat(addr)); } - else if (type->IsA(RUNTIME_CLASS(PName))) + else if (type == TypeName) { return GlobalACSStrings.AddString(FName(ENamedName(type->GetValueInt(addr))).GetChars()); } - else if (type->IsA(RUNTIME_CLASS(PString))) + else if (type == TypeString) { return GlobalACSStrings.AddString(*(FString *)addr); } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 030bdae513..19cafed238 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -4753,7 +4753,7 @@ static PField *GetVar(DObject *self, FName varname) { PField *var = dyn_cast(self->GetClass()->FindSymbol(varname, true)); - if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType))) + if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || !var->Type->isScalar()) { Printf("%s is not a user variable in class %s\n", varname.GetChars(), self->GetClass()->TypeName.GetChars()); @@ -4803,8 +4803,7 @@ static PField *GetArrayVar(DObject *self, FName varname, int pos) PField *var = dyn_cast(self->GetClass()->FindSymbol(varname, true)); if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || - !var->Type->IsKindOf(RUNTIME_CLASS(PArray)) || - !static_cast(var->Type)->ElementType->IsKindOf(RUNTIME_CLASS(PBasicType))) + !var->Type->isArray() || !static_cast(var->Type)->ElementType->isScalar()) { Printf("%s is not a user array in class %s\n", varname.GetChars(), self->GetClass()->TypeName.GetChars()); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 9ee249cc19..5a800225b1 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1621,7 +1621,7 @@ static void SetMapThingUserData(AActor *actor, unsigned udi) udi++; - if (var == NULL || (var->Flags & (VARF_Native|VARF_Private|VARF_Protected|VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType))) + if (var == NULL || (var->Flags & (VARF_Native|VARF_Private|VARF_Protected|VARF_Static)) || !var->Type->isScalar()) { DPrintf(DMSG_WARNING, "%s is not a user variable in class %s\n", varname.GetChars(), actor->GetClass()->TypeName.GetChars()); diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 0c47493ea0..5b7fcddc9d 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -207,7 +207,7 @@ static PContainerType *FindContainerType(FName name, FCompileContext &ctx) if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) { auto type = static_cast(sym); - return dyn_cast(type->Type); + return type->Type->toContainer(); } return nullptr; } @@ -219,7 +219,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx) if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) { auto type = static_cast(sym); - auto ctype = dyn_cast(type->Type); + auto ctype = PType::toClass(type->Type); if (ctype) return ctype->Descriptor; } return nullptr; @@ -227,7 +227,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx) bool isActor(PContainerType *type) { - auto cls = dyn_cast(type); + auto cls = PType::toClass(type); return cls ? cls->Descriptor->IsDescendantOf(RUNTIME_CLASS(AActor)) : false; } @@ -292,10 +292,10 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare = false) { - if (dest->IsKindOf(RUNTIME_CLASS(PPointer)) && source->IsKindOf(RUNTIME_CLASS(PPointer))) + if (dest->isPointer() && source->isPointer()) { - auto fromtype = static_cast(source); - auto totype = static_cast(dest); + auto fromtype = source->toPointer(); + auto totype = dest->toPointer(); // null pointers can be assigned to everything, everything can be assigned to void pointers. if (fromtype == nullptr || totype == TypeVoidPtr) return true; // when comparing const-ness does not matter. @@ -303,7 +303,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar // A type is always compatible to itself. if (fromtype == totype) return true; // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. - if (source->IsA(RUNTIME_CLASS(PObjectPointer)) && dest->IsA(RUNTIME_CLASS(PObjectPointer))) + if (source->isObjectPointer() && dest->isObjectPointer()) { auto fromcls = static_cast(source)->PointedClass(); auto tocls = static_cast(dest)->PointedClass(); @@ -311,7 +311,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar return (fromcls->IsDescendantOf(tocls)); } // The same rules apply to class pointers. A child type can be assigned to a variable of a parent type. - if (source->IsA(RUNTIME_CLASS(PClassPointer)) && dest->IsA(RUNTIME_CLASS(PClassPointer))) + if (source->isClassPointer() && dest->isClassPointer()) { auto fromcls = static_cast(source)->ClassRestriction; auto tocls = static_cast(dest)->ClassRestriction; @@ -557,11 +557,11 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos) PSymbolConstNumeric *csym = dyn_cast(sym); if (csym != nullptr) { - if (csym->ValueType->IsA(RUNTIME_CLASS(PInt))) + if (csym->ValueType->isInt()) { x = new FxConstant(csym->Value, pos); } - else if (csym->ValueType->IsA(RUNTIME_CLASS(PFloat))) + else if (csym->ValueType->isFloat()) { x = new FxConstant(csym->Float, pos); } @@ -1158,7 +1158,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(basex, ctx); - if (mExplicit && basex->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + if (mExplicit && basex->ValueType->isClassPointer()) { if (basex->isConstant()) { @@ -1356,7 +1356,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(basex, ctx); - if (basex->ValueType == TypeColor || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt)) + if (basex->ValueType == TypeColor || basex->ValueType->isInt()) { FxExpression *x = basex; x->ValueType = TypeColor; @@ -1445,7 +1445,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx) CHECKRESOLVED(); SAFE_RESOLVE(basex, ctx); - if (basex->ValueType == TypeSound || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt)) + if (basex->ValueType == TypeSound || basex->ValueType->isInt()) { FxExpression *x = basex; x->ValueType = TypeSound; @@ -1617,7 +1617,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) // don't go through the entire list if the types are the same. goto basereturn; } - else if (basex->ValueType == TypeNullPtr && (ValueType == TypeState || ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))) + else if (basex->ValueType == TypeNullPtr && ValueType->isPointer()) { goto basereturn; } @@ -1629,7 +1629,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } - else if (ValueType->IsA(RUNTIME_CLASS(PInt))) + else if (ValueType->isInt()) { // This is only for casting to actual ints. Subtypes representing an int will be handled elsewhere. FxExpression *x = new FxIntCast(basex, NoWarn, Explicit); @@ -1750,7 +1750,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) } } } - else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + else if (ValueType->isClassPointer()) { FxExpression *x = new FxClassTypeCast(static_cast(ValueType), basex, Explicit); x = x->Resolve(ctx); @@ -1758,14 +1758,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } - /* else if (ValueType->IsKindOf(RUNTIME_CLASS(PEnum))) + /* else if (ValueType->isEnum()) { // this is not yet ready and does not get assigned to actual values. } */ - else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassType))) // this should never happen because the VM doesn't handle plain class types - just pointers + else if (ValueType->isClass()) // this should never happen because the VM doesn't handle plain class types - just pointers { - if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PClassType))) + if (basex->ValueType->isClass()) { // class types are only compatible if the base type is a descendant of the result type. auto fromtype = static_cast(basex->ValueType)->Descriptor; @@ -1773,7 +1773,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) if (fromtype->IsDescendantOf(totype)) goto basereturn; } } - else if (basex->IsNativeStruct() && ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType == basex->ValueType) + else if (basex->IsNativeStruct() && ValueType->isRealPointer() && ValueType->toPointer()->PointedType == basex->ValueType) { bool writable; basex->RequestAddress(ctx, &writable); @@ -2480,13 +2480,13 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) } else if (Base->ValueType == Right->ValueType) { - if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PArray))) + if (Base->ValueType->isArray()) { ScriptPosition.Message(MSG_ERROR, "Cannot assign arrays"); delete this; return nullptr; } - if (!Base->IsVector() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + if (!Base->IsVector() && Base->ValueType->isStruct()) { ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet"); delete this; @@ -2494,7 +2494,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) } // Both types are the same so this is ok. } - else if (Right->IsNativeStruct() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(Base->ValueType)->PointedType == Right->ValueType) + else if (Right->IsNativeStruct() && Base->ValueType->isRealPointer() && Base->ValueType->toPointer()->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. @@ -3611,7 +3611,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) // Special cases: Compare strings and names with names, sounds, colors, state labels and class types. // These are all types a string can be implicitly cast into, so for convenience, so they should when doing a comparison. if ((left->ValueType == TypeString || left->ValueType == TypeName) && - (right->ValueType == TypeName || right->ValueType == TypeSound || right->ValueType == TypeColor || right->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || right->ValueType == TypeStateLabel)) + (right->ValueType == TypeName || right->ValueType == TypeSound || right->ValueType == TypeColor || right->ValueType->isClassPointer() || right->ValueType == TypeStateLabel)) { left = new FxTypeCast(left, right->ValueType, false, true); left = left->Resolve(ctx); @@ -3619,7 +3619,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) ValueType = right->ValueType; } else if ((right->ValueType == TypeString || right->ValueType == TypeName) && - (left->ValueType == TypeName || left->ValueType == TypeSound || left->ValueType == TypeColor || left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || left->ValueType == TypeStateLabel)) + (left->ValueType == TypeName || left->ValueType == TypeSound || left->ValueType == TypeColor || left->ValueType->isClassPointer() || left->ValueType == TypeStateLabel)) { right = new FxTypeCast(right, left->ValueType, false, true); right = right->Resolve(ctx); @@ -3649,12 +3649,12 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) goto error; } } - else if (left->IsPointer() && static_cast(left->ValueType)->PointedType == right->ValueType) + else if (left->IsPointer() && left->ValueType->toPointer()->PointedType == right->ValueType) { bool writable; if (!right->RequestAddress(ctx, &writable)) goto error; } - else if (right->IsPointer() && static_cast(right->ValueType)->PointedType == left->ValueType) + else if (right->IsPointer() && right->ValueType->toPointer()->PointedType == left->ValueType) { bool writable; if (!left->RequestAddress(ctx, &writable)) goto error; @@ -4596,7 +4596,7 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx) RESOLVE(right, ctx); ABORT(right && left); - if (left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + if (left->ValueType->isClassPointer()) { left = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), left, false); ClassCheck = true; @@ -4684,7 +4684,7 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); SAFE_RESOLVE(expr, ctx); - bool constflag = expr->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(expr->ValueType)->IsConst; + bool constflag = expr->ValueType->isPointer() && expr->ValueType->toPointer()->IsConst; if (constflag) { // readonly pointers are normally only used for class defaults which lack type information to be cast properly, so we have to error out here. @@ -5140,7 +5140,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx) SAFE_RESOLVE(val, ctx); CallingFunction = ctx.Function; - if (!val->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + if (!val->ValueType->isClassPointer()) { ScriptPosition.Message(MSG_ERROR, "Class type expected"); delete this; @@ -5159,8 +5159,8 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx) // int outerside = ctx.Function && ctx.Function->Variants.Size() ? FScopeBarrier::SideFromFlags(ctx.Function->Variants[0].Flags) : FScopeBarrier::Side_Virtual; if (outerside == FScopeBarrier::Side_Virtual) - outerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags); - int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ObjectFlags); + outerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags); + int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ScopeFlags); if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context" { ScriptPosition.Message(MSG_ERROR, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside)); @@ -5190,7 +5190,7 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build) { int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); if (outerside == FScopeBarrier::Side_Virtual) - outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ObjectFlags); + outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ScopeFlags); build->Emit(OP_NEW, to.RegNum, from.RegNum, outerside+1); // +1 to ensure it's not 0 } else @@ -6126,7 +6126,7 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType * { PSymbol *sym; PSymbolTable *symtbl; - bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClassType)); + bool isclass = objtype->isClass(); if (Identifier == NAME_Default) { @@ -6180,8 +6180,8 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType * object = nullptr; return nullptr; } - auto cls_ctx = dyn_cast(classctx); - auto cls_target = dyn_cast(objtype); + auto cls_ctx = PType::toClass(classctx); + auto cls_target = PType::toClass(objtype); // [ZZ] neither PSymbol, PField or PSymbolTable have the necessary information. so we need to do the more complex check here. if (vsym->Flags & VARF_Protected) { @@ -6342,7 +6342,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) auto sn = static_cast(sym); VMValue vmv; - if (sn->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) vmv = sn->Value; + if (sn->ValueType->isIntCompatible()) vmv = sn->Value; else vmv = sn->Float; auto x = new FxConstant(sn->ValueType, vmv, ScriptPosition); delete this; @@ -6393,17 +6393,17 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) { Object->ValueType = TypeColorStruct; } - if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + if (Object->ValueType->isRealPointer()) { - auto ptype = static_cast(Object->ValueType)->PointedType; - if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType))) + auto ptype = Object->ValueType->toPointer()->PointedType; + if (ptype->isContainer()) { auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(ptype)); delete this; return ret; } } - else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + else if (Object->ValueType->isStruct()) { auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast(Object->ValueType)); delete this; @@ -6603,8 +6603,8 @@ FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); SAFE_RESOLVE(obj, ctx); - assert(obj->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))); - ValueType = NewPointer(static_cast(obj->ValueType)->PointedType, true); + assert(obj->ValueType->isRealPointer()); + ValueType = NewPointer(obj->ValueType->toPointer()->PointedType, true); return this; } @@ -6938,7 +6938,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) { // [ZZ] original check. bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) && - (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast(classx->ValueType)->IsConst)); + (!classx->ValueType->isPointer() || !classx->ValueType->toPointer()->IsConst)); // [ZZ] implement write barrier between different scopes if (bWritable) { @@ -6947,7 +6947,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) { outerflags = ctx.Function->Variants[0].Flags; if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class) - outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags)); + outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags)); } FScopeBarrier scopeBarrier(outerflags, FScopeBarrier::FlagsFromSide(BarrierSide), membervar->SymbolName.GetChars()); if (!scopeBarrier.writable) @@ -6972,7 +6972,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) if (membervar->SymbolName == NAME_Default) { - if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)) + if (!classx->ValueType->isObjectPointer() || !static_cast(classx->ValueType)->PointedClass()->IsDescendantOf(RUNTIME_CLASS(AActor))) { ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type"); @@ -6991,7 +6991,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) { outerflags = ctx.Function->Variants[0].Flags; if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class) - outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags)); + outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags)); } FScopeBarrier scopeBarrier(outerflags, membervar->Flags, membervar->SymbolName.GetChars()); if (!scopeBarrier.readable) @@ -7018,17 +7018,17 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) return x->Resolve(ctx); } - if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + if (classx->ValueType->isPointer()) { - PPointer *ptrtype = dyn_cast(classx->ValueType); - if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PContainerType))) + PPointer *ptrtype = classx->ValueType->toPointer(); + if (ptrtype == nullptr || !ptrtype->PointedType->isContainer()) { ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object"); delete this; return nullptr; } } - else if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + else if (classx->ValueType->isStruct()) { // if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember || classx->ExprType == EFX_GlobalVariable || classx->ExprType == EFX_StackVariable) @@ -7237,12 +7237,11 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) } else { - arraytype = dyn_cast(Array->ValueType); - if (arraytype == nullptr) + if (!Array->ValueType->isArray()) { // Check if we got a pointer to an array. Some native data structures (like the line list in sectors) use this. - PPointer *ptype = dyn_cast(Array->ValueType); - if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray))) + PPointer *ptype = Array->ValueType->toPointer(); + if (ptype == nullptr || !ptype->PointedType->isArray()) { ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); delete this; @@ -7251,10 +7250,14 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) arraytype = static_cast(ptype->PointedType); arrayispointer = true; } + else + { + arraytype = static_cast(Array->ValueType); + } elementtype = arraytype->ElementType; } - if (Array->IsResizableArray()) + if (Array->isStaticArray()) { // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable) @@ -7316,7 +7319,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) if (arrayispointer) { - arraytype = static_cast(static_cast(Array->ValueType)->PointedType); + arraytype = static_cast(Array->ValueType->toPointer()->PointedType); } else { @@ -7498,8 +7501,8 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction bool match = (callingself == calledself); if (!match) { - auto callingselfcls = dyn_cast(caller->Variants[0].SelfClass); - auto calledselfcls = dyn_cast(callee->Variants[0].SelfClass); + auto callingselfcls = PType::toClass(caller->Variants[0].SelfClass); + auto calledselfcls = PType::toClass(callee->Variants[0].SelfClass); match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->Descriptor->IsDescendantOf(calledselfcls->Descriptor); } @@ -7616,14 +7619,14 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { outerflags = ctx.Function->Variants[0].Flags; if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class) - outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags)); + outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags)); } int innerflags = afd->Variants[0].Flags; int innerside = FScopeBarrier::SideFromFlags(innerflags); // [ZZ] check this at compile time. this would work for most legit cases. if (innerside == FScopeBarrier::Side_Virtual) { - innerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags); + innerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags); innerflags = FScopeBarrier::FlagsFromSide(innerside); } FScopeBarrier scopeBarrier(outerflags, innerflags, MethodName.GetChars()); @@ -7860,7 +7863,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition)) { // [ZZ] allow implicit new() call to mean "create current class instance" - if (!ArgList.Size() && !ctx.Class->IsKindOf(RUNTIME_CLASS(PClassType))) + if (!ArgList.Size() && !ctx.Class->isClass()) { ScriptPosition.Message(MSG_ERROR, "Cannot use implicit new() in a struct"); delete this; @@ -7969,7 +7972,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) { cls = ccls; staticonly = true; - if (ccls->IsKindOf(RUNTIME_CLASS(PClassType))) + if (ccls->isClass()) { if (ctx.Function == nullptr) { @@ -7977,7 +7980,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - auto clstype = dyn_cast(ctx.Function->Variants[0].SelfClass); + auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass); if (clstype != nullptr) { novirtual = clstype->Descriptor->IsDescendantOf(static_cast(ccls)->Descriptor); @@ -8009,7 +8012,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - auto clstype = dyn_cast(ctx.Function->Variants[0].SelfClass); + auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass); if (clstype != nullptr) { // give the node the proper value type now that we know it's properly used. @@ -8150,7 +8153,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) member->membervar = newfield; } } - else if (a->IsPointer() && Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + else if (a->IsPointer() && Self->ValueType->isPointer()) { // the only case which must be checked up front is for pointer arrays receiving a new element. // Since there is only one native backing class it uses a neutral void pointer as its argument, @@ -8175,10 +8178,10 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - if (!Self->IsResizableArray()) + if (!Self->isStaticArray()) { auto atype = Self->ValueType; - if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) atype = static_cast(ValueType)->PointedType; + if (Self->ValueType->isPointer()) atype = ValueType->toPointer()->PointedType; auto size = static_cast(atype)->ElementCount; auto x = new FxConstant(size, ScriptPosition); delete this; @@ -8210,7 +8213,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (MethodName == NAME_GetParentClass && - (Self->IsObject() || Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))) + (Self->IsObject() || Self->ValueType->isClassPointer())) { if (ArgList.Size() > 0) { @@ -8222,12 +8225,13 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return x->Resolve(ctx); } - if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + if (Self->ValueType->isRealPointer()) { - auto ptype = static_cast(Self->ValueType)->PointedType; - if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType))) + auto ptype = Self->ValueType->toPointer()->PointedType; + cls = ptype->toContainer(); + if (cls != nullptr) { - if (ptype->IsKindOf(RUNTIME_CLASS(PClassType)) && MethodName == NAME_GetClass) + if (ptype->isClass() && MethodName == NAME_GetClass) { if (ArgList.Size() > 0) { @@ -8238,9 +8242,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) auto x = new FxGetClass(Self); return x->Resolve(ctx); } - - - cls = static_cast(ptype); } else { @@ -8249,7 +8250,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return nullptr; } } - else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) + else if (Self->ValueType->isStruct()) { bool writable; @@ -8299,14 +8300,14 @@ isresolved: { outerflags = ctx.Function->Variants[0].Flags; if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class) - outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags)); + outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags)); } int innerflags = afd->Variants[0].Flags; int innerside = FScopeBarrier::SideFromFlags(innerflags); // [ZZ] check this at compile time. this would work for most legit cases. if (innerside == FScopeBarrier::Side_Virtual) { - innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags); + innerside = FScopeBarrier::SideFromObjectFlags(cls->ScopeFlags); innerflags = FScopeBarrier::FlagsFromSide(innerside); } else if (innerside != FScopeBarrier::Side_Clear) @@ -8330,8 +8331,8 @@ isresolved: { if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual)) { - auto clstype = dyn_cast(ctx.Class); - auto ccls = dyn_cast(cls); + auto clstype = PType::toClass(ctx.Class); + auto ccls = PType::toClass(cls); if (clstype == nullptr || ccls == nullptr || !clstype->Descriptor->IsDescendantOf(ccls->Descriptor)) { ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here", cls->TypeName.GetChars(), MethodName.GetChars()); @@ -8759,7 +8760,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) // If this is a reference argument, the pointer type must be undone because the code below expects the pointed type as value type. if (argflags[i + k + implicit] & VARF_Ref) { - assert(ntype->IsKindOf(RUNTIME_CLASS(PPointer))); + assert(ntype->isPointer()); ntype = TypeNullPtr; // the default of a reference type can only be a null pointer } if (ntype->GetRegCount() == 1) @@ -8822,7 +8823,7 @@ 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)->PointedType->IsA(RUNTIME_CLASS(PStruct))) + if (type == ArgList[i]->ValueType && type->isRealPointer() && type->toPointer()->PointedType->isStruct()) { // trying to pass a struct reference as a struct reference. This must preserve the type. } @@ -8937,11 +8938,11 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) if (innerside == FScopeBarrier::Side_Virtual) { - auto selfside = FScopeBarrier::SideFromObjectFlags(static_cast(Self->ValueType)->PointedType->ObjectFlags); + auto selfside = FScopeBarrier::SideFromObjectFlags(Self->ValueType->toPointer()->PointedType->ScopeFlags); int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); if (outerside == FScopeBarrier::Side_Virtual) - outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ObjectFlags); + outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ScopeFlags); // [ZZ] only emit if target side cannot be checked at compile time. if (selfside == FScopeBarrier::Side_PlainData) @@ -9300,7 +9301,7 @@ FxExpression *FxGetClass::Resolve(FCompileContext &ctx) delete this; return nullptr; } - ValueType = NewClassPointer(static_cast(static_cast(Self->ValueType)->PointedType)->Descriptor); + ValueType = NewClassPointer(static_cast(Self->ValueType->toPointer()->PointedType)->Descriptor); return this; } @@ -9333,7 +9334,7 @@ FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx) { SAFE_RESOLVE(Self, ctx); - if (!Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && !Self->IsObject()) + if (!Self->ValueType->isClassPointer() && !Self->IsObject()) { ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object"); delete this; @@ -9404,7 +9405,7 @@ FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx) } else { - auto cp = dyn_cast(Self->ValueType); + auto cp = PType::toClassPointer(Self->ValueType); if (cp == nullptr || !cp->ClassRestriction->IsDescendantOf(RUNTIME_CLASS(AActor))) { ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type"); @@ -10603,7 +10604,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) return x; } auto to = static_cast(ValueType); - if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) + if (basex->ValueType->isClassPointer()) { auto from = static_cast(basex->ValueType); if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction)) @@ -10771,7 +10772,7 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx) return x; } auto to = static_cast(ValueType); - if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) + if (basex->ValueType->isClassPointer()) { auto from = static_cast(basex->ValueType); // Downcast is always ok. @@ -10848,7 +10849,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); ABORT(ctx.Class); - auto vclass = dyn_cast(ctx.Class); + auto vclass = PType::toClass(ctx.Class); assert(vclass != nullptr); auto aclass = ValidateActor(vclass->Descriptor); @@ -10927,7 +10928,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx) SAFE_RESOLVE(Index, ctx); } - auto vclass = dyn_cast(ctx.Class); + auto vclass = PType::toClass(ctx.Class); assert(vclass != nullptr); auto aclass = ValidateActor(vclass->Descriptor); assert(aclass != nullptr && aclass->GetStateCount() > 0); @@ -10987,7 +10988,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx) ABORT(ctx.Class); int symlabel; - auto vclass = dyn_cast(ctx.Class); + auto vclass = PType::toClass(ctx.Class); assert(vclass != nullptr); auto clstype = ValidateActor(vclass->Descriptor); @@ -11203,7 +11204,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) else { // Init arrays and structs. - if (ValueType->IsA(RUNTIME_CLASS(PStruct))) + if (ValueType->isStruct()) { auto pstr = static_cast(ValueType); if (pstr->mConstructor != nullptr) @@ -11229,7 +11230,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) } else { - if (ValueType->IsA(RUNTIME_CLASS(PStruct))) + if (ValueType->isStruct()) { auto pstr = static_cast(ValueType); if (pstr->mDestructor != nullptr) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 1f6c8baca2..aa2e06910d 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -330,16 +330,16 @@ public: virtual bool CheckReturn() { return false; } virtual int GetBitValue() { return -1; } bool IsNumeric() const { return ValueType->isNumeric(); } - bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; } - bool IsInteger() const { return ValueType->isNumeric() && (ValueType->GetRegType() == REGT_INT); } - bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; } + bool IsFloat() const { return ValueType->isFloat(); } + bool IsInteger() const { return ValueType->isNumeric() && ValueType->isIntCompatible(); } + bool IsPointer() const { return ValueType->isPointer(); } bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; - bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); } - bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)); } - 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); } + bool IsBoolCompat() const { return ValueType->isScalar(); } + bool IsObject() const { return ValueType->isObjectPointer(); } + bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); } + bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form. + bool IsDynamicArray() const { return (ValueType->isDynArray()); } + bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast(ValueType)->isNative); } virtual ExpEmit Emit(VMFunctionBuilder *build); void EmitStatement(VMFunctionBuilder *build); diff --git a/src/scripting/backend/scopebarrier.cpp b/src/scripting/backend/scopebarrier.cpp index c426323183..65740ec180 100644 --- a/src/scripting/backend/scopebarrier.cpp +++ b/src/scripting/backend/scopebarrier.cpp @@ -19,11 +19,11 @@ int FScopeBarrier::SideFromFlags(int flags) } // same as above, but from object flags -int FScopeBarrier::SideFromObjectFlags(int flags) +int FScopeBarrier::SideFromObjectFlags(EScopeFlags flags) { - if (flags & OF_UI) + if (flags & Scope_UI) return Side_UI; - if (flags & OF_Play) + if (flags & Scope_Play) return Side_Play; return Side_PlainData; } @@ -46,16 +46,16 @@ int FScopeBarrier::FlagsFromSide(int side) } } -int FScopeBarrier::ObjectFlagsFromSide(int side) +EScopeFlags FScopeBarrier::ObjectFlagsFromSide(int side) { switch (side) { case Side_Play: - return OF_Play; + return Scope_Play; case Side_UI: - return OF_UI; + return Scope_UI; default: - return 0; + return Scope_All; } } @@ -88,11 +88,12 @@ int FScopeBarrier::ChangeSideInFlags(int flags, int side) } // this modifies OF_ flags and sets the side properly. -int FScopeBarrier::ChangeSideInObjectFlags(int flags, int side) +EScopeFlags FScopeBarrier::ChangeSideInObjectFlags(EScopeFlags flags, int side) { - flags &= ~(OF_UI | OF_Play); - flags |= ObjectFlagsFromSide(side); - return flags; + int f = int(flags); + f &= ~(Scope_UI | Scope_Play); + f |= ObjectFlagsFromSide(side); + return (EScopeFlags)flags; } FScopeBarrier::FScopeBarrier() @@ -177,14 +178,14 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name) // these are for vmexec.h void FScopeBarrier::ValidateNew(PClass* cls, int outerside) { - int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ObjectFlags); + int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ScopeFlags); if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context" ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside)); } void FScopeBarrier::ValidateCall(PClass* selftype, VMFunction *calledfunc, int outerside) { - int innerside = FScopeBarrier::SideFromObjectFlags(selftype->VMType->ObjectFlags); + int innerside = FScopeBarrier::SideFromObjectFlags(selftype->VMType->ScopeFlags); if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->PrintableName.GetChars(), FScopeBarrier::StringFromSide(outerside)); } \ No newline at end of file diff --git a/src/scripting/backend/scopebarrier.h b/src/scripting/backend/scopebarrier.h index fdcfedfbac..fb931d2233 100644 --- a/src/scripting/backend/scopebarrier.h +++ b/src/scripting/backend/scopebarrier.h @@ -2,6 +2,13 @@ #include "zstring.h" +enum EScopeFlags +{ + Scope_All = 0, + Scope_UI = 1, // Marks a class that defaults to VARF_UI for its fields/methods + Scope_Play = 2, // Marks a class that defaults to VARF_Play for its fields/methods +}; + class PClass; class VMFunction; @@ -34,11 +41,11 @@ struct FScopeBarrier static int SideFromFlags(int flags); // same as above, but from object flags - static int SideFromObjectFlags(int flags); + static int SideFromObjectFlags(EScopeFlags flags); // static int FlagsFromSide(int side); - static int ObjectFlagsFromSide(int side); + static EScopeFlags ObjectFlagsFromSide(int side); // used for errors static const char* StringFromSide(int side); @@ -46,7 +53,7 @@ struct FScopeBarrier // this modifies VARF_ flags and sets the side properly. static int ChangeSideInFlags(int flags, int side); // this modifies OF_ flags and sets the side properly. - static int ChangeSideInObjectFlags(int flags, int side); + static EScopeFlags ChangeSideInObjectFlags(EScopeFlags flags, int side); FScopeBarrier(); FScopeBarrier(int flags1, int flags2, const char* name); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 4758aaa237..0a0b2fa3d1 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -102,7 +102,7 @@ PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FN { // [ZZ] DECORATE classes are always play auto vmtype = type->VMType; - vmtype->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(vmtype->ObjectFlags, FScopeBarrier::Side_Play); + vmtype->ScopeFlags = FScopeBarrier::ChangeSideInObjectFlags(vmtype->ScopeFlags, FScopeBarrier::Side_Play); } return type; @@ -203,7 +203,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type) x = new FxRuntimeStateIndex(ParseExpression(sc, cls)); } } - else if (type->GetClass() == RUNTIME_CLASS(PClassPointer)) + else if (type->isClassPointer()) { // Actor name sc.SetEscape(true); sc.MustGetString(); @@ -866,22 +866,22 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul if (sc.CheckNumber()) *(int*)addr = sc.Number; else *(PalEntry*)addr = V_GetColor(nullptr, sc); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt))) + else if (f->Type->isIntCompatible()) { sc.MustGetNumber(); static_cast(f->Type)->SetValue(addr, sc.Number); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat))) + else if (f->Type->isFloat()) { sc.MustGetFloat(); static_cast(f->Type)->SetValue(addr, sc.Float); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PString))) + else if (f->Type == TypeString) { sc.MustGetString(); *(FString*)addr = strbin1(sc.String); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer))) + else if (f->Type->isClassPointer()) { sc.MustGetString(); @@ -892,13 +892,14 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul else { auto cls = PClass::FindClass(sc.String); + auto cp = static_cast(f->Type); if (cls == nullptr) { - cls = static_cast(f->Type)->ClassRestriction->FindClassTentative(sc.String); + cls = cp->ClassRestriction->FindClassTentative(sc.String); } - else if (!cls->IsDescendantOf(static_cast(f->Type)->ClassRestriction)) + else if (!cls->IsDescendantOf(cp->ClassRestriction)) { - sc.ScriptMessage("class %s is not compatible with property type %s", sc.String, static_cast(f->Type)->ClassRestriction->TypeName.GetChars()); + sc.ScriptMessage("class %s is not compatible with property type %s", sc.String, cp->ClassRestriction->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } *(PClass**)addr = cls; diff --git a/src/scripting/symbols.cpp b/src/scripting/symbols.cpp index 098ecaaa5a..057b6ef290 100644 --- a/src/scripting/symbols.cpp +++ b/src/scripting/symbols.cpp @@ -47,7 +47,6 @@ FNamespaceManager Namespaces; // Symbol tables ------------------------------------------------------------ -IMPLEMENT_CLASS(PTypeBase, true, false); IMPLEMENT_CLASS(PSymbol, true, false); IMPLEMENT_CLASS(PSymbolConst, false, false); IMPLEMENT_CLASS(PSymbolConstNumeric, false, false); @@ -56,12 +55,6 @@ IMPLEMENT_CLASS(PSymbolTreeNode, false, false) IMPLEMENT_CLASS(PSymbolType, false, false) IMPLEMENT_CLASS(PSymbolVMFunction, false, false) IMPLEMENT_CLASS(PFunction, false, false) -IMPLEMENT_CLASS(PNamespace, false, true) - -IMPLEMENT_POINTERS_START(PNamespace) -IMPLEMENT_POINTER(Parent) -IMPLEMENT_POINTERS_END - //========================================================================== // @@ -104,9 +97,9 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray &argflags, TA if (flags & VARF_Method) { assert(proto->ArgumentTypes.Size() > 0); - auto selftypeptr = dyn_cast(proto->ArgumentTypes[0]); + auto selftypeptr = proto->ArgumentTypes[0]->toPointer(); assert(selftypeptr != nullptr); - variant.SelfClass = dyn_cast(selftypeptr->PointedType); + variant.SelfClass = selftypeptr->PointedType->toContainer(); assert(variant.SelfClass != nullptr); } else @@ -155,7 +148,7 @@ PField::PField(FName name, PType *type, uint32_t flags, size_t offset, int bitva unsigned val = bitvalue; while ((val >>= 1)) BitValue++; - if (type->IsA(RUNTIME_CLASS(PInt)) && unsigned(BitValue) < 8u * type->Size) + if (type->isInt() && unsigned(BitValue) < 8u * type->Size) { // map to the single bytes in the actual variable. The internal bit instructions operate on 8 bit values. #ifndef __BIG_ENDIAN__ @@ -523,21 +516,6 @@ PNamespace *FNamespaceManager::NewNamespace(int filenum) // //========================================================================== -size_t FNamespaceManager::MarkSymbols() -{ - for (auto ns : AllNamespaces) - { - GC::Mark(ns); - } - return AllNamespaces.Size(); -} - -//========================================================================== -// -// -// -//========================================================================== - void FNamespaceManager::ReleaseSymbols() { RemoveSymbols(); @@ -559,7 +537,7 @@ int FNamespaceManager::RemoveSymbols() for (auto ns : AllNamespaces) { count += ns->Symbols.Symbols.CountUsed(); - ns->Symbols.ReleaseSymbols(); + delete ns; } return count; } @@ -582,7 +560,7 @@ void RemoveUnusedSymbols() { for (PType *ty = TypeTable.TypeHash[i]; ty != nullptr; ty = ty->HashNext) { - if (ty->IsKindOf(RUNTIME_CLASS(PContainerType))) + if (ty->isContainer()) { auto it = ty->Symbols.GetIterator(); PSymbolTable::MapType::Pair *pair; diff --git a/src/scripting/symbols.h b/src/scripting/symbols.h index 2268bd5ea9..bc6de46b64 100644 --- a/src/scripting/symbols.h +++ b/src/scripting/symbols.h @@ -1,10 +1,6 @@ // Note: This must not be included by anything but dobject.h! #pragma once -#ifndef __DOBJECT_H__ -#error You must #include "dobject.h" to get symbols.h -#endif - class VMFunction; class PType; @@ -14,11 +10,18 @@ class PContainerType; // Symbol information ------------------------------------------------------- -class PTypeBase : public DObject +class PTypeBase { - DECLARE_ABSTRACT_CLASS(PTypeBase, DObject) - public: + // Allocate everything on the global memory arena because all subtypes of this + // will live until the end of the game. + void *operator new(size_t size) + { + return ClassDataAllocator.Alloc(size); + } + + void operator delete(void *) + {} }; class PSymbol : public DObject @@ -249,15 +252,11 @@ private: class PNamespace : public PTypeBase { - DECLARE_CLASS(PNamespace, PTypeBase) - HAS_OBJECT_POINTERS; - public: PSymbolTable Symbols; PNamespace *Parent; int FileNum; // This is for blocking DECORATE access to later files. - PNamespace() {} PNamespace(int filenum, PNamespace *parent); }; @@ -268,7 +267,6 @@ struct FNamespaceManager FNamespaceManager(); PNamespace *NewNamespace(int filenum); - size_t MarkSymbols(); void ReleaseSymbols(); int RemoveSymbols(); }; diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 19a7316bcc..a76fdd5fb9 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -195,8 +195,8 @@ PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *func if (symbol != nullptr) { - auto cls_ctx = dyn_cast(funccls); - auto cls_target = funcsym ? dyn_cast(funcsym->OwningClass) : nullptr; + auto cls_ctx = PType::toClass(funccls); + auto cls_target = funcsym ? PType::toClass(funcsym->OwningClass) : nullptr; if (funcsym == nullptr) { sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars()); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 3c2b4e3f12..be8726b06c 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -70,14 +70,6 @@ static TArray FieldTable; extern int BackbuttonTime; extern float BackbuttonAlpha; -// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but is used everywhere as a special flag. -// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' -// is to create a static variable from it that points to an otherwise unused object and reference that in the script. Yuck!!! -// This must point to a valid DObject derived object so that the garbage collector can deal with it. -// The global VM types are the most convenient options here because they get created before the compiler is started and they -// are not exposed in other ways to scripts - and they do not change unless the engine is shut down. -DEFINE_GLOBAL_NAMED(TypeSInt32, wp_nochange); - //========================================================================== // // List of all flags diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 374d8a524f..c948d05e35 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -446,8 +446,8 @@ int MatchString (const char *in, const char **strings) static bool PointerCheck(PType *symtype, PType *checktype) { - auto symptype = dyn_cast(symtype); - auto checkptype = dyn_cast(checktype); + auto symptype = PType::toClassPointer(symtype); + auto checkptype = PType::toClassPointer(checktype); return symptype != nullptr && checkptype != nullptr && symptype->ClassRestriction->IsDescendantOf(checkptype->ClassRestriction); } diff --git a/src/scripting/types.cpp b/src/scripting/types.cpp index b445ad8844..4649777afe 100644 --- a/src/scripting/types.cpp +++ b/src/scripting/types.cpp @@ -68,9 +68,6 @@ PPointer *TypeVoidPtr; // CODE -------------------------------------------------------------------- -IMPLEMENT_CLASS(PErrorType, false, false) -IMPLEMENT_CLASS(PVoidType, false, false) - void DumpTypeTable() { int used = 0; @@ -116,8 +113,6 @@ void DumpTypeTable() /* PType ******************************************************************/ -IMPLEMENT_CLASS(PType, true, false) - //========================================================================== // // PType Parameterized Constructor @@ -289,27 +284,27 @@ const char *PType::DescriptiveName() const void PType::StaticInit() { // Create types and add them type the type table. - TypeTable.AddType(TypeError = new PErrorType); - TypeTable.AddType(TypeAuto = new PErrorType(2)); - TypeTable.AddType(TypeVoid = new PVoidType); - TypeTable.AddType(TypeSInt8 = new PInt(1, false)); - TypeTable.AddType(TypeUInt8 = new PInt(1, true)); - TypeTable.AddType(TypeSInt16 = new PInt(2, false)); - TypeTable.AddType(TypeUInt16 = new PInt(2, true)); - TypeTable.AddType(TypeSInt32 = new PInt(4, false)); - TypeTable.AddType(TypeUInt32 = new PInt(4, true)); - TypeTable.AddType(TypeBool = new PBool); - TypeTable.AddType(TypeFloat32 = new PFloat(4)); - TypeTable.AddType(TypeFloat64 = new PFloat(8)); - TypeTable.AddType(TypeString = new PString); - TypeTable.AddType(TypeName = new PName); - TypeTable.AddType(TypeSound = new PSound); - TypeTable.AddType(TypeColor = new PColor); - TypeTable.AddType(TypeState = new PStatePointer); - TypeTable.AddType(TypeStateLabel = new PStateLabel); - TypeTable.AddType(TypeNullPtr = new PPointer); - TypeTable.AddType(TypeSpriteID = new PSpriteID); - TypeTable.AddType(TypeTextureID = new PTextureID); + TypeTable.AddType(TypeError = new PErrorType, NAME_None); + TypeTable.AddType(TypeAuto = new PErrorType(2), NAME_None); + TypeTable.AddType(TypeVoid = new PVoidType, NAME_Void); + TypeTable.AddType(TypeSInt8 = new PInt(1, false), NAME_Int); + TypeTable.AddType(TypeUInt8 = new PInt(1, true), NAME_Int); + TypeTable.AddType(TypeSInt16 = new PInt(2, false), NAME_Int); + TypeTable.AddType(TypeUInt16 = new PInt(2, true), NAME_Int); + TypeTable.AddType(TypeSInt32 = new PInt(4, false), NAME_Int); + TypeTable.AddType(TypeUInt32 = new PInt(4, true), NAME_Int); + TypeTable.AddType(TypeBool = new PBool, NAME_Bool); + TypeTable.AddType(TypeFloat32 = new PFloat(4), NAME_Float); + TypeTable.AddType(TypeFloat64 = new PFloat(8), NAME_Float); + TypeTable.AddType(TypeString = new PString, NAME_String); + TypeTable.AddType(TypeName = new PName, NAME_Name); + TypeTable.AddType(TypeSound = new PSound, NAME_Sound); + TypeTable.AddType(TypeColor = new PColor, NAME_Color); + TypeTable.AddType(TypeState = new PStatePointer, NAME_Pointer); + TypeTable.AddType(TypeStateLabel = new PStateLabel, NAME_Label); + TypeTable.AddType(TypeNullPtr = new PPointer, NAME_Pointer); + TypeTable.AddType(TypeSpriteID = new PSpriteID, NAME_SpriteID); + TypeTable.AddType(TypeTextureID = new PTextureID, NAME_TextureID); 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. @@ -330,7 +325,7 @@ void PType::StaticInit() TypeVector2 = new PStruct(NAME_Vector2, nullptr); TypeVector2->AddField(NAME_X, TypeFloat64); TypeVector2->AddField(NAME_Y, TypeFloat64); - TypeTable.AddType(TypeVector2); + TypeTable.AddType(TypeVector2, NAME_Struct); TypeVector2->loadOp = OP_LV2; TypeVector2->storeOp = OP_SV2; TypeVector2->moveOp = OP_MOVEV2; @@ -343,7 +338,7 @@ void PType::StaticInit() TypeVector3->AddField(NAME_Z, TypeFloat64); // allow accessing xy as a vector2. This is not supposed to be serialized so it's marked transient TypeVector3->Symbols.AddSymbol(new PField(NAME_XY, TypeVector2, VARF_Transient, 0)); - TypeTable.AddType(TypeVector3); + TypeTable.AddType(TypeVector3, NAME_Struct); TypeVector3->loadOp = OP_LV3; TypeVector3->storeOp = OP_SV3; TypeVector3->moveOp = OP_MOVEV3; @@ -375,18 +370,6 @@ void PType::StaticInit() /* PBasicType *************************************************************/ -IMPLEMENT_CLASS(PBasicType, true, false) - -//========================================================================== -// -// PBasicType Default Constructor -// -//========================================================================== - -PBasicType::PBasicType() -{ -} - //========================================================================== // // PBasicType Parameterized Constructor @@ -397,16 +380,25 @@ PBasicType::PBasicType(unsigned int size, unsigned int align) : PType(size, align) { mDescriptiveName = "BasicType"; + Flags |= TYPE_Scalar; } /* PCompoundType **********************************************************/ -IMPLEMENT_CLASS(PCompoundType, true, false) +//========================================================================== +// +// PBasicType Parameterized Constructor +// +//========================================================================== + +PCompoundType::PCompoundType(unsigned int size, unsigned int align) + : PType(size, align) +{ + mDescriptiveName = "CompoundType"; +} /* PContainerType *************************************************************/ -IMPLEMENT_CLASS(PContainerType, true, false) - //========================================================================== // // PContainerType :: IsMatch @@ -415,7 +407,7 @@ IMPLEMENT_CLASS(PContainerType, true, false) bool PContainerType::IsMatch(intptr_t id1, intptr_t id2) const { - const DObject *outer = (const DObject *)id1; + const PTypeBase *outer = (const PTypeBase *)id1; FName name = (ENamedName)(intptr_t)id2; return Outer == outer && TypeName == name; @@ -435,23 +427,6 @@ void PContainerType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const /* PInt *******************************************************************/ -IMPLEMENT_CLASS(PInt, false, false) - -//========================================================================== -// -// PInt Default Constructor -// -//========================================================================== - -PInt::PInt() -: PBasicType(4, 4), Unsigned(false), IntCompatible(true) -{ - mDescriptiveName = "SInt32"; - Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1)); - Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF)); - SetOps(); -} - //========================================================================== // // PInt Parameterized Constructor @@ -462,6 +437,7 @@ PInt::PInt(unsigned int size, bool unsign, bool compatible) : PBasicType(size, size), Unsigned(unsign), IntCompatible(compatible) { mDescriptiveName.Format("%cInt%d", unsign? 'U':'S', size); + Flags |= TYPE_Int; MemberOnly = (size < 4); if (!unsign) @@ -674,8 +650,6 @@ double PInt::GetValueFloat(void *addr) const /* PBool ******************************************************************/ -IMPLEMENT_CLASS(PBool, false, false) - //========================================================================== // // PInt :: SetValue @@ -713,26 +687,11 @@ PBool::PBool() { mDescriptiveName = "Bool"; MemberOnly = false; + Flags |= TYPE_IntNotInt; } /* PFloat *****************************************************************/ -IMPLEMENT_CLASS(PFloat, false, false) - -//========================================================================== -// -// PFloat Default Constructor -// -//========================================================================== - -PFloat::PFloat() -: PBasicType(8, 8) -{ - mDescriptiveName = "Float"; - SetDoubleSymbols(); - SetOps(); -} - //========================================================================== // // PFloat Parameterized Constructor @@ -743,6 +702,7 @@ PFloat::PFloat(unsigned int size) : PBasicType(size, size) { mDescriptiveName.Format("Float%d", size); + Flags |= TYPE_Float; if (size == 8) { #ifdef __i386__ @@ -976,8 +936,6 @@ void PFloat::SetOps() /* PString ****************************************************************/ -IMPLEMENT_CLASS(PString, false, false) - //========================================================================== // // PString Default Constructor @@ -1073,8 +1031,6 @@ void PString::DestroyValue(void *addr) const /* PName ******************************************************************/ -IMPLEMENT_CLASS(PName, false, false) - //========================================================================== // // PName Default Constructor @@ -1085,6 +1041,7 @@ PName::PName() : PInt(sizeof(FName), true, false) { mDescriptiveName = "Name"; + Flags |= TYPE_IntNotInt; assert(sizeof(FName) == alignof(FName)); } @@ -1123,8 +1080,6 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSpriteID ******************************************************************/ -IMPLEMENT_CLASS(PSpriteID, false, false) - //========================================================================== // // PName Default Constructor @@ -1134,6 +1089,7 @@ IMPLEMENT_CLASS(PSpriteID, false, false) PSpriteID::PSpriteID() : PInt(sizeof(int), true, true) { + Flags |= TYPE_IntNotInt; mDescriptiveName = "SpriteID"; } @@ -1165,8 +1121,6 @@ bool PSpriteID::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PTextureID ******************************************************************/ -IMPLEMENT_CLASS(PTextureID, false, false) - //========================================================================== // // PTextureID Default Constructor @@ -1177,6 +1131,7 @@ PTextureID::PTextureID() : PInt(sizeof(FTextureID), true, false) { mDescriptiveName = "TextureID"; + Flags |= TYPE_IntNotInt; assert(sizeof(FTextureID) == alignof(FTextureID)); } @@ -1208,8 +1163,6 @@ bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSound *****************************************************************/ -IMPLEMENT_CLASS(PSound, false, false) - //========================================================================== // // PSound Default Constructor @@ -1220,6 +1173,7 @@ PSound::PSound() : PInt(sizeof(FSoundID), true) { mDescriptiveName = "Sound"; + Flags |= TYPE_IntNotInt; assert(sizeof(FSoundID) == alignof(FSoundID)); } @@ -1258,8 +1212,6 @@ bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PColor *****************************************************************/ -IMPLEMENT_CLASS(PColor, false, false) - //========================================================================== // // PColor Default Constructor @@ -1270,13 +1222,12 @@ PColor::PColor() : PInt(sizeof(PalEntry), true) { mDescriptiveName = "Color"; + Flags |= TYPE_IntNotInt; assert(sizeof(PalEntry) == alignof(PalEntry)); } /* PStateLabel *****************************************************************/ -IMPLEMENT_CLASS(PStateLabel, false, false) - //========================================================================== // // PStateLabel Default Constructor @@ -1286,13 +1237,12 @@ IMPLEMENT_CLASS(PStateLabel, false, false) PStateLabel::PStateLabel() : PInt(sizeof(int), false, false) { + Flags |= TYPE_IntNotInt; mDescriptiveName = "StateLabel"; } /* PPointer ***************************************************************/ -IMPLEMENT_CLASS(PPointer, false, false) - //========================================================================== // // PPointer - Default Constructor @@ -1307,6 +1257,7 @@ PPointer::PPointer() storeOp = OP_SP; moveOp = OP_MOVEA; RegType = REGT_POINTER; + Flags |= TYPE_Pointer; } //========================================================================== @@ -1332,6 +1283,7 @@ PPointer::PPointer(PType *pointsat, bool isconst) storeOp = OP_SP; moveOp = OP_MOVEA; RegType = REGT_POINTER; + Flags |= TYPE_Pointer; } //========================================================================== @@ -1395,8 +1347,6 @@ bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PObjectPointer **********************************************************/ -IMPLEMENT_CLASS(PObjectPointer, false, false) - //========================================================================== // // PPointer :: GetStoreOp @@ -1407,6 +1357,7 @@ PObjectPointer::PObjectPointer(PClass *cls, bool isconst) : PPointer(cls->VMType, isconst) { loadOp = OP_LO; + Flags |= TYPE_ObjectPointer; // Non-destroyed thinkers are always guaranteed to be linked into the thinker chain so we don't need the write barrier for them. if (cls && !cls->IsDescendantOf(RUNTIME_CLASS(DThinker))) storeOp = OP_SO; } @@ -1457,15 +1408,15 @@ bool PObjectPointer::ReadValue(FSerializer &ar, const char *key, void *addr) con PPointer *NewPointer(PType *type, bool isconst) { - auto cp = dyn_cast(type); + auto cp = PType::toClass(type); if (cp) return NewPointer(cp->Descriptor, isconst); size_t bucket; - PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, &bucket); + PType *ptype = TypeTable.FindType(NAME_Pointer, (intptr_t)type, isconst ? 1 : 0, &bucket); if (ptype == nullptr) { ptype = new PPointer(type, isconst); - TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, bucket); + TypeTable.AddType(ptype, NAME_Pointer, (intptr_t)type, isconst ? 1 : 0, bucket); } return static_cast(ptype); } @@ -1476,19 +1427,17 @@ PPointer *NewPointer(PClass *cls, bool isconst) auto type = cls->VMType; size_t bucket; - PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PObjectPointer), (intptr_t)type, isconst ? 1 : 0, &bucket); + PType *ptype = TypeTable.FindType(NAME_Pointer, (intptr_t)type, isconst ? 1 : 0, &bucket); if (ptype == nullptr) { ptype = new PObjectPointer(cls, isconst); - TypeTable.AddType(ptype, RUNTIME_CLASS(PObjectPointer), (intptr_t)type, isconst ? 1 : 0, bucket); + TypeTable.AddType(ptype, NAME_Pointer, (intptr_t)type, isconst ? 1 : 0, bucket); } return static_cast(ptype); } /* PStatePointer **********************************************************/ -IMPLEMENT_CLASS(PStatePointer, false, false) - //========================================================================== // // PStatePointer Default Constructor @@ -1530,8 +1479,6 @@ bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons /* PClassPointer **********************************************************/ -IMPLEMENT_CLASS(PClassPointer,false, false) - //========================================================================== // // PClassPointer - Parameterized Constructor @@ -1545,6 +1492,7 @@ PClassPointer::PClassPointer(PClass *restrict) else mDescriptiveName = "ClassPointer"; loadOp = OP_LP; storeOp = OP_SP; + Flags |= TYPE_ClassPointer; mVersion = restrict->VMType->mVersion; } @@ -1579,7 +1527,7 @@ bool PClassPointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons bool PClassPointer::isCompatible(PType *type) { - auto other = dyn_cast(type); + auto other = PType::toClassPointer(type); return (other != nullptr && other->ClassRestriction->IsDescendantOf(ClassRestriction)); } @@ -1628,31 +1576,17 @@ void PClassPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const PClassPointer *NewClassPointer(PClass *restrict) { size_t bucket; - PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PClassPointer), 0, (intptr_t)restrict, &bucket); + PType *ptype = TypeTable.FindType(NAME_Class, 0, (intptr_t)restrict, &bucket); if (ptype == nullptr) { ptype = new PClassPointer(restrict); - TypeTable.AddType(ptype, RUNTIME_CLASS(PClassPointer), 0, (intptr_t)restrict, bucket); + TypeTable.AddType(ptype, NAME_Class, 0, (intptr_t)restrict, bucket); } return static_cast(ptype); } /* PEnum ******************************************************************/ -IMPLEMENT_CLASS(PEnum, false, false) - -//========================================================================== -// -// PEnum - Default Constructor -// -//========================================================================== - -PEnum::PEnum() -: PInt(4, false) -{ - mDescriptiveName = "Enum"; -} - //========================================================================== // // PEnum - Parameterized Constructor @@ -1664,6 +1598,7 @@ PEnum::PEnum(FName name, PTypeBase *outer) { EnumName = name; Outer = outer; + Flags |= TYPE_IntNotInt; mDescriptiveName.Format("Enum<%s>", name.GetChars()); } @@ -1680,31 +1615,17 @@ PEnum *NewEnum(FName name, PTypeBase *outer) { size_t bucket; if (outer == nullptr) outer = Namespaces.GlobalNamespace; - PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket); + PType *etype = TypeTable.FindType(NAME_Enum, (intptr_t)outer, (intptr_t)name, &bucket); if (etype == nullptr) { etype = new PEnum(name, outer); - TypeTable.AddType(etype, RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, bucket); + TypeTable.AddType(etype, NAME_Enum, (intptr_t)outer, (intptr_t)name, bucket); } return static_cast(etype); } /* PArray *****************************************************************/ -IMPLEMENT_CLASS(PArray, false, false) - -//========================================================================== -// -// PArray - Default Constructor -// -//========================================================================== - -PArray::PArray() -: ElementType(nullptr), ElementCount(0) -{ - mDescriptiveName = "Array"; -} - //========================================================================== // // PArray - Parameterized Constructor @@ -1721,6 +1642,7 @@ PArray::PArray(PType *etype, unsigned int ecount) // also be padded to the nearest alignment. ElementSize = (etype->Size + (etype->Align - 1)) & ~(etype->Align - 1); Size = ElementSize * ecount; + Flags |= TYPE_Array; } //========================================================================== @@ -1839,30 +1761,17 @@ void PArray::SetPointer(void *base, unsigned offset, TArray *special) PArray *NewArray(PType *type, unsigned int count) { size_t bucket; - PType *atype = TypeTable.FindType(RUNTIME_CLASS(PArray), (intptr_t)type, count, &bucket); + PType *atype = TypeTable.FindType(NAME_Array, (intptr_t)type, count, &bucket); if (atype == nullptr) { atype = new PArray(type, count); - TypeTable.AddType(atype, RUNTIME_CLASS(PArray), (intptr_t)type, count, bucket); + TypeTable.AddType(atype, NAME_Array, (intptr_t)type, count, bucket); } return (PArray *)atype; } /* PArray *****************************************************************/ -IMPLEMENT_CLASS(PStaticArray, false, false) - -//========================================================================== -// -// PArray - Default Constructor -// -//========================================================================== - -PStaticArray::PStaticArray() -{ - mDescriptiveName = "ResizableArray"; -} - //========================================================================== // // PArray - Parameterized Constructor @@ -1913,33 +1822,17 @@ void PStaticArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const PStaticArray *NewStaticArray(PType *type) { size_t bucket; - PType *atype = TypeTable.FindType(RUNTIME_CLASS(PStaticArray), (intptr_t)type, 0, &bucket); + PType *atype = TypeTable.FindType(NAME_StaticArray, (intptr_t)type, 0, &bucket); if (atype == nullptr) { atype = new PStaticArray(type); - TypeTable.AddType(atype, RUNTIME_CLASS(PStaticArray), (intptr_t)type, 0, bucket); + TypeTable.AddType(atype, NAME_StaticArray, (intptr_t)type, 0, bucket); } return (PStaticArray *)atype; } /* PDynArray **************************************************************/ -IMPLEMENT_CLASS(PDynArray, false, false) - -//========================================================================== -// -// PDynArray - Default Constructor -// -//========================================================================== - -PDynArray::PDynArray() -: ElementType(nullptr) -{ - mDescriptiveName = "DynArray"; - Size = sizeof(FArray); - Align = alignof(FArray); -} - //========================================================================== // // PDynArray - Parameterized Constructor @@ -2060,7 +1953,7 @@ void PDynArray::SetDefaultValue(void *base, unsigned offset, TArray *special) const { - if (ElementType->IsKindOf(RUNTIME_CLASS(PObjectPointer))) + if (ElementType->isObjectPointer()) { // Add to the list of pointer arrays for this class. special->Push(offset); @@ -2138,7 +2031,7 @@ bool PDynArray::ReadValue(FSerializer &ar, const char *key, void *addr) const PDynArray *NewDynArray(PType *type) { size_t bucket; - PType *atype = TypeTable.FindType(RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, &bucket); + PType *atype = TypeTable.FindType(NAME_DynArray, (intptr_t)type, 0, &bucket); if (atype == nullptr) { FString backingname; @@ -2168,29 +2061,13 @@ PDynArray *NewDynArray(PType *type) auto backing = NewStruct(backingname, nullptr, true); atype = new PDynArray(type, backing); - TypeTable.AddType(atype, RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, bucket); + TypeTable.AddType(atype, NAME_DynArray, (intptr_t)type, 0, bucket); } return (PDynArray *)atype; } /* PMap *******************************************************************/ -IMPLEMENT_CLASS(PMap, false, false) - -//========================================================================== -// -// PMap - Default Constructor -// -//========================================================================== - -PMap::PMap() -: KeyType(nullptr), ValueType(nullptr) -{ - mDescriptiveName = "Map"; - Size = sizeof(FMap); - Align = alignof(FMap); -} - //========================================================================== // // PMap - Parameterized Constructor @@ -2243,31 +2120,17 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const PMap *NewMap(PType *keytype, PType *valuetype) { size_t bucket; - PType *maptype = TypeTable.FindType(RUNTIME_CLASS(PMap), (intptr_t)keytype, (intptr_t)valuetype, &bucket); + PType *maptype = TypeTable.FindType(NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, &bucket); if (maptype == nullptr) { maptype = new PMap(keytype, valuetype); - TypeTable.AddType(maptype, RUNTIME_CLASS(PMap), (intptr_t)keytype, (intptr_t)valuetype, bucket); + TypeTable.AddType(maptype, NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, bucket); } return (PMap *)maptype; } /* PStruct ****************************************************************/ -IMPLEMENT_CLASS(PStruct, false, false) - -//========================================================================== -// -// PStruct - Default Constructor -// -//========================================================================== - -PStruct::PStruct() -{ - mDescriptiveName = "Struct"; - Size = 0; -} - //========================================================================== // // PStruct - Parameterized Constructor @@ -2394,11 +2257,11 @@ 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); + PType *stype = TypeTable.FindType(NAME_Struct, (intptr_t)outer, (intptr_t)name, &bucket); if (stype == nullptr) { stype = new PStruct(name, outer, native); - TypeTable.AddType(stype, RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, bucket); + TypeTable.AddType(stype, NAME_Struct, (intptr_t)outer, (intptr_t)name, bucket); } return static_cast(stype); } @@ -2406,18 +2269,6 @@ PStruct *NewStruct(FName name, PTypeBase *outer, bool native) /* PPrototype *************************************************************/ -IMPLEMENT_CLASS(PPrototype, false, false) - -//========================================================================== -// -// PPrototype - Default Constructor -// -//========================================================================== - -PPrototype::PPrototype() -{ -} - //========================================================================== // // PPrototype - Parameterized Constructor @@ -2455,20 +2306,6 @@ void PPrototype::GetTypeIDs(intptr_t &id1, intptr_t &id2) const id2 = (intptr_t)&ReturnTypes; } -//========================================================================== -// -// PPrototype :: PropagateMark -// -//========================================================================== - -size_t PPrototype::PropagateMark() -{ - GC::MarkArray(ArgumentTypes); - GC::MarkArray(ReturnTypes); - return (ArgumentTypes.Size() + ReturnTypes.Size()) * sizeof(void*) + - Super::PropagateMark(); -} - //========================================================================== // // NewPrototype @@ -2481,19 +2318,17 @@ size_t PPrototype::PropagateMark() PPrototype *NewPrototype(const TArray &rettypes, const TArray &argtypes) { size_t bucket; - PType *proto = TypeTable.FindType(RUNTIME_CLASS(PPrototype), (intptr_t)&argtypes, (intptr_t)&rettypes, &bucket); + PType *proto = TypeTable.FindType(NAME_Prototype, (intptr_t)&argtypes, (intptr_t)&rettypes, &bucket); if (proto == nullptr) { proto = new PPrototype(rettypes, argtypes); - TypeTable.AddType(proto, RUNTIME_CLASS(PPrototype), (intptr_t)&argtypes, (intptr_t)&rettypes, bucket); + TypeTable.AddType(proto, NAME_Prototype, (intptr_t)&argtypes, (intptr_t)&rettypes, bucket); } return static_cast(proto); } /* PClass *****************************************************************/ -IMPLEMENT_CLASS(PClassType, false, false) - //========================================================================== // // @@ -2510,6 +2345,7 @@ PClassType::PClassType(PClass *cls) ParentType = cls->ParentClass->VMType; assert(ParentType != nullptr); Symbols.SetParentTable(&ParentType->Symbols); + ScopeFlags = ParentType->ScopeFlags; } cls->VMType = this; mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars()); @@ -2548,11 +2384,11 @@ PField *PClassType::AddNativeField(FName name, PType *type, size_t address, uint PClassType *NewClassType(PClass *cls) { size_t bucket; - PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PClassType), 0, (intptr_t)cls->TypeName, &bucket); + PType *ptype = TypeTable.FindType(NAME_Object, 0, (intptr_t)cls->TypeName, &bucket); if (ptype == nullptr) { ptype = new PClassType(cls); - TypeTable.AddType(ptype, RUNTIME_CLASS(PClassType), 0, (intptr_t)cls->TypeName, bucket); + TypeTable.AddType(ptype, NAME_Object, 0, (intptr_t)cls->TypeName, bucket); } return static_cast(ptype); } @@ -2566,16 +2402,16 @@ PClassType *NewClassType(PClass *cls) // //========================================================================== -PType *FTypeTable::FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, size_t *bucketnum) +PType *FTypeTable::FindType(FName type_name, intptr_t parm1, intptr_t parm2, size_t *bucketnum) { - size_t bucket = Hash(metatype, parm1, parm2) % HASH_SIZE; + size_t bucket = Hash(type_name, parm1, parm2) % HASH_SIZE; if (bucketnum != nullptr) { *bucketnum = bucket; } for (PType *type = TypeHash[bucket]; type != nullptr; type = type->HashNext) { - if (type->TypeTableType == metatype && type->IsMatch(parm1, parm2)) + if (type->TypeTableType == type_name && type->IsMatch(parm1, parm2)) { return type; } @@ -2589,17 +2425,16 @@ PType *FTypeTable::FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, si // //========================================================================== -void FTypeTable::AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t parm2, size_t bucket) +void FTypeTable::AddType(PType *type, FName type_name, intptr_t parm1, intptr_t parm2, size_t bucket) { #ifdef _DEBUG size_t bucketcheck; - assert(FindType(metatype, parm1, parm2, &bucketcheck) == nullptr && "Type must not be inserted more than once"); + assert(FindType(type_name, parm1, parm2, &bucketcheck) == nullptr && "Type must not be inserted more than once"); assert(bucketcheck == bucket && "Passed bucket was wrong"); #endif - type->TypeTableType = metatype; + type->TypeTableType = type_name; type->HashNext = TypeHash[bucket]; TypeHash[bucket] = type; - type->Release(); } //========================================================================== @@ -2608,21 +2443,19 @@ void FTypeTable::AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t // //========================================================================== -void FTypeTable::AddType(PType *type) +void FTypeTable::AddType(PType *type, FName type_name) { intptr_t parm1, parm2; size_t bucket; // Type table stuff id only needed to let all classes hash to the same group. For all other types this is pointless. - type->TypeTableType = type->GetClass(); - PClass *metatype = type->TypeTableType; + type->TypeTableType = type_name; type->GetTypeIDs(parm1, parm2); - bucket = Hash(metatype, parm1, parm2) % HASH_SIZE; - assert(FindType(metatype, parm1, parm2, nullptr) == nullptr && "Type must not be inserted more than once"); + bucket = Hash(type_name, parm1, parm2) % HASH_SIZE; + assert(FindType(type_name, parm1, parm2, nullptr) == nullptr && "Type must not be inserted more than once"); type->HashNext = TypeHash[bucket]; TypeHash[bucket] = type; - type->Release(); } //========================================================================== @@ -2631,7 +2464,7 @@ void FTypeTable::AddType(PType *type) // //========================================================================== -size_t FTypeTable::Hash(const PClass *p1, intptr_t p2, intptr_t p3) +size_t FTypeTable::Hash(FName p1, intptr_t p2, intptr_t p3) { size_t i1 = (size_t)p1; @@ -2639,7 +2472,7 @@ size_t FTypeTable::Hash(const PClass *p1, intptr_t p2, intptr_t p3) // to transform this into a ROR or ROL. i1 = (i1 >> (sizeof(size_t)*4)) | (i1 << (sizeof(size_t)*4)); - if (p1 != RUNTIME_CLASS(PPrototype)) + if (p1 != NAME_Prototype) { size_t i2 = (size_t)p2; size_t i3 = (size_t)p3; diff --git a/src/scripting/types.h b/src/scripting/types.h index 3c233c6175..d4dc196f7a 100644 --- a/src/scripting/types.h +++ b/src/scripting/types.h @@ -2,9 +2,9 @@ #include "dobject.h" #include "serializer.h" +#include "scripting/backend/scopebarrier.h" // Variable/parameter/field flags ------------------------------------------- -class PStruct; // Making all these different storage types use a common set of flags seems // like the simplest thing to do. @@ -61,22 +61,45 @@ enum // Map * * // Prototype *+ *+ +class PContainerType; +class PPointer; +class PClassPointer; +class PArray; +class PStruct; +class PClassType; + struct ZCC_ExprConstant; class PType : public PTypeBase { - DECLARE_ABSTRACT_CLASS(PType, PTypeBase) protected: + enum ETypeFlags + { + TYPE_Scalar = 1, + TYPE_Container = 2, + TYPE_Int = 4, + TYPE_IntNotInt = 8, // catch-all for subtypes that are not being checked by type directly. + TYPE_Float = 16, + TYPE_Pointer = 32, + TYPE_ObjectPointer = 64, + TYPE_ClassPointer = 128, + TYPE_Array = 256, + + TYPE_IntCompatible = TYPE_Int | TYPE_IntNotInt, // must be the combination of all flags that are subtypes of int and can be cast to an int. + }; + public: - PClass *TypeTableType; // The type to use for hashing into the type table + FName TypeTableType; // The type to use for hashing into the type table unsigned int Size; // this type's size unsigned int Align; // this type's preferred alignment + unsigned int Flags = 0; // What is this type? PType *HashNext; // next type in this type table PSymbolTable Symbols; bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument. FString mDescriptiveName; VersionInfo mVersion = { 0,0,0 }; uint8_t loadOp, storeOp, moveOp, RegType, RegCount; + EScopeFlags ScopeFlags = (EScopeFlags)0; PType(unsigned int size = 1, unsigned int align = 1); virtual ~PType(); @@ -160,20 +183,40 @@ public: const char *DescriptiveName() const; static void StaticInit(); + + bool isScalar() const { return !!(Flags & TYPE_Scalar); } + bool isContainer() const { return !!(Flags & TYPE_Container); } + bool isInt() const { return (Flags & TYPE_IntCompatible) == TYPE_Int; } + bool isIntCompatible() const { return !!(Flags & TYPE_IntCompatible); } + bool isFloat() const { return !!(Flags & TYPE_Float); } + bool isPointer() const { return !!(Flags & TYPE_Pointer); } + bool isRealPointer() const { return (Flags & (TYPE_Pointer|TYPE_ClassPointer)) == TYPE_Pointer; } // This excludes class pointers which use their PointedType differently + bool isObjectPointer() const { return !!(Flags & TYPE_ObjectPointer); } + bool isClassPointer() const { return !!(Flags & TYPE_ClassPointer); } + bool isEnum() const { return TypeTableType == NAME_Enum; } + bool isArray() const { return !!(Flags & TYPE_Array); } + bool isStaticArray() const { return TypeTableType == NAME_StaticArray; } + bool isDynArray() const { return TypeTableType == NAME_DynArray; } + bool isStruct() const { return TypeTableType == NAME_Struct; } + bool isClass() const { return TypeTableType == NAME_Object; } + bool isPrototype() const { return TypeTableType == NAME_Prototype; } + + PContainerType *toContainer() { return isContainer() ? (PContainerType*)this : nullptr; } + PPointer *toPointer() { return isPointer() ? (PPointer*)this : nullptr; } + static PClassPointer *toClassPointer(PType *t) { return t && t->isClassPointer() ? (PClassPointer*)t : nullptr; } + static PClassType *toClass(PType *t) { return t && t->isClass() ? (PClassType*)t : nullptr; } }; // Not-really-a-type types -------------------------------------------------- class PErrorType : public PType { - DECLARE_CLASS(PErrorType, PType); public: PErrorType(int which = 1) : PType(0, which) {} }; class PVoidType : public PType { - DECLARE_CLASS(PVoidType, PType); public: PVoidType() : PType(0, 1) {} }; @@ -182,29 +225,31 @@ public: class PBasicType : public PType { - DECLARE_ABSTRACT_CLASS(PBasicType, PType); -public: - PBasicType(); - PBasicType(unsigned int size, unsigned int align); +protected: + PBasicType(unsigned int size = 1, unsigned int align = 1); }; class PCompoundType : public PType { - DECLARE_ABSTRACT_CLASS(PCompoundType, PType); +protected: + PCompoundType(unsigned int size = 1, unsigned int align = 1); }; class PContainerType : public PCompoundType { - DECLARE_ABSTRACT_CLASS(PContainerType, PCompoundType); public: PTypeBase *Outer; // object this type is contained within FName TypeName; // this type's name - PContainerType() : Outer(NULL) { - mDescriptiveName = "NamedType"; + PContainerType() : Outer(NULL) + { + mDescriptiveName = "ContainerType"; + Flags |= TYPE_Container; } - PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) { + PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) + { mDescriptiveName = name.GetChars(); + Flags |= TYPE_Container; } virtual bool IsMatch(intptr_t id1, intptr_t id2) const; @@ -217,7 +262,6 @@ public: class PInt : public PBasicType { - DECLARE_CLASS(PInt, PBasicType); public: PInt(unsigned int size, bool unsign, bool compatible = true); @@ -233,13 +277,11 @@ public: bool Unsigned; bool IntCompatible; protected: - PInt(); void SetOps(); }; class PBool : public PInt { - DECLARE_CLASS(PBool, PInt); public: PBool(); virtual void SetValue(void *addr, int val); @@ -250,9 +292,8 @@ public: class PFloat : public PBasicType { - DECLARE_CLASS(PFloat, PBasicType); public: - PFloat(unsigned int size); + PFloat(unsigned int size = 8); void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; @@ -263,7 +304,6 @@ public: virtual double GetValueFloat(void *addr) const; virtual bool isNumeric() override { return true; } protected: - PFloat(); void SetOps(); private: struct SymbolInitF @@ -285,7 +325,6 @@ private: class PString : public PBasicType { - DECLARE_CLASS(PString, PBasicType); public: PString(); @@ -300,7 +339,6 @@ public: class PName : public PInt { - DECLARE_CLASS(PName, PInt); public: PName(); @@ -310,7 +348,6 @@ public: class PSound : public PInt { - DECLARE_CLASS(PSound, PInt); public: PSound(); @@ -320,7 +357,6 @@ public: class PSpriteID : public PInt { - DECLARE_CLASS(PSpriteID, PInt); public: PSpriteID(); @@ -330,7 +366,6 @@ public: class PTextureID : public PInt { - DECLARE_CLASS(PTextureID, PInt); public: PTextureID(); @@ -340,14 +375,12 @@ public: class PColor : public PInt { - DECLARE_CLASS(PColor, PInt); public: PColor(); }; class PStateLabel : public PInt { - DECLARE_CLASS(PStateLabel, PInt); public: PStateLabel(); }; @@ -356,7 +389,6 @@ public: class PPointer : public PBasicType { - DECLARE_CLASS(PPointer, PBasicType); public: typedef void(*WriteHandler)(FSerializer &ar, const char *key, const void *addr); @@ -389,7 +421,6 @@ protected: class PStatePointer : public PPointer { - DECLARE_CLASS(PStatePointer, PPointer); public: PStatePointer(); @@ -400,7 +431,6 @@ public: class PObjectPointer : public PPointer { - DECLARE_CLASS(PObjectPointer, PPointer); public: PObjectPointer(PClass *pointedtype = nullptr, bool isconst = false); @@ -413,7 +443,6 @@ public: class PClassPointer : public PPointer { - DECLARE_CLASS(PClassPointer, PPointer); public: PClassPointer(class PClass *restrict = nullptr); @@ -432,19 +461,15 @@ public: class PEnum : public PInt { - DECLARE_CLASS(PEnum, PInt); public: PEnum(FName name, PTypeBase *outer); PTypeBase *Outer; FName EnumName; -protected: - PEnum(); }; class PArray : public PCompoundType { - DECLARE_CLASS(PArray, PCompoundType); public: PArray(PType *etype, unsigned int ecount); @@ -460,27 +485,19 @@ public: void SetDefaultValue(void *base, unsigned offset, TArray *special) override; void SetPointer(void *base, unsigned offset, TArray *special) override; - -protected: - PArray(); }; class PStaticArray : public PArray { - DECLARE_CLASS(PStaticArray, PArray); public: PStaticArray(PType *etype); virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; - -protected: - PStaticArray(); }; class PDynArray : public PCompoundType { - DECLARE_CLASS(PDynArray, PCompoundType); public: PDynArray(PType *etype, PStruct *backing); @@ -496,14 +513,10 @@ public: void InitializeValue(void *addr, const void *def) const override; void DestroyValue(void *addr) const override; void SetPointerArray(void *base, unsigned offset, TArray *ptrofs = NULL) const override; - -protected: - PDynArray(); }; class PMap : public PCompoundType { - DECLARE_CLASS(PMap, PCompoundType); public: PMap(PType *keytype, PType *valtype); @@ -512,14 +525,10 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; -protected: - PMap(); }; class PStruct : public PContainerType { - DECLARE_CLASS(PStruct, PContainerType); - public: PStruct(FName name, PTypeBase *outer, bool isnative = false); @@ -535,25 +544,18 @@ public: bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; void SetDefaultValue(void *base, unsigned offset, TArray *specials) override; void SetPointer(void *base, unsigned offset, TArray *specials) override; - -protected: - PStruct(); }; class PPrototype : public PCompoundType { - DECLARE_CLASS(PPrototype, PCompoundType); public: PPrototype(const TArray &rettypes, const TArray &argtypes); TArray ArgumentTypes; TArray ReturnTypes; - size_t PropagateMark(); virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; -protected: - PPrototype(); }; @@ -561,10 +563,6 @@ protected: class PClassType : public PContainerType { - DECLARE_CLASS(PClassType, PContainerType); - -private: - public: PClass *Descriptor; PClassType *ParentType; @@ -628,12 +626,12 @@ struct FTypeTable PType *TypeHash[HASH_SIZE]; - PType *FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, size_t *bucketnum); - void AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t parm2, size_t bucket); - void AddType(PType *type); + PType *FindType(FName type_name, intptr_t parm1, intptr_t parm2, size_t *bucketnum); + void AddType(PType *type, FName type_name, intptr_t parm1, intptr_t parm2, size_t bucket); + void AddType(PType *type, FName type_name); void Clear(); - static size_t Hash(const PClass *p1, intptr_t p2, intptr_t p3); + static size_t Hash(FName p1, intptr_t p2, intptr_t p3); }; diff --git a/src/scripting/zscript/ast.cpp b/src/scripting/zscript/ast.cpp index d886c8db27..463364f99a 100644 --- a/src/scripting/zscript/ast.cpp +++ b/src/scripting/zscript/ast.cpp @@ -593,7 +593,7 @@ static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node) { out.AddName(ENamedName(enode->IntVal)); } - else if (enode->Type->IsKindOf(RUNTIME_CLASS(PInt))) + else if (enode->Type->isIntCompatible()) { out.AddInt(enode->IntVal, static_cast(enode->Type)->Unsigned); } diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index cf7eb45661..923c40eef4 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -403,7 +403,7 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC // Compute implicit values by adding one to the preceding value. assert(prev->Value != NULL); // If the preceding node is a constant, then we can do this now. - if (prev->Value->Operation == PEX_ConstValue && prev->Value->Type->IsA(RUNTIME_CLASS(PInt))) + if (prev->Value->Operation == PEX_ConstValue && prev->Value->Type->isInt()) { NEW_INTCONST_NODE(cval, prev->Value->Type, static_cast(prev->Value)->IntVal + 1, node); node->Value = cval; @@ -1256,9 +1256,9 @@ unary_expr(X) ::= primary(X). unary_expr(X) ::= SUB unary_expr(A). [UNARY] { ZCC_ExprConstant *con = static_cast(A); - if (A->Operation == PEX_ConstValue && (con->Type->IsA(RUNTIME_CLASS(PInt)) || con->Type->IsA(RUNTIME_CLASS(PFloat)))) + if (A->Operation == PEX_ConstValue && (con->Type->isInt() || con->Type->isFloat())) { // For constants, manipulate the child node directly, and don't create a new node. - if (con->Type->IsA(RUNTIME_CLASS(PInt))) + if (con->Type->isInt()) { con->IntVal = -con->IntVal; } @@ -1280,7 +1280,7 @@ unary_expr(X) ::= ADD unary_expr(A). [UNARY] // it so we can type check that it is being applied to something numeric. // But we can do that right now for constant numerals. ZCC_ExprConstant *con = static_cast(A); - if (A->Operation != PEX_ConstValue || (!con->Type->IsA(RUNTIME_CLASS(PInt)) && !con->Type->IsA(RUNTIME_CLASS(PFloat)))) + if (A->Operation != PEX_ConstValue || (!con->Type->isInt() && !con->Type->isFloat())) { UNARY_EXPR(A,PEX_AntiNegate); X = expr1; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 1e4acc9b18..c6f65dc983 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -527,6 +527,7 @@ void ZCCCompiler::CreateStructTypes() s->strct->Type->mVersion = s->strct->Version; } + auto &sf = s->Type()->ScopeFlags; if (mVersion >= MakeVersion(2, 4, 0)) { if ((s->strct->Flags & (ZCC_UIFlag | ZCC_Play)) == (ZCC_UIFlag | ZCC_Play)) @@ -534,19 +535,19 @@ void ZCCCompiler::CreateStructTypes() Error(s->strct, "Struct %s has incompatible flags", s->NodeName().GetChars()); } - if (outer != OutNamespace) s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::SideFromObjectFlags(outer->ObjectFlags)); + if (outer != OutNamespace) sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::SideFromObjectFlags(static_cast(outer)->ScopeFlags)); else if (s->strct->Flags & ZCC_ClearScope) Warn(s->strct, "Useless 'ClearScope' on struct %s not inside a class", s->NodeName().GetChars()); if (s->strct->Flags & ZCC_UIFlag) - s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_UI); + sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_UI); if (s->strct->Flags & ZCC_Play) - s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_Play); + sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_Play); if (s->strct->Flags & ZCC_ClearScope) - s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_PlainData); // don't inherit the scope from the outer class + sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_PlainData); // don't inherit the scope from the outer class } else { // old versions force 'play'. - s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_Play); + sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_Play); } s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type()); syms->AddSymbol(s->strct->Symbol); @@ -663,7 +664,7 @@ void ZCCCompiler::CreateClassTypes() } if (c->cls->Flags & ZCC_Abstract) - c->Type()->ObjectFlags |= OF_Abstract; + c->ClassType()->bAbstract = true; if (c->cls->Flags & ZCC_Version) { @@ -683,21 +684,21 @@ void ZCCCompiler::CreateClassTypes() } if (c->cls->Flags & ZCC_UIFlag) - c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_Play) | OF_UI; + c->Type()->ScopeFlags = EScopeFlags((c->Type()->ScopeFlags&~Scope_Play) | Scope_UI); if (c->cls->Flags & ZCC_Play) - c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_UI) | OF_Play; - if (parent->VMType->ObjectFlags & (OF_UI | OF_Play)) // parent is either ui or play + c->Type()->ScopeFlags = EScopeFlags((c->Type()->ScopeFlags&~Scope_UI) | Scope_Play); + if (parent->VMType->ScopeFlags & (Scope_UI | Scope_Play)) // parent is either ui or play { if (c->cls->Flags & (ZCC_UIFlag | ZCC_Play)) { Error(c->cls, "Can't change class scope in class %s", c->NodeName().GetChars()); } - c->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ObjectFlags, FScopeBarrier::SideFromObjectFlags(parent->VMType->ObjectFlags)); + c->Type()->ScopeFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ScopeFlags, FScopeBarrier::SideFromObjectFlags(parent->VMType->ScopeFlags)); } } else { - c->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ObjectFlags, FScopeBarrier::Side_Play); + c->Type()->ScopeFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ScopeFlags, FScopeBarrier::Side_Play); } c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); @@ -873,13 +874,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) { def->Symbol = new PSymbolConstString(def->NodeName, *(cval->StringVal)); } - else if (cval->Type->IsA(RUNTIME_CLASS(PInt))) + else if (cval->Type->isInt()) { // How do we get an Enum type in here without screwing everything up??? //auto type = def->Type != nullptr ? def->Type : cval->Type; def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal); } - else if (cval->Type->IsA(RUNTIME_CLASS(PFloat))) + else if (cval->Type->isFloat()) { if (def->Type != nullptr) { @@ -899,13 +900,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) { def->Symbol = new PSymbolConstString(def->NodeName, c.GetString()); } - else if (c.Type->IsA(RUNTIME_CLASS(PInt))) + else if (c.Type->isInt()) { // How do we get an Enum type in here without screwing everything up??? //auto type = def->Type != nullptr ? def->Type : cval->Type; def->Symbol = new PSymbolConstNumeric(def->NodeName, c.Type, c.GetInt()); } - else if (c.Type->IsA(RUNTIME_CLASS(PFloat))) + else if (c.Type->isFloat()) { if (def->Type != nullptr) { @@ -974,7 +975,7 @@ void ZCCCompiler::CompileArrays(ZCC_StructWork *work) FArgumentList values; // Don't use narrow typea for casting. - if (ctype->IsA(RUNTIME_CLASS(PInt))) ctype = static_cast(ztype)->Unsigned ? TypeUInt32 : TypeSInt32; + if (ctype->isInt()) ctype = static_cast(ztype)->Unsigned ? TypeUInt32 : TypeSInt32; else if (ctype == TypeFloat32) ctype = TypeFloat64; ConvertNodeList(values, sas->Values); @@ -1077,13 +1078,13 @@ ZCC_ExprConstant *ZCCCompiler::NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expres if (val->Type != TypeError) { assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); - if (sym->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) + if (sym->ValueType->isIntCompatible()) { val->IntVal = static_cast(sym)->Value; } else { - assert(sym->ValueType->IsKindOf(RUNTIME_CLASS(PFloat))); + assert(sym->ValueType->isFloat()); val->DoubleVal = static_cast(sym)->Float; } } @@ -1104,7 +1105,7 @@ ZCC_ExprTypeRef *ZCCCompiler::NodeFromSymbolType(PSymbolType *sym, ZCC_Expressio ZCC_ExprTypeRef *ref = static_cast(AST.InitNode(sizeof(*ref), AST_ExprTypeRef, idnode)); ref->Operation = PEX_TypeRef; ref->RefType = sym->Type; - ref->Type = NewClassPointer(RUNTIME_CLASS(PType)); + ref->Type = NewClassPointer(RUNTIME_CLASS(DObject)); return ref; } @@ -1245,9 +1246,9 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArrayObjectFlags & OF_UI) + if (type->ScopeFlags & Scope_UI) varflags |= VARF_UI; - if (type->ObjectFlags & OF_Play) + if (type->ScopeFlags & Scope_Play) varflags |= VARF_Play; } if (field->Flags & ZCC_UIFlag) @@ -1320,7 +1321,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArraySize != ~0u && fd->FieldSize != ~0u && thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0 && - (!thisfieldtype->IsA(RUNTIME_CLASS(PStruct)) || !static_cast(thisfieldtype)->isNative)) + (!thisfieldtype->isStruct() || !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); } @@ -1652,7 +1653,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n return TypeError; } auto typesym = dyn_cast(sym); - if (typesym == nullptr || !typesym->Type->IsKindOf(RUNTIME_CLASS(PClassType))) + if (typesym == nullptr || !typesym->Type->isClass()) { Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars()); return TypeError; @@ -1703,15 +1704,15 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo return TypeError; } - if (ptype->IsKindOf(RUNTIME_CLASS(PEnum))) + if (ptype->isEnum()) { if (!nativetype) return TypeSInt32; // hack this to an integer until we can resolve the enum mess. } - else if (ptype->IsKindOf(RUNTIME_CLASS(PClassType))) // classes cannot be instantiated at all, they always get used as references. + else if (ptype->isClass()) // 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. + else if (ptype->isStruct() && static_cast(ptype)->isNative) // native structs and classes cannot be instantiated, they always get used as reference. { if (!nativetype) return NewPointer(ptype, type->isconst); return ptype; // instantiation of native structs. Only for internal use. @@ -1752,7 +1753,7 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, ex = ex->Resolve(ctx); if (ex == nullptr) return TypeError; - if (!ex->isConstant() || !ex->ValueType->IsA(RUNTIME_CLASS(PInt))) + if (!ex->isConstant() || !ex->ValueType->isInt()) { Error(arraysize, "Array index must be an integer constant"); return TypeError; @@ -2023,19 +2024,19 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop { *(PalEntry*)addr = V_GetColor(nullptr, GetStringConst(ex, ctx), &ex->ScriptPosition); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt))) + else if (f->Type->isIntCompatible()) { static_cast(f->Type)->SetValue(addr, GetIntConst(ex, ctx)); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat))) + else if (f->Type->isFloat()) { static_cast(f->Type)->SetValue(addr, GetFloatConst(ex, ctx)); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PString))) + else if (f->Type == TypeString) { *(FString*)addr = GetStringConst(ex, ctx); } - else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer))) + else if (f->Type->isClassPointer()) { auto clsname = GetStringConst(ex, ctx); if (*clsname == 0 || !stricmp(clsname, "none")) @@ -2045,13 +2046,14 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop else { auto cls = PClass::FindClass(clsname); + auto cp = static_cast(f->Type); if (cls == nullptr) { - cls = static_cast(f->Type)->ClassRestriction->FindClassTentative(clsname); + cls = cp->ClassRestriction->FindClassTentative(clsname); } - else if (!cls->IsDescendantOf(static_cast(f->Type)->ClassRestriction)) + else if (!cls->IsDescendantOf(cp->ClassRestriction)) { - Error(property, "class %s is not compatible with property type %s", clsname, static_cast(f->Type)->ClassRestriction->TypeName.GetChars()); + Error(property, "class %s is not compatible with property type %s", clsname, cp->ClassRestriction->TypeName.GetChars()); } *(PClass**)addr = cls; } @@ -2304,7 +2306,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(PContainerType)) && type != TypeVector2 && type != TypeVector3) + if (type->isContainer() && type != TypeVector2 && type != TypeVector3) { // structs and classes only get passed by pointer. type = NewPointer(type); @@ -2365,9 +2367,9 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool if (f->Flags & ZCC_FuncConst) varflags |= VARF_ReadOnly; // FuncConst method is internally marked as VARF_ReadOnly if (mVersion >= MakeVersion(2, 4, 0)) { - if (c->Type()->ObjectFlags & OF_UI) + if (c->Type()->ScopeFlags & Scope_UI) varflags |= VARF_UI; - if (c->Type()->ObjectFlags & OF_Play) + if (c->Type()->ScopeFlags & Scope_Play) varflags |= VARF_Play; //if (f->Flags & ZCC_FuncConst) // varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_PlainData); // const implies clearscope. this is checked a bit later to also not have ZCC_Play/ZCC_UIFlag. @@ -2495,7 +2497,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags = 0; - if ((type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) || type->IsA(RUNTIME_CLASS(PDynArray))) + if ((type->isStruct() && type != TypeVector2 && type != TypeVector3) || type->isDynArray()) { // Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly. type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/); @@ -2565,7 +2567,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool break; case REGT_POINTER: - if (type->IsKindOf(RUNTIME_CLASS(PClassPointer))) + if (type->isClassPointer()) vmval[0] = (DObject*)cnst->GetValue().GetPointer(); else vmval[0] = cnst->GetValue().GetPointer(); @@ -2609,7 +2611,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr ? nullptr : *(afd->VMPointer), varflags, useflags); c->Type()->Symbols.ReplaceSymbol(sym); - auto vcls = dyn_cast(c->Type()); + auto vcls = PType::toClass(c->Type()); auto cls = vcls ? vcls->Descriptor : nullptr; PFunction *virtsym = nullptr; if (cls != nullptr && cls->ParentClass != nullptr) virtsym = dyn_cast(cls->ParentClass->VMType->Symbols.FindSymbol(FName(f->Name), true)); @@ -2656,7 +2658,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; } - PClass *clstype = static_cast(c->Type())->Descriptor; + PClass *clstype = forclass? static_cast(c->Type())->Descriptor : nullptr; if (varflags & VARF_Virtual) { if (sym->Variants[0].Implementation == nullptr) @@ -2817,7 +2819,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af, in { FArgumentList argumentlist; // We can use this function directly without wrapping it in a caller. - assert(dyn_cast(afd->Variants[0].SelfClass) != nullptr); // non classes are not supposed to get here. + assert(PType::toClass(afd->Variants[0].SelfClass) != nullptr); // non classes are not supposed to get here. int comboflags = afd->Variants[0].UseFlags & StateFlags; if (comboflags == StateFlags) // the function must satisfy all the flags the state requires @@ -3228,23 +3230,23 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) case AST_ExprConstant: { auto cnst = static_cast(ast); - if (cnst->Type->IsA(RUNTIME_CLASS(PName))) + if (cnst->Type == TypeName) { return new FxConstant(FName(ENamedName(cnst->IntVal)), *ast); } - else if (cnst->Type->IsA(RUNTIME_CLASS(PInt))) + else if (cnst->Type->isInt()) { return new FxConstant(cnst->IntVal, *ast); } - else if (cnst->Type->IsA(RUNTIME_CLASS(PBool))) + else if (cnst->Type == TypeBool) { return new FxConstant(!!cnst->IntVal, *ast); } - else if (cnst->Type->IsA(RUNTIME_CLASS(PFloat))) + else if (cnst->Type->isFloat()) { return new FxConstant(cnst->DoubleVal, *ast); } - else if (cnst->Type->IsA(RUNTIME_CLASS(PString))) + else if (cnst->Type == TypeString) { return new FxConstant(*cnst->StringVal, *ast); } diff --git a/src/swrenderer/drawers/r_draw_sprite32.h b/src/swrenderer/drawers/r_draw_sprite32.h index f042bac312..59b04b6479 100644 --- a/src/swrenderer/drawers/r_draw_sprite32.h +++ b/src/swrenderer/drawers/r_draw_sprite32.h @@ -126,7 +126,7 @@ namespace swrenderer } int textureheight = args.TextureHeight(); - uint32_t one = ((0x80000000 + textureheight - 1) / textureheight) * 2 + 1; + uint32_t one = ((0x20000000 + textureheight - 1) / textureheight) * 2 + 1; // Shade constants BgraColor dynlight = args.DynamicLight(); diff --git a/src/swrenderer/drawers/r_draw_sprite32_sse2.h b/src/swrenderer/drawers/r_draw_sprite32_sse2.h index 3d728d2c98..d8afc3ae94 100644 --- a/src/swrenderer/drawers/r_draw_sprite32_sse2.h +++ b/src/swrenderer/drawers/r_draw_sprite32_sse2.h @@ -126,7 +126,7 @@ namespace swrenderer } int textureheight = args.TextureHeight(); - uint32_t one = ((0x80000000 + textureheight - 1) / textureheight) * 2 + 1; + uint32_t one = ((0x20000000 + textureheight - 1) / textureheight) * 2 + 1; // Shade constants __m128i dynlight = _mm_cvtsi32_si128(args.DynamicLight()); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 9defba9de5..c834dff946 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -643,11 +643,11 @@ struct StringStruct native native vararg void AppendFormat(String fmt, ...); native void Replace(String pattern, String replacement); - native String Left(int len); - native String Mid(int pos = 0, int len = 2147483647); + native String Left(int len) const; + native String Mid(int pos = 0, int len = 2147483647) const; native void Truncate(int newlen); - native String CharAt(int pos); - native int CharCodeAt(int pos); + native String CharAt(int pos) const; + native int CharCodeAt(int pos) const; native String Filter(); } diff --git a/wadsrc/static/zscript/statusbar/doom_sbar.txt b/wadsrc/static/zscript/statusbar/doom_sbar.txt index 12935fa896..00471540b8 100644 --- a/wadsrc/static/zscript/statusbar/doom_sbar.txt +++ b/wadsrc/static/zscript/statusbar/doom_sbar.txt @@ -139,7 +139,7 @@ class DoomStatusBar : BaseStatusBar DrawString(mHUDFont, FormatNumber(CPlayer.health, 3), (44, -20)); let armor = CPlayer.mo.FindInventory("BasicArmor"); - if (armor != null) + if (armor != null && armor.Amount > 0) { DrawInventoryIcon(armor, (20, -22)); DrawString(mHUDFont, FormatNumber(armor.Amount, 3), (44, -40)); diff --git a/wadsrc/static/zscript/statusbar/heretic_sbar.txt b/wadsrc/static/zscript/statusbar/heretic_sbar.txt index b6db47dcf0..691a89e332 100644 --- a/wadsrc/static/zscript/statusbar/heretic_sbar.txt +++ b/wadsrc/static/zscript/statusbar/heretic_sbar.txt @@ -143,7 +143,7 @@ class HereticStatusBar : BaseStatusBar //armor let armor = CPlayer.mo.FindInventory("BasicArmor"); - if (armor != null) + if (armor != null && armor.Amount > 0) { DrawInventoryIcon(armor, (58, -24)); DrawString(mBigFont, FormatNumber(armor.Amount, 3), (41, -43), DI_TEXT_ALIGN_RIGHT);