- 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; 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";
} }
//========================================================================== //==========================================================================

View file

@ -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 ---------------------------------------------------------

View file

@ -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,9 +1777,64 @@ 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"); if (Right->ValueType != ValueType)
{
if (ValueType == TypeBool)
{
Right = new FxBoolCast(Right);
}
else if (ValueType->GetRegType() == REGT_INT)
{
Right = new FxIntCast(Right, ctx.FromDecorate);
}
else
{
Right = new FxFloatCast(Right);
}
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; delete this;
return nullptr; return nullptr;
} }
@ -1785,22 +1845,6 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
return nullptr; return nullptr;
} }
if (Right->ValueType != ValueType)
{
if (ValueType == TypeBool)
{
Right = new FxBoolCast(Right);
}
else if (ValueType->GetRegType() == REGT_INT)
{
Right = new FxIntCast(Right, ctx.FromDecorate);
}
else
{
Right = new FxFloatCast(Right);
}
SAFE_RESOLVE(Right, ctx);
}
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);

View file

@ -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