mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-25 13:41:05 +00:00
- implemented super calls and proper dispatch of scripted virtual overrides for Destroy.
This commit is contained in:
parent
72e77a6c65
commit
924096694e
5 changed files with 93 additions and 4 deletions
|
@ -366,6 +366,7 @@ void DObject::Destroy ()
|
||||||
DEFINE_ACTION_FUNCTION(DObject, Destroy)
|
DEFINE_ACTION_FUNCTION(DObject, Destroy)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(DObject);
|
PARAM_SELF_PROLOGUE(DObject);
|
||||||
|
self->VMSuperCall();
|
||||||
self->Destroy();
|
self->Destroy();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,7 +235,6 @@ enum EObjectFlags
|
||||||
OF_EuthanizeMe = 1 << 5, // Object wants to die
|
OF_EuthanizeMe = 1 << 5, // Object wants to die
|
||||||
OF_Cleanup = 1 << 6, // Object is now being deleted by the collector
|
OF_Cleanup = 1 << 6, // Object is now being deleted by the collector
|
||||||
OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning
|
OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning
|
||||||
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
|
||||||
|
|
||||||
OF_WhiteBits = OF_White0 | OF_White1,
|
OF_WhiteBits = OF_White0 | OF_White1,
|
||||||
OF_MarkBits = OF_WhiteBits | OF_Black,
|
OF_MarkBits = OF_WhiteBits | OF_Black,
|
||||||
|
@ -244,6 +243,8 @@ enum EObjectFlags
|
||||||
OF_JustSpawned = 1 << 8, // Thinker was spawned this tic
|
OF_JustSpawned = 1 << 8, // Thinker was spawned this tic
|
||||||
OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls
|
OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls
|
||||||
OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list
|
OF_Sentinel = 1 << 10, // Object is serving as the sentinel in a ring list
|
||||||
|
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
||||||
|
OF_SuperCall = 1 << 12, // A super call from the VM is about to be performed
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> class TObjPtr;
|
template<class T> class TObjPtr;
|
||||||
|
@ -498,6 +499,11 @@ public:
|
||||||
void SerializeUserVars(FSerializer &arc);
|
void SerializeUserVars(FSerializer &arc);
|
||||||
virtual void Serialize(FSerializer &arc);
|
virtual void Serialize(FSerializer &arc);
|
||||||
|
|
||||||
|
void VMSuperCall()
|
||||||
|
{
|
||||||
|
ObjectFlags |= OF_SuperCall;
|
||||||
|
}
|
||||||
|
|
||||||
void ClearClass()
|
void ClearClass()
|
||||||
{
|
{
|
||||||
Class = NULL;
|
Class = NULL;
|
||||||
|
@ -652,8 +658,28 @@ private:
|
||||||
public:
|
public:
|
||||||
void Destroy()
|
void Destroy()
|
||||||
{
|
{
|
||||||
|
if (ObjectFlags & OF_SuperCall)
|
||||||
|
{
|
||||||
|
ObjectFlags &= OF_SuperCall;
|
||||||
ExportedNatives<T>::Get()->template Destroy<void, T>(this);
|
ExportedNatives<T>::Get()->template Destroy<void, T>(this);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static int VIndex = -1;
|
||||||
|
if (VIndex < 0)
|
||||||
|
{
|
||||||
|
// Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override.
|
||||||
|
auto sym = dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false));
|
||||||
|
assert(sym != nullptr);
|
||||||
|
VIndex = sym->Variants[0].Implementation->VirtualIndex;
|
||||||
|
assert(VIndex >= 0);
|
||||||
|
}
|
||||||
|
// Without the type cast this picks the 'void *' assignment...
|
||||||
|
VMValue params[1] = { (DObject*)this };
|
||||||
|
VMFrameStack stack;
|
||||||
|
stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
void Tick()
|
void Tick()
|
||||||
{
|
{
|
||||||
ExportedNatives<T>::Get()->template Tick<void, T>(this);
|
ExportedNatives<T>::Get()->template Tick<void, T>(this);
|
||||||
|
|
|
@ -1350,7 +1350,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
||||||
// first deal with the simple types
|
// first deal with the simple types
|
||||||
if (ValueType == TypeError || basex->ValueType == TypeError)
|
if (ValueType == TypeError || basex->ValueType == TypeError)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Trying to cast to invalid type. This error message means that somewhere in the script compiler an error check is missing.");
|
ScriptPosition.Message(MSG_ERROR, "Trying to cast to invalid type.");
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -5433,6 +5433,25 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxExpression *FxSuper::Resolve(FCompileContext& ctx)
|
||||||
|
{
|
||||||
|
CHECKRESOLVED();
|
||||||
|
if (ctx.Function == nullptr || ctx.Function->Variants[0].SelfClass == nullptr)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "super used outside of a member function");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ValueType = TypeError; // this intentionally resolves to an invalid type so that it cannot be used outside of super calls.
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -6268,6 +6287,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
ABORT(ctx.Class);
|
ABORT(ctx.Class);
|
||||||
PClass *cls;
|
PClass *cls;
|
||||||
bool staticonly = false;
|
bool staticonly = false;
|
||||||
|
bool novirtual = false;
|
||||||
|
|
||||||
if (Self->ExprType == EFX_Identifier)
|
if (Self->ExprType == EFX_Identifier)
|
||||||
{
|
{
|
||||||
|
@ -6282,6 +6302,15 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
SAFE_RESOLVE(Self, ctx);
|
SAFE_RESOLVE(Self, ctx);
|
||||||
|
|
||||||
|
if (Self->ExprType == EFX_Super)
|
||||||
|
{
|
||||||
|
// give the node the proper value type now that we know it's properly used.
|
||||||
|
cls = ctx.Function->Variants[0].SelfClass->ParentClass;
|
||||||
|
Self->ValueType = NewPointer(cls);
|
||||||
|
Self->ExprType = EFX_Self;
|
||||||
|
novirtual = true; // super calls are always non-virtual
|
||||||
|
}
|
||||||
|
|
||||||
if (Self->IsVector())
|
if (Self->IsVector())
|
||||||
{
|
{
|
||||||
// handle builtins: Vectors got 2: Length and Unit.
|
// handle builtins: Vectors got 2: Length and Unit.
|
||||||
|
@ -6349,7 +6378,7 @@ isresolved:
|
||||||
|
|
||||||
// do not pass the self pointer to static functions.
|
// do not pass the self pointer to static functions.
|
||||||
auto self = (afd->Variants[0].Flags & VARF_Method) ? Self : nullptr;
|
auto self = (afd->Variants[0].Flags & VARF_Method) ? Self : nullptr;
|
||||||
auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly);
|
auto x = new FxVMFunctionCall(self, afd, ArgList, ScriptPosition, staticonly|novirtual);
|
||||||
if (Self == self) Self = nullptr;
|
if (Self == self) Self = nullptr;
|
||||||
delete this;
|
delete this;
|
||||||
return x->Resolve(ctx);
|
return x->Resolve(ctx);
|
||||||
|
@ -6971,6 +7000,11 @@ FxExpression *FxSequence::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
fail = true;
|
fail = true;
|
||||||
}
|
}
|
||||||
|
if (Expressions[i]->ValueType == TypeError)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Invalid statement");
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fail)
|
if (fail)
|
||||||
{
|
{
|
||||||
|
|
|
@ -276,6 +276,7 @@ enum EFxType
|
||||||
EFX_TypeCheck,
|
EFX_TypeCheck,
|
||||||
EFX_DynamicCast,
|
EFX_DynamicCast,
|
||||||
EFX_GlobalVariable,
|
EFX_GlobalVariable,
|
||||||
|
EFX_Super,
|
||||||
EFX_COUNT
|
EFX_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1241,6 +1242,23 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FxSuper
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxSuper : public FxSelf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FxSuper(const FScriptPosition&pos)
|
||||||
|
: FxSelf(pos)
|
||||||
|
{
|
||||||
|
ExprType = EFX_Super;
|
||||||
|
}
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxArrayElement
|
// FxArrayElement
|
||||||
|
|
|
@ -2898,6 +2898,16 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_Expression:
|
||||||
|
{
|
||||||
|
auto ret = static_cast<ZCC_Expression *>(ast);
|
||||||
|
if (ret->Operation == PEX_Super)
|
||||||
|
{
|
||||||
|
return new FxSuper(*ast);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AST_ExpressionStmt:
|
case AST_ExpressionStmt:
|
||||||
return ConvertNode(static_cast<ZCC_ExpressionStmt *>(ast)->Expression);
|
return ConvertNode(static_cast<ZCC_ExpressionStmt *>(ast)->Expression);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue