This commit is contained in:
Rachael Alexanderson 2017-04-14 01:05:26 -04:00
commit 93564078fe
33 changed files with 421 additions and 615 deletions

View file

@ -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

View file

@ -377,6 +377,8 @@ static inline void GC::WriteBarrier(DObject *pointed)
}
}
#include "memarena.h"
extern FMemArena ClassDataAllocator;
#include "symbols.h"
#include "dobjtype.h"

View file

@ -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);

View file

@ -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 T> class TObjPtr;

View file

@ -74,6 +74,12 @@ TArray<VMFunction**> PClass::FunctionPtrList;
bool PClass::bShutdown;
bool PClass::bVMOperational;
// Originally this was just a bogus pointer, but with the VM performing a read barrier on every object pointer write
// that does not work anymore. WP_NOCHANGE needs to point to a vaild object to work as intended.
// This Object does not need to be garbage collected, though, but it needs to provide the proper structure so that the
// GC can process it.
AWeapon *WP_NOCHANGE;
DEFINE_GLOBAL(WP_NOCHANGE);
// PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -205,7 +211,6 @@ void PClass::StaticInit ()
{
atterm (StaticShutdown);
StaticBootstrap();
Namespaces.GlobalNamespace = Namespaces.NewNamespace(0);
FAutoSegIterator probe(CRegHead, CRegTail);
@ -219,6 +224,10 @@ void PClass::StaticInit ()
// I'm not sure if this is really necessary to maintain any sort of sync.
qsort(&AllClasses[0], AllClasses.Size(), sizeof(AllClasses[0]), cregcmp);
// WP_NOCHANGE must point to a valid object, although it does not need to be a weapon.
// A simple DObject is enough to give the GC the ability to deal with it, if subjected to it.
WP_NOCHANGE = (AWeapon*)new DObject;
WP_NOCHANGE->Release();
}
//==========================================================================
@ -231,6 +240,12 @@ void PClass::StaticInit ()
void PClass::StaticShutdown ()
{
if (WP_NOCHANGE != nullptr)
{
WP_NOCHANGE->ObjectFlags |= OF_YesReallyDelete;
delete WP_NOCHANGE;
}
// delete all variables containing pointers to script functions.
for (auto p : FunctionPtrList)
{
@ -265,6 +280,7 @@ void PClass::StaticShutdown ()
ClassDataAllocator.FreeAllBlocks();
AllClasses.Clear();
PClassActor::AllActorClasses.Clear();
ClassMap.Clear();
FAutoSegIterator probe(CRegHead, CRegTail);
@ -276,16 +292,6 @@ void PClass::StaticShutdown ()
}
//==========================================================================
//
// PClass :: StaticBootstrap STATIC
//
//==========================================================================
void PClass::StaticBootstrap()
{
}
//==========================================================================
//
// PClass Constructor
@ -363,7 +369,6 @@ void ClassReg::SetupClass(PClass *cls)
cls->Size = SizeOf;
cls->Pointers = Pointers;
cls->ConstructNative = ConstructNative;
//cls->mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars());
}
//==========================================================================

View file

@ -5,8 +5,6 @@
#error You must #include "dobject.h" to get dobjtype.h
#endif
#include "memarena.h"
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
#if 0
@ -28,8 +26,6 @@ class VMFunction;
class PClassType;
struct FNamespaceManager;
extern FMemArena ClassDataAllocator;
enum
{
TentativeClass = UINT_MAX,
@ -52,7 +48,6 @@ public:
static void StaticInit();
static void StaticShutdown();
static void StaticBootstrap();
// Per-class information -------------------------------------
PClass *ParentClass = nullptr; // the class this class derives from

View file

@ -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)

View file

@ -75,12 +75,11 @@ cycle_t ActionCycles;
//
//==========================================================================
class PActorInfo : public PBasicType
class PActorInfo : public PCompoundType
{
DECLARE_CLASS(PActorInfo, PBasicType);
public:
PActorInfo()
:PBasicType(sizeof(FActorInfo), alignof(FActorInfo))
:PCompoundType(sizeof(FActorInfo), alignof(FActorInfo))
{
}
@ -113,12 +112,10 @@ public:
};
IMPLEMENT_CLASS(PActorInfo, false, false)
void AddActorInfo(PClass *cls)
{
auto type = new PActorInfo;
TypeTable.AddType(type);
TypeTable.AddType(type, NAME_Actor);
cls->AddField("*", type, VARF_Meta);
}

View file

@ -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);

View file

@ -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)

View file

