mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- removed all RTTI checks for the types.
This commit is contained in:
parent
b2d944974e
commit
aeb455d705
11 changed files with 133 additions and 100 deletions
|
@ -7,7 +7,6 @@ xx(Super)
|
|||
xx(Object)
|
||||
xx(Actor)
|
||||
xx(Class)
|
||||
xx(ClassClass)
|
||||
|
||||
xx(Untranslated)
|
||||
|
||||
|
@ -904,3 +903,12 @@ xx(Player8)
|
|||
xx(PlayerChunk)
|
||||
xx(RestrictedToPlayerClass)
|
||||
xx(ForbiddenToPlayerClass)
|
||||
|
||||
xx(Prototype)
|
||||
xx(Void)
|
||||
xx(Label)
|
||||
xx(Pointer)
|
||||
xx(Enum)
|
||||
xx(StaticArray)
|
||||
xx(DynArray)
|
||||
xx(Struct)
|
|
@ -5015,7 +5015,6 @@ int DLevelScript::LineFromID(int id)
|
|||
bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *&type, bool readonly)
|
||||
{
|
||||
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
|
||||
PArray *arraytype;
|
||||
|
||||
if (var == NULL || (!readonly && (var->Flags & VARF_Native)))
|
||||
{
|
||||
|
@ -5023,9 +5022,9 @@ bool GetVarAddrType(AActor *self, FName varname, int index, void *&addr, PType *
|
|||
}
|
||||
type = var->Type;
|
||||
uint8_t *baddr = reinterpret_cast<uint8_t *>(self) + var->Offset;
|
||||
arraytype = dyn_cast<PArray>(type);
|
||||
if (arraytype != NULL)
|
||||
if (type->isArray())
|
||||
{
|
||||
PArray *arraytype = static_cast<PArray*>(type);
|
||||
// unwrap contained type
|
||||
type = arraytype->ElementType;
|
||||
// offset by index (if in bounds)
|
||||
|
|
|
@ -4803,7 +4803,7 @@ static PField *GetArrayVar(DObject *self, FName varname, int pos)
|
|||
PField *var = dyn_cast<PField>(self->GetClass()->FindSymbol(varname, true));
|
||||
|
||||
if (var == NULL || (var->Flags & (VARF_Native | VARF_Private | VARF_Protected | VARF_Static)) ||
|
||||
!var->Type->IsKindOf(RUNTIME_CLASS(PArray)) || !static_cast<PArray *>(var->Type)->ElementType->isScalar())
|
||||
!var->Type->isArray() || !static_cast<PArray *>(var->Type)->ElementType->isScalar())
|
||||
{
|
||||
Printf("%s is not a user array in class %s\n", varname.GetChars(),
|
||||
self->GetClass()->TypeName.GetChars());
|
||||
|
|
|
@ -219,7 +219,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx)
|
|||
if (sym && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
|
||||
{
|
||||
auto type = static_cast<PSymbolType*>(sym);
|
||||
auto ctype = dyn_cast<PClassType>(type->Type);
|
||||
auto ctype = PType::toClass(type->Type);
|
||||
if (ctype) return ctype->Descriptor;
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -227,7 +227,7 @@ static PClass *FindClassType(FName name, FCompileContext &ctx)
|
|||
|
||||
bool isActor(PContainerType *type)
|
||||
{
|
||||
auto cls = dyn_cast<PClassType>(type);
|
||||
auto cls = PType::toClass(type);
|
||||
return cls ? cls->Descriptor->IsDescendantOf(RUNTIME_CLASS(AActor)) : false;
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar
|
|||
// A type is always compatible to itself.
|
||||
if (fromtype == totype) return true;
|
||||
// Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type.
|
||||
if (source->IsA(RUNTIME_CLASS(PObjectPointer)) && dest->IsA(RUNTIME_CLASS(PObjectPointer)))
|
||||
if (source->isObjectPointer() && dest->isObjectPointer())
|
||||
{
|
||||
auto fromcls = static_cast<PObjectPointer*>(source)->PointedClass();
|
||||
auto tocls = static_cast<PObjectPointer*>(dest)->PointedClass();
|
||||
|
@ -311,7 +311,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar
|
|||
return (fromcls->IsDescendantOf(tocls));
|
||||
}
|
||||
// The same rules apply to class pointers. A child type can be assigned to a variable of a parent type.
|
||||
if (source->IsA(RUNTIME_CLASS(PClassPointer)) && dest->IsA(RUNTIME_CLASS(PClassPointer)))
|
||||
if (source->isClassPointer() && dest->isClassPointer())
|
||||
{
|
||||
auto fromcls = static_cast<PClassPointer*>(source)->ClassRestriction;
|
||||
auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction;
|
||||
|
@ -1158,7 +1158,7 @@ FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
if (mExplicit && basex->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
if (mExplicit && basex->ValueType->isClassPointer())
|
||||
{
|
||||
if (basex->isConstant())
|
||||
{
|
||||
|
@ -1750,7 +1750,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
else if (ValueType->isClassPointer())
|
||||
{
|
||||
FxExpression *x = new FxClassTypeCast(static_cast<PClassPointer*>(ValueType), basex, Explicit);
|
||||
x = x->Resolve(ctx);
|
||||
|
@ -1758,14 +1758,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
|||
delete this;
|
||||
return x;
|
||||
}
|
||||
/* else if (ValueType->IsKindOf(RUNTIME_CLASS(PEnum)))
|
||||
/* else if (ValueType->isEnum())
|
||||
{
|
||||
// this is not yet ready and does not get assigned to actual values.
|
||||
}
|
||||
*/
|
||||
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassType))) // this should never happen because the VM doesn't handle plain class types - just pointers
|
||||
else if (ValueType->isClass()) // this should never happen because the VM doesn't handle plain class types - just pointers
|
||||
{
|
||||
if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PClassType)))
|
||||
if (basex->ValueType->isClass())
|
||||
{
|
||||
// class types are only compatible if the base type is a descendant of the result type.
|
||||
auto fromtype = static_cast<PClassType *>(basex->ValueType)->Descriptor;
|
||||
|
@ -2480,13 +2480,13 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
else if (Base->ValueType == Right->ValueType)
|
||||
{
|
||||
if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PArray)))
|
||||
if (Base->ValueType->isArray())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot assign arrays");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (!Base->IsVector() && Base->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
if (!Base->IsVector() && Base->ValueType->isStruct())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet");
|
||||
delete this;
|
||||
|
@ -3611,7 +3611,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
|||
// Special cases: Compare strings and names with names, sounds, colors, state labels and class types.
|
||||
// These are all types a string can be implicitly cast into, so for convenience, so they should when doing a comparison.
|
||||
if ((left->ValueType == TypeString || left->ValueType == TypeName) &&
|
||||
(right->ValueType == TypeName || right->ValueType == TypeSound || right->ValueType == TypeColor || right->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || right->ValueType == TypeStateLabel))
|
||||
(right->ValueType == TypeName || right->ValueType == TypeSound || right->ValueType == TypeColor || right->ValueType->isClassPointer() || right->ValueType == TypeStateLabel))
|
||||
{
|
||||
left = new FxTypeCast(left, right->ValueType, false, true);
|
||||
left = left->Resolve(ctx);
|
||||
|
@ -3619,7 +3619,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
|||
ValueType = right->ValueType;
|
||||
}
|
||||
else if ((right->ValueType == TypeString || right->ValueType == TypeName) &&
|
||||
(left->ValueType == TypeName || left->ValueType == TypeSound || left->ValueType == TypeColor || left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) || left->ValueType == TypeStateLabel))
|
||||
(left->ValueType == TypeName || left->ValueType == TypeSound || left->ValueType == TypeColor || left->ValueType->isClassPointer() || left->ValueType == TypeStateLabel))
|
||||
{
|
||||
right = new FxTypeCast(right, left->ValueType, false, true);
|
||||
right = right->Resolve(ctx);
|
||||
|
@ -4596,7 +4596,7 @@ FxExpression *FxTypeCheck::Resolve(FCompileContext& ctx)
|
|||
RESOLVE(right, ctx);
|
||||
ABORT(right && left);
|
||||
|
||||
if (left->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
if (left->ValueType->isClassPointer())
|
||||
{
|
||||
left = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), left, false);
|
||||
ClassCheck = true;
|
||||
|
@ -5140,7 +5140,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
|
|||
SAFE_RESOLVE(val, ctx);
|
||||
|
||||
CallingFunction = ctx.Function;
|
||||
if (!val->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
if (!val->ValueType->isClassPointer())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Class type expected");
|
||||
delete this;
|
||||
|
@ -6126,7 +6126,7 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *
|
|||
{
|
||||
PSymbol *sym;
|
||||
PSymbolTable *symtbl;
|
||||
bool isclass = objtype->IsKindOf(RUNTIME_CLASS(PClassType));
|
||||
bool isclass = objtype->isClass();
|
||||
|
||||
if (Identifier == NAME_Default)
|
||||
{
|
||||
|
@ -6180,8 +6180,8 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType *
|
|||
object = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
auto cls_ctx = dyn_cast<PClassType>(classctx);
|
||||
auto cls_target = dyn_cast<PClassType>(objtype);
|
||||
auto cls_ctx = PType::toClass(classctx);
|
||||
auto cls_target = PType::toClass(objtype);
|
||||
// [ZZ] neither PSymbol, PField or PSymbolTable have the necessary information. so we need to do the more complex check here.
|
||||
if (vsym->Flags & VARF_Protected)
|
||||
{
|
||||
|
@ -6403,7 +6403,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
else if (Object->ValueType->isStruct())
|
||||
{
|
||||
auto ret = ResolveMember(ctx, ctx.Class, Object, static_cast<PStruct *>(Object->ValueType));
|
||||
delete this;
|
||||
|
@ -6972,7 +6972,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
|
||||
if (membervar->SymbolName == NAME_Default)
|
||||
{
|
||||
if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer))
|
||||
if (!classx->ValueType->isObjectPointer()
|
||||
|| !static_cast<PObjectPointer *>(classx->ValueType)->PointedClass()->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type");
|
||||
|
@ -7028,7 +7028,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
else if (classx->ValueType->isStruct())
|
||||
{
|
||||
// if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
|
||||
if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember || classx->ExprType == EFX_GlobalVariable || classx->ExprType == EFX_StackVariable)
|
||||
|
@ -7237,12 +7237,11 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
arraytype = dyn_cast<PArray>(Array->ValueType);
|
||||
if (arraytype == nullptr)
|
||||
if (!Array->ValueType->isArray())
|
||||
{
|
||||
// Check if we got a pointer to an array. Some native data structures (like the line list in sectors) use this.
|
||||
PPointer *ptype = 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.");
|
||||
delete this;
|
||||
|
@ -7251,10 +7250,14 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
|||
arraytype = static_cast<PArray*>(ptype->PointedType);
|
||||
arrayispointer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
arraytype = static_cast<PArray*>(Array->ValueType);
|
||||
}
|
||||
elementtype = arraytype->ElementType;
|
||||
}
|
||||
|
||||
if (Array->IsResizableArray())
|
||||
if (Array->isStaticArray())
|
||||
{
|
||||
// if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
|
||||
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable)
|
||||
|
@ -7498,8 +7501,8 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction
|
|||
bool match = (callingself == calledself);
|
||||
if (!match)
|
||||
{
|
||||
auto callingselfcls = dyn_cast<PClassType>(caller->Variants[0].SelfClass);
|
||||
auto calledselfcls = dyn_cast<PClassType>(callee->Variants[0].SelfClass);
|
||||
auto callingselfcls = PType::toClass(caller->Variants[0].SelfClass);
|
||||
auto calledselfcls = PType::toClass(callee->Variants[0].SelfClass);
|
||||
match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->Descriptor->IsDescendantOf(calledselfcls->Descriptor);
|
||||
}
|
||||
|
||||
|
@ -7860,7 +7863,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition))
|
||||
{
|
||||
// [ZZ] allow implicit new() call to mean "create current class instance"
|
||||
if (!ArgList.Size() && !ctx.Class->IsKindOf(RUNTIME_CLASS(PClassType)))
|
||||
if (!ArgList.Size() && !ctx.Class->isClass())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot use implicit new() in a struct");
|
||||
delete this;
|
||||
|
@ -7969,7 +7972,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
cls = ccls;
|
||||
staticonly = true;
|
||||
if (ccls->IsKindOf(RUNTIME_CLASS(PClassType)))
|
||||
if (ccls->isClass())
|
||||
{
|
||||
if (ctx.Function == nullptr)
|
||||
{
|
||||
|
@ -7977,7 +7980,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass);
|
||||
auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass);
|
||||
if (clstype != nullptr)
|
||||
{
|
||||
novirtual = clstype->Descriptor->IsDescendantOf(static_cast<PClassType*>(ccls)->Descriptor);
|
||||
|
@ -8009,7 +8012,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
auto clstype = dyn_cast<PClassType>(ctx.Function->Variants[0].SelfClass);
|
||||
auto clstype = PType::toClass(ctx.Function->Variants[0].SelfClass);
|
||||
if (clstype != nullptr)
|
||||
{
|
||||
// give the node the proper value type now that we know it's properly used.
|
||||
|
@ -8175,7 +8178,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (!Self->IsResizableArray())
|
||||
if (!Self->isStaticArray())
|
||||
{
|
||||
auto atype = Self->ValueType;
|
||||
if (Self->ValueType->isPointer()) atype = ValueType->toPointer()->PointedType;
|
||||
|
@ -8210,7 +8213,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
|
||||
|
||||
if (MethodName == NAME_GetParentClass &&
|
||||
(Self->IsObject() || Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))))
|
||||
(Self->IsObject() || Self->ValueType->isClassPointer()))
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
|
@ -8228,7 +8231,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
cls = ptype->toContainer();
|
||||
if (cls != nullptr)
|
||||
{
|
||||
if (ptype->IsKindOf(RUNTIME_CLASS(PClassType)) && MethodName == NAME_GetClass)
|
||||
if (ptype->isClass() && MethodName == NAME_GetClass)
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
|
@ -8247,7 +8250,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
else if (Self->ValueType->isStruct())
|
||||
{
|
||||
bool writable;
|
||||
|
||||
|
@ -8328,8 +8331,8 @@ isresolved:
|
|||
{
|
||||
if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual))
|
||||
{
|
||||
auto clstype = dyn_cast<PClassType>(ctx.Class);
|
||||
auto ccls = dyn_cast<PClassType>(cls);
|
||||
auto clstype = PType::toClass(ctx.Class);
|
||||
auto ccls = PType::toClass(cls);
|
||||
if (clstype == nullptr || ccls == nullptr || !clstype->Descriptor->IsDescendantOf(ccls->Descriptor))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here", cls->TypeName.GetChars(), MethodName.GetChars());
|
||||
|
@ -8820,7 +8823,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
ArgList[i] = ArgList[i]->Resolve(ctx); // nust be resolved before the address is requested.
|
||||
if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr)
|
||||
{
|
||||
if (type == ArgList[i]->ValueType && type->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.
|
||||
}
|
||||
|
@ -9331,7 +9334,7 @@ FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
SAFE_RESOLVE(Self, ctx);
|
||||
|
||||
if (!Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && !Self->IsObject())
|
||||
if (!Self->ValueType->isClassPointer() && !Self->IsObject())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object");
|
||||
delete this;
|
||||
|
@ -9402,7 +9405,7 @@ FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
auto cp = dyn_cast<PClassPointer>(Self->ValueType);
|
||||
auto cp = PType::toClassPointer(Self->ValueType);
|
||||
if (cp == nullptr || !cp->ClassRestriction->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type");
|
||||
|
@ -10601,7 +10604,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
|||
return x;
|
||||
}
|
||||
auto to = static_cast<PClassPointer *>(ValueType);
|
||||
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||
if (basex->ValueType->isClassPointer())
|
||||
{
|
||||
auto from = static_cast<PClassPointer *>(basex->ValueType);
|
||||
if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction))
|
||||
|
@ -10769,7 +10772,7 @@ FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
|
|||
return x;
|
||||
}
|
||||
auto to = static_cast<PClassPointer *>(ValueType);
|
||||
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||
if (basex->ValueType->isClassPointer())
|
||||
{
|
||||
auto from = static_cast<PClassPointer *>(basex->ValueType);
|
||||
// Downcast is always ok.
|
||||
|
@ -10846,7 +10849,7 @@ FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
ABORT(ctx.Class);
|
||||
auto vclass = dyn_cast<PClassType>(ctx.Class);
|
||||
auto vclass = PType::toClass(ctx.Class);
|
||||
assert(vclass != nullptr);
|
||||
auto aclass = ValidateActor(vclass->Descriptor);
|
||||
|
||||
|
@ -10925,7 +10928,7 @@ FxExpression *FxRuntimeStateIndex::Resolve(FCompileContext &ctx)
|
|||
SAFE_RESOLVE(Index, ctx);
|
||||
}
|
||||
|
||||
auto vclass = dyn_cast<PClassType>(ctx.Class);
|
||||
auto vclass = PType::toClass(ctx.Class);
|
||||
assert(vclass != nullptr);
|
||||
auto aclass = ValidateActor(vclass->Descriptor);
|
||||
assert(aclass != nullptr && aclass->GetStateCount() > 0);
|
||||
|
@ -10985,7 +10988,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
|||
ABORT(ctx.Class);
|
||||
int symlabel;
|
||||
|
||||
auto vclass = dyn_cast<PClassType>(ctx.Class);
|
||||
auto vclass = PType::toClass(ctx.Class);
|
||||
assert(vclass != nullptr);
|
||||
auto clstype = ValidateActor(vclass->Descriptor);
|
||||
|
||||
|
@ -11201,7 +11204,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
|
|||
else
|
||||
{
|
||||
// Init arrays and structs.
|
||||
if (ValueType->IsA(RUNTIME_CLASS(PStruct)))
|
||||
if (ValueType->isStruct())
|
||||
{
|
||||
auto pstr = static_cast<PStruct*>(ValueType);
|
||||
if (pstr->mConstructor != nullptr)
|
||||
|
@ -11227,7 +11230,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (ValueType->IsA(RUNTIME_CLASS(PStruct)))
|
||||
if (ValueType->isStruct())
|
||||
{
|
||||
auto pstr = static_cast<PStruct*>(ValueType);
|
||||
if (pstr->mDestructor != nullptr)
|
||||
|
|
|
@ -335,11 +335,11 @@ public:
|
|||
bool IsPointer() const { return ValueType->isPointer(); }
|
||||
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
|
||||
bool IsBoolCompat() const { return ValueType->isScalar(); }
|
||||
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)); }
|
||||
bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->isPointer() && ValueType->toPointer()->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); }
|
||||
bool IsResizableArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->IsKindOf(RUNTIME_CLASS(PStaticArray))); } // can only exist in pointer form.
|
||||
bool IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); }
|
||||
bool IsNativeStruct() const { return (ValueType->IsA(RUNTIME_CLASS(PStruct)) && static_cast<PStruct*>(ValueType)->isNative); }
|
||||
bool IsObject() const { return ValueType->isObjectPointer(); }
|
||||
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
|
||||
bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form.
|
||||
bool IsDynamicArray() const { return (ValueType->isDynArray()); }
|
||||
bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }
|
||||
|
||||
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||
void EmitStatement(VMFunctionBuilder *build);
|
||||
|
|
|
@ -203,7 +203,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type)
|
|||
x = new FxRuntimeStateIndex(ParseExpression(sc, cls));
|
||||
}
|
||||
}
|
||||
else if (type->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||
else if (type->isClassPointer())
|
||||
{ // Actor name
|
||||
sc.SetEscape(true);
|
||||
sc.MustGetString();
|
||||
|
@ -881,7 +881,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
|
|||
sc.MustGetString();
|
||||
*(FString*)addr = strbin1(sc.String);
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
else if (f->Type->isClassPointer())
|
||||
{
|
||||
sc.MustGetString();
|
||||
|
||||
|
@ -892,13 +892,14 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
|
|||
else
|
||||
{
|
||||
auto cls = PClass::FindClass(sc.String);
|
||||
auto cp = static_cast<PClassPointer*>(f->Type);
|
||||
if (cls == nullptr)
|
||||
{
|
||||
cls = static_cast<PClassPointer*>(f->Type)->ClassRestriction->FindClassTentative(sc.String);
|
||||
cls = cp->ClassRestriction->FindClassTentative(sc.String);
|
||||
}
|
||||
else if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
|
||||
else if (!cls->IsDescendantOf(cp->ClassRestriction))
|
||||
{
|
||||
sc.ScriptMessage("class %s is not compatible with property type %s", sc.String, static_cast<PClassPointer*>(f->Type)->ClassRestriction->TypeName.GetChars());
|
||||
sc.ScriptMessage("class %s is not compatible with property type %s", sc.String, cp->ClassRestriction->TypeName.GetChars());
|
||||
FScriptPosition::ErrorCounter++;
|
||||
}
|
||||
*(PClass**)addr = cls;
|
||||
|
|
|
@ -195,8 +195,8 @@ PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *func
|
|||
|
||||
if (symbol != nullptr)
|
||||
{
|
||||
auto cls_ctx = dyn_cast<PClassType>(funccls);
|
||||
auto cls_target = funcsym ? dyn_cast<PClassType>(funcsym->OwningClass) : nullptr;
|
||||
auto cls_ctx = PType::toClass(funccls);
|
||||
auto cls_target = funcsym ? PType::toClass(funcsym->OwningClass) : nullptr;
|
||||
if (funcsym == nullptr)
|
||||
{
|
||||
sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars());
|
||||
|
|
|
@ -446,8 +446,8 @@ int MatchString (const char *in, const char **strings)
|
|||
|
||||
static bool PointerCheck(PType *symtype, PType *checktype)
|
||||
{
|
||||
auto symptype = dyn_cast<PClassPointer>(symtype);
|
||||
auto checkptype = dyn_cast<PClassPointer>(checktype);
|
||||
auto symptype = PType::toClassPointer(symtype);
|
||||
auto checkptype = PType::toClassPointer(checktype);
|
||||
return symptype != nullptr && checkptype != nullptr && symptype->ClassRestriction->IsDescendantOf(checkptype->ClassRestriction);
|
||||
}
|
||||
|
||||
|
|
|
@ -1407,6 +1407,7 @@ PObjectPointer::PObjectPointer(PClass *cls, bool isconst)
|
|||
: PPointer(cls->VMType, isconst)
|
||||
{
|
||||
loadOp = OP_LO;
|
||||
Flags |= TYPE_ObjectPointer;
|
||||
// Non-destroyed thinkers are always guaranteed to be linked into the thinker chain so we don't need the write barrier for them.
|
||||
if (cls && !cls->IsDescendantOf(RUNTIME_CLASS(DThinker))) storeOp = OP_SO;
|
||||
}
|
||||
|
@ -1545,6 +1546,7 @@ PClassPointer::PClassPointer(PClass *restrict)
|
|||
else mDescriptiveName = "ClassPointer";
|
||||
loadOp = OP_LP;
|
||||
storeOp = OP_SP;
|
||||
Flags |= TYPE_ClassPointer;
|
||||
mVersion = restrict->VMType->mVersion;
|
||||
}
|
||||
|
||||
|
@ -1664,6 +1666,7 @@ PEnum::PEnum(FName name, PTypeBase *outer)
|
|||
{
|
||||
EnumName = name;
|
||||
Outer = outer;
|
||||
Flags |= TYPE_IntNotInt;
|
||||
mDescriptiveName.Format("Enum<%s>", name.GetChars());
|
||||
}
|
||||
|
||||
|
@ -1721,6 +1724,7 @@ PArray::PArray(PType *etype, unsigned int ecount)
|
|||
// also be padded to the nearest alignment.
|
||||
ElementSize = (etype->Size + (etype->Align - 1)) & ~(etype->Align - 1);
|
||||
Size = ElementSize * ecount;
|
||||
Flags |= TYPE_Array;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "serializer.h"
|
||||
|
||||
// Variable/parameter/field flags -------------------------------------------
|
||||
class PStruct;
|
||||
|
||||
// Making all these different storage types use a common set of flags seems
|
||||
// like the simplest thing to do.
|
||||
|
@ -61,20 +60,12 @@ enum
|
|||
// Map * *
|
||||
// Prototype *+ *+
|
||||
|
||||
enum ETypeFlags
|
||||
{
|
||||
TYPE_Scalar = 1,
|
||||
TYPE_Container = 2,
|
||||
TYPE_Int = 4,
|
||||
TYPE_IntNotInt = 8, // catch-all for subtypes that are not being checked by type directly.
|
||||
TYPE_Float = 16,
|
||||
TYPE_Pointer = 32,
|
||||
|
||||
TYPE_IntCompatible = TYPE_Int | TYPE_IntNotInt, // must be the combination of all flags that are subtypes of int and can be cast to an int.
|
||||
};
|
||||
|
||||
class PContainerType;
|
||||
class PPointer;
|
||||
class PClassPointer;
|
||||
class PArray;
|
||||
class PStruct;
|
||||
class PClassType;
|
||||
|
||||
struct ZCC_ExprConstant;
|
||||
class PType : public PTypeBase
|
||||
|
@ -82,6 +73,21 @@ class PType : public PTypeBase
|
|||
DECLARE_ABSTRACT_CLASS(PType, PTypeBase)
|
||||
protected:
|
||||
|
||||
enum ETypeFlags
|
||||
{
|
||||
TYPE_Scalar = 1,
|
||||
TYPE_Container = 2,
|
||||
TYPE_Int = 4,
|
||||
TYPE_IntNotInt = 8, // catch-all for subtypes that are not being checked by type directly.
|
||||
TYPE_Float = 16,
|
||||
TYPE_Pointer = 32,
|
||||
TYPE_ObjectPointer = 64,
|
||||
TYPE_ClassPointer = 128,
|
||||
TYPE_Array = 256,
|
||||
|
||||
TYPE_IntCompatible = TYPE_Int | TYPE_IntNotInt, // must be the combination of all flags that are subtypes of int and can be cast to an int.
|
||||
};
|
||||
|
||||
public:
|
||||
PClass *TypeTableType; // The type to use for hashing into the type table
|
||||
unsigned int Size; // this type's size
|
||||
|
@ -183,10 +189,21 @@ public:
|
|||
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
|
||||
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; }
|
||||
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 --------------------------------------------------
|
||||
|
@ -493,7 +510,7 @@ public:
|
|||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
|
||||
|
||||
protected:
|
||||
PArray();
|
||||
PArray();//deleteme
|
||||
};
|
||||
|
||||
class PStaticArray : public PArray
|
||||
|
@ -506,7 +523,7 @@ public:
|
|||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
|
||||
protected:
|
||||
PStaticArray();
|
||||
PStaticArray();// deleteme
|
||||
};
|
||||
|
||||
class PDynArray : public PCompoundType
|
||||
|
@ -529,7 +546,7 @@ public:
|
|||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) const override;
|
||||
|
||||
protected:
|
||||
PDynArray();
|
||||
PDynArray(); // deleteme
|
||||
};
|
||||
|
||||
class PMap : public PCompoundType
|
||||
|
@ -544,7 +561,7 @@ public:
|
|||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
protected:
|
||||
PMap();
|
||||
PMap(); // deleteme
|
||||
};
|
||||
|
||||
class PStruct : public PContainerType
|
||||
|
@ -568,7 +585,7 @@ public:
|
|||
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
|
||||
|
||||
protected:
|
||||
PStruct();
|
||||
PStruct(); // deleteme
|
||||
};
|
||||
|
||||
class PPrototype : public PCompoundType
|
||||
|
@ -584,7 +601,7 @@ public:
|
|||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||
protected:
|
||||
PPrototype();
|
||||
PPrototype(); // deleteme
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
else if (thisfieldtype->Size != ~0u && fd->FieldSize != ~0u && thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0 &&
|
||||
(!thisfieldtype->IsA(RUNTIME_CLASS(PStruct)) || !static_cast<PStruct*>(thisfieldtype)->isNative))
|
||||
(!thisfieldtype->isStruct() || !static_cast<PStruct*>(thisfieldtype)->isNative))
|
||||
{
|
||||
Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type == nullptr ? "" : type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size);
|
||||
}
|
||||
|
@ -1652,7 +1652,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
return TypeError;
|
||||
}
|
||||
auto typesym = dyn_cast<PSymbolType>(sym);
|
||||
if (typesym == nullptr || !typesym->Type->IsKindOf(RUNTIME_CLASS(PClassType)))
|
||||
if (typesym == nullptr || !typesym->Type->isClass())
|
||||
{
|
||||
Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars());
|
||||
return TypeError;
|
||||
|
@ -1703,15 +1703,15 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, boo
|
|||
return TypeError;
|
||||
}
|
||||
|
||||
if (ptype->IsKindOf(RUNTIME_CLASS(PEnum)))
|
||||
if (ptype->isEnum())
|
||||
{
|
||||
if (!nativetype) return TypeSInt32; // hack this to an integer until we can resolve the enum mess.
|
||||
}
|
||||
else if (ptype->IsKindOf(RUNTIME_CLASS(PClassType))) // classes cannot be instantiated at all, they always get used as references.
|
||||
else if (ptype->isClass()) // classes cannot be instantiated at all, they always get used as references.
|
||||
{
|
||||
return NewPointer(ptype, type->isconst);
|
||||
}
|
||||
else if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)) && static_cast<PStruct*>(ptype)->isNative) // native structs and classes cannot be instantiated, they always get used as reference.
|
||||
else if (ptype->isStruct() && static_cast<PStruct*>(ptype)->isNative) // native structs and classes cannot be instantiated, they always get used as reference.
|
||||
{
|
||||
if (!nativetype) return NewPointer(ptype, type->isconst);
|
||||
return ptype; // instantiation of native structs. Only for internal use.
|
||||
|
@ -2035,7 +2035,7 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
|
|||
{
|
||||
*(FString*)addr = GetStringConst(ex, ctx);
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
else if (f->Type->isClassPointer())
|
||||
{
|
||||
auto clsname = GetStringConst(ex, ctx);
|
||||
if (*clsname == 0 || !stricmp(clsname, "none"))
|
||||
|
@ -2045,13 +2045,14 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
|
|||
else
|
||||
{
|
||||
auto cls = PClass::FindClass(clsname);
|
||||
auto cp = static_cast<PClassPointer*>(f->Type);
|
||||
if (cls == nullptr)
|
||||
{
|
||||
cls = static_cast<PClassPointer*>(f->Type)->ClassRestriction->FindClassTentative(clsname);
|
||||
cls = cp->ClassRestriction->FindClassTentative(clsname);
|
||||
}
|
||||
else if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
|
||||
else if (!cls->IsDescendantOf(cp->ClassRestriction))
|
||||
{
|
||||
Error(property, "class %s is not compatible with property type %s", clsname, static_cast<PClassPointer*>(f->Type)->ClassRestriction->TypeName.GetChars());
|
||||
Error(property, "class %s is not compatible with property type %s", clsname, cp->ClassRestriction->TypeName.GetChars());
|
||||
}
|
||||
*(PClass**)addr = cls;
|
||||
}
|
||||
|
@ -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);
|
||||
int flags = 0;
|
||||
if ((type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) || type->IsA(RUNTIME_CLASS(PDynArray)))
|
||||
if ((type->isStruct() && type != TypeVector2 && type != TypeVector3) || type->isDynArray())
|
||||
{
|
||||
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
||||
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
||||
|
@ -2565,7 +2566,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
|||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
if (type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
if (type->isClassPointer())
|
||||
vmval[0] = (DObject*)cnst->GetValue().GetPointer();
|
||||
else
|
||||
vmval[0] = cnst->GetValue().GetPointer();
|
||||
|
@ -2609,7 +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);
|
||||
c->Type()->Symbols.ReplaceSymbol(sym);
|
||||
|
||||
auto vcls = dyn_cast<PClassType>(c->Type());
|
||||
auto vcls = PType::toClass(c->Type());
|
||||
auto cls = vcls ? vcls->Descriptor : nullptr;
|
||||
PFunction *virtsym = nullptr;
|
||||
if (cls != nullptr && cls->ParentClass != nullptr) virtsym = dyn_cast<PFunction>(cls->ParentClass->VMType->Symbols.FindSymbol(FName(f->Name), true));
|
||||
|
@ -2656,7 +2657,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
|||
sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags;
|
||||
}
|
||||
|
||||
PClass *clstype = static_cast<PClassType *>(c->Type())->Descriptor;
|
||||
PClass *clstype = forclass? static_cast<PClassType *>(c->Type())->Descriptor : nullptr;
|
||||
if (varflags & VARF_Virtual)
|
||||
{
|
||||
if (sym->Variants[0].Implementation == nullptr)
|
||||
|
@ -2817,7 +2818,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af, in
|
|||
{
|
||||
FArgumentList argumentlist;
|
||||
// We can use this function directly without wrapping it in a caller.
|
||||
assert(dyn_cast<PClassType>(afd->Variants[0].SelfClass) != nullptr); // non classes are not supposed to get here.
|
||||
assert(PType::toClass(afd->Variants[0].SelfClass) != nullptr); // non classes are not supposed to get here.
|
||||
|
||||
int comboflags = afd->Variants[0].UseFlags & StateFlags;
|
||||
if (comboflags == StateFlags) // the function must satisfy all the flags the state requires
|
||||
|
|
Loading…
Reference in a new issue