- added null pointer.

- fixed: FxMemberIdentifier checked for ClassPointers instead of object pointers to resolve the left hand side of the expression.
- allow comparison of pointers.
This commit is contained in:
Christoph Oelckers 2016-10-22 00:50:04 +02:00
parent 3b0b0baf05
commit 4b41e735f1
7 changed files with 104 additions and 61 deletions

View file

@ -1671,7 +1671,7 @@ int PPointer::GetStoreOp() const
int PPointer::GetLoadOp() const int PPointer::GetLoadOp() const
{ {
return PointedType->IsKindOf(RUNTIME_CLASS(PClass)) ? OP_LO : OP_LP; return (PointedType && PointedType->IsKindOf(RUNTIME_CLASS(PClass))) ? OP_LO : OP_LP;
} }
//========================================================================== //==========================================================================

View file

@ -229,6 +229,31 @@ static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::Na
// //
//========================================================================== //==========================================================================
static bool AreCompatiblePointerTypes(PType *dest, PType *source)
{
if (dest->IsKindOf(RUNTIME_CLASS(PPointer)) && source->IsKindOf(RUNTIME_CLASS(PPointer)))
{
// Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type.
auto fromtype = static_cast<PPointer *>(source);
auto totype = static_cast<PPointer *>(dest);
if (fromtype == nullptr) return true;
if (fromtype == totype) return true;
if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{
auto fromcls = static_cast<PClass *>(fromtype->PointedType);
auto tocls = static_cast<PClass *>(totype->PointedType);
return (fromcls->IsDescendantOf(tocls));
}
}
return false;
}
//==========================================================================
//
//
//
//==========================================================================
ExpEmit FxExpression::Emit (VMFunctionBuilder *build) ExpEmit FxExpression::Emit (VMFunctionBuilder *build)
{ {
ScriptPosition.Message(MSG_ERROR, "Unemitted expression found"); ScriptPosition.Message(MSG_ERROR, "Unemitted expression found");
@ -1174,21 +1199,9 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
if (fromtype->IsDescendantOf(totype)) goto basereturn; if (fromtype->IsDescendantOf(totype)) goto basereturn;
} }
} }
else if (ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) else if (AreCompatiblePointerTypes(ValueType, basex->ValueType))
{ {
// Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. goto basereturn;
if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{
auto fromtype = static_cast<PPointer *>(basex->ValueType);
auto totype = static_cast<PPointer *>(ValueType);
if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{
auto fromcls = static_cast<PClass *>(fromtype->PointedType);
auto tocls = static_cast<PClass *>(totype->PointedType);
if (fromcls->IsDescendantOf(tocls)) goto basereturn;
}
}
} }
// todo: pointers to class objects. // todo: pointers to class objects.
// All other types are only compatible to themselves and have already been handled above by the equality check. // All other types are only compatible to themselves and have already been handled above by the equality check.
@ -1201,9 +1214,9 @@ errormsg:
basereturn: basereturn:
auto x = basex; auto x = basex;
x->ValueType = ValueType;
basex = nullptr; basex = nullptr;
delete this; delete this;
x->ValueType = ValueType;
return x; return x;
} }
@ -1996,14 +2009,21 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
ValueType = TypeFloat64; ValueType = TypeFloat64;
} }
} }
else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType) else if (left->ValueType->GetRegType() == REGT_POINTER)
{ {
ValueType = left->ValueType; if (left->ValueType == right->ValueType || right->ValueType == TypeNullPtr || left->ValueType == TypeNullPtr ||
AreCompatiblePointerTypes(left->ValueType, right->ValueType))
{
// pointers can only be compared for equality.
assert(Operator == TK_Eq || Operator == TK_Neq);
ValueType = TypeBool;
}
} }
else else
{ {
ValueType = TypeVoid; ValueType = TypeVoid;
} }
assert(ValueType > nullptr && ValueType < (PType*)0xfffffffffffffff);
if (castnumeric) if (castnumeric)
{ {
@ -4191,10 +4211,14 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
SAFE_RESOLVE(Object, ctx); SAFE_RESOLVE(Object, ctx);
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{ {
PSymbolTable *symtbl; PSymbolTable *symtbl;
PClass *cls = static_cast<PClassPointer *>(Object->ValueType)->ClassRestriction; auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType;
if (ptype->IsKindOf(RUNTIME_CLASS(PClass)))
{
PClass *cls = static_cast<PClass *>(ptype);
if ((sym = cls->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr) if ((sym = cls->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr)
{ {
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst))) if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
@ -4247,11 +4271,12 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
return nullptr; return nullptr;
} }
} }
else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct))) else if (ptype->IsA(RUNTIME_CLASS(PStruct)))
{ {
// todo // todo
} }
else if (Object->ValueType->IsA(RUNTIME_CLASS(PPointer))) }
else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct)))
{ {
// todo // todo
} }

