mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 22:11:43 +00:00
This commit is contained in:
commit
93564078fe
33 changed files with 421 additions and 615 deletions
|
@ -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
|
||||
|
|
|
@ -377,6 +377,8 @@ static inline void GC::WriteBarrier(DObject *pointed)
|
|||
}
|
||||
}
|
||||
|
||||
#include "memarena.h"
|
||||
extern FMemArena ClassDataAllocator;
|
||||
#include "symbols.h"
|
||||
#include "dobjtype.h"
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue