- removed all RTTI checks for the types.

This commit is contained in:
Christoph Oelckers 2017-04-13 15:13:14 +02:00
parent b2d944974e
commit aeb455d705
11 changed files with 133 additions and 100 deletions

View file

@ -7,7 +7,6 @@ xx(Super)
xx(Object) xx(Object)
xx(Actor) xx(Actor)
xx(Class) xx(Class)
xx(ClassClass)
xx(Untranslated) xx(Untranslated)
@ -904,3 +903,12 @@ xx(Player8)
xx(PlayerChunk) xx(PlayerChunk)
xx(RestrictedToPlayerClass) xx(RestrictedToPlayerClass)
xx(ForbiddenToPlayerClass) xx(ForbiddenToPlayerClass)
xx(Prototype)
xx(Void)
xx(Label)
xx(Pointer)
xx(Enum)
xx(StaticArray)
xx(DynArray)
xx(Struct)

View file

@ -5015,7 +5015,6 @@ int DLevelScript::LineFromID(int id)
bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *&type, bool readonly) bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *&type, bool readonly)
{ {
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true)); PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
PArray *arraytype;
if (var == NULL || (!readonly && (var->Flags & VARF_Native))) 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; type = var->Type;
uint8_t *baddr = reinterpret_cast<uint8_t *>(self) + var->Offset; uint8_t *baddr = reinterpret_cast<uint8_t *>(self) + var->Offset;
arraytype = dyn_cast<PArray>(type); if (type->isArray())
if (arraytype != NULL)
{ {
PArray *arraytype = static_cast<PArray*>(type);
// unwrap contained type // unwrap contained type
type = arraytype->ElementType; type = arraytype->ElementType;
// offset by index (if in bounds) // offset by index (if in bounds)

View file

@ -4803,7 +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)) || !static_cast<PArray *>(var->Type)->ElementType->isScalar()) !var->Type->isArray() || !static_cast<PArray *>(var->Type)->ElementType->isScalar())
{ {
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

@ -219,7 +219,7 @@ static PClass *FindClassType(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);
auto ctype = dyn_cast<PClassType>(type->Type); auto ctype = PType::toClass(type->Type);
if (ctype) return ctype->Descriptor; if (ctype) return ctype->Descriptor;
} }
return nullptr; return nullptr;
@ -227,7 +227,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx)
bool isActor(PContainerType *type) bool isActor(PContainerType *type)
{ {
auto cls = dyn_cast<PClassType>(type); auto cls = PType::toClass(type);
return cls ? cls->Descriptor->IsDescendantOf(RUNTIME_CLASS(AActor)) : false; return cls ? cls->Descriptor->IsDescendantOf(RUNTIME_CLASS(AActor)) : false;
} }
@ -303,7 +303,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar
// A type is always compatible to itself. // A type is always compatible to itself.
if (fromtype == totype) return true; 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. // 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 fromcls = static_cast<PObjectPointer*>(source)->PointedClass();
auto tocls = static_cast<PObjectPointer*>(dest)->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)); return (fromcls->IsDescendantOf(tocls));
} }
// The same rules apply to class pointers. A child type can be assigned to a variable of a parent type. // 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 fromcls = static_cast<PClassPointer*>(source)->ClassRestriction;
auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction; auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction;
@ -1158,7 +1158,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED(); CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx); SAFE_RESOLVE(basex, ctx);
if (mExplicit && basex->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) if (mExplicit && basex->ValueType->isClassPointer())
{ {
if (basex->isConstant()) if (basex->isConstant())
{ {
@ -1750,7 +1750,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
} }
} }
} }
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) else if (ValueType->isClassPointer())
{ {
FxExpression *x = new FxClassTypeCast(static_cast<PClassPointer*>(ValueType), basex, Explicit); FxExpression *x = new FxClassTypeCast(static_cast<PClassPointer*>(ValueType), basex, Explicit);
x = x->Resolve(ctx); x = x->Resolve(ctx);
@ -1758,14 +1758,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
delete this; delete this;
return x; 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. // 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. // class types are only compatible if the base type is a descendant of the result type.
auto fromtype = static_cast<PClassType *>(basex->ValueType)->Descriptor; auto fromtype = static_cast<PClassType *>(basex->ValueType)->Descriptor;
@ -2480,13 +2480,13 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
} }
else if (Base->ValueType == Right->ValueType) else if (Base->ValueType == Right->ValueType)
{ {
if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PArray))) if (Base->ValueType->isArray())
{ {
ScriptPosition.Message(MSG_ERROR, "Cannot assign arrays"); ScriptPosition.Message(MSG_ERROR, "Cannot assign arrays");
delete this; delete this;
return nullptr; 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"); ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet");
delete this; delete this;
@ -3611,7 +3611,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
// Special cases: Compare strings and names with names, sounds, colors, state labels and class types. // 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. // 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) && 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 = new FxTypeCast(left, right->ValueType, false, true);
left = left->Resolve(ctx); left = left->Resolve(ctx);
@ -3619,7 +3619,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
ValueType = right->ValueType; ValueType = right->ValueType;
} }
else if ((right->ValueType == TypeString || right->ValueType == TypeName) && 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 = new FxTypeCast(right, left->ValueType, false, true);
right = right->Resolve(ctx); right = right->Resolve(ctx);
@ -4596,7 +4596,7 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx)
RESOLVE(right, ctx); RESOLVE(right, ctx);
ABORT(right && left); ABORT(right && left);
if (left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) if (left->ValueType->isClassPointer())
{ {
left = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), left, false); left = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), left, false);
ClassCheck = true; ClassCheck = true;
@ -5140,7 +5140,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
SAFE_RESOLVE(val, ctx); SAFE_RESOLVE(val, ctx);
CallingFunction = ctx.Function; CallingFunction = ctx.Function;
if (!val->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) if (!val->ValueType->isClassPointer())
{ {
ScriptPosition.Message(MSG_ERROR, "Class type expected"); ScriptPosition.Message(MSG_ERROR, "Class type expected");
delete this; delete this;
@ -6126,7 +6126,7 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *
{ {
PSymbol *sym; PSymbol *sym;
PSymbolTable *symtbl; PSymbolTable *symtbl;
bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClassType)); bool isclass = objtype->isClass();
if (Identifier == NAME_Default) if (Identifier == NAME_Default)
{ {
@ -6180,8 +6180,8 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *
object = nullptr; object = nullptr;
return nullptr; return nullptr;
} }
auto cls_ctx = dyn_cast<PClassType>(classctx); auto cls_ctx = PType::toClass(classctx);
auto cls_target = dyn_cast<PClassType>(objtype); 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. // [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) if (vsym->Flags & VARF_Protected)
{ {
@ -6403,7 +6403,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
return ret; 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)); auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PStruct *>(Object->ValueType));
delete this; delete this;
@ -6972,7 +6972,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
if (membervar->SymbolName == NAME_Default) 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))) || !static_cast<PObjectPointer *>(classx->ValueType)->PointedClass()->IsDescendantOf(RUNTIME_CLASS(AActor)))
{ {
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type"); ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type");
@ -7028,7 +7028,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
return nullptr; 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 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) 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 else
{ {
arraytype = dyn_cast<PArray>(Array->ValueType); if (!Array->ValueType->isArray())
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 = Array->ValueType->toPointer(); PPointer *ptype = Array->ValueType->toPointer();
if (ptype == nullptr || !ptype->PointedType->IsKindOf(RUNTIME_CLASS(PArray))) if (ptype == nullptr || !ptype->PointedType->isArray())
{ {
ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays."); ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
delete this; delete this;
@ -7251,10 +7250,14 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
arraytype = static_cast<PArray*>(ptype->PointedType); arraytype = static_cast<PArray*>(ptype->PointedType);
arrayispointer = true; arrayispointer = true;
} }
else
{
arraytype = static_cast<PArray*>(Array->ValueType);
}
elementtype = arraytype->ElementType; 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 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) if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable)
@ -7498,8 +7501,8 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction
bool match = (callingself == calledself); bool match = (callingself == calledself);
if (!match) if (!match)
{ {
auto callingselfcls = dyn_cast<PClassType>(caller->Variants[0].SelfClass); auto callingselfcls = PType::toClass(caller->Variants[0].SelfClass);
auto calledselfcls = dyn_cast<PClassType>(callee->Variants[0].SelfClass); auto calledselfcls = PType::toClass(callee->Variants[0].SelfClass);
match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->Descriptor->IsDescendantOf(calledselfcls->Descriptor); match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->Descriptor->IsDescendantOf(calledselfcls->Descriptor);
} }
@ -7860,7 +7863,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition)) if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition))
{ {
// [ZZ] allow implicit new() call to mean "create current class instance" // [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"); ScriptPosition.Message(MSG_ERROR, "Cannot use implicit new() in a struct");
delete this; delete this;
@ -7969,7 +7972,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
{ {
cls = ccls; cls = ccls;
staticonly = true; staticonly = true;
if (ccls->IsKindOf(RUNTIME_CLASS(PClassType))) if (ccls->isClass())
{ {
if (ctx.Function == nullptr) if (ctx.Function == nullptr)
{ {
@ -7977,7 +7980,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
delete this; delete this;
return nullptr; return nullptr;
} }
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass); auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr) if (clstype != nullptr)
{ {
novirtual = clstype->Descriptor->IsDescendantOf(static_cast<PClassType*>(ccls)->Descriptor); novirtual = clstype->Descriptor->IsDescendantOf(static_cast<PClassType*>(ccls)->Descriptor);
@ -8009,7 +8012,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
delete this; delete this;
return nullptr; return nullptr;
} }
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass); auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr) if (clstype != nullptr)
{ {
// give the node the proper value type now that we know it's properly used. // give the node the proper value type now that we know it's properly used.
@ -8175,7 +8178,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
delete this; delete this;
return nullptr; return nullptr;
} }
if (!Self->IsResizableArray()) if (!Self->isStaticArray())
{ {
auto atype = Self->ValueType; auto atype = Self->ValueType;
if (Self->ValueType->isPointer()) atype = ValueType->toPointer()->PointedType; if (Self->ValueType->isPointer()) atype = ValueType->toPointer()->PointedType;
@ -8210,7 +8213,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (MethodName == NAME_GetParentClass && if (MethodName == NAME_GetParentClass &&
(Self->IsObject() || Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))) (Self->IsObject() || Self->ValueType->isClassPointer()))
{ {
if (ArgList.Size() > 0) if (ArgList.Size() > 0)
{ {
@ -8228,7 +8231,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
cls = ptype->toContainer(); cls = ptype->toContainer();
if (cls != nullptr) if (cls != nullptr)
{ {
if (ptype->IsKindOf(RUNTIME_CLASS(PClassType)) && MethodName == NAME_GetClass) if (ptype->isClass() && MethodName == NAME_GetClass)
{ {
if (ArgList.Size() > 0) if (ArgList.Size() > 0)
{ {
@ -8247,7 +8250,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
return nullptr; return nullptr;
} }
} }
else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct))) else if (Self->ValueType->isStruct())
{ {
bool writable; bool writable;
@ -8328,8 +8331,8 @@ isresolved:
{ {
if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual)) if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual))
{ {
auto clstype = dyn_cast<PClassType>(ctx.Class); auto clstype = PType::toClass(ctx.Class);
auto ccls = dyn_cast<PClassType>(cls); auto ccls = PType::toClass(cls);
if (clstype == nullptr || ccls == nullptr || !clstype->Descriptor->IsDescendantOf(ccls->Descriptor)) 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()); ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here", cls->TypeName.GetChars(), MethodName.GetChars());
@ -8820,7 +8823,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested. 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->isRealPointer() && type->toPointer()->PointedType->IsA(RUNTIME_CLASS(PStruct))) if (type == ArgList[i]->ValueType && type->isRealPointer() && type->toPointer()->PointedType->isStruct())
{ {
// trying to pass a struct reference as a struct reference. This must preserve the type. // trying to pass a struct reference as a struct reference. This must preserve the type.
} }
@ -9331,7 +9334,7 @@ FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx)
{ {
SAFE_RESOLVE(Self, ctx); 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"); ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object");
delete this; delete this;
@ -9402,7 +9405,7 @@ FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx)
} }
else else
{ {
auto cp = dyn_cast<PClassPointer>(Self->ValueType); auto cp = PType::toClassPointer(Self->ValueType);
if (cp == nullptr || !cp->ClassRestriction->IsDescendantOf(RUNTIME_CLASS(AActor))) if (cp == nullptr || !cp->ClassRestriction->IsDescendantOf(RUNTIME_CLASS(AActor)))
{ {
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type"); ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type");
@ -10601,7 +10604,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
return x; return x;
} }
auto to = static_cast<PClassPointer *>(ValueType); auto to = static_cast<PClassPointer *>(ValueType);
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) if (basex->ValueType->isClassPointer())
{ {
auto from = static_cast<PClassPointer *>(basex->ValueType); auto from = static_cast<PClassPointer *>(basex->ValueType);
if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction)) if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction))
@ -10769,7 +10772,7 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
return x; return x;
} }
auto to = static_cast<PClassPointer *>(ValueType); auto to = static_cast<PClassPointer *>(ValueType);
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer)) if (basex->ValueType->isClassPointer())
{ {
auto from = static_cast<PClassPointer *>(basex->ValueType); auto from = static_cast<PClassPointer *>(basex->ValueType);
// Downcast is always ok. // Downcast is always ok.
@ -10846,7 +10849,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
{ {
CHECKRESOLVED(); CHECKRESOLVED();
ABORT(ctx.Class); ABORT(ctx.Class);
auto vclass = dyn_cast<PClassType>(ctx.Class); auto vclass = PType::toClass(ctx.Class);
assert(vclass != nullptr); assert(vclass != nullptr);
auto aclass = ValidateActor(vclass->Descriptor); auto aclass = ValidateActor(vclass->Descriptor);
@ -10925,7 +10928,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx)
SAFE_RESOLVE(Index, ctx); SAFE_RESOLVE(Index, ctx);
} }
auto vclass = dyn_cast<PClassType>(ctx.Class); auto vclass = PType::toClass(ctx.Class);
assert(vclass != nullptr); assert(vclass != nullptr);
auto aclass = ValidateActor(vclass->Descriptor); auto aclass = ValidateActor(vclass->Descriptor);
assert(aclass != nullptr && aclass->GetStateCount() > 0); assert(aclass != nullptr && aclass->GetStateCount() > 0);
@ -10985,7 +10988,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
ABORT(ctx.Class); ABORT(ctx.Class);
int symlabel; int symlabel;
auto vclass = dyn_cast<PClassType>(ctx.Class); auto vclass = PType::toClass(ctx.Class);
assert(vclass != nullptr); assert(vclass != nullptr);
auto clstype = ValidateActor(vclass->Descriptor); auto clstype = ValidateActor(vclass->Descriptor);
@ -11201,7 +11204,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
else else
{ {
// Init arrays and structs. // Init arrays and structs.
if (ValueType->IsA(RUNTIME_CLASS(PStruct))) if (ValueType->isStruct())
{ {
auto pstr = static_cast<PStruct*>(ValueType); auto pstr = static_cast<PStruct*>(ValueType);
if (pstr->mConstructor != nullptr) if (pstr->mConstructor != nullptr)
@ -11227,7 +11230,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
} }
else else
{ {
if (ValueType->IsA(RUNTIME_CLASS(PStruct))) if (ValueType->isStruct())
{ {
auto pstr = static_cast<PStruct*>(ValueType); auto pstr = static_cast<PStruct*>(ValueType);
if (pstr->mDestructor != nullptr) if (pstr->mDestructor != nullptr)

View file

@ -335,11 +335,11 @@ public:
bool IsPointer() const { return ValueType->isPointer(); } 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->isScalar(); } bool IsBoolCompat() const { return ValueType->isScalar(); }
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)); } bool IsObject() const { return ValueType->isObjectPointer(); }
bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->isPointer() && ValueType->toPointer()->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); } bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
bool IsResizableArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->IsKindOf(RUNTIME_CLASS(PStaticArray))); } // can only exist in pointer form. bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form.
bool IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); } bool IsDynamicArray() const { return (ValueType->isDynArray()); }
bool IsNativeStruct() const { return (ValueType->IsA(RUNTIME_CLASS(PStruct)) && static_cast<PStruct*>(ValueType)->isNative); } bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }
virtual ExpEmit Emit(VMFunctionBuilder *build); virtual ExpEmit Emit(VMFunctionBuilder *build);
void EmitStatement(VMFunctionBuilder *build); void EmitStatement(VMFunctionBuilder *build);

