- first stage of simplifying the type system.

Let's use inline checkers in PType instead of constantly having to do clumsy IsKindOf checks etc. Once complete this also means that the types can be taken out of the class hierarchy, freeing up some common names.
This commit is contained in:
Christoph Oelckers 2017-04-13 12:47:41 +02:00
parent 522ce59be2
commit b2d944974e
16 changed files with 153 additions and 138 deletions

View file

@ -205,7 +205,6 @@ void PClass::StaticInit ()
{
atterm (StaticShutdown);
StaticBootstrap();
Namespaces.GlobalNamespace = Namespaces.NewNamespace(0);
FAutoSegIterator probe(CRegHead, CRegTail);
@ -265,6 +264,7 @@ void PClass::StaticShutdown ()
ClassDataAllocator.FreeAllBlocks();
AllClasses.Clear();
PClassActor::AllActorClasses.Clear();
ClassMap.Clear();
FAutoSegIterator probe(CRegHead, CRegTail);
@ -276,16 +276,6 @@ void PClass::StaticShutdown ()
}
//==========================================================================
//
// PClass :: StaticBootstrap STATIC
//
//==========================================================================
void PClass::StaticBootstrap()
{
}
//==========================================================================
//
// PClass Constructor
@ -363,7 +353,6 @@ void ClassReg::SetupClass(PClass *cls)
cls->Size = SizeOf;
cls->Pointers = Pointers;
cls->ConstructNative = ConstructNative;
//cls->mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars());
}
//==========================================================================

View file

@ -52,7 +52,6 @@ public:
static void StaticInit();
static void StaticShutdown();
static void StaticBootstrap();
// Per-class information -------------------------------------
PClass *ParentClass = nullptr; // the class this class derives from

View file