@ -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<PField>(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<uint8_t *>(self) + var->Offset;
arraytype = dyn_cast<PArray>(type);
if (arraytype != NULL)
if (type->isArray())
{
PArray *arraytype = static_cast<PArray*>(type);
// unwrap contained type
type = arraytype->ElementType;
// offset by index (if in bounds)
@ -5040,12 +5039,11 @@ bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *
return false;
}
addr = baddr;
// We don't want Int subclasses like Name or Color to be accessible,
// but we do want to support Float subclasses like Fixed.
if (!type->IsA(RUNTIME_CLASS(PInt)) && !type->IsKindOf(RUNTIME_CLASS(PFloat)))
// We don't want Int subclasses like Name or Color to be accessible here.
if (!type->isInt() && !type->isFloat())
{
// For reading, we also support Name and String types.
if (readonly && (type->IsA(RUNTIME_CLASS(PName)) || type->IsA(RUNTIME_CLASS(PString))))
if (readonly && (type == TypeName || type == TypeString))
{
return true;
}
@ -5061,7 +5059,7 @@ static void SetUserVariable(AActor *self, FName varname, int index, int value)
if (GetVarAddrType(self, varname, index, addr, type, false))
{
if (!type->IsKindOf(RUNTIME_CLASS(PFloat)))
if (!type->isFloat())
{
type->SetValue(addr, value);
}
@ -5079,15 +5077,15 @@ static int GetUserVariable(AActor *self, FName varname, int index)
if (GetVarAddrType(self, varname, index, addr, type, true))
{
if (type->IsKindOf(RUNTIME_CLASS(PFloat)))
if (type->isFloat())
{
return DoubleToACS(type->GetValueFloat(addr));
}
else if (type->IsA(RUNTIME_CLASS(PName)))
else if (type == TypeName)
{
return GlobalACSStrings.AddString(FName(ENamedName(type->GetValueInt(addr))).GetChars());
}
else if (type->IsA(RUNTIME_CLASS(PString)))
else if (type == TypeString)
{
return GlobalACSStrings.AddString(*(FString *)addr);
}

View file

@ -4753,7 +4753,7 @@ static PField *GetVar(DObject *self, FName varname)
{
PField *var = dyn_cast<PField>(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<PField>(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<PArray *>(var->Type)->ElementType->IsKindOf(RUNTIME_CLASS(PBasicType)))
!var->Type->isArray() || !static_cast<PArray *>(var->Type)->ElementType->isScalar())
{
Printf("%s is not a user array in class %s\n", varname.GetChars(),
self->GetClass()->TypeName.GetChars());

View file

@ -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());

View file

@ -207,7 +207,7 @@ static PContainerType *FindContainerType(FName name, FCompileContext &ctx)
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{
auto type = static_cast<PSymbolType*>(sym);
return dyn_cast<PContainerType>(type->Type);
return type->Type->toContainer();
}
return nullptr;
}
@ -219,7 +219,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx)
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{
auto type = static_cast<PSymbolType*>(sym);
auto ctype = dyn_cast<PClassType>(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<PClassType>(type);
auto cls = PType::toClass(type);
return cls ? cls->Descriptor->IsDescendantOf(RUNTIME_CLASS(AActor)) : false;
}
@ -292,10 +292,10 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall
static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare = false)
{
if (dest->IsKindOf(RUNTIME_CLASS(PPointer)) && source->IsKindOf(RUNTIME_CLASS(PPointer)))
if (dest->isPointer() && source->isPointer())
{
auto fromtype = static_cast<PPointer *>(source);
auto totype = static_cast<PPointer *>(dest);
auto fromtype = source->toPointer();
auto totype = dest->toPointer();
// null pointers can be assigned to everything, everything can be assigned to void pointers.
if (fromtype == nullptr || totype == TypeVoidPtr) return true;
// when comparing const-ness does not matter.
@ -303,7 +303,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar
// A type is always compatible to itself.
if (fromtype == totype) return true;
// Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type.
if (source->IsA(RUNTIME_CLASS(PObjectPointer)) && dest->IsA(RUNTIME_CLASS(PObjectPointer)))
if (source->isObjectPointer() && dest->isObjectPointer())
{
auto fromcls = static_cast<PObjectPointer*>(source)->PointedClass();
auto tocls = static_cast<PObjectPointer*>(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<PClassPointer*>(source)->ClassRestriction;
auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction;
@ -557,11 +557,11 @@ FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
PSymbolConstNumeric *csym = dyn_cast<PSymbolConstNumeric>(sym);
if (csym != nullptr)
{
if (csym->ValueType->IsA(RUNTIME_CLASS(PInt)))
if (csym->ValueType->isInt())
{
x = new FxConstant(csym->Value, pos);
}
else if (csym->ValueType->IsA(RUNTIME_CLASS(PFloat)))
else if (csym->ValueType->isFloat())
{
x = new FxConstant(csym->Float, pos);
}
@ -1158,7 +1158,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx);
if (mExplicit && basex->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
if (mExplicit && basex->ValueType->isClassPointer())
{
if (basex->isConstant())
{
@ -1356,7 +1356,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx);
if (basex->ValueType == TypeColor || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt))
if (basex->ValueType == TypeColor || basex->ValueType->isInt())
{
FxExpression *x = basex;
x->ValueType = TypeColor;
@ -1445,7 +1445,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx);
if (basex->ValueType == TypeSound || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt))
if (basex->ValueType == TypeSound || basex->ValueType->isInt())
{
FxExpression *x = basex;
x->ValueType = TypeSound;
@ -1617,7 +1617,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
// don't go through the entire list if the types are the same.
goto basereturn;
}
else if (basex->ValueType == TypeNullPtr && (ValueType == TypeState || ValueType->IsKindOf(RUNTIME_CLASS(PPointer))))
else if (basex->ValueType == TypeNullPtr && ValueType->isPointer())
{
goto basereturn;
}
@ -1629,7 +1629,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
delete this;
return x;
}
else if (ValueType->IsA(RUNTIME_CLASS(PInt)))
else if (ValueType->isInt())
{
// This is only for casting to actual ints. Subtypes representing an int will be handled elsewhere.
FxExpression *x = new FxIntCast(basex, NoWarn, Explicit);
@ -1750,7 +1750,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
}
}
}
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
else if (ValueType->isClassPointer())
{
FxExpression *x = new FxClassTypeCast(static_cast<PClassPointer*>(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<PClassType *>(basex->ValueType)->Descriptor;
@ -1773,7 +1773,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
if (fromtype->IsDescendantOf(totype)) goto basereturn;
}
}
else if (basex->IsNativeStruct() && ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType == basex->ValueType)
else if (basex->IsNativeStruct() && ValueType->isRealPointer() && ValueType->toPointer()->PointedType == basex->ValueType)
{
bool writable;
basex->RequestAddress(ctx, &writable);
@ -2480,13 +2480,13 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
}
else if (Base->ValueType == Right->ValueType)
{
if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PArray)))
if (Base->ValueType->isArray())
{
ScriptPosition.Message(MSG_ERROR, "Cannot assign arrays");
delete this;
return nullptr;
}
if (!Base->IsVector() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
if (!Base->IsVector() && Base->ValueType->isStruct())
{
ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet");
delete this;
@ -2494,7 +2494,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
}
// Both types are the same so this is ok.
}
else if (Right->IsNativeStruct() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(Base->ValueType)->PointedType == Right->ValueType)
else if (Right->IsNativeStruct() && Base->ValueType->isRealPointer() && Base->ValueType->toPointer()->PointedType == Right->ValueType)
{
// allow conversion of native structs to pointers of the same type. This is necessary to assign elements from global arrays like players, sectors, etc. to local pointers.
// For all other types this is not needed. Structs are not assignable and classes can only exist as references.
@ -3611,7 +3611,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
// Special cases: Compare strings and names with names, sounds, colors, state labels and class types.
// These are all types a string can be implicitly cast into, so for convenience, so they should when doing a comparison.
if ((left->ValueType == TypeString || left->ValueType == TypeName) &&
(right->ValueType == TypeName || right->ValueType == TypeSound || right->ValueType == TypeColor || right->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || right->ValueType == TypeStateLabel))
(right->ValueType == TypeName || right->ValueType == TypeSound || right->ValueType == TypeColor || right->ValueType->isClassPointer() || right->ValueType == TypeStateLabel))
{
left = new FxTypeCast(left, right->ValueType, false, true);
left = left->Resolve(ctx);
@ -3619,7 +3619,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
ValueType = right->ValueType;
}
else if ((right->ValueType == TypeString || right->ValueType == TypeName) &&
(left->ValueType == TypeName || left->ValueType == TypeSound || left->ValueType == TypeColor || left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || left->ValueType == TypeStateLabel))
(left->ValueType == TypeName || left->ValueType == TypeSound || left->ValueType == TypeColor || left->ValueType->isClassPointer() || left->ValueType == TypeStateLabel))
{
right = new FxTypeCast(right, left->ValueType, false, true);
right = right->Resolve(ctx);
@ -3649,12 +3649,12 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
goto error;
}
}
else if (left->IsPointer() && static_cast<PPointer*>(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<PPointer*>(right->ValueType)->PointedType == left->ValueType)
else if (right->IsPointer() && right->ValueType->toPointer()->PointedType == left->ValueType)
{
bool writable;
if (!left->RequestAddress(ctx, &writable)) goto error;
@ -4596,7 +4596,7 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx)
RESOLVE(right, ctx);
ABORT(right && left);
if (left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
if (left->ValueType->isClassPointer())
{
left = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), left, false);
ClassCheck = true;
@ -4684,7 +4684,7 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
SAFE_RESOLVE(expr, ctx);
bool constflag = expr->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer *>(expr->ValueType)->IsConst;
bool constflag = expr->ValueType->isPointer() && expr->ValueType->toPointer()->IsConst;
if (constflag)
{
// readonly pointers are normally only used for class defaults which lack type information to be cast properly, so we have to error out here.
@ -5140,7 +5140,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
SAFE_RESOLVE(val, ctx);
CallingFunction = ctx.Function;
if (!val->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
if (!val->ValueType->isClassPointer())
{
ScriptPosition.Message(MSG_ERROR, "Class type expected");
delete this;
@ -5159,8 +5159,8 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
//
int outerside = ctx.Function && ctx.Function->Variants.Size() ? FScopeBarrier::SideFromFlags(ctx.Function->Variants[0].Flags) : FScopeBarrier::Side_Virtual;
if (outerside == FScopeBarrier::Side_Virtual)
outerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags);
int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ObjectFlags);
outerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags);
int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ScopeFlags);
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
{
ScriptPosition.Message(MSG_ERROR, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside));
@ -5190,7 +5190,7 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build)
{
int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags);
if (outerside == FScopeBarrier::Side_Virtual)
outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ObjectFlags);
outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ScopeFlags);
build->Emit(OP_NEW, to.RegNum, from.RegNum, outerside+1); // +1 to ensure it's not 0
}
else
@ -6126,7 +6126,7 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *
{
PSymbol *sym;
PSymbolTable *symtbl;
bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClassType));
bool isclass = objtype->isClass();
if (Identifier == NAME_Default)
{
@ -6180,8 +6180,8 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *
object = nullptr;
return nullptr;
}
auto cls_ctx = dyn_cast<PClassType>(classctx);
auto cls_target = dyn_cast<PClassType>(objtype);
auto cls_ctx = PType::toClass(classctx);
auto cls_target = PType::toClass(objtype);
// [ZZ] neither PSymbol, PField or PSymbolTable have the necessary information. so we need to do the more complex check here.
if (vsym->Flags & VARF_Protected)
{
@ -6342,7 +6342,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
auto sn = static_cast<PSymbolConstNumeric*>(sym);
VMValue vmv;
if (sn->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) vmv = sn->Value;
if (sn->ValueType->isIntCompatible()) vmv = sn->Value;
else vmv = sn->Float;
auto x = new FxConstant(sn->ValueType, vmv, ScriptPosition);
delete this;
@ -6393,17 +6393,17 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
{
Object->ValueType = TypeColorStruct;
}
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
if (Object->ValueType->isRealPointer())
{
auto ptype = static_cast<PPointer *>(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<PContainerType *>(ptype));
delete this;
return ret;
}
}
else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
else if (Object->ValueType->isStruct())
{
auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PStruct *>(Object->ValueType));
delete this;
@ -6603,8 +6603,8 @@ FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
SAFE_RESOLVE(obj, ctx);
assert(obj->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)));
ValueType = NewPointer(static_cast<PPointer*>(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<PPointer*>(classx->ValueType)->IsConst));
(!classx->ValueType->isPointer() || !classx->ValueType->toPointer()->IsConst));
// [ZZ] implement write barrier between different scopes
if (bWritable)
{
@ -6947,7 +6947,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable)
{
outerflags = ctx.Function->Variants[0].Flags;
if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class)
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags));
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags));
}
FScopeBarrier scopeBarrier(outerflags, FScopeBarrier::FlagsFromSide(BarrierSide), membervar->SymbolName.GetChars());
if (!scopeBarrier.writable)
@ -6972,7 +6972,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
if (membervar->SymbolName == NAME_Default)
{
if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer))
if (!classx->ValueType->isObjectPointer()
|| !static_cast<PObjectPointer *>(classx->ValueType)->PointedClass()->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type");
@ -6991,7 +6991,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
{
outerflags = ctx.Function->Variants[0].Flags;
if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class)
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags));
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags));
}
FScopeBarrier scopeBarrier(outerflags, membervar->Flags, membervar->SymbolName.GetChars());
if (!scopeBarrier.readable)
@ -7018,17 +7018,17 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
return x->Resolve(ctx);
}
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
if (classx->ValueType->isPointer())
{
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType);
if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PContainerType)))
PPointer *ptrtype = classx->ValueType->toPointer();
if (ptrtype == nullptr || !ptrtype->PointedType->isContainer())
{
ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object");
delete this;
return nullptr;
}
}
else if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
else if (classx->ValueType->isStruct())
{
// if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember || classx->ExprType == EFX_GlobalVariable || classx->ExprType == EFX_StackVariable)
@ -7237,12 +7237,11 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
}
else
{
arraytype = dyn_cast<PArray>(Array->ValueType);
if (arraytype == nullptr)
if (!Array->ValueType->isArray())
{
// Check if we got a pointer to an array. Some native data structures (like the line list in sectors) use this.
PPointer *ptype = dyn_cast<PPointer>(Array->ValueType);
if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray)))
PPointer *ptype = Array->ValueType->toPointer();
if (ptype == nullptr || !ptype->PointedType->isArray())
{
ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
delete this;
@ -7251,10 +7250,14 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
arraytype = static_cast<PArray*>(ptype->PointedType);
arrayispointer = true;
}
else
{
arraytype = static_cast<PArray*>(Array->ValueType);
}
elementtype = arraytype->ElementType;
}
if (Array->IsResizableArray())
if (Array->isStaticArray())
{
// if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable)
@ -7316,7 +7319,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
if (arrayispointer)
{
arraytype = static_cast<PArray*>(static_cast<PPointer*>(Array->ValueType)->PointedType);
arraytype = static_cast<PArray*>(Array->ValueType->toPointer()->PointedType);
}
else
{
@ -7498,8 +7501,8 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction
bool match = (callingself == calledself);
if (!match)
{
auto callingselfcls = dyn_cast<PClassType>(caller->Variants[0].SelfClass);
auto calledselfcls = dyn_cast<PClassType>(callee->Variants[0].SelfClass);
auto callingselfcls = PType::toClass(caller->Variants[0].SelfClass);
auto calledselfcls = PType::toClass(callee->Variants[0].SelfClass);
match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->Descriptor->IsDescendantOf(calledselfcls->Descriptor);
}
@ -7616,14 +7619,14 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
{
outerflags = ctx.Function->Variants[0].Flags;
if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class)
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags));
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags));
}
int innerflags = afd->Variants[0].Flags;
int innerside = FScopeBarrier::SideFromFlags(innerflags);
// [ZZ] check this at compile time. this would work for most legit cases.
if (innerside == FScopeBarrier::Side_Virtual)
{
innerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags);
innerside = FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags);
innerflags = FScopeBarrier::FlagsFromSide(innerside);
}
FScopeBarrier scopeBarrier(outerflags, innerflags, MethodName.GetChars());
@ -7860,7 +7863,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition))
{
// [ZZ] allow implicit new() call to mean "create current class instance"
if (!ArgList.Size() && !ctx.Class->IsKindOf(RUNTIME_CLASS(PClassType)))
if (!ArgList.Size() && !ctx.Class->isClass())
{
ScriptPosition.Message(MSG_ERROR, "Cannot use implicit new() in a struct");
delete this;
@ -7969,7 +7972,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
{
cls = ccls;
staticonly = true;
if (ccls->IsKindOf(RUNTIME_CLASS(PClassType)))
if (ccls->isClass())
{
if (ctx.Function == nullptr)
{
@ -7977,7 +7980,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
delete this;
return nullptr;
}
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass);
auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr)
{
novirtual = clstype->Descriptor->IsDescendantOf(static_cast<PClassType*>(ccls)->Descriptor);
@ -8009,7 +8012,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
delete this;
return nullptr;
}
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass);
auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr)
{
// give the node the proper value type now that we know it's properly used.
@ -8150,7 +8153,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
member->membervar = newfield;
}
}
else if (a->IsPointer() && Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
else if (a->IsPointer() && Self->ValueType->isPointer())
{
// the only case which must be checked up front is for pointer arrays receiving a new element.
// Since there is only one native backing class it uses a neutral void pointer as its argument,
@ -8175,10 +8178,10 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
delete this;
return nullptr;
}
if (!Self->IsResizableArray())
if (!Self->isStaticArray())
{
auto atype = Self->ValueType;
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) atype = static_cast<PPointer*>(ValueType)->PointedType;
if (Self->ValueType->isPointer()) atype = ValueType->toPointer()->PointedType;
auto size = static_cast<PArray*>(atype)->ElementCount;
auto x = new FxConstant(size, ScriptPosition);
delete this;
@ -8210,7 +8213,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (MethodName == NAME_GetParentClass &&
(Self->IsObject() || Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))))
(Self->IsObject() || Self->ValueType->isClassPointer()))
{
if (ArgList.Size() > 0)
{
@ -8222,12 +8225,13 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
return x->Resolve(ctx);
}
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
if (Self->ValueType->isRealPointer())
{
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType)))
auto ptype = Self->ValueType->toPointer()->PointedType;
cls = ptype->toContainer();
if (cls != nullptr)
{
if (ptype->IsKindOf(RUNTIME_CLASS(PClassType)) && MethodName == NAME_GetClass)
if (ptype->isClass() && MethodName == NAME_GetClass)
{
if (ArgList.Size() > 0)
{
@ -8238,9 +8242,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
auto x = new FxGetClass(Self);
return x->Resolve(ctx);
}
cls = static_cast<PContainerType *>(ptype);
}
else
{
@ -8249,7 +8250,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
return nullptr;
}
}
else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
else if (Self->ValueType->isStruct())
{
bool writable;
@ -8299,14 +8300,14 @@ isresolved:
{
outerflags = ctx.Function->Variants[0].Flags;
if (((outerflags & (VARF_VirtualScope | VARF_Virtual)) == (VARF_VirtualScope | VARF_Virtual)) && ctx.Class)
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ObjectFlags));
outerflags = FScopeBarrier::FlagsFromSide(FScopeBarrier::SideFromObjectFlags(ctx.Class->ScopeFlags));
}
int innerflags = afd->Variants[0].Flags;
int innerside = FScopeBarrier::SideFromFlags(innerflags);
// [ZZ] check this at compile time. this would work for most legit cases.
if (innerside == FScopeBarrier::Side_Virtual)
{
innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
innerside = FScopeBarrier::SideFromObjectFlags(cls->ScopeFlags);
innerflags = FScopeBarrier::FlagsFromSide(innerside);
}
else if (innerside != FScopeBarrier::Side_Clear)
@ -8330,8 +8331,8 @@ isresolved:
{
if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual))
{
auto clstype = dyn_cast<PClassType>(ctx.Class);
auto ccls = dyn_cast<PClassType>(cls);
auto clstype = PType::toClass(ctx.Class);
auto ccls = PType::toClass(cls);
if (clstype == nullptr || ccls == nullptr || !clstype->Descriptor->IsDescendantOf(ccls->Descriptor))
{
ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here", cls->TypeName.GetChars(), MethodName.GetChars());
@ -8759,7 +8760,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
// If this is a reference argument, the pointer type must be undone because the code below expects the pointed type as value type.
if (argflags[i + k + implicit] & VARF_Ref)
{
assert(ntype->IsKindOf(RUNTIME_CLASS(PPointer)));
assert(ntype->isPointer());
ntype = TypeNullPtr; // the default of a reference type can only be a null pointer
}
if (ntype->GetRegCount() == 1)
@ -8822,7 +8823,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr)
{
if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(type)->PointedType->IsA(RUNTIME_CLASS(PStruct)))
if (type == ArgList[i]->ValueType && type->isRealPointer() && type->toPointer()->PointedType->isStruct())
{
// trying to pass a struct reference as a struct reference. This must preserve the type.
}
@ -8937,11 +8938,11 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
if (innerside == FScopeBarrier::Side_Virtual)
{
auto selfside = FScopeBarrier::SideFromObjectFlags(static_cast<PPointer*>(Self->ValueType)->PointedType->ObjectFlags);
auto selfside = FScopeBarrier::SideFromObjectFlags(Self->ValueType->toPointer()->PointedType->ScopeFlags);
int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags);
if (outerside == FScopeBarrier::Side_Virtual)
outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ObjectFlags);
outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ScopeFlags);
// [ZZ] only emit if target side cannot be checked at compile time.
if (selfside == FScopeBarrier::Side_PlainData)
@ -9300,7 +9301,7 @@ FxExpression *FxGetClass::Resolve(FCompileContext &ctx)
delete this;
return nullptr;
}
ValueType = NewClassPointer(static_cast<PClassType*>(static_cast<PPointer*>(Self->ValueType)->PointedType)->Descriptor);
ValueType = NewClassPointer(static_cast<PClassType*>(Self->ValueType->toPointer()->PointedType)->Descriptor);
return this;
}
@ -9333,7 +9334,7 @@ FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx)
{
SAFE_RESOLVE(Self, ctx);
if (!Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && !Self->IsObject())
if (!Self->ValueType->isClassPointer() && !Self->IsObject())
{
ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object");
delete this;
@ -9404,7 +9405,7 @@ FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx)
}
else
{
auto cp = dyn_cast<PClassPointer>(Self->ValueType);
auto cp = PType::toClassPointer(Self->ValueType);
if (cp == nullptr || !cp->ClassRestriction->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type");
@ -10603,7 +10604,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
return x;
}
auto to = static_cast<PClassPointer *>(ValueType);
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
if (basex->ValueType->isClassPointer())
{
auto from = static_cast<PClassPointer *>(basex->ValueType);
if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction))
@ -10771,7 +10772,7 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
return x;
}
auto to = static_cast<PClassPointer *>(ValueType);
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
if (basex->ValueType->isClassPointer())
{
auto from = static_cast<PClassPointer *>(basex->ValueType);
// Downcast is always ok.
@ -10848,7 +10849,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
ABORT(ctx.Class);
auto vclass = dyn_cast<PClassType>(ctx.Class);
auto vclass = PType::toClass(ctx.Class);
assert(vclass != nullptr);
auto aclass = ValidateActor(vclass->Descriptor);
@ -10927,7 +10928,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx)
SAFE_RESOLVE(Index, ctx);
}
auto vclass = dyn_cast<PClassType>(ctx.Class);
auto vclass = PType::toClass(ctx.Class);
assert(vclass != nullptr);
auto aclass = ValidateActor(vclass->Descriptor);
assert(aclass != nullptr && aclass->GetStateCount() > 0);
@ -10987,7 +10988,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
ABORT(ctx.Class);
int symlabel;
auto vclass = dyn_cast<PClassType>(ctx.Class);
auto vclass = PType::toClass(ctx.Class);
assert(vclass != nullptr);
auto clstype = ValidateActor(vclass->Descriptor);
@ -11203,7 +11204,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
else
{
// Init arrays and structs.
if (ValueType->IsA(RUNTIME_CLASS(PStruct)))
if (ValueType->isStruct())
{
auto pstr = static_cast<PStruct*>(ValueType);
if (pstr->mConstructor != nullptr)
@ -11229,7 +11230,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
}
else
{
if (ValueType->IsA(RUNTIME_CLASS(PStruct)))
if (ValueType->isStruct())
{
auto pstr = static_cast<PStruct*>(ValueType);
if (pstr->mDestructor != nullptr)

View file

@ -330,16 +330,16 @@ public:
virtual bool CheckReturn() { return false; }
virtual int GetBitValue() { return -1; }
bool IsNumeric() const { return ValueType->isNumeric(); }
bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; }
bool IsInteger() const { return ValueType->isNumeric() && (ValueType->GetRegType() == REGT_INT); }
bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; }
bool IsFloat() const { return ValueType->isFloat(); }
bool IsInteger() const { return ValueType->isNumeric() && ValueType->isIntCompatible(); }
bool IsPointer() const { return ValueType->isPointer(); }
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); }
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)); }
bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); }
bool IsResizableArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PStaticArray))); } // can only exist in pointer form.
bool IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); }
bool IsNativeStruct() const { return (ValueType->IsA(RUNTIME_CLASS(PStruct)) && static_cast<PStruct*>(ValueType)->isNative); }
bool IsBoolCompat() const { return ValueType->isScalar(); }
bool IsObject() const { return ValueType->isObjectPointer(); }
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form.
bool IsDynamicArray() const { return (ValueType->isDynArray()); }
bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }
virtual ExpEmit Emit(VMFunctionBuilder *build);
void EmitStatement(VMFunctionBuilder *build);