View file

@ -203,7 +203,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type)
x = new FxRuntimeStateIndex(ParseExpression(sc, cls)); x = new FxRuntimeStateIndex(ParseExpression(sc, cls));
} }
} }
else if (type->GetClass() == RUNTIME_CLASS(PClassPointer)) else if (type->isClassPointer())
{ // Actor name { // Actor name
sc.SetEscape(true); sc.SetEscape(true);
sc.MustGetString(); sc.MustGetString();
@ -881,7 +881,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
sc.MustGetString(); sc.MustGetString();
*(FString*)addr = strbin1(sc.String); *(FString*)addr = strbin1(sc.String);
} }
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer))) else if (f->Type->isClassPointer())
{ {
sc.MustGetString(); sc.MustGetString();
@ -892,13 +892,14 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
else else
{ {
auto cls = PClass::FindClass(sc.String); auto cls = PClass::FindClass(sc.String);
auto cp = static_cast<PClassPointer*>(f->Type);
if (cls == nullptr) 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++; FScriptPosition::ErrorCounter++;
} }
*(PClass**)addr = cls; *(PClass**)addr = cls;

View file

@ -195,8 +195,8 @@ PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *func
if (symbol != nullptr) if (symbol != nullptr)
{ {
auto cls_ctx = dyn_cast<PClassType>(funccls); auto cls_ctx = PType::toClass(funccls);
auto cls_target = funcsym ? dyn_cast<PClassType>(funcsym->OwningClass) : nullptr; auto cls_target = funcsym ? PType::toClass(funcsym->OwningClass) : nullptr;
if (funcsym == nullptr) if (funcsym == nullptr)
{ {
sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars()); sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars());

View file

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

View file

@ -1407,6 +1407,7 @@ PObjectPointer::PObjectPointer(PClass *cls, bool isconst)
: PPointer(cls->VMType, isconst) : PPointer(cls->VMType, isconst)
{ {
loadOp = OP_LO; 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. // 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; if (cls && !cls->IsDescendantOf(RUNTIME_CLASS(DThinker))) storeOp = OP_SO;
} }
@ -1545,6 +1546,7 @@ PClassPointer::PClassPointer(PClass *restrict)
else mDescriptiveName = "ClassPointer"; else mDescriptiveName = "ClassPointer";
loadOp = OP_LP; loadOp = OP_LP;
storeOp = OP_SP; storeOp = OP_SP;
Flags |= TYPE_ClassPointer;
mVersion = restrict->VMType->mVersion; mVersion = restrict->VMType->mVersion;
} }
@ -1664,6 +1666,7 @@ PEnum::PEnum(FName name, PTypeBase *outer)
{ {
EnumName = name; EnumName = name;
Outer = outer; Outer = outer;
Flags |= TYPE_IntNotInt;
mDescriptiveName.Format("Enum<%s>", name.GetChars()); mDescriptiveName.Format("Enum<%s>", name.GetChars());
} }
@ -1721,6 +1724,7 @@ PArray::PArray(PType *etype, unsigned int ecount)
// also be padded to the nearest alignment. // also be padded to the nearest alignment.
ElementSize = (etype->Size + (etype->Align - 1)) & ~(etype->Align - 1); ElementSize = (etype->Size + (etype->Align - 1)) & ~(etype->Align - 1);
Size = ElementSize * ecount; Size = ElementSize * ecount;
Flags |= TYPE_Array;
} }
//========================================================================== //==========================================================================

