mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 13:31:07 +00:00
- preparations for null pointer support.
- add pointer support to FxAssign.
This commit is contained in:
parent
5bed0a2b39
commit
89416835a8
4 changed files with 90 additions and 22 deletions
|
@ -84,6 +84,7 @@ PColor *TypeColor;
|
||||||
PStatePointer *TypeState;
|
PStatePointer *TypeState;
|
||||||
PStruct *TypeVector2;
|
PStruct *TypeVector2;
|
||||||
PStruct *TypeVector3;
|
PStruct *TypeVector3;
|
||||||
|
PPointer *TypeNullPtr;
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
|
@ -616,6 +617,7 @@ void PType::StaticInit()
|
||||||
TypeTable.AddType(TypeSound = new PSound);
|
TypeTable.AddType(TypeSound = new PSound);
|
||||||
TypeTable.AddType(TypeColor = new PColor);
|
TypeTable.AddType(TypeColor = new PColor);
|
||||||
TypeTable.AddType(TypeState = new PStatePointer);
|
TypeTable.AddType(TypeState = new PStatePointer);
|
||||||
|
TypeTable.AddType(TypeNullPtr = new PPointer);
|
||||||
|
|
||||||
TypeVector2 = new PStruct(NAME_Vector2, nullptr);
|
TypeVector2 = new PStruct(NAME_Vector2, nullptr);
|
||||||
TypeVector2->AddField(NAME_X, TypeFloat64);
|
TypeVector2->AddField(NAME_X, TypeFloat64);
|
||||||
|
@ -1635,7 +1637,7 @@ END_POINTERS
|
||||||
PPointer::PPointer()
|
PPointer::PPointer()
|
||||||
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL)
|
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL)
|
||||||
{
|
{
|
||||||
mDescriptiveName = "Pointer";
|
mDescriptiveName = "NullPointer";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -530,6 +530,7 @@ class PPointer : public PBasicType
|
||||||
DECLARE_CLASS(PPointer, PBasicType);
|
DECLARE_CLASS(PPointer, PBasicType);
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
|
PPointer();
|
||||||
PPointer(PType *pointsat);
|
PPointer(PType *pointsat);
|
||||||
|
|
||||||
PType *PointedType;
|
PType *PointedType;
|
||||||
|
@ -546,7 +547,6 @@ public:
|
||||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PPointer();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PClassPointer : public PPointer
|
class PClassPointer : public PPointer
|
||||||
|
@ -890,6 +890,7 @@ extern PColor *TypeColor;
|
||||||
extern PStruct *TypeVector2;
|
extern PStruct *TypeVector2;
|
||||||
extern PStruct *TypeVector3;
|
extern PStruct *TypeVector3;
|
||||||
extern PStatePointer *TypeState;
|
extern PStatePointer *TypeState;
|
||||||
|
extern PPointer *TypeNullPtr;
|
||||||
|
|
||||||
// A constant value ---------------------------------------------------------
|
// A constant value ---------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1078,6 +1078,10 @@ 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))))
|
||||||
|
{
|
||||||
|
goto basereturn;
|
||||||
|
}
|
||||||
else if (ValueType->GetRegType() == REGT_FLOAT)
|
else if (ValueType->GetRegType() == REGT_FLOAT)
|
||||||
{
|
{
|
||||||
FxExpression *x = new FxFloatCast(basex);
|
FxExpression *x = new FxFloatCast(basex);
|
||||||
|
@ -1199,6 +1203,7 @@ basereturn:
|
||||||
auto x = basex;
|
auto x = basex;
|
||||||
basex = nullptr;
|
basex = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
|
x->ValueType = ValueType;
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1772,19 +1777,8 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
SAFE_RESOLVE(Right, ctx);
|
SAFE_RESOLVE(Right, ctx);
|
||||||
|
|
||||||
if (!Base->IsNumeric() || !Right->IsNumeric())
|
if (Base->IsNumeric() && Right->IsNumeric())
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
|
||||||
delete this;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (!Base->RequestAddress(&AddressWritable) || !AddressWritable)
|
|
||||||
{
|
|
||||||
ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value");
|
|
||||||
delete this;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Right->ValueType != ValueType)
|
if (Right->ValueType != ValueType)
|
||||||
{
|
{
|
||||||
if (ValueType == TypeBool)
|
if (ValueType == TypeBool)
|
||||||
|
@ -1801,6 +1795,56 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
SAFE_RESOLVE(Right, ctx);
|
SAFE_RESOLVE(Right, ctx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (Base->ValueType == Right->ValueType)
|
||||||
|
{
|
||||||
|
if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PArray)))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Cannot assign arrays");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
// Both types are the same so this is ok.
|
||||||
|
}
|
||||||
|
else if ((Base->ValueType == TypeState || Base->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) && Right->ValueType == TypeNullPtr)
|
||||||
|
{
|
||||||
|
// null pointers can be assigned to any other pointer
|
||||||
|
}
|
||||||
|
else if (Base->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||||
|
{
|
||||||
|
// class pointers may be assignable so add a cast which performs a check.
|
||||||
|
Right = new FxClassTypeCast(static_cast<PClassPointer *>(ValueType), Right);
|
||||||
|
SAFE_RESOLVE(Right, ctx);
|
||||||
|
}
|
||||||
|
else if (Base->ValueType == TypeString && (Right->ValueType == TypeName || Right->ValueType == TypeSound))
|
||||||
|
{
|
||||||
|
Right = new FxStringCast(Right);
|
||||||
|
SAFE_RESOLVE(Right, ctx);
|
||||||
|
}
|
||||||
|
else if (Base->ValueType == TypeName && Right->ValueType == TypeString)
|
||||||
|
{
|
||||||
|
Right = new FxNameCast(Right);
|
||||||
|
SAFE_RESOLVE(Right, ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Assignment between incompatible types.");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!Base->RequestAddress(&AddressWritable) || !AddressWritable)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1808,7 +1852,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
||||||
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP };
|
static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP };
|
||||||
assert(ValueType == Base->ValueType && IsNumeric());
|
assert(ValueType == Base->ValueType);
|
||||||
assert(ValueType->GetRegType() == Right->ValueType->GetRegType());
|
assert(ValueType->GetRegType() == Right->ValueType->GetRegType());
|
||||||
|
|
||||||
ExpEmit pointer = Base->Emit(build);
|
ExpEmit pointer = Base->Emit(build);
|
||||||
|
@ -2272,8 +2316,14 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
|
|
||||||
if (!ResolveLR(ctx, true)) return NULL;
|
if (!ResolveLR(ctx, true)) return nullptr;
|
||||||
|
|
||||||
|
if (!IsNumeric())
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
if (left->isConstant() && right->isConstant())
|
if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
||||||
|
@ -6015,6 +6065,14 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
SAFE_RESOLVE(basex, ctx);
|
SAFE_RESOLVE(basex, ctx);
|
||||||
|
|
||||||
|
if (basex->ValueType == TypeNullPtr)
|
||||||
|
{
|
||||||
|
basex->ValueType = ValueType;
|
||||||
|
auto x = basex;
|
||||||
|
basex = nullptr;
|
||||||
|
delete this;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
|
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||||
{
|
{
|
||||||
auto to = static_cast<PClassPointer *>(ValueType);
|
auto to = static_cast<PClassPointer *>(ValueType);
|
||||||
|
|
|
@ -380,6 +380,13 @@ public:
|
||||||
isresolved = true;
|
isresolved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FxConstant(nullptr_t *nullp, const FScriptPosition &pos) : FxExpression(pos)
|
||||||
|
{
|
||||||
|
value.pointer = nullptr;
|
||||||
|
ValueType = value.Type = TypeNullPtr;
|
||||||
|
isresolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos);
|
static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos);
|
||||||
|
|
||||||
bool isConstant() const
|
bool isConstant() const
|
||||||
|
|
Loading…
Reference in a new issue