View file

@ -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));
}

View file

@ -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);

View file

@ -102,7 +102,7 @@ PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FN
{
// [ZZ] DECORATE classes are always play
auto vmtype = type->VMType;
vmtype->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(vmtype->ObjectFlags, FScopeBarrier::Side_Play);
vmtype->ScopeFlags = FScopeBarrier::ChangeSideInObjectFlags(vmtype->ScopeFlags, FScopeBarrier::Side_Play);
}
return type;
@ -203,7 +203,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type)
x = new FxRuntimeStateIndex(ParseExpression(sc, cls));
}
}
else if (type->GetClass() == RUNTIME_CLASS(PClassPointer))
else if (type->isClassPointer())
{ // Actor name
sc.SetEscape(true);
sc.MustGetString();
@ -866,22 +866,22 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
if (sc.CheckNumber()) *(int*)addr = sc.Number;
else *(PalEntry*)addr = V_GetColor(nullptr, sc);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
else if (f->Type->isIntCompatible())
{
sc.MustGetNumber();
static_cast<PInt*>(f->Type)->SetValue(addr, sc.Number);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat)))
else if (f->Type->isFloat())
{
sc.MustGetFloat();
static_cast<PFloat*>(f->Type)->SetValue(addr, sc.Float);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PString)))
else if (f->Type == TypeString)
{
sc.MustGetString();
*(FString*)addr = strbin1(sc.String);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
else if (f->Type->isClassPointer())
{
sc.MustGetString();
@ -892,13 +892,14 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
else
{
auto cls = PClass::FindClass(sc.String);
auto cp = static_cast<PClassPointer*>(f->Type);
if (cls == nullptr)
{
cls = static_cast<PClassPointer*>(f->Type)->ClassRestriction->FindClassTentative(sc.String);
cls = cp->ClassRestriction->FindClassTentative(sc.String);
}
else if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
else if (!cls->IsDescendantOf(cp->ClassRestriction))
{
sc.ScriptMessage("class %s is not compatible with property type %s", sc.String, static_cast<PClassPointer*>(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;

View file

@ -47,7 +47,6 @@ FNamespaceManager Namespaces;
// Symbol tables ------------------------------------------------------------
IMPLEMENT_CLASS(PTypeBase, true, false);
IMPLEMENT_CLASS(PSymbol, true, false);
IMPLEMENT_CLASS(PSymbolConst, false, false);
IMPLEMENT_CLASS(PSymbolConstNumeric, false, false);
@ -56,12 +55,6 @@ IMPLEMENT_CLASS(PSymbolTreeNode, false, false)
IMPLEMENT_CLASS(PSymbolType, false, false)
IMPLEMENT_CLASS(PSymbolVMFunction, false, false)
IMPLEMENT_CLASS(PFunction, false, false)
IMPLEMENT_CLASS(PNamespace, false, true)
IMPLEMENT_POINTERS_START(PNamespace)
IMPLEMENT_POINTER(Parent)
IMPLEMENT_POINTERS_END
//==========================================================================
//
@ -104,9 +97,9 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray<uint32_t> &argflags, TA
if (flags & VARF_Method)
{
assert(proto->ArgumentTypes.Size() > 0);
auto selftypeptr = dyn_cast<PPointer>(proto->ArgumentTypes[0]);
auto selftypeptr = proto->ArgumentTypes[0]->toPointer();
assert(selftypeptr != nullptr);
variant.SelfClass = dyn_cast<PContainerType>(selftypeptr->PointedType);
variant.SelfClass = selftypeptr->PointedType->toContainer();
assert(variant.SelfClass != nullptr);
}
else
@ -155,7 +148,7 @@ PField::PField(FName name, PType *type, uint32_t flags, size_t offset, int bitva
unsigned val = bitvalue;
while ((val >>= 1)) BitValue++;
if (type->IsA(RUNTIME_CLASS(PInt)) && unsigned(BitValue) < 8u * type->Size)
if (type->isInt() && unsigned(BitValue) < 8u * type->Size)
{
// map to the single bytes in the actual variable. The internal bit instructions operate on 8 bit values.
#ifndef __BIG_ENDIAN__
@ -523,21 +516,6 @@ PNamespace *FNamespaceManager::NewNamespace(int filenum)
//
//==========================================================================
size_t FNamespaceManager::MarkSymbols()
{
for (auto ns : AllNamespaces)
{
GC::Mark(ns);
}
return AllNamespaces.Size();
}
//==========================================================================
//
//
//
//==========================================================================
void FNamespaceManager::ReleaseSymbols()
{
RemoveSymbols();
@ -559,7 +537,7 @@ int FNamespaceManager::RemoveSymbols()
for (auto ns : AllNamespaces)
{
count += ns->Symbols.Symbols.CountUsed();
ns->Symbols.ReleaseSymbols();
delete ns;
}
return count;
}
@ -582,7 +560,7 @@ void RemoveUnusedSymbols()
{
for (PType *ty = TypeTable.TypeHash[i]; ty != nullptr; ty = ty->HashNext)
{
if (ty->IsKindOf(RUNTIME_CLASS(PContainerType)))
if (ty->isContainer())
{
auto it = ty->Symbols.GetIterator();
PSymbolTable::MapType::Pair *pair;

View file

@ -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();
};

View file

@ -195,8 +195,8 @@ PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *func
if (symbol != nullptr)
{
auto cls_ctx = dyn_cast<PClassType>(funccls);
auto cls_target = funcsym ? dyn_cast<PClassType>(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());

View file

@ -70,14 +70,6 @@ static TArray<FieldDesc> 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

View file

@ -446,8 +446,8 @@ int MatchString (const char *in, const char **strings)
static bool PointerCheck(PType *symtype, PType *checktype)
{
auto symptype = dyn_cast<PClassPointer>(symtype);
auto checkptype = dyn_cast<PClassPointer>(checktype);
auto symptype = PType::toClassPointer(symtype);
auto checkptype = PType::toClassPointer(checktype);
return symptype != nullptr && checkptype != nullptr && symptype->ClassRestriction->IsDescendantOf(checkptype->ClassRestriction);
}

View file

@ -68,9 +68,6 @@ PPointer *TypeVoidPtr;
// CODE --------------------------------------------------------------------
IMPLEMENT_CLASS(PErrorType, false, false)
IMPLEMENT_CLASS(PVoidType, false, false)
void DumpTypeTable()
{
int used = 0;
@ -116,8 +113,6 @@ void DumpTypeTable()
/* PType ******************************************************************/
IMPLEMENT_CLASS(PType, true, false)
//==========================================================================
//
// PType Parameterized Constructor
@ -289,27 +284,27 @@ const char *PType::DescriptiveName() const
void PType::StaticInit()
{
// Create types and add them type the type table.
TypeTable.AddType(TypeError = new PErrorType);
TypeTable.AddType(TypeAuto = new PErrorType(2));
TypeTable.AddType(TypeVoid = new PVoidType);
TypeTable.AddType(TypeSInt8 = new PInt(1, false));
TypeTable.AddType(TypeUInt8 = new PInt(1, true));
TypeTable.AddType(TypeSInt16 = new PInt(2, false));
TypeTable.AddType(TypeUInt16 = new PInt(2, true));
TypeTable.AddType(TypeSInt32 = new PInt(4, false));
TypeTable.AddType(TypeUInt32 = new PInt(4, true));
TypeTable.AddType(TypeBool = new PBool);
TypeTable.AddType(TypeFloat32 = new PFloat(4));
TypeTable.AddType(TypeFloat64 = new PFloat(8));
TypeTable.AddType(TypeString = new PString);
TypeTable.AddType(TypeName = new PName);
TypeTable.AddType(TypeSound = new PSound);
TypeTable.AddType(TypeColor = new PColor);
TypeTable.AddType(TypeState = new PStatePointer);
TypeTable.AddType(TypeStateLabel = new PStateLabel);
TypeTable.AddType(TypeNullPtr = new PPointer);
TypeTable.AddType(TypeSpriteID = new PSpriteID);
TypeTable.AddType(TypeTextureID = new PTextureID);
TypeTable.AddType(TypeError = new PErrorType, NAME_None);
TypeTable.AddType(TypeAuto = new PErrorType(2), NAME_None);
TypeTable.AddType(TypeVoid = new PVoidType, NAME_Void);
TypeTable.AddType(TypeSInt8 = new PInt(1, false), NAME_Int);
TypeTable.AddType(TypeUInt8 = new PInt(1, true), NAME_Int);
TypeTable.AddType(TypeSInt16 = new PInt(2, false), NAME_Int);
TypeTable.AddType(TypeUInt16 = new PInt(2, true), NAME_Int);
TypeTable.AddType(TypeSInt32 = new PInt(4, false), NAME_Int);
TypeTable.AddType(TypeUInt32 = new PInt(4, true), NAME_Int);
TypeTable.AddType(TypeBool = new PBool, NAME_Bool);
TypeTable.AddType(TypeFloat32 = new PFloat(4), NAME_Float);
TypeTable.AddType(TypeFloat64 = new PFloat(8), NAME_Float);
TypeTable.AddType(TypeString = new PString, NAME_String);
TypeTable.AddType(TypeName = new PName, NAME_Name);
TypeTable.AddType(TypeSound = new PSound, NAME_Sound);
TypeTable.AddType(TypeColor = new PColor, NAME_Color);
TypeTable.AddType(TypeState = new PStatePointer, NAME_Pointer);
TypeTable.AddType(TypeStateLabel = new PStateLabel, NAME_Label);
TypeTable.AddType(TypeNullPtr = new PPointer, NAME_Pointer);
TypeTable.AddType(TypeSpriteID = new PSpriteID, NAME_SpriteID);
TypeTable.AddType(TypeTextureID = new PTextureID, NAME_TextureID);
TypeVoidPtr = NewPointer(TypeVoid, false);
TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value.
@ -330,7 +325,7 @@ void PType::StaticInit()
TypeVector2 = new PStruct(NAME_Vector2, nullptr);
TypeVector2->AddField(NAME_X, TypeFloat64);
TypeVector2->AddField(NAME_Y, TypeFloat64);
TypeTable.AddType(TypeVector2);
TypeTable.AddType(TypeVector2, NAME_Struct);
TypeVector2->loadOp = OP_LV2;
TypeVector2->storeOp = OP_SV2;
TypeVector2->moveOp = OP_MOVEV2;
@ -343,7 +338,7 @@ void PType::StaticInit()
TypeVector3->AddField(NAME_Z, TypeFloat64);
// allow accessing xy as a vector2. This is not supposed to be serialized so it's marked transient
TypeVector3->Symbols.AddSymbol(new PField(NAME_XY, TypeVector2, VARF_Transient, 0));
TypeTable.AddType(TypeVector3);
TypeTable.AddType(TypeVector3, NAME_Struct);
TypeVector3->loadOp = OP_LV3;
TypeVector3->storeOp = OP_SV3;
TypeVector3->moveOp = OP_MOVEV3;
@ -375,18 +370,6 @@ void PType::StaticInit()
/* PBasicType *************************************************************/
IMPLEMENT_CLASS(PBasicType, true, false)
//==========================================================================
//
// PBasicType Default Constructor
//
//==========================================================================
PBasicType::PBasicType()
{
}
//==========================================================================
//
// PBasicType Parameterized Constructor
@ -397,16 +380,25 @@ PBasicType::PBasicType(unsigned int size, unsigned int align)
: PType(size, align)
{
mDescriptiveName = "BasicType";
Flags |= TYPE_Scalar;
}
/* PCompoundType **********************************************************/
IMPLEMENT_CLASS(PCompoundType, true, false)
//==========================================================================
//
// PBasicType Parameterized Constructor
//
//==========================================================================
PCompoundType::PCompoundType(unsigned int size, unsigned int align)
: PType(size, align)
{
mDescriptiveName = "CompoundType";
}
/* PContainerType *************************************************************/
IMPLEMENT_CLASS(PContainerType, true, false)
//==========================================================================
//
// PContainerType :: IsMatch
@ -415,7 +407,7 @@ IMPLEMENT_CLASS(PContainerType, true, false)
bool PContainerType::IsMatch(intptr_t id1, intptr_t id2) const
{
const DObject *outer = (const DObject *)id1;
const PTypeBase *outer = (const PTypeBase *)id1;
FName name = (ENamedName)(intptr_t)id2;
return Outer == outer && TypeName == name;
@ -435,23 +427,6 @@ void PContainerType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
/* PInt *******************************************************************/
IMPLEMENT_CLASS(PInt, false, false)
//==========================================================================
//
// PInt Default Constructor
//
//==========================================================================
PInt::PInt()
: PBasicType(4, 4), Unsigned(false), IntCompatible(true)
{
mDescriptiveName = "SInt32";
Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1));
Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF));
SetOps();
}
//==========================================================================
//
// PInt Parameterized Constructor
@ -462,6 +437,7 @@ PInt::PInt(unsigned int size, bool unsign, bool compatible)
: PBasicType(size, size), Unsigned(unsign), IntCompatible(compatible)
{
mDescriptiveName.Format("%cInt%d", unsign? 'U':'S', size);
Flags |= TYPE_Int;
MemberOnly = (size < 4);
if (!unsign)
@ -674,8 +650,6 @@ double PInt::GetValueFloat(void *addr) const
/* PBool ******************************************************************/
IMPLEMENT_CLASS(PBool, false, false)
//==========================================================================
//
// PInt :: SetValue
@ -713,26 +687,11 @@ PBool::PBool()
{
mDescriptiveName = "Bool";
MemberOnly = false;
Flags |= TYPE_IntNotInt;
}
/* PFloat *****************************************************************/
IMPLEMENT_CLASS(PFloat, false, false)
//==========================================================================
//
// PFloat Default Constructor
//
//==========================================================================
PFloat::PFloat()
: PBasicType(8, 8)
{
mDescriptiveName = "Float";
SetDoubleSymbols();
SetOps();
}
//==========================================================================
//
// PFloat Parameterized Constructor
@ -743,6 +702,7 @@ PFloat::PFloat(unsigned int size)
: PBasicType(size, size)
{
mDescriptiveName.Format("Float%d", size);
Flags |= TYPE_Float;
if (size == 8)
{
#ifdef __i386__
@ -976,8 +936,6 @@ void PFloat::SetOps()
/* PString ****************************************************************/
IMPLEMENT_CLASS(PString, false, false)
//==========================================================================
//
// PString Default Constructor
@ -1073,8 +1031,6 @@ void PString::DestroyValue(void *addr) const
/* PName ******************************************************************/
IMPLEMENT_CLASS(PName, false, false)
//==========================================================================
//
// PName Default Constructor
@ -1085,6 +1041,7 @@ PName::PName()
: PInt(sizeof(FName), true, false)
{
mDescriptiveName = "Name";
Flags |= TYPE_IntNotInt;
assert(sizeof(FName) == alignof(FName));
}
@ -1123,8 +1080,6 @@ bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const
/* PSpriteID ******************************************************************/
IMPLEMENT_CLASS(PSpriteID, false, false)
//==========================================================================
//
// PName Default Constructor
@ -1134,6 +1089,7 @@ IMPLEMENT_CLASS(PSpriteID, false, false)
PSpriteID::PSpriteID()
: PInt(sizeof(int), true, true)
{
Flags |= TYPE_IntNotInt;
mDescriptiveName = "SpriteID";
}
@ -1165,8 +1121,6 @@ bool PSpriteID::ReadValue(FSerializer &ar, const char *key, void *addr) const
/* PTextureID ******************************************************************/
IMPLEMENT_CLASS(PTextureID, false, false)
//==========================================================================
//
// PTextureID Default Constructor
@ -1177,6 +1131,7 @@ PTextureID::PTextureID()
: PInt(sizeof(FTextureID), true, false)
{
mDescriptiveName = "TextureID";
Flags |= TYPE_IntNotInt;
assert(sizeof(FTextureID) == alignof(FTextureID));
}
@ -1208,8 +1163,6 @@ bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const
/* PSound *****************************************************************/
IMPLEMENT_CLASS(PSound, false, false)
//==========================================================================
//
// PSound Default Constructor
@ -1220,6 +1173,7 @@ PSound::PSound()
: PInt(sizeof(FSoundID), true)
{
mDescriptiveName = "Sound";
Flags |= TYPE_IntNotInt;
assert(sizeof(FSoundID) == alignof(FSoundID));
}
@ -1258,8 +1212,6 @@ bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const
/* PColor *****************************************************************/
IMPLEMENT_CLASS(PColor, false, false)
//==========================================================================
//
// PColor Default Constructor
@ -1270,13 +1222,12 @@ PColor::PColor()
: PInt(sizeof(PalEntry), true)
{
mDescriptiveName = "Color";
Flags |= TYPE_IntNotInt;
assert(sizeof(PalEntry) == alignof(PalEntry));
}
/* PStateLabel *****************************************************************/
IMPLEMENT_CLASS(PStateLabel, false, false)
//==========================================================================
//
// PStateLabel Default Constructor
@ -1286,13 +1237,12 @@ IMPLEMENT_CLASS(PStateLabel, false, false)
PStateLabel::PStateLabel()
: PInt(sizeof(int), false, false)
{
Flags |= TYPE_IntNotInt;
mDescriptiveName = "StateLabel";
}
/* PPointer ***************************************************************/
IMPLEMENT_CLASS(PPointer, false, false)
//==========================================================================
//
// PPointer - Default Constructor
@ -1307,6 +1257,7 @@ PPointer::PPointer()
storeOp = OP_SP;
moveOp = OP_MOVEA;
RegType = REGT_POINTER;
Flags |= TYPE_Pointer;
}
//==========================================================================
@ -1332,6 +1283,7 @@ PPointer::PPointer(PType *pointsat, bool isconst)
storeOp = OP_SP;
moveOp = OP_MOVEA;
RegType = REGT_POINTER;
Flags |= TYPE_Pointer;
}
//==========================================================================
@ -1395,8 +1347,6 @@ bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
/* PObjectPointer **********************************************************/
IMPLEMENT_CLASS(PObjectPointer, false, false)
//==========================================================================
//
// PPointer :: GetStoreOp
@ -1407,6 +1357,7 @@ PObjectPointer::PObjectPointer(PClass *cls, bool isconst)
: PPointer(cls->VMType, isconst)
{
loadOp = OP_LO;
Flags |= TYPE_ObjectPointer;
// Non-destroyed thinkers are always guaranteed to be linked into the thinker chain so we don't need the write barrier for them.
if (cls && !cls->IsDescendantOf(RUNTIME_CLASS(DThinker))) storeOp = OP_SO;
}
@ -1457,15 +1408,15 @@ bool PObjectPointer::ReadValue(FSerializer &ar, const char *key, void *addr) con
PPointer *NewPointer(PType *type, bool isconst)
{
auto cp = dyn_cast<PClassType>(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<PPointer *>(ptype);
}
@ -1476,19 +1427,17 @@ PPointer *NewPointer(PClass *cls, bool isconst)
auto type = cls->VMType;
size_t bucket;
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PObjectPointer), (intptr_t)type, isconst ? 1 : 0, &bucket);
PType *ptype = TypeTable.FindType(NAME_Pointer, (intptr_t)type, isconst ? 1 : 0, &bucket);
if (ptype == nullptr)
{
ptype = new PObjectPointer(cls, isconst);
TypeTable.AddType(ptype, RUNTIME_CLASS(PObjectPointer), (intptr_t)type, isconst ? 1 : 0, bucket);
TypeTable.AddType(ptype, NAME_Pointer, (intptr_t)type, isconst ? 1 : 0, bucket);
}
return static_cast<PPointer *>(ptype);
}
/* PStatePointer **********************************************************/
IMPLEMENT_CLASS(PStatePointer, false, false)
//==========================================================================
//
// PStatePointer Default Constructor
@ -1530,8 +1479,6 @@ bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons
/* PClassPointer **********************************************************/
IMPLEMENT_CLASS(PClassPointer,false, false)
//==========================================================================
//
// PClassPointer - Parameterized Constructor
@ -1545,6 +1492,7 @@ PClassPointer::PClassPointer(PClass *restrict)
else mDescriptiveName = "ClassPointer";
loadOp = OP_LP;
storeOp = OP_SP;
Flags |= TYPE_ClassPointer;
mVersion = restrict->VMType->mVersion;
}
@ -1579,7 +1527,7 @@ bool PClassPointer::ReadValue(FSerializer &ar, const char *key, void *addr) cons
bool PClassPointer::isCompatible(PType *type)
{
auto other = dyn_cast<PClassPointer>(type);
auto other = PType::toClassPointer(type);
return (other != nullptr && other->ClassRestriction->IsDescendantOf(ClassRestriction));
}
@ -1628,31 +1576,17 @@ void PClassPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
PClassPointer *NewClassPointer(PClass *restrict)
{
size_t bucket;
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PClassPointer), 0, (intptr_t)restrict, &bucket);
PType *ptype = TypeTable.FindType(NAME_Class, 0, (intptr_t)restrict, &bucket);
if (ptype == nullptr)
{
ptype = new PClassPointer(restrict);
TypeTable.AddType(ptype, RUNTIME_CLASS(PClassPointer), 0, (intptr_t)restrict, bucket);
TypeTable.AddType(ptype, NAME_Class, 0, (intptr_t)restrict, bucket);
}
return static_cast<PClassPointer *>(ptype);
}
/* PEnum ******************************************************************/
IMPLEMENT_CLASS(PEnum, false, false)
//==========================================================================
//
// PEnum - Default Constructor
//
//==========================================================================
PEnum::PEnum()
: PInt(4, false)
{
mDescriptiveName = "Enum";
}
//==========================================================================
//
// PEnum - Parameterized Constructor
@ -1664,6 +1598,7 @@ PEnum::PEnum(FName name, PTypeBase *outer)
{
EnumName = name;
Outer = outer;
Flags |= TYPE_IntNotInt;
mDescriptiveName.Format("Enum<%s>", name.GetChars());
}
@ -1680,31 +1615,17 @@ PEnum *NewEnum(FName name, PTypeBase *outer)
{
size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket);
PType *etype = TypeTable.FindType(NAME_Enum, (intptr_t)outer, (intptr_t)name, &bucket);
if (etype == nullptr)
{
etype = new PEnum(name, outer);
TypeTable.AddType(etype, RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, bucket);
TypeTable.AddType(etype, NAME_Enum, (intptr_t)outer, (intptr_t)name, bucket);
}
return static_cast<PEnum *>(etype);
}
/* PArray *****************************************************************/
IMPLEMENT_CLASS(PArray, false, false)
//==========================================================================
//
// PArray - Default Constructor
//
//==========================================================================
PArray::PArray()
: ElementType(nullptr), ElementCount(0)
{
mDescriptiveName = "Array";
}
//==========================================================================
//
// PArray - Parameterized Constructor
@ -1721,6 +1642,7 @@ PArray::PArray(PType *etype, unsigned int ecount)
// also be padded to the nearest alignment.
ElementSize = (etype->Size + (etype->Align - 1)) & ~(etype->Align - 1);
Size = ElementSize * ecount;
Flags |= TYPE_Array;
}
//==========================================================================
@ -1839,30 +1761,17 @@ void PArray::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
PArray *NewArray(PType *type, unsigned int count)
{
size_t bucket;
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PArray), (intptr_t)type, count, &bucket);
PType *atype = TypeTable.FindType(NAME_Array, (intptr_t)type, count, &bucket);
if (atype == nullptr)
{
atype = new PArray(type, count);
TypeTable.AddType(atype, RUNTIME_CLASS(PArray), (intptr_t)type, count, bucket);
TypeTable.AddType(atype, NAME_Array, (intptr_t)type, count, bucket);
}
return (PArray *)atype;
}
/* PArray *****************************************************************/
IMPLEMENT_CLASS(PStaticArray, false, false)
//==========================================================================
//
// PArray - Default Constructor
//
//==========================================================================
PStaticArray::PStaticArray()
{
mDescriptiveName = "ResizableArray";
}
//==========================================================================
//
// PArray - Parameterized Constructor
@ -1913,33 +1822,17 @@ void PStaticArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
PStaticArray *NewStaticArray(PType *type)
{
size_t bucket;
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PStaticArray), (intptr_t)type, 0, &bucket);
PType *atype = TypeTable.FindType(NAME_StaticArray, (intptr_t)type, 0, &bucket);
if (atype == nullptr)
{
atype = new PStaticArray(type);
TypeTable.AddType(atype, RUNTIME_CLASS(PStaticArray), (intptr_t)type, 0, bucket);
TypeTable.AddType(atype, NAME_StaticArray, (intptr_t)type, 0, bucket);
}
return (PStaticArray *)atype;
}
/* PDynArray **************************************************************/
IMPLEMENT_CLASS(PDynArray, false, false)
//==========================================================================
//
// PDynArray - Default Constructor
//
//==========================================================================
PDynArray::PDynArray()
: ElementType(nullptr)
{
mDescriptiveName = "DynArray";
Size = sizeof(FArray);
Align = alignof(FArray);
}
//==========================================================================
//
// PDynArray - Parameterized Constructor
@ -2060,7 +1953,7 @@ void PDynArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffs
void PDynArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) const
{
if (ElementType->IsKindOf(RUNTIME_CLASS(PObjectPointer)))
if (ElementType->isObjectPointer())
{
// Add to the list of pointer arrays for this class.
special->Push(offset);
@ -2138,7 +2031,7 @@ bool PDynArray::ReadValue(FSerializer &ar, const char *key, void *addr) const
PDynArray *NewDynArray(PType *type)
{
size_t bucket;
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, &bucket);
PType *atype = TypeTable.FindType(NAME_DynArray, (intptr_t)type, 0, &bucket);
if (atype == nullptr)
{
FString backingname;
@ -2168,29 +2061,13 @@ PDynArray *NewDynArray(PType *type)
auto backing = NewStruct(backingname, nullptr, true);
atype = new PDynArray(type, backing);
TypeTable.AddType(atype, RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, bucket);
TypeTable.AddType(atype, NAME_DynArray, (intptr_t)type, 0, bucket);
}
return (PDynArray *)atype;
}
/* PMap *******************************************************************/
IMPLEMENT_CLASS(PMap, false, false)
//==========================================================================
//
// PMap - Default Constructor
//
//==========================================================================
PMap::PMap()
: KeyType(nullptr), ValueType(nullptr)
{
mDescriptiveName = "Map";
Size = sizeof(FMap);
Align = alignof(FMap);
}
//==========================================================================
//
// PMap - Parameterized Constructor
@ -2243,31 +2120,17 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
PMap *NewMap(PType *keytype, PType *valuetype)
{
size_t bucket;
PType *maptype = TypeTable.FindType(RUNTIME_CLASS(PMap), (intptr_t)keytype, (intptr_t)valuetype, &bucket);
PType *maptype = TypeTable.FindType(NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, &bucket);
if (maptype == nullptr)
{
maptype = new PMap(keytype, valuetype);
TypeTable.AddType(maptype, RUNTIME_CLASS(PMap), (intptr_t)keytype, (intptr_t)valuetype, bucket);
TypeTable.AddType(maptype, NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, bucket);
}
return (PMap *)maptype;
}
/* PStruct ****************************************************************/
IMPLEMENT_CLASS(PStruct, false, false)
//==========================================================================
//
// PStruct - Default Constructor
//
//==========================================================================
PStruct::PStruct()
{
mDescriptiveName = "Struct";
Size = 0;
}
//==========================================================================
//
// PStruct - Parameterized Constructor
@ -2394,11 +2257,11 @@ PStruct *NewStruct(FName name, PTypeBase *outer, bool native)
{
size_t bucket;
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket);
PType *stype = TypeTable.FindType(NAME_Struct, (intptr_t)outer, (intptr_t)name, &bucket);
if (stype == nullptr)
{
stype = new PStruct(name, outer, native);
TypeTable.AddType(stype, RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, bucket);
TypeTable.AddType(stype, NAME_Struct, (intptr_t)outer, (intptr_t)name, bucket);
}
return static_cast<PStruct *>(stype);
}
@ -2406,18 +2269,6 @@ PStruct *NewStruct(FName name, PTypeBase *outer, bool native)
/* PPrototype *************************************************************/
IMPLEMENT_CLASS(PPrototype, false, false)
//==========================================================================
//
// PPrototype - Default Constructor
//
//==========================================================================
PPrototype::PPrototype()
{
}
//==========================================================================
//
// PPrototype - Parameterized Constructor
@ -2455,20 +2306,6 @@ void PPrototype::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
id2 = (intptr_t)&ReturnTypes;
}
//==========================================================================
//
// PPrototype :: PropagateMark
//
//==========================================================================
size_t PPrototype::PropagateMark()
{
GC::MarkArray(ArgumentTypes);
GC::MarkArray(ReturnTypes);
return (ArgumentTypes.Size() + ReturnTypes.Size()) * sizeof(void*) +
Super::PropagateMark();
}
//==========================================================================
//
// NewPrototype
@ -2481,19 +2318,17 @@ size_t PPrototype::PropagateMark()
PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &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<PPrototype *>(proto);
}
/* PClass *****************************************************************/
IMPLEMENT_CLASS(PClassType, false, false)
//==========================================================================
//
//
@ -2510,6 +2345,7 @@ PClassType::PClassType(PClass *cls)
ParentType = cls->ParentClass->VMType;
assert(ParentType != nullptr);
Symbols.SetParentTable(&ParentType->Symbols);
ScopeFlags = ParentType->ScopeFlags;
}
cls->VMType = this;
mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars());
@ -2548,11 +2384,11 @@ PField *PClassType::AddNativeField(FName name, PType *type, size_t address, uint
PClassType *NewClassType(PClass *cls)
{
size_t bucket;
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PClassType), 0, (intptr_t)cls->TypeName, &bucket);
PType *ptype = TypeTable.FindType(NAME_Object, 0, (intptr_t)cls->TypeName, &bucket);
if (ptype == nullptr)
{
ptype = new PClassType(cls);
TypeTable.AddType(ptype, RUNTIME_CLASS(PClassType), 0, (intptr_t)cls->TypeName, bucket);
TypeTable.AddType(ptype, NAME_Object, 0, (intptr_t)cls->TypeName, bucket);
}
return static_cast<PClassType *>(ptype);
}
@ -2566,16 +2402,16 @@ PClassType *NewClassType(PClass *cls)
//
//==========================================================================
PType *FTypeTable::FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, size_t *bucketnum)
PType *FTypeTable::FindType(FName type_name, intptr_t parm1, intptr_t parm2, size_t *bucketnum)
{
size_t bucket = Hash(metatype, parm1, parm2) % HASH_SIZE;
size_t bucket = Hash(type_name, parm1, parm2) % HASH_SIZE;
if (bucketnum != nullptr)
{
*bucketnum = bucket;
}
for (PType *type = TypeHash[bucket]; type != nullptr; type = type->HashNext)
{
if (type->TypeTableType == metatype && type->IsMatch(parm1, parm2))
if (type->TypeTableType == type_name && type->IsMatch(parm1, parm2))
{
return type;
}
@ -2589,17 +2425,16 @@ PType *FTypeTable::FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, si
//
//==========================================================================
void FTypeTable::AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t parm2, size_t bucket)
void FTypeTable::AddType(PType *type, FName type_name, intptr_t parm1, intptr_t parm2, size_t bucket)
{
#ifdef _DEBUG
size_t bucketcheck;
assert(FindType(metatype, parm1, parm2, &bucketcheck) == nullptr && "Type must not be inserted more than once");
assert(FindType(type_name, parm1, parm2, &bucketcheck) == nullptr && "Type must not be inserted more than once");
assert(bucketcheck == bucket && "Passed bucket was wrong");
#endif
type->TypeTableType = metatype;
type->TypeTableType = type_name;
type->HashNext = TypeHash[bucket];
TypeHash[bucket] = type;
type->Release();
}
//==========================================================================
@ -2608,21 +2443,19 @@ void FTypeTable::AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t
//
//==========================================================================
void FTypeTable::AddType(PType *type)
void FTypeTable::AddType(PType *type, FName type_name)
{
intptr_t parm1, parm2;
size_t bucket;
// Type table stuff id only needed to let all classes hash to the same group. For all other types this is pointless.
type->TypeTableType = type->GetClass();
PClass *metatype = type->TypeTableType;
type->TypeTableType = type_name;
type->GetTypeIDs(parm1, parm2);
bucket = Hash(metatype, parm1, parm2) % HASH_SIZE;
assert(FindType(metatype, parm1, parm2, nullptr) == nullptr && "Type must not be inserted more than once");
bucket = Hash(type_name, parm1, parm2) % HASH_SIZE;
assert(FindType(type_name, parm1, parm2, nullptr) == nullptr && "Type must not be inserted more than once");
type->HashNext = TypeHash[bucket];
TypeHash[bucket] = type;
type->Release();
}
//==========================================================================
@ -2631,7 +2464,7 @@ void FTypeTable::AddType(PType *type)
//
//==========================================================================
size_t FTypeTable::Hash(const PClass *p1, intptr_t p2, intptr_t p3)
size_t FTypeTable::Hash(FName p1, intptr_t p2, intptr_t p3)
{
size_t i1 = (size_t)p1;
@ -2639,7 +2472,7 @@ size_t FTypeTable::Hash(const PClass *p1, intptr_t p2, intptr_t p3)
// to transform this into a ROR or ROL.
i1 = (i1 >> (sizeof(size_t)*4)) | (i1 << (sizeof(size_t)*4));
if (p1 != RUNTIME_CLASS(PPrototype))
if (p1 != NAME_Prototype)
{
size_t i2 = (size_t)p2;
size_t i3 = (size_t)p3;

View file

@ -2,9 +2,9 @@
#include "dobject.h"
#include "serializer.h"
#include "scripting/backend/scopebarrier.h"
// Variable/parameter/field flags -------------------------------------------
class PStruct;
// Making all these different storage types use a common set of flags seems
// like the simplest thing to do.
@ -61,22 +61,45 @@ enum
// Map * *
// Prototype *+ *+
class PContainerType;
class PPointer;
class PClassPointer;
class PArray;
class PStruct;
class PClassType;
struct ZCC_ExprConstant;
class PType : public PTypeBase
{
DECLARE_ABSTRACT_CLASS(PType, PTypeBase)
protected:
enum ETypeFlags
{
TYPE_Scalar = 1,
TYPE_Container = 2,
TYPE_Int = 4,
TYPE_IntNotInt = 8, // catch-all for subtypes that are not being checked by type directly.
TYPE_Float = 16,
TYPE_Pointer = 32,
TYPE_ObjectPointer = 64,
TYPE_ClassPointer = 128,
TYPE_Array = 256,
TYPE_IntCompatible = TYPE_Int | TYPE_IntNotInt, // must be the combination of all flags that are subtypes of int and can be cast to an int.
};
public:
PClass *TypeTableType; // The type to use for hashing into the type table
FName TypeTableType; // The type to use for hashing into the type table
unsigned int Size; // this type's size
unsigned int Align; // this type's preferred alignment
unsigned int Flags = 0; // What is this type?
PType *HashNext; // next type in this type table
PSymbolTable Symbols;
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
FString mDescriptiveName;
VersionInfo mVersion = { 0,0,0 };
uint8_t loadOp, storeOp, moveOp, RegType, RegCount;
EScopeFlags ScopeFlags = (EScopeFlags)0;
PType(unsigned int size = 1, unsigned int align = 1);
virtual ~PType();
@ -160,20 +183,40 @@ public:
const char *DescriptiveName() const;
static void StaticInit();
bool isScalar() const { return !!(Flags & TYPE_Scalar); }
bool isContainer() const { return !!(Flags & TYPE_Container); }
bool isInt() const { return (Flags & TYPE_IntCompatible) == TYPE_Int; }
bool isIntCompatible() const { return !!(Flags & TYPE_IntCompatible); }
bool isFloat() const { return !!(Flags & TYPE_Float); }
bool isPointer() const { return !!(Flags & TYPE_Pointer); }
bool isRealPointer() const { return (Flags & (TYPE_Pointer|TYPE_ClassPointer)) == TYPE_Pointer; } // This excludes class pointers which use their PointedType differently
bool isObjectPointer() const { return !!(Flags & TYPE_ObjectPointer); }
bool isClassPointer() const { return !!(Flags & TYPE_ClassPointer); }
bool isEnum() const { return TypeTableType == NAME_Enum; }
bool isArray() const { return !!(Flags & TYPE_Array); }
bool isStaticArray() const { return TypeTableType == NAME_StaticArray; }
bool isDynArray() const { return TypeTableType == NAME_DynArray; }
bool isStruct() const { return TypeTableType == NAME_Struct; }
bool isClass() const { return TypeTableType == NAME_Object; }
bool isPrototype() const { return TypeTableType == NAME_Prototype; }
PContainerType *toContainer() { return isContainer() ? (PContainerType*)this : nullptr; }
PPointer *toPointer() { return isPointer() ? (PPointer*)this : nullptr; }
static PClassPointer *toClassPointer(PType *t) { return t && t->isClassPointer() ? (PClassPointer*)t : nullptr; }
static PClassType *toClass(PType *t) { return t && t->isClass() ? (PClassType*)t : nullptr; }
};
// Not-really-a-type types --------------------------------------------------
class PErrorType : public PType
{
DECLARE_CLASS(PErrorType, PType);
public:
PErrorType(int which = 1) : PType(0, which) {}
};
class PVoidType : public PType
{
DECLARE_CLASS(PVoidType, PType);
public:
PVoidType() : PType(0, 1) {}
};
@ -182,29 +225,31 @@ public:
class PBasicType : public PType
{
DECLARE_ABSTRACT_CLASS(PBasicType, PType);
public:
PBasicType();
PBasicType(unsigned int size, unsigned int align);
protected:
PBasicType(unsigned int size = 1, unsigned int align = 1);
};
class PCompoundType : public PType
{
DECLARE_ABSTRACT_CLASS(PCompoundType, PType);
protected:
PCompoundType(unsigned int size = 1, unsigned int align = 1);
};
class PContainerType : public PCompoundType
{
DECLARE_ABSTRACT_CLASS(PContainerType, PCompoundType);
public:
PTypeBase *Outer; // object this type is contained within
FName TypeName; // this type's name
PContainerType() : Outer(NULL) {
mDescriptiveName = "NamedType";
PContainerType() : Outer(NULL)
{
mDescriptiveName = "ContainerType";
Flags |= TYPE_Container;
}
PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {
PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name)
{
mDescriptiveName = name.GetChars();
Flags |= TYPE_Container;
}
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
@ -217,7 +262,6 @@ public:
class PInt : public PBasicType
{
DECLARE_CLASS(PInt, PBasicType);
public:
PInt(unsigned int size, bool unsign, bool compatible = true);
@ -233,13 +277,11 @@ public:
bool Unsigned;
bool IntCompatible;
protected:
PInt();
void SetOps();
};
class PBool : public PInt
{
DECLARE_CLASS(PBool, PInt);
public:
PBool();
virtual void SetValue(void *addr, int val);
@ -250,9 +292,8 @@ public:
class PFloat : public PBasicType
{
DECLARE_CLASS(PFloat, PBasicType);
public:
PFloat(unsigned int size);
PFloat(unsigned int size = 8);
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
@ -263,7 +304,6 @@ public:
virtual double GetValueFloat(void *addr) const;
virtual bool isNumeric() override { return true; }
protected:
PFloat();
void SetOps();
private:
struct SymbolInitF
@ -285,7 +325,6 @@ private:
class PString : public PBasicType
{
DECLARE_CLASS(PString, PBasicType);
public:
PString();
@ -300,7 +339,6 @@ public:
class PName : public PInt
{
DECLARE_CLASS(PName, PInt);
public:
PName();
@ -310,7 +348,6 @@ public:
class PSound : public PInt
{
DECLARE_CLASS(PSound, PInt);
public:
PSound();
@ -320,7 +357,6 @@ public:
class PSpriteID : public PInt
{
DECLARE_CLASS(PSpriteID, PInt);
public:
PSpriteID();
@ -330,7 +366,6 @@ public:
class PTextureID : public PInt
{
DECLARE_CLASS(PTextureID, PInt);
public:
PTextureID();
@ -340,14 +375,12 @@ public:
class PColor : public PInt
{
DECLARE_CLASS(PColor, PInt);
public:
PColor();
};
class PStateLabel : public PInt
{
DECLARE_CLASS(PStateLabel, PInt);
public:
PStateLabel();
};
@ -356,7 +389,6 @@ public:
class PPointer : public PBasicType
{
DECLARE_CLASS(PPointer, PBasicType);
public:
typedef void(*WriteHandler)(FSerializer &ar, const char *key, const void *addr);
@ -389,7 +421,6 @@ protected:
class PStatePointer : public PPointer
{
DECLARE_CLASS(PStatePointer, PPointer);
public:
PStatePointer();
@ -400,7 +431,6 @@ public:
class PObjectPointer : public PPointer
{
DECLARE_CLASS(PObjectPointer, PPointer);
public:
PObjectPointer(PClass *pointedtype = nullptr, bool isconst = false);
@ -413,7 +443,6 @@ public:
class PClassPointer : public PPointer
{
DECLARE_CLASS(PClassPointer, PPointer);
public:
PClassPointer(class PClass *restrict = nullptr);
@ -432,19 +461,15 @@ public:
class PEnum : public PInt
{
DECLARE_CLASS(PEnum, PInt);
public:
PEnum(FName name, PTypeBase *outer);
PTypeBase *Outer;
FName EnumName;
protected:
PEnum();
};
class PArray : public PCompoundType
{
DECLARE_CLASS(PArray, PCompoundType);
public:
PArray(PType *etype, unsigned int ecount);
@ -460,27 +485,19 @@ public:
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override;
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
protected:
PArray();
};
class PStaticArray : public PArray
{
DECLARE_CLASS(PStaticArray, PArray);
public:
PStaticArray(PType *etype);
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected:
PStaticArray();
};
class PDynArray : public PCompoundType
{
DECLARE_CLASS(PDynArray, PCompoundType);
public:
PDynArray(PType *etype, PStruct *backing);
@ -496,14 +513,10 @@ public:
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const override;
protected:
PDynArray();
};
class PMap : public PCompoundType
{
DECLARE_CLASS(PMap, PCompoundType);
public:
PMap(PType *keytype, PType *valtype);
@ -512,14 +525,10 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected:
PMap();
};
class PStruct : public PContainerType
{
DECLARE_CLASS(PStruct, PContainerType);
public:
PStruct(FName name, PTypeBase *outer, bool isnative = false);
@ -535,25 +544,18 @@ public:
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
protected:
PStruct();
};
class PPrototype : public PCompoundType
{
DECLARE_CLASS(PPrototype, PCompoundType);
public:
PPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes);
TArray<PType *> ArgumentTypes;
TArray<PType *> ReturnTypes;
size_t PropagateMark();
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected:
PPrototype();
};
@ -561,10 +563,6 @@ protected:
class PClassType : public PContainerType
{
DECLARE_CLASS(PClassType, PContainerType);
private:
public:
PClass *Descriptor;
PClassType *ParentType;
@ -628,12 +626,12 @@ struct FTypeTable
PType *TypeHash[HASH_SIZE];
PType *FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, size_t *bucketnum);
void AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t parm2, size_t bucket);
void AddType(PType *type);
PType *FindType(FName type_name, intptr_t parm1, intptr_t parm2, size_t *bucketnum);
void AddType(PType *type, FName type_name, intptr_t parm1, intptr_t parm2, size_t bucket);
void AddType(PType *type, FName type_name);
void Clear();
static size_t Hash(const PClass *p1, intptr_t p2, intptr_t p3);
static size_t Hash(FName p1, intptr_t p2, intptr_t p3);
};

View file

@ -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<PInt *>(enode->Type)->Unsigned);
}

View file

@ -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<ZCC_ExprConstant *>(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<ZCC_ExprConstant *>(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<ZCC_ExprConstant *>(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;

View file

@ -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<PType*>(outer)->ScopeFlags));
else if (s->strct->Flags & ZCC_ClearScope) Warn(s->strct, "Useless 'ClearScope' on struct %s not inside a class", s->NodeName().GetChars());
if (s->strct->Flags & ZCC_UIFlag)
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_UI);
sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_UI);
if (s->strct->Flags & ZCC_Play)
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_Play);
sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_Play);
if (s->strct->Flags & ZCC_ClearScope)
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_PlainData); // don't inherit the scope from the outer class
sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_PlainData); // don't inherit the scope from the outer class
}
else
{
// old versions force 'play'.
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_Play);
sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_Play);
}
s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type());
syms->AddSymbol(s->strct->Symbol);
@ -663,7 +664,7 @@ void ZCCCompiler::CreateClassTypes()
}
if (c->cls->Flags & ZCC_Abstract)
c->Type()->ObjectFlags |= OF_Abstract;
c->ClassType()->bAbstract = true;
if (c->cls->Flags & ZCC_Version)
{
@ -683,21 +684,21 @@ void ZCCCompiler::CreateClassTypes()
}
if (c->cls->Flags & ZCC_UIFlag)
c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_Play) | OF_UI;
c->Type()->ScopeFlags = EScopeFlags((c->Type()->ScopeFlags&~Scope_Play) | Scope_UI);
if (c->cls->Flags & ZCC_Play)
c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_UI) | OF_Play;
if (parent->VMType->ObjectFlags & (OF_UI | OF_Play)) // parent is either ui or play
c->Type()->ScopeFlags = EScopeFlags((c->Type()->ScopeFlags&~Scope_UI) | Scope_Play);
if (parent->VMType->ScopeFlags & (Scope_UI | Scope_Play)) // parent is either ui or play
{
if (c->cls->Flags & (ZCC_UIFlag | ZCC_Play))
{
Error(c->cls, "Can't change class scope in class %s", c->NodeName().GetChars());
}
c->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ObjectFlags, FScopeBarrier::SideFromObjectFlags(parent->VMType->ObjectFlags));
c->Type()->ScopeFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ScopeFlags, FScopeBarrier::SideFromObjectFlags(parent->VMType->ScopeFlags));
}
}
else
{
c->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ObjectFlags, FScopeBarrier::Side_Play);
c->Type()->ScopeFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ScopeFlags, FScopeBarrier::Side_Play);
}
c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type());
@ -873,13 +874,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant)
{
def->Symbol = new PSymbolConstString(def->NodeName, *(cval->StringVal));
}
else if (cval->Type->IsA(RUNTIME_CLASS(PInt)))
else if (cval->Type->isInt())
{
// How do we get an Enum type in here without screwing everything up???
//auto type = def->Type != nullptr ? def->Type : cval->Type;
def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal);
}
else if (cval->Type->IsA(RUNTIME_CLASS(PFloat)))
else if (cval->Type->isFloat())
{
if (def->Type != nullptr)
{
@ -899,13 +900,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant)
{
def->Symbol = new PSymbolConstString(def->NodeName, c.GetString());
}
else if (c.Type->IsA(RUNTIME_CLASS(PInt)))
else if (c.Type->isInt())
{
// How do we get an Enum type in here without screwing everything up???
//auto type = def->Type != nullptr ? def->Type : cval->Type;
def->Symbol = new PSymbolConstNumeric(def->NodeName, c.Type, c.GetInt());
}
else if (c.Type->IsA(RUNTIME_CLASS(PFloat)))
else if (c.Type->isFloat())
{
if (def->Type != nullptr)
{
@ -974,7 +975,7 @@ void ZCCCompiler::CompileArrays(ZCC_StructWork *work)
FArgumentList values;
// Don't use narrow typea for casting.
if (ctype->IsA(RUNTIME_CLASS(PInt))) ctype = static_cast<PInt*>(ztype)->Unsigned ? TypeUInt32 : TypeSInt32;
if (ctype->isInt()) ctype = static_cast<PInt*>(ztype)->Unsigned ? TypeUInt32 : TypeSInt32;
else if (ctype == TypeFloat32) ctype = TypeFloat64;
ConvertNodeList(values, sas->Values);
@ -1077,13 +1078,13 @@ ZCC_ExprConstant *ZCCCompiler::NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expres
if (val->Type != TypeError)
{
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric)));
if (sym->ValueType->IsKindOf(RUNTIME_CLASS(PInt)))
if (sym->ValueType->isIntCompatible())
{
val->IntVal = static_cast<PSymbolConstNumeric *>(sym)->Value;
}
else
{
assert(sym->ValueType->IsKindOf(RUNTIME_CLASS(PFloat)));
assert(sym->ValueType->isFloat());
val->DoubleVal = static_cast<PSymbolConstNumeric *>(sym)->Float;
}
}
@ -1104,7 +1105,7 @@ ZCC_ExprTypeRef *ZCCCompiler::NodeFromSymbolType(PSymbolType *sym, ZCC_Expressio
ZCC_ExprTypeRef *ref = static_cast<ZCC_ExprTypeRef *>(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, TArray<ZCC_VarDeclarator *
{
if (type != nullptr)
{
if (type->ObjectFlags & OF_UI)
if (type->ScopeFlags & Scope_UI)
varflags |= VARF_UI;
if (type->ObjectFlags & OF_Play)
if (type->ScopeFlags & Scope_Play)
varflags |= VARF_Play;
}
if (field->Flags & ZCC_UIFlag)
@ -1320,7 +1321,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *
}
// For native structs a size check cannot be done because they normally have no size. But for a native reference they are still fine.
else if (thisfieldtype->Size != ~0u && fd->FieldSize != ~0u && thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0 &&
(!thisfieldtype->IsA(RUNTIME_CLASS(PStruct)) || !static_cast<PStruct*>(thisfieldtype)->isNative))
(!thisfieldtype->isStruct() || !static_cast<PStruct*>(thisfieldtype)->isNative))
{
Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type == nullptr ? "" : type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size);
}
@ -1652,7 +1653,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
return TypeError;
}
auto typesym = dyn_cast<PSymbolType>(sym);
if (typesym == nullptr || !typesym->Type->IsKindOf(RUNTIME_CLASS(PClassType)))
if (typesym == nullptr || !typesym->Type->isClass())
{
Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars());
return TypeError;
@ -1703,15 +1704,15 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo
return TypeError;
}
if (ptype->IsKindOf(RUNTIME_CLASS(PEnum)))
if (ptype->isEnum())
{
if (!nativetype) return TypeSInt32; // hack this to an integer until we can resolve the enum mess.
}
else if (ptype->IsKindOf(RUNTIME_CLASS(PClassType))) // classes cannot be instantiated at all, they always get used as references.
else if (ptype->isClass()) // classes cannot be instantiated at all, they always get used as references.
{
return NewPointer(ptype, type->isconst);
}
else if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)) && static_cast<PStruct*>(ptype)->isNative) // native structs and classes cannot be instantiated, they always get used as reference.
else if (ptype->isStruct() && static_cast<PStruct*>(ptype)->isNative) // native structs and classes cannot be instantiated, they always get used as reference.
{
if (!nativetype) return NewPointer(ptype, type->isconst);
return ptype; // instantiation of native structs. Only for internal use.
@ -1752,7 +1753,7 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
ex = ex->Resolve(ctx);
if (ex == nullptr) return TypeError;
if (!ex->isConstant() || !ex->ValueType->IsA(RUNTIME_CLASS(PInt)))
if (!ex->isConstant() || !ex->ValueType->isInt())
{
Error(arraysize, "Array index must be an integer constant");
return TypeError;
@ -2023,19 +2024,19 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
{
*(PalEntry*)addr = V_GetColor(nullptr, GetStringConst(ex, ctx), &ex->ScriptPosition);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
else if (f->Type->isIntCompatible())
{
static_cast<PInt*>(f->Type)->SetValue(addr, GetIntConst(ex, ctx));
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat)))
else if (f->Type->isFloat())
{
static_cast<PFloat*>(f->Type)->SetValue(addr, GetFloatConst(ex, ctx));
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PString)))
else if (f->Type == TypeString)
{
*(FString*)addr = GetStringConst(ex, ctx);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
else if (f->Type->isClassPointer())
{
auto clsname = GetStringConst(ex, ctx);
if (*clsname == 0 || !stricmp(clsname, "none"))
@ -2045,13 +2046,14 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
else
{
auto cls = PClass::FindClass(clsname);
auto cp = static_cast<PClassPointer*>(f->Type);
if (cls == nullptr)
{
cls = static_cast<PClassPointer*>(f->Type)->ClassRestriction->FindClassTentative(clsname);
cls = cp->ClassRestriction->FindClassTentative(clsname);
}
else if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
else if (!cls->IsDescendantOf(cp->ClassRestriction))
{
Error(property, "class %s is not compatible with property type %s", clsname, static_cast<PClassPointer*>(f->Type)->ClassRestriction->TypeName.GetChars());
Error(property, "class %s is not compatible with property type %s", clsname, cp->ClassRestriction->TypeName.GetChars());
}
*(PClass**)addr = cls;
}
@ -2304,7 +2306,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
do
{
auto type = DetermineType(c->Type(), f, f->Name, t, false, false);
if (type->IsKindOf(RUNTIME_CLASS(PContainerType)) && type != TypeVector2 && type != TypeVector3)
if (type->isContainer() && type != TypeVector2 && type != TypeVector3)
{
// structs and classes only get passed by pointer.
type = NewPointer(type);
@ -2365,9 +2367,9 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
if (f->Flags & ZCC_FuncConst) varflags |= VARF_ReadOnly; // FuncConst method is internally marked as VARF_ReadOnly
if (mVersion >= MakeVersion(2, 4, 0))
{
if (c->Type()->ObjectFlags & OF_UI)
if (c->Type()->ScopeFlags & Scope_UI)
varflags |= VARF_UI;
if (c->Type()->ObjectFlags & OF_Play)
if (c->Type()->ScopeFlags & Scope_Play)
varflags |= VARF_Play;
//if (f->Flags & ZCC_FuncConst)
// varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_PlainData); // const implies clearscope. this is checked a bit later to also not have ZCC_Play/ZCC_UIFlag.
@ -2495,7 +2497,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
{
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
int flags = 0;
if ((type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) || type->IsA(RUNTIME_CLASS(PDynArray)))
if ((type->isStruct() && type != TypeVector2 && type != TypeVector3) || type->isDynArray())
{
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
@ -2565,7 +2567,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
break;
case REGT_POINTER:
if (type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
if (type->isClassPointer())
vmval[0] = (DObject*)cnst->GetValue().GetPointer();
else
vmval[0] = cnst->GetValue().GetPointer();
@ -2609,7 +2611,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr ? nullptr : *(afd->VMPointer), varflags, useflags);
c->Type()->Symbols.ReplaceSymbol(sym);
auto vcls = dyn_cast<PClassType>(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<PFunction>(cls->ParentClass->VMType->Symbols.FindSymbol(FName(f->Name), true));
@ -2656,7 +2658,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags;
}
PClass *clstype = static_cast<PClassType *>(c->Type())->Descriptor;
PClass *clstype = forclass? static_cast<PClassType *>(c->Type())->Descriptor : nullptr;
if (varflags & VARF_Virtual)
{
if (sym->Variants[0].Implementation == nullptr)
@ -2817,7 +2819,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af, in
{
FArgumentList argumentlist;
// We can use this function directly without wrapping it in a caller.
assert(dyn_cast<PClassType>(afd->Variants[0].SelfClass) != nullptr); // non classes are not supposed to get here.
assert(PType::toClass(afd->Variants[0].SelfClass) != nullptr); // non classes are not supposed to get here.
int comboflags = afd->Variants[0].UseFlags & StateFlags;
if (comboflags == StateFlags) // the function must satisfy all the flags the state requires
@ -3228,23 +3230,23 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
case AST_ExprConstant:
{
auto cnst = static_cast<ZCC_ExprConstant *>(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);
}

View file

@ -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();

View file

@ -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());

View file

@ -643,11 +643,11 @@ struct StringStruct native
native vararg void AppendFormat(String fmt, ...);
native void Replace(String pattern, String replacement);
native String Left(int len);
native String Mid(int pos = 0, int len = 2147483647);
native String Left(int len) const;
native String Mid(int pos = 0, int len = 2147483647) const;
native void Truncate(int newlen);
native String CharAt(int pos);
native int CharCodeAt(int pos);
native String CharAt(int pos) const;
native int CharCodeAt(int pos) const;
native String Filter();
}

View file

@ -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));

View file

@ -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);