diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 117180d750..0ae2b47716 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -205,7 +205,6 @@ void PClass::StaticInit () { atterm (StaticShutdown); - StaticBootstrap(); Namespaces.GlobalNamespace = Namespaces.NewNamespace(0); FAutoSegIterator probe(CRegHead, CRegTail); @@ -265,6 +264,7 @@ void PClass::StaticShutdown () ClassDataAllocator.FreeAllBlocks(); AllClasses.Clear(); PClassActor::AllActorClasses.Clear(); + ClassMap.Clear(); FAutoSegIterator probe(CRegHead, CRegTail); @@ -276,16 +276,6 @@ void PClass::StaticShutdown () } -//========================================================================== -// -// PClass :: StaticBootstrap STATIC -// -//========================================================================== - -void PClass::StaticBootstrap() -{ -} - //========================================================================== // // PClass Constructor @@ -363,7 +353,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..b98f3e7b55 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -52,7 +52,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/info.cpp b/src/info.cpp index c6072afca3..aa0eac170d 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -75,12 +75,12 @@ cycle_t ActionCycles; // //========================================================================== -class PActorInfo : public PBasicType +class PActorInfo : public PCompoundType { - DECLARE_CLASS(PActorInfo, PBasicType); + DECLARE_CLASS(PActorInfo, PCompoundType); public: PActorInfo() - :PBasicType(sizeof(FActorInfo), alignof(FActorInfo)) + :PCompoundType(sizeof(FActorInfo), alignof(FActorInfo)) { } 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/p_acs.cpp b/src/p_acs.cpp index 55dfdd8e67..9f14f5321c 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5040,12 +5040,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 +5060,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 +5078,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..adff180276 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->IsKindOf(RUNTIME_CLASS(PArray)) || !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 08cb7123cc..341caab7b2 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..12c92e82dc 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; } @@ -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. @@ -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); } @@ -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); @@ -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); @@ -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. @@ -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; @@ -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. @@ -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,10 +6393,10 @@ 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; @@ -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) { @@ -7018,10 +7018,10 @@ 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; @@ -7241,7 +7241,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) if (arraytype == nullptr) { // 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); + PPointer *ptype = Array->ValueType->toPointer(); if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray))) { ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); @@ -7316,7 +7316,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) if (arrayispointer) { - arraytype = static_cast(static_cast(Array->ValueType)->PointedType); + arraytype = static_cast(Array->ValueType->toPointer()->PointedType); } else { @@ -8150,7 +8150,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, @@ -8178,7 +8178,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (!Self->IsResizableArray()) { 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; @@ -8222,10 +8222,11 @@ 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) { @@ -8238,9 +8239,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) auto x = new FxGetClass(Self); return x->Resolve(ctx); } - - - cls = static_cast(ptype); } else { @@ -8759,7 +8757,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 +8820,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->IsA(RUNTIME_CLASS(PStruct))) { // trying to pass a struct reference as a struct reference. This must preserve the type. } @@ -8937,7 +8935,7 @@ 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->ObjectFlags); int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); if (outerside == FScopeBarrier::Side_Virtual) @@ -9300,7 +9298,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; } diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 1f6c8baca2..06047225b4 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -330,14 +330,14 @@ 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 IsBoolCompat() const { return ValueType->isScalar(); } 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 IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->isPointer() && ValueType->toPointer()->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); } + bool IsResizableArray() const { return (ValueType->isPointer() && ValueType->toPointer()->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); } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 4758aaa237..0f06b40636 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -866,17 +866,17 @@ 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); diff --git a/src/scripting/symbols.cpp b/src/scripting/symbols.cpp index 098ecaaa5a..bb720875ef 100644 --- a/src/scripting/symbols.cpp +++ b/src/scripting/symbols.cpp @@ -104,9 +104,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 +155,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__ @@ -582,7 +582,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/types.cpp b/src/scripting/types.cpp index b445ad8844..ae4fe67f16 100644 --- a/src/scripting/types.cpp +++ b/src/scripting/types.cpp @@ -377,16 +377,6 @@ void PType::StaticInit() IMPLEMENT_CLASS(PBasicType, true, false) -//========================================================================== -// -// PBasicType Default Constructor -// -//========================================================================== - -PBasicType::PBasicType() -{ -} - //========================================================================== // // PBasicType Parameterized Constructor @@ -397,12 +387,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) @@ -462,6 +465,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) @@ -713,26 +717,13 @@ 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 +734,7 @@ PFloat::PFloat(unsigned int size) : PBasicType(size, size) { mDescriptiveName.Format("Float%d", size); + Flags |= TYPE_Float; if (size == 8) { #ifdef __i386__ @@ -1085,6 +1077,7 @@ PName::PName() : PInt(sizeof(FName), true, false) { mDescriptiveName = "Name"; + Flags |= TYPE_IntNotInt; assert(sizeof(FName) == alignof(FName)); } @@ -1134,6 +1127,7 @@ IMPLEMENT_CLASS(PSpriteID, false, false) PSpriteID::PSpriteID() : PInt(sizeof(int), true, true) { + Flags |= TYPE_IntNotInt; mDescriptiveName = "SpriteID"; } @@ -1177,6 +1171,7 @@ PTextureID::PTextureID() : PInt(sizeof(FTextureID), true, false) { mDescriptiveName = "TextureID"; + Flags |= TYPE_IntNotInt; assert(sizeof(FTextureID) == alignof(FTextureID)); } @@ -1220,6 +1215,7 @@ PSound::PSound() : PInt(sizeof(FSoundID), true) { mDescriptiveName = "Sound"; + Flags |= TYPE_IntNotInt; assert(sizeof(FSoundID) == alignof(FSoundID)); } @@ -1270,6 +1266,7 @@ PColor::PColor() : PInt(sizeof(PalEntry), true) { mDescriptiveName = "Color"; + Flags |= TYPE_IntNotInt; assert(sizeof(PalEntry) == alignof(PalEntry)); } @@ -1286,6 +1283,7 @@ IMPLEMENT_CLASS(PStateLabel, false, false) PStateLabel::PStateLabel() : PInt(sizeof(int), false, false) { + Flags |= TYPE_IntNotInt; mDescriptiveName = "StateLabel"; } @@ -1307,6 +1305,7 @@ PPointer::PPointer() storeOp = OP_SP; moveOp = OP_MOVEA; RegType = REGT_POINTER; + Flags |= TYPE_Pointer; } //========================================================================== @@ -1332,6 +1331,7 @@ PPointer::PPointer(PType *pointsat, bool isconst) storeOp = OP_SP; moveOp = OP_MOVEA; RegType = REGT_POINTER; + Flags |= TYPE_Pointer; } //========================================================================== diff --git a/src/scripting/types.h b/src/scripting/types.h index 3c233c6175..df5cdb8269 100644 --- a/src/scripting/types.h +++ b/src/scripting/types.h @@ -61,6 +61,21 @@ enum // Map * * // Prototype *+ *+ +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_IntCompatible = TYPE_Int | TYPE_IntNotInt, // must be the combination of all flags that are subtypes of int and can be cast to an int. +}; + +class PContainerType; +class PPointer; + struct ZCC_ExprConstant; class PType : public PTypeBase { @@ -71,6 +86,7 @@ public: PClass *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. @@ -160,6 +176,17 @@ 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); } // This excludes class pointers which use their PointedType differently + + PContainerType *toContainer() { return isContainer() ? (PContainerType*)this : nullptr; } + PPointer *toPointer() { return isPointer() ? (PPointer*)this : nullptr; } }; // Not-really-a-type types -------------------------------------------------- @@ -183,14 +210,15 @@ 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 @@ -200,11 +228,15 @@ 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; @@ -252,7 +284,7 @@ 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 +295,6 @@ public: virtual double GetValueFloat(void *addr) const; virtual bool isNumeric() override { return true; } protected: - PFloat(); void SetOps(); private: struct SymbolInitF 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..4bb2a47472 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -873,13 +873,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 +899,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 +974,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 +1077,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; } } @@ -1752,7 +1752,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,15 +2023,15 @@ 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); } @@ -2304,7 +2304,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); @@ -3228,23 +3228,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); }