- preparations for null pointer support.

- add pointer support to FxAssign.
This commit is contained in:
Christoph Oelckers 2016-10-21 19:18:39 +02:00
parent 5bed0a2b39
commit 89416835a8
4 changed files with 90 additions and 22 deletions

View file

@ -84,6 +84,7 @@ PColor *TypeColor;
PStatePointer *TypeState;
PStruct *TypeVector2;
PStruct *TypeVector3;
PPointer *TypeNullPtr;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -616,6 +617,7 @@ void PType::StaticInit()
TypeTable.AddType(TypeSound = new PSound);
TypeTable.AddType(TypeColor = new PColor);
TypeTable.AddType(TypeState = new PStatePointer);
TypeTable.AddType(TypeNullPtr = new PPointer);
TypeVector2 = new PStruct(NAME_Vector2, nullptr);
TypeVector2->AddField(NAME_X, TypeFloat64);
@ -1635,7 +1637,7 @@ END_POINTERS
PPointer::PPointer()
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL)
{
mDescriptiveName = "Pointer";
mDescriptiveName = "NullPointer";
}
//==========================================================================

View file

@ -530,6 +530,7 @@ class PPointer : public PBasicType
DECLARE_CLASS(PPointer, PBasicType);
HAS_OBJECT_POINTERS;
public:
PPointer();
PPointer(PType *pointsat);
PType *PointedType;
@ -546,7 +547,6 @@ public:
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
protected:
PPointer();
};
class PClassPointer : public PPointer
@ -890,6 +890,7 @@ extern PColor *TypeColor;
extern PStruct *TypeVector2;
extern PStruct *TypeVector3;
extern PStatePointer *TypeState;
extern PPointer *TypeNullPtr;
// A constant value ---------------------------------------------------------

View file

@ -1078,6 +1078,10 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
// don't go through the entire list if the types are the same.
goto basereturn;
}
else if (basex->ValueType == TypeNullPtr && (ValueType == TypeState || ValueType->IsKindOf(RUNTIME_CLASS(PPointer))))
{
goto basereturn;
}
else if (ValueType->GetRegType() == REGT_FLOAT)
{
FxExpression *x = new FxFloatCast(basex);
@ -1199,6 +1203,7 @@ basereturn:
auto x = basex;
basex = nullptr;
delete this;
x->ValueType = ValueType;
return x;
}
@ -1772,19 +1777,8 @@ FxExpression *FxAssign::Resolve(FCompileContext &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 (ValueType == TypeBool)
@ -1801,6 +1795,56 @@ FxExpression *FxAssign::Resolve(FCompileContext &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;
}
@ -1808,7 +1852,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
ExpEmit FxAssign::Emit(VMFunctionBuilder *build)
{
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());
ExpEmit pointer = Base->Emit(build);
@ -2272,8 +2316,14 @@ FxExpression *FxPow::Resolve(FCompileContext& ctx)
{
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())
{
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
@ -6015,6 +6065,14 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
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))
{
auto to = static_cast<PClassPointer *>(ValueType);

View file

@ -380,6 +380,13 @@ public:
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);
bool isConstant() const