View file

@ -4,7 +4,6 @@
#include "serializer.h" #include "serializer.h"
// Variable/parameter/field flags ------------------------------------------- // Variable/parameter/field flags -------------------------------------------
class PStruct;
// Making all these different storage types use a common set of flags seems // Making all these different storage types use a common set of flags seems
// like the simplest thing to do. // like the simplest thing to do.
@ -61,20 +60,12 @@ 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 PContainerType;
class PPointer; class PPointer;
class PClassPointer;
class PArray;
class PStruct;
class PClassType;
struct ZCC_ExprConstant; struct ZCC_ExprConstant;
class PType : public PTypeBase class PType : public PTypeBase
@ -82,6 +73,21 @@ class PType : public PTypeBase
DECLARE_ABSTRACT_CLASS(PType, PTypeBase) DECLARE_ABSTRACT_CLASS(PType, PTypeBase)
protected: 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: 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
@ -183,10 +189,21 @@ public:
bool isIntCompatible() const { return !!(Flags & TYPE_IntCompatible); } bool isIntCompatible() const { return !!(Flags & TYPE_IntCompatible); }
bool isFloat() const { return !!(Flags & TYPE_Float); } bool isFloat() const { return !!(Flags & TYPE_Float); }
bool isPointer() const { return !!(Flags & TYPE_Pointer); } bool isPointer() const { return !!(Flags & TYPE_Pointer); }
bool isRealPointer() const { return !!(Flags & TYPE_Pointer); } // This excludes class pointers which use their PointedType differently bool isRealPointer() const { return (Flags & (TYPE_Pointer|TYPE_ClassPointer)) == TYPE_Pointer; } // This excludes class pointers which use their PointedType differently
bool isObjectPointer() const { return !!(Flags & TYPE_ObjectPointer); }
bool isClassPointer() const { return !!(Flags & TYPE_ClassPointer); }
bool isEnum() const { return TypeTableType->TypeName == NAME_Enum; }
bool isArray() const { return !!(Flags & TYPE_Array); }
bool isStaticArray() const { return TypeTableType->TypeName == NAME_StaticArray; }
bool isDynArray() const { return TypeTableType->TypeName == NAME_DynArray; }
bool isStruct() const { return TypeTableType->TypeName == NAME_Struct; }
bool isClass() const { return TypeTableType->TypeName == FName("ClassType"); }
bool isPrototype() const { return TypeTableType->TypeName == NAME_Prototype; }
PContainerType *toContainer() { return isContainer() ? (PContainerType*)this : nullptr; } PContainerType *toContainer() { return isContainer() ? (PContainerType*)this : nullptr; }
PPointer *toPointer() { return isPointer() ? (PPointer*)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 -------------------------------------------------- // Not-really-a-type types --------------------------------------------------
@ -493,7 +510,7 @@ public:
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override; void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
protected: protected:
PArray(); PArray();//deleteme
}; };
class PStaticArray : public PArray class PStaticArray : public PArray
@ -506,7 +523,7 @@ public:
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected: protected:
PStaticArray(); PStaticArray();// deleteme
}; };
class PDynArray : public PCompoundType class PDynArray : public PCompoundType
@ -529,7 +546,7 @@ public:
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const override; void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const override;
protected: protected:
PDynArray(); PDynArray(); // deleteme
}; };
class PMap : public PCompoundType class PMap : public PCompoundType
@ -544,7 +561,7 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected: protected:
PMap(); PMap(); // deleteme
}; };
class PStruct : public PContainerType class PStruct : public PContainerType
@ -568,7 +585,7 @@ public:
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override; void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
protected: protected:
PStruct(); PStruct(); // deleteme
}; };
class PPrototype : public PCompoundType class PPrototype : public PCompoundType
@ -584,7 +601,7 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const; virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
protected: protected:
PPrototype(); PPrototype(); // deleteme
}; };