View file

@ -380,7 +380,7 @@ public:
isresolved = true; isresolved = true;
} }
FxConstant(nullptr_t *nullp, const FScriptPosition &pos) : FxExpression(pos) FxConstant(const FScriptPosition &pos) : FxExpression(pos)
{ {
value.pointer = nullptr; value.pointer = nullptr;
ValueType = value.Type = TypeNullPtr; ValueType = value.Type = TypeNullPtr;

View file

@ -636,7 +636,7 @@ void InitThingdef()
// Define some member variables we feel like exposing to the user // Define some member variables we feel like exposing to the user
PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols;
PType *array5 = NewArray(TypeSInt32, 5); PType *array5 = NewArray(TypeSInt32, 5);
PType *TypeActor = NewClassPointer(RUNTIME_CLASS(AActor)); PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor));
symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha))); symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha)));
symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw))); symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw)));
symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args))); symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args)));

View file

@ -1450,6 +1450,14 @@ constant(X) ::= TRUE(A).
NEW_INTCONST_NODE(boolconst, TypeBool, true, A); NEW_INTCONST_NODE(boolconst, TypeBool, true, A);
X = boolconst; X = boolconst;
} }
constant(X) ::= NULLPTR(A).
{
NEW_AST_NODE(ExprConstant, nullptrconst, A);
nullptrconst->Operation = PEX_ConstValue;
nullptrconst->Type = TypeNullPtr;
nullptrconst->StringVal = nullptr;
X = nullptrconst;
}
/************ Statements ************/ /************ Statements ************/

View file

@ -1462,6 +1462,10 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt)
{ {
return TypeSInt32; // hack this to an integer until we can resolve the enum mess. return TypeSInt32; // hack this to an integer until we can resolve the enum mess.
} }
if (type->IsKindOf(RUNTIME_CLASS(PClass)))
{
return NewPointer(type);
}
return type; return type;
} }
return TypeError; return TypeError;
@ -2353,6 +2357,8 @@ static FxExpression *ModifyAssign(FxBinary *operation, FxExpression *left)
FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
{ {
if (ast == nullptr) return nullptr;
// Note: Do not call 'Simplify' here because that function tends to destroy identifiers due to lack of context in which to resolve them. // Note: Do not call 'Simplify' here because that function tends to destroy identifiers due to lack of context in which to resolve them.
// The Fx nodes created here will be better suited for that. // The Fx nodes created here will be better suited for that.
switch (ast->NodeType) switch (ast->NodeType)
@ -2436,6 +2442,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
{ {
return new FxConstant(*cnst->StringVal, *ast); return new FxConstant(*cnst->StringVal, *ast);
} }
else if (cnst->Type == TypeNullPtr)
{
return new FxConstant(*ast);
}
else else
{ {
// can there be other types? // can there be other types?

View file

@ -154,7 +154,7 @@ static void InitTokenMap()
TOKENDEF (TK_Out, ZCC_OUT); TOKENDEF (TK_Out, ZCC_OUT);
TOKENDEF (TK_Optional, ZCC_OPTIONAL); TOKENDEF (TK_Optional, ZCC_OPTIONAL);
TOKENDEF (TK_Super, ZCC_SUPER); TOKENDEF (TK_Super, ZCC_SUPER);
TOKENDEF (TK_Null, ZCC_NULL); TOKENDEF (TK_Null, ZCC_NULLPTR);
TOKENDEF (TK_Self, ZCC_SELF); TOKENDEF (TK_Self, ZCC_SELF);
TOKENDEF ('~', ZCC_TILDE); TOKENDEF ('~', ZCC_TILDE);
TOKENDEF ('!', ZCC_BANG); TOKENDEF ('!', ZCC_BANG);