added class pointer casts. Due to grammar problems the type has to be put into parentheses to get the class token out of the global parsing namespace:

class<Actor> myclass = (class<Actor>)(GetClass());
This commit is contained in:
Christoph Oelckers 2016-11-17 20:31:53 +01:00
commit 3bcd85eb8a
8 changed files with 167 additions and 0 deletions

View file

@ -8382,6 +8382,107 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
return dest;
}
//==========================================================================
//
//==========================================================================
FxClassPtrCast::FxClassPtrCast(PClass *dtype, FxExpression *x)
: FxExpression(EFX_ClassPtrCast, x->ScriptPosition)
{
ValueType = NewClassPointer(dtype);
desttype = dtype;
basex = x;
}
//==========================================================================
//
//
//
//==========================================================================
FxClassPtrCast::~FxClassPtrCast()
{
SAFE_DELETE(basex);
}
//==========================================================================
//
//
//
//==========================================================================
FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
SAFE_RESOLVE(basex, ctx);
if (basex->ValueType == TypeNullPtr)
{
basex->ValueType = ValueType;
auto x = basex;
basex = nullptr;
delete this;
return x;
}
auto to = static_cast<PClassPointer *>(ValueType);
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
{
auto from = static_cast<PClassPointer *>(basex->ValueType);
// Downcast is always ok.
if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction))
{
basex->ValueType = to;
auto x = basex;
basex = nullptr;
delete this;
return x;
}
// Upcast needs a runtime check.
else if (to->ClassRestriction->IsDescendantOf(from->ClassRestriction))
{
return this;
}
}
// Everything else is an error.
ScriptPosition.Message(MSG_ERROR, "Cannot cast %s to %s. The types are incompatible.", basex->ValueType->DescriptiveName(), to->DescriptiveName());
delete this;
return nullptr;
}
//==========================================================================
//
//
//
//==========================================================================
int BuiltinClassCast(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
{
PARAM_PROLOGUE;
PARAM_CLASS(from, DObject);
PARAM_CLASS(to, DObject);
ACTION_RETURN_OBJECT(from->IsDescendantOf(to) ? from : nullptr);
}
ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
{
ExpEmit clsname = basex->Emit(build);
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype, ATAG_OBJECT));
VMFunction *callfunc;
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast);
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function;
clsname.Free(build);
ExpEmit dest(build, REGT_POINTER);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
return dest;
}
//==========================================================================
//
// Symbolic state labels.

View file

@ -258,6 +258,7 @@ enum EFxType
EFX_JumpStatement,
EFX_ReturnStatement,
EFX_ClassTypeCast,
EFX_ClassPtrCast,
EFX_StateByIndex,
EFX_RuntimeStateIndex,
EFX_MultiNameState,
@ -1668,6 +1669,25 @@ public:
ExpEmit Emit(VMFunctionBuilder *build);
};
//==========================================================================
//
//
//
//==========================================================================
class FxClassPtrCast : public FxExpression
{
PClass *desttype;
FxExpression *basex;
public:
FxClassPtrCast(PClass *dtype, FxExpression *x);
~FxClassPtrCast();
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
};
//==========================================================================
//
// Only used to resolve the old jump by index feature of DECORATE