View file

@ -1320,7 +1320,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. // 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 && 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); Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type == nullptr ? "" : type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size);
} }
@ -1652,7 +1652,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
return TypeError; return TypeError;
} }
auto typesym = dyn_cast<PSymbolType>(sym); 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()); Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars());
return TypeError; return TypeError;
@ -1703,15 +1703,15 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo
return TypeError; 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. 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); 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); if (!nativetype) return NewPointer(ptype, type->isconst);
return ptype; // instantiation of native structs. Only for internal use. return ptype; // instantiation of native structs. Only for internal use.
@ -2035,7 +2035,7 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
{ {
*(FString*)addr = GetStringConst(ex, ctx); *(FString*)addr = GetStringConst(ex, ctx);
} }
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer))) else if (f->Type->isClassPointer())
{ {
auto clsname = GetStringConst(ex, ctx); auto clsname = GetStringConst(ex, ctx);
if (*clsname == 0 || !stricmp(clsname, "none")) if (*clsname == 0 || !stricmp(clsname, "none"))
@ -2045,13 +2045,14 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
else else
{ {
auto cls = PClass::FindClass(clsname); auto cls = PClass::FindClass(clsname);
auto cp = static_cast<PClassPointer*>(f->Type);
if (cls == nullptr) 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; *(PClass**)addr = cls;
} }
@ -2495,7 +2496,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
{ {
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
int flags = 0; 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. // Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/); type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
@ -2565,7 +2566,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
break; break;
case REGT_POINTER: case REGT_POINTER:
if (type->IsKindOf(RUNTIME_CLASS(PClassPointer))) if (type->isClassPointer())
vmval[0] = (DObject*)cnst->GetValue().GetPointer(); vmval[0] = (DObject*)cnst->GetValue().GetPointer();
else else
vmval[0] = cnst->GetValue().GetPointer(); vmval[0] = cnst->GetValue().GetPointer();
@ -2609,7 +2610,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr ? nullptr : *(afd->VMPointer), varflags, useflags); sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr ? nullptr : *(afd->VMPointer), varflags, useflags);
c->Type()->Symbols.ReplaceSymbol(sym); c->Type()->Symbols.ReplaceSymbol(sym);
auto vcls = dyn_cast<PClassType>(c->Type()); auto vcls = PType::toClass(c->Type());
auto cls = vcls ? vcls->Descriptor : nullptr; auto cls = vcls ? vcls->Descriptor : nullptr;
PFunction *virtsym = nullptr; PFunction *virtsym = nullptr;
if (cls != nullptr && cls->ParentClass != nullptr) virtsym = dyn_cast<PFunction>(cls->ParentClass->VMType->Symbols.FindSymbol(FName(f->Name), true)); if (cls != nullptr && cls->ParentClass != nullptr) virtsym = dyn_cast<PFunction>(cls->ParentClass->VMType->Symbols.FindSymbol(FName(f->Name), true));
@ -2656,7 +2657,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; 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 (varflags & VARF_Virtual)
{ {
if (sym->Variants[0].Implementation == nullptr) if (sym->Variants[0].Implementation == nullptr)
@ -2817,7 +2818,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af, in
{ {
FArgumentList argumentlist; FArgumentList argumentlist;
// We can use this function directly without wrapping it in a caller. // 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; int comboflags = afd->Variants[0].UseFlags & StateFlags;
if (comboflags == StateFlags) // the function must satisfy all the flags the state requires if (comboflags == StateFlags) // the function must satisfy all the flags the state requires