- made GetClassName an intrinsic and expanded it to also work on class types.

This commit is contained in:
Christoph Oelckers 2017-04-14 16:14:27 +02:00
parent 1135f154b7
commit 92acbdc625
5 changed files with 87 additions and 15 deletions

View file

@ -612,12 +612,6 @@ void DObject::CheckIfSerialized () const
} }
DEFINE_ACTION_FUNCTION(DObject, GetClassName)
{
PARAM_SELF_PROLOGUE(DObject);
ACTION_RETURN_INT(self->GetClass()->TypeName);
}
DEFINE_ACTION_FUNCTION(DObject, MSTime) DEFINE_ACTION_FUNCTION(DObject, MSTime)
{ {
ACTION_RETURN_INT(I_MSTime()); ACTION_RETURN_INT(I_MSTime());

View file

@ -335,6 +335,7 @@ xx(RandomPick)
xx(FRandomPick) xx(FRandomPick)
xx(GetClass) xx(GetClass)
xx(GetParentClass) xx(GetParentClass)
xx(GetClassName)
xx(GetDefaultByType) xx(GetDefaultByType)
xx(Exp) xx(Exp)
xx(Log10) xx(Log10)

View file

@ -7775,6 +7775,13 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
} }
break; break;
case NAME_GetClassName:
if (CheckArgSize(NAME_GetClassName, ArgList, 0, 0, ScriptPosition))
{
func = new FxGetClassName(new FxSelf(ScriptPosition));
}
break;
case NAME_GetDefaultByType: case NAME_GetDefaultByType:
if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition)) if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition))
{ {
@ -8215,14 +8222,20 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (MethodName == NAME_GetParentClass && if (MethodName == NAME_GetParentClass &&
(Self->IsObject() || Self->ValueType->isClassPointer())) (Self->IsObject() || Self->ValueType->isClassPointer()))
{ {
if (ArgList.Size() > 0) if (CheckArgSize(NAME_GetParentClass, ArgList, 0, 0, ScriptPosition))
{ {
ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars()); auto x = new FxGetParentClass(Self);
delete this; return x->Resolve(ctx);
return nullptr; }
}
if (MethodName == NAME_GetClassName &&
(Self->IsObject() || Self->ValueType->isClassPointer()))
{
if (CheckArgSize(NAME_GetClassName, ArgList, 0, 0, ScriptPosition))
{
auto x = new FxGetClassName(Self);
return x->Resolve(ctx);
} }
auto x = new FxGetParentClass(Self);
return x->Resolve(ctx);
} }
if (Self->ValueType->isRealPointer()) if (Self->ValueType->isRealPointer())
@ -9336,11 +9349,11 @@ FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx)
if (!Self->ValueType->isClassPointer() && !Self->IsObject()) if (!Self->ValueType->isClassPointer() && !Self->IsObject())
{ {
ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object"); ScriptPosition.Message(MSG_ERROR, "GetParentClass() requires an object");
delete this; delete this;
return nullptr; return nullptr;
} }
ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); // ValueType = NewClassPointer(RUNTIME_CLASS(DObject));
return this; return this;
} }
@ -9365,6 +9378,52 @@ ExpEmit FxGetParentClass::Emit(VMFunctionBuilder *build)
// //
//========================================================================== //==========================================================================
FxGetClassName::FxGetClassName(FxExpression *self)
:FxExpression(EFX_GetClassName, self->ScriptPosition)
{
Self = self;
}
FxGetClassName::~FxGetClassName()
{
SAFE_DELETE(Self);
}
FxExpression *FxGetClassName::Resolve(FCompileContext &ctx)
{
SAFE_RESOLVE(Self, ctx);
if (!Self->ValueType->isClassPointer() && !Self->IsObject())
{
ScriptPosition.Message(MSG_ERROR, "GetClassName() requires an object");
delete this;
return nullptr;
}
ValueType = TypeName;
return this;
}
ExpEmit FxGetClassName::Emit(VMFunctionBuilder *build)
{
ExpEmit op = Self->Emit(build);
op.Free(build);
if (Self->IsObject())
{
ExpEmit to(build, REGT_POINTER);
build->Emit(OP_CLSS, to.RegNum, op.RegNum);
op = to;
op.Free(build);
}
ExpEmit to(build, REGT_INT);
build->Emit(OP_LW, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, TypeName)));
return to;
}
//==========================================================================
//
//
//==========================================================================
FxGetDefaultByType::FxGetDefaultByType(FxExpression *self) FxGetDefaultByType::FxGetDefaultByType(FxExpression *self)
:FxExpression(EFX_GetDefaultByType, self->ScriptPosition) :FxExpression(EFX_GetDefaultByType, self->ScriptPosition)
{ {

View file

@ -296,6 +296,7 @@ enum EFxType
EFX_NamedNode, EFX_NamedNode,
EFX_GetClass, EFX_GetClass,
EFX_GetParentClass, EFX_GetParentClass,
EFX_GetClassName,
EFX_StrLen, EFX_StrLen,
EFX_ColorLiteral, EFX_ColorLiteral,
EFX_GetDefaultByType, EFX_GetDefaultByType,
@ -1660,6 +1661,24 @@ public:
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);
}; };
//==========================================================================
//
// FxGetClass
//
//==========================================================================
class FxGetClassName : public FxExpression
{
FxExpression *Self;
public:
FxGetClassName(FxExpression *self);
~FxGetClassName();
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
};
//========================================================================== //==========================================================================
// //
// FxGetDefaultByType // FxGetDefaultByType

View file

@ -342,7 +342,6 @@ class Object native
native static uint MSTime(); native static uint MSTime();
native vararg static void ThrowAbortException(String fmt, ...); native vararg static void ThrowAbortException(String fmt, ...);
native Name GetClassName();
native virtualscope void Destroy(); native virtualscope void Destroy();
// This does not call into the native method of the same name to avoid problems with objects that get garbage collected late on shutdown. // This does not call into the native method of the same name to avoid problems with objects that get garbage collected late on shutdown.