@ -75,12 +75,12 @@ cycle_t ActionCycles;
//
//==========================================================================
class PActorInfo : public PBasicType
class PActorInfo : public PCompoundType
{
DECLARE_CLASS(PActorInfo, PBasicType);
DECLARE_CLASS(PActorInfo, PCompoundType);
public:
PActorInfo()
:PBasicType(sizeof(FActorInfo), alignof(FActorInfo))
:PCompoundType(sizeof(FActorInfo), alignof(FActorInfo))
{
}

View file

@ -424,7 +424,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
}
params.Push(f.GetIndex());
}
else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt)))
else if (args[i]->isIntCompatible())
{
char *endp;
int v = (int)strtoll(sc.String, &endp, 0);
@ -441,7 +441,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
if (args[i] == TypeBool) v = !!v;
params.Push(v);
}
else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat)))
else if (args[i]->isFloat())
{
char *endp;
double v = strtod(sc.String, &endp);
@ -775,7 +775,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
{
params.Push(V_GetColor(nullptr, sc));
}
else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt)))
else if (args[i]->isIntCompatible())
{
char *endp;
int v = (int)strtoll(sc.String, &endp, 0);
@ -794,7 +794,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
if (args[i] == TypeBool) v = !!v;
params.Push(v);
}
else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat)))
else if (args[i]->isFloat())
{
char *endp;
double v = strtod(sc.String, &endp);

View file

@ -5040,12 +5040,11 @@ bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *
return false;
}
addr = baddr;
// We don't want Int subclasses like Name or Color to be accessible,
// but we do want to support Float subclasses like Fixed.
if (!type->IsA(RUNTIME_CLASS(PInt)) && !type->IsKindOf(RUNTIME_CLASS(PFloat)))
// We don't want Int subclasses like Name or Color to be accessible here.
if (!type->isInt() && !type->isFloat())
{
// For reading, we also support Name and String types.
if (readonly && (type->IsA(RUNTIME_CLASS(PName)) || type->IsA(RUNTIME_CLASS(PString))))
if (readonly && (type == TypeName || type == TypeString))
{
return true;
}
@ -5061,7 +5060,7 @@ static void SetUserVariable(AActor *self, FName varname, int index, int value)
if (GetVarAddrType(self, varname, index, addr, type, false))
{
if (!type->IsKindOf(RUNTIME_CLASS(PFloat)))
if (!type->isFloat())
{
type->SetValue(addr, value);
}
@ -5079,15 +5078,15 @@ static int GetUserVariable(AActor *self, FName varname, int index)
if (GetVarAddrType(self, varname, index, addr, type, true))
{
if (type->IsKindOf(RUNTIME_CLASS(PFloat)))
if (type->isFloat())
{
return DoubleToACS(type->GetValueFloat(addr));
}
else if (type->IsA(RUNTIME_CLASS(PName)))
else if (type == TypeName)
{
return GlobalACSStrings.AddString(FName(ENamedName(type->GetValueInt(addr))).GetChars());
}
else if (type->IsA(RUNTIME_CLASS(PString)))
else if (type == TypeString)
{
return GlobalACSStrings.AddString(*(FString *)addr);
}

View file

@ -4753,7 +4753,7 @@ static PField *GetVar(DObject *self, FName varname)
{
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType)))
if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || !var->Type->isScalar())
{
Printf("%s is not a user variable in class %s\n", varname.GetChars(),
self->GetClass()->TypeName.GetChars());
@ -4803,8 +4803,7 @@ static PField *GetArrayVar(DObject *self, FName varname, int pos)
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) ||
!var->Type->IsKindOf(RUNTIME_CLASS(PArray)) ||
!static_cast<PArray *>(var->Type)->ElementType->IsKindOf(RUNTIME_CLASS(PBasicType)))
!var->Type->IsKindOf(RUNTIME_CLASS(PArray)) || !static_cast<PArray *>(var->Type)->ElementType->isScalar())
{
Printf("%s is not a user array in class %s\n", varname.GetChars(),
self->GetClass()->TypeName.GetChars());

View file

@ -1621,7 +1621,7 @@ static void SetMapThingUserData(AActor *actor, unsigned udi)
udi++;
if (var == NULL || (var->Flags & (VARF_Native|VARF_Private|VARF_Protected|VARF_Static)) || !var->Type->IsKindOf(RUNTIME_CLASS(PBasicType)))
if (var == NULL || (var->Flags & (VARF_Native|VARF_Private|VARF_Protected|VARF_Static)) || !var->Type->isScalar())
{
DPrintf(DMSG_WARNING, "%s is not a user variable in class %s\n", varname.GetChars(),
actor->GetClass()->TypeName.GetChars());

View file

@ -207,7 +207,7 @@ static PContainerType *FindContainerType(FName name, FCompileContext &ctx)
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{
auto type = static_cast<PSymbolType*>(sym);
return dyn_cast<PContainerType>(type->Type);
return type->Type->toContainer();
}
return nullptr;
}
@ -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.
@ -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);
}
@ -1356,7 +1356,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx);
if (basex->ValueType == TypeColor || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt))
if (basex->ValueType == TypeColor || basex->ValueType->isInt())
{
FxExpression *x = basex;
x->ValueType = TypeColor;
@ -1445,7 +1445,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx);
if (basex->ValueType == TypeSound || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt))
if (basex->ValueType == TypeSound || basex->ValueType->isInt())
{
FxExpression *x = basex;
x->ValueType = TypeSound;
@ -1617,7 +1617,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
// don't go through the entire list if the types are the same.
goto basereturn;
}
else if (basex->ValueType == TypeNullPtr && (ValueType == TypeState || ValueType->IsKindOf(RUNTIME_CLASS(PPointer))))
else if (basex->ValueType == TypeNullPtr && ValueType->isPointer())
{
goto basereturn;
}
@ -1629,7 +1629,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
delete this;
return x;
}
else if (ValueType->IsA(RUNTIME_CLASS(PInt)))
else if (ValueType->isInt())
{
// This is only for casting to actual ints. Subtypes representing an int will be handled elsewhere.
FxExpression *x = new FxIntCast(basex, NoWarn, Explicit);
@ -1773,7 +1773,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
if (fromtype->IsDescendantOf(totype)) goto basereturn;
}
}
else if (basex->IsNativeStruct() && ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType == basex->ValueType)
else if (basex->IsNativeStruct() && ValueType->isRealPointer() && ValueType->toPointer()->PointedType == basex->ValueType)
{
bool writable;
basex->RequestAddress(ctx, &writable);
@ -2494,7 +2494,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
}
// Both types are the same so this is ok.
}
else if (Right->IsNativeStruct() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<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.
@ -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;
@ -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.
@ -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,10 +6393,10 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
{
Object->ValueType = TypeColorStruct;
}
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
if (Object->ValueType->isRealPointer())
{
auto ptype = static_cast<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;
@ -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)
{
@ -7018,10 +7018,10 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
return x->Resolve(ctx);
}
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
if (classx->ValueType->isPointer())
{
PPointer *ptrtype = dyn_cast<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;
@ -7241,7 +7241,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
if (arraytype == nullptr)
{
// Check if we got a pointer to an array. Some native data structures (like the line list in sectors) use this.
PPointer *ptype = dyn_cast<PPointer>(Array->ValueType);
PPointer *ptype = Array->ValueType->toPointer();
if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray)))
{
ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
@ -7316,7 +7316,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
if (arrayispointer)
{
arraytype = static_cast<PArray*>(static_cast<PPointer*>(Array->ValueType)->PointedType);
arraytype = static_cast<PArray*>(Array->ValueType->toPointer()->PointedType);
}
else
{
@ -8150,7 +8150,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
member->membervar = newfield;
}
}
else if (a->IsPointer() && Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
else if (a->IsPointer() && Self->ValueType->isPointer())
{
// the only case which must be checked up front is for pointer arrays receiving a new element.
// Since there is only one native backing class it uses a neutral void pointer as its argument,
@ -8178,7 +8178,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (!Self->IsResizableArray())
{
auto atype = Self->ValueType;
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) atype = static_cast<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;
@ -8222,10 +8222,11 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
return x->Resolve(ctx);
}
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
if (Self->ValueType->isRealPointer())
{
auto ptype = static_cast<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)
{
@ -8238,9 +8239,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
auto x = new FxGetClass(Self);
return x->Resolve(ctx);
}
cls = static_cast<PContainerType *>(ptype);
}
else
{
@ -8759,7 +8757,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
// If this is a reference argument, the pointer type must be undone because the code below expects the pointed type as value type.
if (argflags[i + k + implicit] & VARF_Ref)
{
assert(ntype->IsKindOf(RUNTIME_CLASS(PPointer)));
assert(ntype->isPointer());
ntype = TypeNullPtr; // the default of a reference type can only be a null pointer
}
if (ntype->GetRegCount() == 1)
@ -8822,7 +8820,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr)
{
if (type == ArgList[i]->ValueType && type->IsA(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(type)->PointedType->IsA(RUNTIME_CLASS(PStruct)))
if (type == ArgList[i]->ValueType && type->isRealPointer() && type->toPointer()->PointedType->IsA(RUNTIME_CLASS(PStruct)))
{
// trying to pass a struct reference as a struct reference. This must preserve the type.
}
@ -8937,7 +8935,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
if (innerside == FScopeBarrier::Side_Virtual)
{
auto selfside = FScopeBarrier::SideFromObjectFlags(static_cast<PPointer*>(Self->ValueType)->PointedType->ObjectFlags);
auto selfside = FScopeBarrier::SideFromObjectFlags(Self->ValueType->toPointer()->PointedType->ObjectFlags);
int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags);
if (outerside == FScopeBarrier::Side_Virtual)
@ -9300,7 +9298,7 @@ FxExpression *FxGetClass::Resolve(FCompileContext &ctx)
delete this;
return nullptr;
}
ValueType = NewClassPointer(static_cast<PClassType*>(static_cast<PPointer*>(Self->ValueType)->PointedType)->Descriptor);
ValueType = NewClassPointer(static_cast<PClassType*>(Self->ValueType->toPointer()->PointedType)->Descriptor);
return this;
}

