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

View file

@ -52,7 +52,6 @@ public:
static void StaticInit(); static void StaticInit();
static void StaticShutdown(); static void StaticShutdown();
static void StaticBootstrap();
// Per-class information ------------------------------------- // Per-class information -------------------------------------
PClass *ParentClass = nullptr; // the class this class derives from 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: public:
PActorInfo() 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()); params.Push(f.GetIndex());
} }
else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) else if (args[i]->isIntCompatible())
{ {
char *endp; char *endp;
int v = (int)strtoll(sc.String, &endp, 0); 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; if (args[i] == TypeBool) v = !!v;
params.Push(v); params.Push(v);
} }
else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat))) else if (args[i]->isFloat())
{ {
char *endp; char *endp;
double v = strtod(sc.String, &endp); double v = strtod(sc.String, &endp);
@ -775,7 +775,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
{ {
params.Push(V_GetColor(nullptr, sc)); params.Push(V_GetColor(nullptr, sc));
} }
else if (args[i]->IsKindOf(RUNTIME_CLASS(PInt))) else if (args[i]->isIntCompatible())
{ {
char *endp; char *endp;
int v = (int)strtoll(sc.String, &endp, 0); 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; if (args[i] == TypeBool) v = !!v;
params.Push(v); params.Push(v);
} }
else if (args[i]->IsKindOf(RUNTIME_CLASS(PFloat))) else if (args[i]->isFloat())
{ {
char *endp; char *endp;
double v = strtod(sc.String, &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; return false;
} }
addr = baddr; addr = baddr;
// We don't want Int subclasses like Name or Color to be accessible, // We don't want Int subclasses like Name or Color to be accessible here.
// but we do want to support Float subclasses like Fixed. if (!type->isInt() && !type->isFloat())
if (!type->IsA(RUNTIME_CLASS(PInt)) && !type->IsKindOf(RUNTIME_CLASS(PFloat)))
{ {
// For reading, we also support Name and String types. // 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; 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 (GetVarAddrType(self, varname, index, addr, type, false))
{ {
if (!type->IsKindOf(RUNTIME_CLASS(PFloat))) if (!type->isFloat())
{ {
type->SetValue(addr, value); 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 (GetVarAddrType(self, varname, index, addr, type, true))
{ {
if (type->IsKindOf(RUNTIME_CLASS(PFloat))) if (type->isFloat())
{ {
return DoubleToACS(type->GetValueFloat(addr)); 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()); 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); 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)); 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(), Printf("%s is not a user variable in class %s\n", varname.GetChars(),
self->GetClass()->TypeName.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)); PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) || if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) ||
!var->Type->IsKindOf(RUNTIME_CLASS(PArray)) || !var->Type->IsKindOf(RUNTIME_CLASS(PArray)) || !static_cast<PArray *>(var->Type)->ElementType->isScalar())
!static_cast<PArray *>(var->Type)->ElementType->IsKindOf(RUNTIME_CLASS(PBasicType)))
{ {
Printf("%s is not a user array in class %s\n", varname.GetChars(), Printf("%s is not a user array in class %s\n", varname.GetChars(),
self->GetClass()->TypeName.GetChars()); self->GetClass()->TypeName.GetChars());

View file

@ -1621,7 +1621,7 @@ static void SetMapThingUserData(AActor *actor, unsigned udi)
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(), DPrintf(DMSG_WARNING, "%s is not a user variable in class %s\n", varname.GetChars(),
actor->GetClass()->TypeName.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))) if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{ {
auto type = static_cast<PSymbolType*>(sym); auto type = static_cast<PSymbolType*>(sym);
return dyn_cast<PContainerType>(type->Type); return type->Type->toContainer();
} }
return nullptr; return nullptr;
} }
@ -292,10 +292,10 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall
static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare = false) 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 fromtype = source->toPointer();
auto totype = static_cast<PPointer *>(dest); auto totype = dest->toPointer();
// null pointers can be assigned to everything, everything can be assigned to void pointers. // null pointers can be assigned to everything, everything can be assigned to void pointers.
if (fromtype == nullptr || totype == TypeVoidPtr) return true; if (fromtype == nullptr || totype == TypeVoidPtr) return true;
// when comparing const-ness does not matter. // 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); PSymbolConstNumeric *csym = dyn_cast<PSymbolConstNumeric>(sym);
if (csym != nullptr) if (csym != nullptr)
{ {
if (csym->ValueType->IsA(RUNTIME_CLASS(PInt))) if (csym->ValueType->isInt())
{ {
x = new FxConstant(csym->Value, pos); 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); x = new FxConstant(csym->Float, pos);
} }
@ -1356,7 +1356,7 @@ FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED(); CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx); SAFE_RESOLVE(basex, ctx);
if (basex->ValueType == TypeColor || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt)) if (basex->ValueType == TypeColor || basex->ValueType->isInt())
{ {
FxExpression *x = basex; FxExpression *x = basex;
x->ValueType = TypeColor; x->ValueType = TypeColor;
@ -1445,7 +1445,7 @@ FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED(); CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx); SAFE_RESOLVE(basex, ctx);
if (basex->ValueType == TypeSound || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt)) if (basex->ValueType == TypeSound || basex->ValueType->isInt())
{ {
FxExpression *x = basex; FxExpression *x = basex;
x->ValueType = TypeSound; 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. // don't go through the entire list if the types are the same.
goto basereturn; goto basereturn;
} }
else if (basex->ValueType == TypeNullPtr && (ValueType == TypeState || ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))) else if (basex->ValueType == TypeNullPtr && ValueType->isPointer())
{ {
goto basereturn; goto basereturn;
} }
@ -1629,7 +1629,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
delete this; delete this;
return x; 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. // This is only for casting to actual ints. Subtypes representing an int will be handled elsewhere.
FxExpression *x = new FxIntCast(basex, NoWarn, Explicit); FxExpression *x = new FxIntCast(basex, NoWarn, Explicit);
@ -1773,7 +1773,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
if (fromtype->IsDescendantOf(totype)) goto basereturn; 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; bool writable;
basex->RequestAddress(ctx, &writable); basex->RequestAddress(ctx, &writable);
@ -2494,7 +2494,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
} }
// Both types are the same so this is ok. // 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. // 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. // 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; 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; bool writable;
if (!right->RequestAddress(ctx, &writable)) goto error; 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; bool writable;
if (!left->RequestAddress(ctx, &writable)) goto error; if (!left->RequestAddress(ctx, &writable)) goto error;
@ -4684,7 +4684,7 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx)
{ {
CHECKRESOLVED(); CHECKRESOLVED();
SAFE_RESOLVE(expr, ctx); 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) 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. // 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); auto sn = static_cast<PSymbolConstNumeric*>(sym);
VMValue vmv; VMValue vmv;
if (sn->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) vmv = sn->Value; if (sn->ValueType->isIntCompatible()) vmv = sn->Value;
else vmv = sn->Float; else vmv = sn->Float;
auto x = new FxConstant(sn->ValueType, vmv, ScriptPosition); auto x = new FxConstant(sn->ValueType, vmv, ScriptPosition);
delete this; delete this;
@ -6393,10 +6393,10 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
{ {
Object->ValueType = TypeColorStruct; Object->ValueType = TypeColorStruct;
} }
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) if (Object->ValueType->isRealPointer())
{ {
auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType; auto ptype = Object->ValueType->toPointer()->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType))) if (ptype->isContainer())
{ {
auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PContainerType *>(ptype)); auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PContainerType *>(ptype));
delete this; delete this;
@ -6603,8 +6603,8 @@ FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx)
{ {
CHECKRESOLVED(); CHECKRESOLVED();
SAFE_RESOLVE(obj, ctx); SAFE_RESOLVE(obj, ctx);
assert(obj->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))); assert(obj->ValueType->isRealPointer());
ValueType = NewPointer(static_cast<PPointer*>(obj->ValueType)->PointedType, true); ValueType = NewPointer(obj->ValueType->toPointer()->PointedType, true);
return this; return this;
} }
@ -6938,7 +6938,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable)
{ {
// [ZZ] original check. // [ZZ] original check.
bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) && 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 // [ZZ] implement write barrier between different scopes
if (bWritable) if (bWritable)
{ {
@ -7018,10 +7018,10 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
return x->Resolve(ctx); return x->Resolve(ctx);
} }
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) if (classx->ValueType->isPointer())
{ {
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType); PPointer *ptrtype = classx->ValueType->toPointer();
if (ptrtype == nullptr || !ptrtype->PointedType->IsKindOf(RUNTIME_CLASS(PContainerType))) if (ptrtype == nullptr || !ptrtype->PointedType->isContainer())
{ {
ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object"); ScriptPosition.Message(MSG_ERROR, "Member variable requires a struct or class object");
delete this; delete this;
@ -7241,7 +7241,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
if (arraytype == nullptr) if (arraytype == nullptr)
{ {
// Check if we got a pointer to an array. Some native data structures (like the line list in sectors) use this. // 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))) if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray)))
{ {
ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
@ -7316,7 +7316,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
if (arrayispointer) if (arrayispointer)
{ {
arraytype = static_cast<PArray*>(static_cast<PPointer*>(Array->ValueType)->PointedType); arraytype = static_cast<PArray*>(Array->ValueType->toPointer()->PointedType);
} }
else else
{ {
@ -8150,7 +8150,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
member->membervar = newfield; 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. // 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, // 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()) if (!Self->IsResizableArray())
{ {
auto atype = Self->ValueType; 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 size = static_cast<PArray*>(atype)->ElementCount;
auto x = new FxConstant(size, ScriptPosition); auto x = new FxConstant(size, ScriptPosition);
delete this; delete this;
@ -8222,10 +8222,11 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
return x->Resolve(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; auto ptype = Self->ValueType->toPointer()->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PContainerType))) cls = ptype->toContainer();
if (cls != nullptr)
{ {
if (ptype->IsKindOf(RUNTIME_CLASS(PClassType)) && MethodName == NAME_GetClass) if (ptype->IsKindOf(RUNTIME_CLASS(PClassType)) && MethodName == NAME_GetClass)
{ {
@ -8238,9 +8239,6 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
auto x = new FxGetClass(Self); auto x = new FxGetClass(Self);
return x->Resolve(ctx); return x->Resolve(ctx);
} }
cls = static_cast<PContainerType *>(ptype);
} }
else 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 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) 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 ntype = TypeNullPtr; // the default of a reference type can only be a null pointer
} }
if (ntype->GetRegCount() == 1) 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. ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr) 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. // 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) 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); int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags);
if (outerside == FScopeBarrier::Side_Virtual) if (outerside == FScopeBarrier::Side_Virtual)
@ -9300,7 +9298,7 @@ FxExpression *FxGetClass::Resolve(FCompileContext &ctx)
delete this; delete this;
return nullptr; 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; return this;
} }

View file

@ -330,14 +330,14 @@ public:
virtual bool CheckReturn() { return false; } virtual bool CheckReturn() { return false; }
virtual int GetBitValue() { return -1; } virtual int GetBitValue() { return -1; }
bool IsNumeric() const { return ValueType->isNumeric(); } bool IsNumeric() const { return ValueType->isNumeric(); }
bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; } bool IsFloat() const { return ValueType->isFloat(); }
bool IsInteger() const { return ValueType->isNumeric() && (ValueType->GetRegType() == REGT_INT); } bool IsInteger() const { return ValueType->isNumeric() && ValueType->isIntCompatible(); }
bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; } bool IsPointer() const { return ValueType->isPointer(); }
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; 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 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 IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->isPointer() && ValueType->toPointer()->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 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 IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); }
bool IsNativeStruct() const { return (ValueType->IsA(RUNTIME_CLASS(PStruct)) && static_cast<PStruct*>(ValueType)->isNative); } 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; if (sc.CheckNumber()) *(int*)addr = sc.Number;
else *(PalEntry*)addr = V_GetColor(nullptr, sc); else *(PalEntry*)addr = V_GetColor(nullptr, sc);
} }
else if (f->Type->IsKindOf(RUNTIME_CLASS(PInt))) else if (f->Type->isIntCompatible())
{ {
sc.MustGetNumber(); sc.MustGetNumber();
static_cast<PInt*>(f->Type)->SetValue(addr, sc.Number); static_cast<PInt*>(f->Type)->SetValue(addr, sc.Number);
} }
else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat))) else if (f->Type->isFloat())
{ {
sc.MustGetFloat(); sc.MustGetFloat();
static_cast<PFloat*>(f->Type)->SetValue(addr, sc.Float); static_cast<PFloat*>(f->Type)->SetValue(addr, sc.Float);
} }
else if (f->Type->IsKindOf(RUNTIME_CLASS(PString))) else if (f->Type == TypeString)
{ {
sc.MustGetString(); sc.MustGetString();
*(FString*)addr = strbin1(sc.String); *(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) if (flags & VARF_Method)
{ {
assert(proto->ArgumentTypes.Size() > 0); assert(proto->ArgumentTypes.Size() > 0);
auto selftypeptr = dyn_cast<PPointer>(proto->ArgumentTypes[0]); auto selftypeptr = proto->ArgumentTypes[0]->toPointer();
assert(selftypeptr != nullptr); assert(selftypeptr != nullptr);
variant.SelfClass = dyn_cast<PContainerType>(selftypeptr->PointedType); variant.SelfClass = selftypeptr->PointedType->toContainer();
assert(variant.SelfClass != nullptr); assert(variant.SelfClass != nullptr);
} }
else else
@ -155,7 +155,7 @@ PField::PField(FName name, PType *type, uint32_t flags, size_t offset, int bitva
unsigned val = bitvalue; unsigned val = bitvalue;
while ((val >>= 1)) 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. // map to the single bytes in the actual variable. The internal bit instructions operate on 8 bit values.
#ifndef __BIG_ENDIAN__ #ifndef __BIG_ENDIAN__
@ -582,7 +582,7 @@ void RemoveUnusedSymbols()
{ {
for (PType *ty = TypeTable.TypeHash[i]; ty != nullptr; ty = ty->HashNext) 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(); auto it = ty->Symbols.GetIterator();
PSymbolTable::MapType::Pair *pair; PSymbolTable::MapType::Pair *pair;

View file

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

View file

@ -61,6 +61,21 @@ enum
// Map * * // Map * *
// Prototype *+ *+ // 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; struct ZCC_ExprConstant;
class PType : public PTypeBase class PType : public PTypeBase
{ {
@ -71,6 +86,7 @@ public:
PClass *TypeTableType; // The type to use for hashing into the type table PClass *TypeTableType; // The type to use for hashing into the type table
unsigned int Size; // this type's size unsigned int Size; // this type's size
unsigned int Align; // this type's preferred alignment unsigned int Align; // this type's preferred alignment
unsigned int Flags = 0; // What is this type?
PType *HashNext; // next type in this type table PType *HashNext; // next type in this type table
PSymbolTable Symbols; PSymbolTable Symbols;
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument. 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; const char *DescriptiveName() const;
static void StaticInit(); 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 -------------------------------------------------- // Not-really-a-type types --------------------------------------------------
@ -183,14 +210,15 @@ public:
class PBasicType : public PType class PBasicType : public PType
{ {
DECLARE_ABSTRACT_CLASS(PBasicType, PType); DECLARE_ABSTRACT_CLASS(PBasicType, PType);
public: protected:
PBasicType(); PBasicType(unsigned int size = 1, unsigned int align = 1);
PBasicType(unsigned int size, unsigned int align);
}; };
class PCompoundType : public PType class PCompoundType : public PType
{ {
DECLARE_ABSTRACT_CLASS(PCompoundType, PType); DECLARE_ABSTRACT_CLASS(PCompoundType, PType);
protected:
PCompoundType(unsigned int size = 1, unsigned int align = 1);
}; };
class PContainerType : public PCompoundType class PContainerType : public PCompoundType
@ -200,11 +228,15 @@ public:
PTypeBase *Outer; // object this type is contained within PTypeBase *Outer; // object this type is contained within
FName TypeName; // this type's name FName TypeName; // this type's name
PContainerType() : Outer(NULL) { PContainerType() : Outer(NULL)
mDescriptiveName = "NamedType"; {
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(); mDescriptiveName = name.GetChars();
Flags |= TYPE_Container;
} }
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
@ -252,7 +284,7 @@ class PFloat : public PBasicType
{ {
DECLARE_CLASS(PFloat, PBasicType); DECLARE_CLASS(PFloat, PBasicType);
public: public:
PFloat(unsigned int size); PFloat(unsigned int size = 8);
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,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 double GetValueFloat(void *addr) const;
virtual bool isNumeric() override { return true; } virtual bool isNumeric() override { return true; }
protected: protected:
PFloat();
void SetOps(); void SetOps();
private: private:
struct SymbolInitF struct SymbolInitF

View file

@ -593,7 +593,7 @@ static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node)
{ {
out.AddName(ENamedName(enode->IntVal)); 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); 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. // Compute implicit values by adding one to the preceding value.
assert(prev->Value != NULL); assert(prev->Value != NULL);
// If the preceding node is a constant, then we can do this now. // 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); NEW_INTCONST_NODE(cval, prev->Value->Type, static_cast<ZCC_ExprConstant *>(prev->Value)->IntVal + 1, node);
node->Value = cval; node->Value = cval;
@ -1256,9 +1256,9 @@ unary_expr(X) ::= primary(X).
unary_expr(X) ::= SUB unary_expr(A). [UNARY] unary_expr(X) ::= SUB unary_expr(A). [UNARY]
{ {
ZCC_ExprConstant *con = static_cast<ZCC_ExprConstant *>(A); 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. { // 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; 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. // it so we can type check that it is being applied to something numeric.
// But we can do that right now for constant numerals. // But we can do that right now for constant numerals.
ZCC_ExprConstant *con = static_cast<ZCC_ExprConstant *>(A); 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); UNARY_EXPR(A,PEX_AntiNegate);
X = expr1; X = expr1;

View file

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