diff --git a/src/dobject.cpp b/src/dobject.cpp index 687e76f850..39c55f2b57 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -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) { ACTION_RETURN_INT(I_MSTime()); diff --git a/src/namedef.h b/src/namedef.h index ae0a17afde..fec4093fd0 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -335,6 +335,7 @@ xx(RandomPick) xx(FRandomPick) xx(GetClass) xx(GetParentClass) +xx(GetClassName) xx(GetDefaultByType) xx(Exp) xx(Log10) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 76ab833584..09d85f726b 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -7775,6 +7775,13 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_GetClassName: + if (CheckArgSize(NAME_GetClassName, ArgList, 0, 0, ScriptPosition)) + { + func = new FxGetClassName(new FxSelf(ScriptPosition)); + } + break; + case NAME_GetDefaultByType: if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition)) { @@ -8215,14 +8222,20 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (MethodName == NAME_GetParentClass && (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()); - delete this; - return nullptr; + auto x = new FxGetParentClass(Self); + return x->Resolve(ctx); + } + } + 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()) @@ -9336,11 +9349,11 @@ FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx) if (!Self->ValueType->isClassPointer() && !Self->IsObject()) { - ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object"); + ScriptPosition.Message(MSG_ERROR, "GetParentClass() requires an object"); delete this; return nullptr; } - ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); // + ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); 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) :FxExpression(EFX_GetDefaultByType, self->ScriptPosition) { diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index aa2e06910d..004b1f2289 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -296,6 +296,7 @@ enum EFxType EFX_NamedNode, EFX_GetClass, EFX_GetParentClass, + EFX_GetClassName, EFX_StrLen, EFX_ColorLiteral, EFX_GetDefaultByType, @@ -1660,6 +1661,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxGetClass +// +//========================================================================== + +class FxGetClassName : public FxExpression +{ + FxExpression *Self; + +public: + + FxGetClassName(FxExpression *self); + ~FxGetClassName(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxGetDefaultByType diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index c834dff946..7d0e542135 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -342,7 +342,6 @@ class Object native native static uint MSTime(); native vararg static void ThrowAbortException(String fmt, ...); - native Name GetClassName(); 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.