View file

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

View file

@ -866,17 +866,17 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
if (sc.CheckNumber()) *(int*)addr = sc.Number;
else *(PalEntry*)addr = V_GetColor(nullptr, sc);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
else if (f->Type->isIntCompatible())
{
sc.MustGetNumber();
static_cast<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);

View file

@ -104,9 +104,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 +155,7 @@ PField::PField(FName name, PType *type, uint32_t flags, size_t offset, int bitva
unsigned val = bitvalue;
while ((val >>= 1)) BitValue++;
if (type->IsA(RUNTIME_CLASS(PInt)) && unsigned(BitValue) < 8u * type->Size)
if (type->isInt() && unsigned(BitValue) < 8u * type->Size)
{
// map to the single bytes in the actual variable. The internal bit instructions operate on 8 bit values.
#ifndef __BIG_ENDIAN__
@ -582,7 +582,7 @@ void RemoveUnusedSymbols()
{
for (PType *ty = TypeTable.TypeHash[i]; ty != nullptr; ty = ty->HashNext)
{
if (ty->IsKindOf(RUNTIME_CLASS(PContainerType)))
if (ty->isContainer())
{
auto it = ty->Symbols.GetIterator();
PSymbolTable::MapType::Pair *pair;

View file

@ -377,16 +377,6 @@ void PType::StaticInit()
IMPLEMENT_CLASS(PBasicType, true, false)
//==========================================================================
//
// PBasicType Default Constructor
//
//==========================================================================
PBasicType::PBasicType()
{
}
//==========================================================================
//
// PBasicType Parameterized Constructor
@ -397,12 +387,25 @@ PBasicType::PBasicType(unsigned int size, unsigned int align)
: PType(size, align)
{
mDescriptiveName = "BasicType";
Flags |= TYPE_Scalar;
}
/* PCompoundType **********************************************************/
IMPLEMENT_CLASS(PCompoundType, true, false)
//==========================================================================
//
// PBasicType Parameterized Constructor
//
//==========================================================================
PCompoundType::PCompoundType(unsigned int size, unsigned int align)
: PType(size, align)
{
mDescriptiveName = "CompoundType";
}
/* PContainerType *************************************************************/
IMPLEMENT_CLASS(PContainerType, true, false)
@ -462,6 +465,7 @@ PInt::PInt(unsigned int size, bool unsign, bool compatible)
: PBasicType(size, size), Unsigned(unsign), IntCompatible(compatible)
{
mDescriptiveName.Format("%cInt%d", unsign? 'U':'S', size);
Flags |= TYPE_Int;
MemberOnly = (size < 4);
if (!unsign)
@ -713,26 +717,13 @@ PBool::PBool()
{
mDescriptiveName = "Bool";
MemberOnly = false;
Flags |= TYPE_IntNotInt;
}
/* PFloat *****************************************************************/
IMPLEMENT_CLASS(PFloat, false, false)
//==========================================================================
//
// PFloat Default Constructor
//
//==========================================================================
PFloat::PFloat()
: PBasicType(8, 8)
{
mDescriptiveName = "Float";
SetDoubleSymbols();
SetOps();
}
//==========================================================================
//
// PFloat Parameterized Constructor
@ -743,6 +734,7 @@ PFloat::PFloat(unsigned int size)
: PBasicType(size, size)
{
mDescriptiveName.Format("Float%d", size);
Flags |= TYPE_Float;
if (size == 8)
{
#ifdef __i386__
@ -1085,6 +1077,7 @@ PName::PName()
: PInt(sizeof(FName), true, false)
{
mDescriptiveName = "Name";
Flags |= TYPE_IntNotInt;
assert(sizeof(FName) == alignof(FName));
}
@ -1134,6 +1127,7 @@ IMPLEMENT_CLASS(PSpriteID, false, false)
PSpriteID::PSpriteID()
: PInt(sizeof(int), true, true)
{
Flags |= TYPE_IntNotInt;
mDescriptiveName = "SpriteID";
}
@ -1177,6 +1171,7 @@ PTextureID::PTextureID()
: PInt(sizeof(FTextureID), true, false)
{
mDescriptiveName = "TextureID";
Flags |= TYPE_IntNotInt;
assert(sizeof(FTextureID) == alignof(FTextureID));
}
@ -1220,6 +1215,7 @@ PSound::PSound()
: PInt(sizeof(FSoundID), true)
{
mDescriptiveName = "Sound";
Flags |= TYPE_IntNotInt;
assert(sizeof(FSoundID) == alignof(FSoundID));
}
@ -1270,6 +1266,7 @@ PColor::PColor()
: PInt(sizeof(PalEntry), true)
{
mDescriptiveName = "Color";
Flags |= TYPE_IntNotInt;
assert(sizeof(PalEntry) == alignof(PalEntry));
}
@ -1286,6 +1283,7 @@ IMPLEMENT_CLASS(PStateLabel, false, false)
PStateLabel::PStateLabel()
: PInt(sizeof(int), false, false)
{
Flags |= TYPE_IntNotInt;
mDescriptiveName = "StateLabel";
}
@ -1307,6 +1305,7 @@ PPointer::PPointer()
storeOp = OP_SP;
moveOp = OP_MOVEA;
RegType = REGT_POINTER;
Flags |= TYPE_Pointer;
}
//==========================================================================
@ -1332,6 +1331,7 @@ PPointer::PPointer(PType *pointsat, bool isconst)
storeOp = OP_SP;
moveOp = OP_MOVEA;
RegType = REGT_POINTER;
Flags |= TYPE_Pointer;
}
//==========================================================================

View file

@ -61,6 +61,21 @@ enum
// Map * *
// Prototype *+ *+
enum ETypeFlags
{
TYPE_Scalar = 1,
TYPE_Container = 2,
TYPE_Int = 4,
TYPE_IntNotInt = 8, // catch-all for subtypes that are not being checked by type directly.
TYPE_Float = 16,
TYPE_Pointer = 32,
TYPE_IntCompatible = TYPE_Int | TYPE_IntNotInt, // must be the combination of all flags that are subtypes of int and can be cast to an int.
};
class PContainerType;
class PPointer;
struct ZCC_ExprConstant;
class PType : public PTypeBase
{
@ -71,6 +86,7 @@ public:
PClass *TypeTableType; // The type to use for hashing into the type table
unsigned int Size; // this type's size
unsigned int Align; // this type's preferred alignment
unsigned int Flags = 0; // What is this type?
PType *HashNext; // next type in this type table
PSymbolTable Symbols;
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
@ -160,6 +176,17 @@ public:
const char *DescriptiveName() const;
static void StaticInit();
bool isScalar() const { return !!(Flags & TYPE_Scalar); }
bool isContainer() const { return !!(Flags & TYPE_Container); }
bool isInt() const { return (Flags & TYPE_IntCompatible) == TYPE_Int; }
bool isIntCompatible() const { return !!(Flags & TYPE_IntCompatible); }
bool isFloat() const { return !!(Flags & TYPE_Float); }
bool isPointer() const { return !!(Flags & TYPE_Pointer); }
bool isRealPointer() const { return !!(Flags & TYPE_Pointer); } // This excludes class pointers which use their PointedType differently
PContainerType *toContainer() { return isContainer() ? (PContainerType*)this : nullptr; }
PPointer *toPointer() { return isPointer() ? (PPointer*)this : nullptr; }
};
// Not-really-a-type types --------------------------------------------------
@ -183,14 +210,15 @@ public:
class PBasicType : public PType
{
DECLARE_ABSTRACT_CLASS(PBasicType, PType);
public:
PBasicType();
PBasicType(unsigned int size, unsigned int align);
protected:
PBasicType(unsigned int size = 1, unsigned int align = 1);
};
class PCompoundType : public PType
{
DECLARE_ABSTRACT_CLASS(PCompoundType, PType);
protected:
PCompoundType(unsigned int size = 1, unsigned int align = 1);
};
class PContainerType : public PCompoundType
@ -200,11 +228,15 @@ public:
PTypeBase *Outer; // object this type is contained within
FName TypeName; // this type's name
PContainerType() : Outer(NULL) {
mDescriptiveName = "NamedType";
PContainerType() : Outer(NULL)
{
mDescriptiveName = "ContainerType";
Flags |= TYPE_Container;
}
PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {
PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name)
{
mDescriptiveName = name.GetChars();
Flags |= TYPE_Container;
}
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
@ -252,7 +284,7 @@ class PFloat : public PBasicType
{
DECLARE_CLASS(PFloat, PBasicType);
public:
PFloat(unsigned int size);
PFloat(unsigned int size = 8);
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
@ -263,7 +295,6 @@ public:
virtual double GetValueFloat(void *addr) const;
virtual bool isNumeric() override { return true; }
protected:
PFloat();
void SetOps();
private:
struct SymbolInitF

View file

@ -593,7 +593,7 @@ static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node)
{
out.AddName(ENamedName(enode->IntVal));
}
else if (enode->Type->IsKindOf(RUNTIME_CLASS(PInt)))
else if (enode->Type->isIntCompatible())
{
out.AddInt(enode->IntVal, static_cast<PInt *>(enode->Type)->Unsigned);
}

View file

@ -403,7 +403,7 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC
// Compute implicit values by adding one to the preceding value.
assert(prev->Value != NULL);
// If the preceding node is a constant, then we can do this now.
if (prev->Value->Operation == PEX_ConstValue && prev->Value->Type->IsA(RUNTIME_CLASS(PInt)))
if (prev->Value->Operation == PEX_ConstValue && prev->Value->Type->isInt())
{
NEW_INTCONST_NODE(cval, prev->Value->Type, static_cast<ZCC_ExprConstant *>(prev->Value)->IntVal + 1, node);
node->Value = cval;
@ -1256,9 +1256,9 @@ unary_expr(X) ::= primary(X).
unary_expr(X) ::= SUB unary_expr(A). [UNARY]
{
ZCC_ExprConstant *con = static_cast<ZCC_ExprConstant *>(A);
if (A->Operation == PEX_ConstValue && (con->Type->IsA(RUNTIME_CLASS(PInt)) || con->Type->IsA(RUNTIME_CLASS(PFloat))))
if (A->Operation == PEX_ConstValue && (con->Type->isInt() || con->Type->isFloat()))
{ // For constants, manipulate the child node directly, and don't create a new node.
if (con->Type->IsA(RUNTIME_CLASS(PInt)))
if (con->Type->isInt())
{
con->IntVal = -con->IntVal;
}
@ -1280,7 +1280,7 @@ unary_expr(X) ::= ADD unary_expr(A). [UNARY]
// it so we can type check that it is being applied to something numeric.
// But we can do that right now for constant numerals.
ZCC_ExprConstant *con = static_cast<ZCC_ExprConstant *>(A);
if (A->Operation != PEX_ConstValue || (!con->Type->IsA(RUNTIME_CLASS(PInt)) && !con->Type->IsA(RUNTIME_CLASS(PFloat))))
if (A->Operation != PEX_ConstValue || (!con->Type->isInt() && !con->Type->isFloat()))
{
UNARY_EXPR(A,PEX_AntiNegate);
X = expr1;

View file

@ -873,13 +873,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant)
{
def->Symbol = new PSymbolConstString(def->NodeName, *(cval->StringVal));
}
else if (cval->Type->IsA(RUNTIME_CLASS(PInt)))
else if (cval->Type->isInt())
{
// How do we get an Enum type in here without screwing everything up???
//auto type = def->Type != nullptr ? def->Type : cval->Type;
def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal);
}
else if (cval->Type->IsA(RUNTIME_CLASS(PFloat)))
else if (cval->Type->isFloat())
{
if (def->Type != nullptr)
{
@ -899,13 +899,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant)
{
def->Symbol = new PSymbolConstString(def->NodeName, c.GetString());
}
else if (c.Type->IsA(RUNTIME_CLASS(PInt)))
else if (c.Type->isInt())
{
// How do we get an Enum type in here without screwing everything up???
//auto type = def->Type != nullptr ? def->Type : cval->Type;
def->Symbol = new PSymbolConstNumeric(def->NodeName, c.Type, c.GetInt());
}
else if (c.Type->IsA(RUNTIME_CLASS(PFloat)))
else if (c.Type->isFloat())
{
if (def->Type != nullptr)
{
@ -974,7 +974,7 @@ void ZCCCompiler::CompileArrays(ZCC_StructWork *work)
FArgumentList values;
// Don't use narrow typea for casting.
if (ctype->IsA(RUNTIME_CLASS(PInt))) ctype = static_cast<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 +1077,13 @@ ZCC_ExprConstant *ZCCCompiler::NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expres
if (val->Type != TypeError)
{
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric)));
if (sym->ValueType->IsKindOf(RUNTIME_CLASS(PInt)))
if (sym->ValueType->isIntCompatible())
{
val->IntVal = static_cast<PSymbolConstNumeric *>(sym)->Value;
}
else
{
assert(sym->ValueType->IsKindOf(RUNTIME_CLASS(PFloat)));
assert(sym->ValueType->isFloat());
val->DoubleVal = static_cast<PSymbolConstNumeric *>(sym)->Float;
}
}
@ -1752,7 +1752,7 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
ex = ex->Resolve(ctx);
if (ex == nullptr) return TypeError;
if (!ex->isConstant() || !ex->ValueType->IsA(RUNTIME_CLASS(PInt)))
if (!ex->isConstant() || !ex->ValueType->isInt())
{
Error(arraysize, "Array index must be an integer constant");
return TypeError;
@ -2023,15 +2023,15 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
{
*(PalEntry*)addr = V_GetColor(nullptr, GetStringConst(ex, ctx), &ex->ScriptPosition);
}
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
else if (f->Type->isIntCompatible())
{
static_cast<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);
}
@ -2304,7 +2304,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
do
{
auto type = DetermineType(c->Type(), f, f->Name, t, false, false);
if (type->IsKindOf(RUNTIME_CLASS(PContainerType)) && type != TypeVector2 && type != TypeVector3)
if (type->isContainer() && type != TypeVector2 && type != TypeVector3)
{
// structs and classes only get passed by pointer.
type = NewPointer(type);
@ -3228,23 +3228,23 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
case AST_ExprConstant:
{
auto cnst = static_cast<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);
}