From b2d944974e336830dda358ed69a0dd8b43d5ab1c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Apr 2017 12:47:41 +0200 Subject: [PATCH 1/9] - first stage of simplifying the type system. Let's use inline checkers in PType instead of constantly having to do clumsy IsKindOf checks etc. Once complete this also means that the types can be taken out of the class hierarchy, freeing up some common names. --- src/dobjtype.cpp | 13 +--- src/dobjtype.h | 1 - src/info.cpp | 6 +- src/menu/menudef.cpp | 8 +-- src/p_acs.cpp | 15 +++-- src/p_actionfunctions.cpp | 5 +- src/p_setup.cpp | 2 +- src/scripting/backend/codegen.cpp | 76 +++++++++++------------ src/scripting/backend/codegen.h | 12 ++-- src/scripting/decorate/thingdef_parse.cpp | 6 +- src/scripting/symbols.cpp | 8 +-- src/scripting/types.cpp | 48 +++++++------- src/scripting/types.h | 47 +++++++++++--- src/scripting/zscript/ast.cpp | 2 +- src/scripting/zscript/zcc-parse.lemon | 8 +-- src/scripting/zscript/zcc_compile.cpp | 34 +++++----- 16 files changed, 153 insertions(+), 138 deletions(-) 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); } From aeb455d705c38063df7a99504d10fbc1b6bfc483 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Apr 2017 15:13:14 +0200 Subject: [PATCH 2/9] - removed all RTTI checks for the types. --- src/namedef.h | 10 ++- src/p_acs.cpp | 5 +- src/p_actionfunctions.cpp | 2 +- src/scripting/backend/codegen.cpp | 97 ++++++++++++----------- src/scripting/backend/codegen.h | 10 +-- src/scripting/decorate/thingdef_parse.cpp | 11 +-- src/scripting/thingdef.cpp | 4 +- src/scripting/thingdef_properties.cpp | 4 +- src/scripting/types.cpp | 4 + src/scripting/types.h | 57 ++++++++----- src/scripting/zscript/zcc_compile.cpp | 29 +++---- 11 files changed, 133 insertions(+), 100 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index 4346844fc9..2a88a64a83 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) \ No newline at end of file diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 9f14f5321c..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) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index adff180276..19cafed238 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -4803,7 +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->isScalar()) + !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/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 12c92e82dc..8f746f7fee 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -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; } @@ -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; @@ -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()) { @@ -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; @@ -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; @@ -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); @@ -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; @@ -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; @@ -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) { @@ -6403,7 +6403,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) 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; @@ -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"); @@ -7028,7 +7028,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) 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 = Array->ValueType->toPointer(); - if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray))) + 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) @@ -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); } @@ -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. @@ -8175,7 +8178,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return nullptr; } - if (!Self->IsResizableArray()) + if (!Self->isStaticArray()) { auto atype = Self->ValueType; if (Self->ValueType->isPointer()) atype = ValueType->toPointer()->PointedType; @@ -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) { @@ -8228,7 +8231,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) 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) { @@ -8247,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; @@ -8328,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()); @@ -8820,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->isRealPointer() && type->toPointer()->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. } @@ -9331,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; @@ -9402,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"); @@ -10601,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)) @@ -10769,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. @@ -10846,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); @@ -10925,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); @@ -10985,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); @@ -11201,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) @@ -11227,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 06047225b4..aa2e06910d 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -335,11 +335,11 @@ public: bool IsPointer() const { return ValueType->isPointer(); } bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; 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->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); } + 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/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 0f06b40636..488cce89d7 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -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(); @@ -881,7 +881,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul 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/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_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 ae4fe67f16..3f990b62ee 100644 --- a/src/scripting/types.cpp +++ b/src/scripting/types.cpp @@ -1407,6 +1407,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; } @@ -1545,6 +1546,7 @@ PClassPointer::PClassPointer(PClass *restrict) else mDescriptiveName = "ClassPointer"; loadOp = OP_LP; storeOp = OP_SP; + Flags |= TYPE_ClassPointer; mVersion = restrict->VMType->mVersion; } @@ -1664,6 +1666,7 @@ PEnum::PEnum(FName name, PTypeBase *outer) { EnumName = name; Outer = outer; + Flags |= TYPE_IntNotInt; mDescriptiveName.Format("Enum<%s>", name.GetChars()); } @@ -1721,6 +1724,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; } //========================================================================== diff --git a/src/scripting/types.h b/src/scripting/types.h index df5cdb8269..15442b4e10 100644 --- a/src/scripting/types.h +++ b/src/scripting/types.h @@ -4,7 +4,6 @@ #include "serializer.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,20 +60,12 @@ 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; +class PClassPointer; +class PArray; +class PStruct; +class PClassType; struct ZCC_ExprConstant; class PType : public PTypeBase @@ -82,6 +73,21 @@ 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 unsigned int Size; // this type's size @@ -183,10 +189,21 @@ public: 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 + 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->TypeName == NAME_Enum; } + bool isArray() const { return !!(Flags & TYPE_Array); } + bool isStaticArray() const { return TypeTableType->TypeName == NAME_StaticArray; } + bool isDynArray() const { return TypeTableType->TypeName == NAME_DynArray; } + bool isStruct() const { return TypeTableType->TypeName == NAME_Struct; } + bool isClass() const { return TypeTableType->TypeName == FName("ClassType"); } + bool isPrototype() const { return TypeTableType->TypeName == 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 -------------------------------------------------- @@ -493,7 +510,7 @@ public: void SetPointer(void *base, unsigned offset, TArray *special) override; protected: - PArray(); + PArray();//deleteme }; class PStaticArray : public PArray @@ -506,7 +523,7 @@ public: virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; protected: - PStaticArray(); + PStaticArray();// deleteme }; class PDynArray : public PCompoundType @@ -529,7 +546,7 @@ public: void SetPointerArray(void *base, unsigned offset, TArray *ptrofs = NULL) const override; protected: - PDynArray(); + PDynArray(); // deleteme }; class PMap : public PCompoundType @@ -544,7 +561,7 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; protected: - PMap(); + PMap(); // deleteme }; class PStruct : public PContainerType @@ -568,7 +585,7 @@ public: void SetPointer(void *base, unsigned offset, TArray *specials) override; protected: - PStruct(); + PStruct(); // deleteme }; class PPrototype : public PCompoundType @@ -584,7 +601,7 @@ public: virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; protected: - PPrototype(); + PPrototype(); // deleteme }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 4bb2a47472..f7ac477180 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1320,7 +1320,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 +1652,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 +1703,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. @@ -2035,7 +2035,7 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop { *(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 +2045,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; } @@ -2495,7 +2496,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 +2566,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 +2610,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 +2657,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 +2818,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 From 988fe8d735490f369f867cfbca2782beedb727b0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Apr 2017 15:44:51 +0200 Subject: [PATCH 3/9] - removed all RTTI from the type table. Using names is just as good as using types so now this is what's done. --- src/info.cpp | 2 +- src/namedef.h | 2 +- src/scripting/types.cpp | 119 ++++++++++++++++++++-------------------- src/scripting/types.h | 22 ++++---- 4 files changed, 72 insertions(+), 73 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index aa0eac170d..0066931693 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -118,7 +118,7 @@ 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/namedef.h b/src/namedef.h index 2a88a64a83..18075976d7 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -911,4 +911,4 @@ xx(Pointer) xx(Enum) xx(StaticArray) xx(DynArray) -xx(Struct) \ No newline at end of file +xx(Struct) diff --git a/src/scripting/types.cpp b/src/scripting/types.cpp index 3f990b62ee..2c73aa0509 100644 --- a/src/scripting/types.cpp +++ b/src/scripting/types.cpp @@ -289,27 +289,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 +330,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 +343,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; @@ -1458,15 +1458,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); } @@ -1477,11 +1477,11 @@ 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); } @@ -1581,7 +1581,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)); } @@ -1630,11 +1630,11 @@ 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); } @@ -1683,11 +1683,11 @@ 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); } @@ -1843,11 +1843,11 @@ 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; } @@ -1917,11 +1917,11 @@ 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; } @@ -2142,7 +2142,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; @@ -2172,7 +2172,7 @@ 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; } @@ -2247,11 +2247,11 @@ 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; } @@ -2398,11 +2398,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); } @@ -2485,11 +2485,11 @@ 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); } @@ -2552,11 +2552,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); } @@ -2570,16 +2570,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; } @@ -2593,14 +2593,14 @@ 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(); @@ -2612,17 +2612,16 @@ 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; @@ -2635,7 +2634,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; @@ -2643,7 +2642,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 15442b4e10..89a44ce063 100644 --- a/src/scripting/types.h +++ b/src/scripting/types.h @@ -89,7 +89,7 @@ protected: }; 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? @@ -192,13 +192,13 @@ public: 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->TypeName == NAME_Enum; } + bool isEnum() const { return TypeTableType == NAME_Enum; } bool isArray() const { return !!(Flags & TYPE_Array); } - bool isStaticArray() const { return TypeTableType->TypeName == NAME_StaticArray; } - bool isDynArray() const { return TypeTableType->TypeName == NAME_DynArray; } - bool isStruct() const { return TypeTableType->TypeName == NAME_Struct; } - bool isClass() const { return TypeTableType->TypeName == FName("ClassType"); } - bool isPrototype() const { return TypeTableType->TypeName == NAME_Prototype; } + 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; } @@ -676,12 +676,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); }; From 98dab9c4b9266831fcabb61c9947b0813fe43268 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Apr 2017 17:47:17 +0200 Subject: [PATCH 4/9] - took PTypeBase and all its subclasses out of the DObject hierarchy. - moved scope flag to a new variable that is specific to PType instead of hijacking the ObjectFlags for this. --- src/dobject.h | 2 + src/dobjgc.cpp | 2 - src/dobjgc.h | 3 - src/dobjtype.h | 4 - src/info.cpp | 3 - src/scripting/backend/codegen.cpp | 22 +-- src/scripting/backend/scopebarrier.cpp | 27 ++-- src/scripting/backend/scopebarrier.h | 13 +- src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/symbols.cpp | 24 +-- src/scripting/symbols.h | 22 ++- src/scripting/types.cpp | 176 +--------------------- src/scripting/types.h | 54 +------ src/scripting/zscript/zcc_compile.cpp | 33 ++-- 14 files changed, 71 insertions(+), 316 deletions(-) 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.h b/src/dobjtype.h index b98f3e7b55..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, diff --git a/src/info.cpp b/src/info.cpp index 0066931693..4619b75856 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -77,7 +77,6 @@ cycle_t ActionCycles; class PActorInfo : public PCompoundType { - DECLARE_CLASS(PActorInfo, PCompoundType); public: PActorInfo() :PCompoundType(sizeof(FActorInfo), alignof(FActorInfo)) @@ -113,8 +112,6 @@ public: }; -IMPLEMENT_CLASS(PActorInfo, false, false) - void AddActorInfo(PClass *cls) { auto type = new PActorInfo; diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 8f746f7fee..5b7fcddc9d 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -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 @@ -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) @@ -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) @@ -7619,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()); @@ -8300,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) @@ -8938,11 +8938,11 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) if (innerside == FScopeBarrier::Side_Virtual) { - auto selfside = FScopeBarrier::SideFromObjectFlags(Self->ValueType->toPointer()->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) 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 488cce89d7..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; diff --git a/src/scripting/symbols.cpp b/src/scripting/symbols.cpp index bb720875ef..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 - //========================================================================== // @@ -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; } 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/types.cpp b/src/scripting/types.cpp index 2c73aa0509..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 @@ -375,8 +370,6 @@ void PType::StaticInit() /* PBasicType *************************************************************/ -IMPLEMENT_CLASS(PBasicType, true, false) - //========================================================================== // // PBasicType Parameterized Constructor @@ -392,8 +385,6 @@ PBasicType::PBasicType(unsigned int size, unsigned int align) /* PCompoundType **********************************************************/ -IMPLEMENT_CLASS(PCompoundType, true, false) - //========================================================================== // // PBasicType Parameterized Constructor @@ -408,8 +399,6 @@ PCompoundType::PCompoundType(unsigned int size, unsigned int align) /* PContainerType *************************************************************/ -IMPLEMENT_CLASS(PContainerType, true, false) - //========================================================================== // // PContainerType :: IsMatch @@ -418,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; @@ -438,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 @@ -678,8 +650,6 @@ double PInt::GetValueFloat(void *addr) const /* PBool ******************************************************************/ -IMPLEMENT_CLASS(PBool, false, false) - //========================================================================== // // PInt :: SetValue @@ -722,8 +692,6 @@ PBool::PBool() /* PFloat *****************************************************************/ -IMPLEMENT_CLASS(PFloat, false, false) - //========================================================================== // // PFloat Parameterized Constructor @@ -968,8 +936,6 @@ void PFloat::SetOps() /* PString ****************************************************************/ -IMPLEMENT_CLASS(PString, false, false) - //========================================================================== // // PString Default Constructor @@ -1065,8 +1031,6 @@ void PString::DestroyValue(void *addr) const /* PName ******************************************************************/ -IMPLEMENT_CLASS(PName, false, false) - //========================================================================== // // PName Default Constructor @@ -1116,8 +1080,6 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSpriteID ******************************************************************/ -IMPLEMENT_CLASS(PSpriteID, false, false) - //========================================================================== // // PName Default Constructor @@ -1159,8 +1121,6 @@ bool PSpriteID::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PTextureID ******************************************************************/ -IMPLEMENT_CLASS(PTextureID, false, false) - //========================================================================== // // PTextureID Default Constructor @@ -1203,8 +1163,6 @@ bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PSound *****************************************************************/ -IMPLEMENT_CLASS(PSound, false, false) - //========================================================================== // // PSound Default Constructor @@ -1254,8 +1212,6 @@ bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PColor *****************************************************************/ -IMPLEMENT_CLASS(PColor, false, false) - //========================================================================== // // PColor Default Constructor @@ -1272,8 +1228,6 @@ PColor::PColor() /* PStateLabel *****************************************************************/ -IMPLEMENT_CLASS(PStateLabel, false, false) - //========================================================================== // // PStateLabel Default Constructor @@ -1289,8 +1243,6 @@ PStateLabel::PStateLabel() /* PPointer ***************************************************************/ -IMPLEMENT_CLASS(PPointer, false, false) - //========================================================================== // // PPointer - Default Constructor @@ -1395,8 +1347,6 @@ bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const /* PObjectPointer **********************************************************/ -IMPLEMENT_CLASS(PObjectPointer, false, false) - //========================================================================== // // PPointer :: GetStoreOp @@ -1488,8 +1438,6 @@ PPointer *NewPointer(PClass *cls, bool isconst) /* PStatePointer **********************************************************/ -IMPLEMENT_CLASS(PStatePointer, false, false) - //========================================================================== // // PStatePointer Default Constructor @@ -1531,8 +1479,6 @@ bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons /* PClassPointer **********************************************************/ -IMPLEMENT_CLASS(PClassPointer,false, false) - //========================================================================== // // PClassPointer - Parameterized Constructor @@ -1641,20 +1587,6 @@ PClassPointer *NewClassPointer(PClass *restrict) /* PEnum ******************************************************************/ -IMPLEMENT_CLASS(PEnum, false, false) - -//========================================================================== -// -// PEnum - Default Constructor -// -//========================================================================== - -PEnum::PEnum() -: PInt(4, false) -{ - mDescriptiveName = "Enum"; -} - //========================================================================== // // PEnum - Parameterized Constructor @@ -1694,20 +1626,6 @@ PEnum *NewEnum(FName name, PTypeBase *outer) /* PArray *****************************************************************/ -IMPLEMENT_CLASS(PArray, false, false) - -//========================================================================== -// -// PArray - Default Constructor -// -//========================================================================== - -PArray::PArray() -: ElementType(nullptr), ElementCount(0) -{ - mDescriptiveName = "Array"; -} - //========================================================================== // // PArray - Parameterized Constructor @@ -1854,19 +1772,6 @@ PArray *NewArray(PType *type, unsigned int count) /* PArray *****************************************************************/ -IMPLEMENT_CLASS(PStaticArray, false, false) - -//========================================================================== -// -// PArray - Default Constructor -// -//========================================================================== - -PStaticArray::PStaticArray() -{ - mDescriptiveName = "ResizableArray"; -} - //========================================================================== // // PArray - Parameterized Constructor @@ -1928,22 +1833,6 @@ PStaticArray *NewStaticArray(PType *type) /* PDynArray **************************************************************/ -IMPLEMENT_CLASS(PDynArray, false, false) - -//========================================================================== -// -// PDynArray - Default Constructor -// -//========================================================================== - -PDynArray::PDynArray() -: ElementType(nullptr) -{ - mDescriptiveName = "DynArray"; - Size = sizeof(FArray); - Align = alignof(FArray); -} - //========================================================================== // // PDynArray - Parameterized Constructor @@ -2064,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); @@ -2179,22 +2068,6 @@ PDynArray *NewDynArray(PType *type) /* 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 @@ -2258,20 +2131,6 @@ PMap *NewMap(PType *keytype, PType *valuetype) /* PStruct ****************************************************************/ -IMPLEMENT_CLASS(PStruct, false, false) - -//========================================================================== -// -// PStruct - Default Constructor -// -//========================================================================== - -PStruct::PStruct() -{ - mDescriptiveName = "Struct"; - Size = 0; -} - //========================================================================== // // PStruct - Parameterized Constructor @@ -2410,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 @@ -2459,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 @@ -2496,8 +2329,6 @@ PPrototype *NewPrototype(const TArray &rettypes, const TArray /* PClass *****************************************************************/ -IMPLEMENT_CLASS(PClassType, false, false) - //========================================================================== // // @@ -2514,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()); @@ -2603,7 +2435,6 @@ void FTypeTable::AddType(PType *type, FName type_name, intptr_t parm1, intptr_t type->TypeTableType = type_name; type->HashNext = TypeHash[bucket]; TypeHash[bucket] = type; - type->Release(); } //========================================================================== @@ -2625,7 +2456,6 @@ void FTypeTable::AddType(PType *type, FName type_name) type->HashNext = TypeHash[bucket]; TypeHash[bucket] = type; - type->Release(); } //========================================================================== diff --git a/src/scripting/types.h b/src/scripting/types.h index 89a44ce063..d4dc196f7a 100644 --- a/src/scripting/types.h +++ b/src/scripting/types.h @@ -2,6 +2,7 @@ #include "dobject.h" #include "serializer.h" +#include "scripting/backend/scopebarrier.h" // Variable/parameter/field flags ------------------------------------------- @@ -70,7 +71,6 @@ class PClassType; struct ZCC_ExprConstant; class PType : public PTypeBase { - DECLARE_ABSTRACT_CLASS(PType, PTypeBase) protected: enum ETypeFlags @@ -99,6 +99,7 @@ public: 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(); @@ -210,14 +211,12 @@ public: 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) {} }; @@ -226,21 +225,18 @@ public: class PBasicType : public PType { - DECLARE_ABSTRACT_CLASS(PBasicType, PType); 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 @@ -266,7 +262,6 @@ public: class PInt : public PBasicType { - DECLARE_CLASS(PInt, PBasicType); public: PInt(unsigned int size, bool unsign, bool compatible = true); @@ -282,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); @@ -299,7 +292,6 @@ public: class PFloat : public PBasicType { - DECLARE_CLASS(PFloat, PBasicType); public: PFloat(unsigned int size = 8); @@ -333,7 +325,6 @@ private: class PString : public PBasicType { - DECLARE_CLASS(PString, PBasicType); public: PString(); @@ -348,7 +339,6 @@ public: class PName : public PInt { - DECLARE_CLASS(PName, PInt); public: PName(); @@ -358,7 +348,6 @@ public: class PSound : public PInt { - DECLARE_CLASS(PSound, PInt); public: PSound(); @@ -368,7 +357,6 @@ public: class PSpriteID : public PInt { - DECLARE_CLASS(PSpriteID, PInt); public: PSpriteID(); @@ -378,7 +366,6 @@ public: class PTextureID : public PInt { - DECLARE_CLASS(PTextureID, PInt); public: PTextureID(); @@ -388,14 +375,12 @@ public: class PColor : public PInt { - DECLARE_CLASS(PColor, PInt); public: PColor(); }; class PStateLabel : public PInt { - DECLARE_CLASS(PStateLabel, PInt); public: PStateLabel(); }; @@ -404,7 +389,6 @@ public: class PPointer : public PBasicType { - DECLARE_CLASS(PPointer, PBasicType); public: typedef void(*WriteHandler)(FSerializer &ar, const char *key, const void *addr); @@ -437,7 +421,6 @@ protected: class PStatePointer : public PPointer { - DECLARE_CLASS(PStatePointer, PPointer); public: PStatePointer(); @@ -448,7 +431,6 @@ public: class PObjectPointer : public PPointer { - DECLARE_CLASS(PObjectPointer, PPointer); public: PObjectPointer(PClass *pointedtype = nullptr, bool isconst = false); @@ -461,7 +443,6 @@ public: class PClassPointer : public PPointer { - DECLARE_CLASS(PClassPointer, PPointer); public: PClassPointer(class PClass *restrict = nullptr); @@ -480,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); @@ -508,27 +485,19 @@ public: void SetDefaultValue(void *base, unsigned offset, TArray *special) override; void SetPointer(void *base, unsigned offset, TArray *special) override; - -protected: - PArray();//deleteme }; 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();// deleteme }; class PDynArray : public PCompoundType { - DECLARE_CLASS(PDynArray, PCompoundType); public: PDynArray(PType *etype, PStruct *backing); @@ -544,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(); // deleteme }; class PMap : public PCompoundType { - DECLARE_CLASS(PMap, PCompoundType); public: PMap(PType *keytype, PType *valtype); @@ -560,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(); // deleteme }; class PStruct : public PContainerType { - DECLARE_CLASS(PStruct, PContainerType); - public: PStruct(FName name, PTypeBase *outer, bool isnative = false); @@ -583,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(); // deleteme }; 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(); // deleteme }; @@ -609,10 +563,6 @@ protected: class PClassType : public PContainerType { - DECLARE_CLASS(PClassType, PContainerType); - -private: - public: PClass *Descriptor; PClassType *ParentType; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index f7ac477180..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()); @@ -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) @@ -2366,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. From 2d098e99fbc786fa1650c821ee940ee3e130d3a1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Apr 2017 18:59:45 +0200 Subject: [PATCH 5/9] - fixed: WP_NOCHANGE had different values in native and script code, resulting in problems with weapon selection. This now explicitly allocates a single object it can safely point to instead of trying to hack around it. --- src/d_player.h | 2 +- src/dobjtype.cpp | 16 ++++++++++++++++ src/scripting/thingdef_data.cpp | 8 -------- 3 files changed, 17 insertions(+), 9 deletions(-) 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/dobjtype.cpp b/src/dobjtype.cpp index 0ae2b47716..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 ------------------------------------------------ @@ -218,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(); } //========================================================================== @@ -230,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) { 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 From 523b31a16a558e639b8cd17bd994ce3fe7ba2a85 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Thu, 13 Apr 2017 10:20:06 -0500 Subject: [PATCH 6/9] Made several string functions const. --- wadsrc/static/zscript/base.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 9defba9de5..7fe034f0bf 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -639,15 +639,15 @@ enum EPickStart // Although String is a builtin type, this is a convenient way to attach methods to it. struct StringStruct native { - native static vararg String Format(String fmt, ...); + native static vararg String Format(String fmt, ...) const; 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(); } From 29394da7ed49fa59ecc5c792ca9e142d2a0aa0ba Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Thu, 13 Apr 2017 10:37:29 -0500 Subject: [PATCH 7/9] Static functions cannot have const. --- wadsrc/static/zscript/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 7fe034f0bf..c834dff946 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -639,7 +639,7 @@ enum EPickStart // Although String is a builtin type, this is a convenient way to attach methods to it. struct StringStruct native { - native static vararg String Format(String fmt, ...) const; + native static vararg String Format(String fmt, ...); native vararg void AppendFormat(String fmt, ...); native void Replace(String pattern, String replacement); From b1057cee36025906df27195540f3dd881fa618f3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 13 Apr 2017 20:43:17 +0200 Subject: [PATCH 8/9] - fixed: do not draw armor on the fullscreen HUD if the amount is 0. --- src/dthinker.cpp | 4 ---- wadsrc/static/zscript/statusbar/doom_sbar.txt | 2 +- wadsrc/static/zscript/statusbar/heretic_sbar.txt | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) 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/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); From d407aa3157cfaf637f498f5f44e3e2c271d825d5 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 13 Apr 2017 22:16:26 +0200 Subject: [PATCH 9/9] - Fix linear filtering bug for sprites --- src/swrenderer/drawers/r_draw_sprite32.h | 2 +- src/swrenderer/drawers/r_draw_sprite32_sse2.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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());