mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 15:02:01 +00:00
- allow calling non-action functions directly from a state.
Ironically this only requires a very minor change in the calling code and an added member for the VMFunction to tell that code how many parameters to pass. This change will allow to turn the vast majority of action functions into regular members, the only ones that still need to be an action function are the few that actually use the pointers.
This commit is contained in:
parent
d6047ae651
commit
d714670acc
8 changed files with 22 additions and 14 deletions
|
@ -823,7 +823,9 @@ void SetDehParams(FState *state, int codepointer)
|
|||
VMScriptFunction *sfunc = new VMScriptFunction;
|
||||
buildit.MakeFunction(sfunc);
|
||||
sfunc->NumArgs = NAP;
|
||||
sfunc->ImplicitArgs = NAP;
|
||||
state->SetAction(sfunc);
|
||||
sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -719,6 +719,12 @@ public:
|
|||
PClass *OwningClass = nullptr;
|
||||
|
||||
unsigned AddVariant(PPrototype *proto, TArray<DWORD> &argflags, TArray<FName> &argnames, VMFunction *impl, int flags);
|
||||
int GetImplicitArgs()
|
||||
{
|
||||
if (Variants[0].Flags & VARF_Action) return 3;
|
||||
else if (Variants[0].Flags & VARF_Method) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t PropagateMark();
|
||||
|
||||
|
|
|
@ -94,13 +94,13 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
|
|||
}
|
||||
if (stateret == NULL)
|
||||
{
|
||||
stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL);
|
||||
stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
VMReturn ret;
|
||||
ret.PointerAt((void **)stateret);
|
||||
stack.Call(ActionFunc, params, countof(params), &ret, 1, NULL);
|
||||
stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL);
|
||||
}
|
||||
ActionCycles.Unclock();
|
||||
return true;
|
||||
|
|
|
@ -168,7 +168,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state)
|
|||
numret = 2;
|
||||
}
|
||||
}
|
||||
stack.Call(state->ActionFunc, params, countof(params), wantret, numret);
|
||||
stack.Call(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
|
||||
// As long as even one state succeeds, the whole chain succeeds unless aborted below.
|
||||
// A state that wants to jump does not count as "succeeded".
|
||||
if (nextstate == NULL)
|
||||
|
|
|
@ -5196,11 +5196,11 @@ PPrototype *FxVMFunctionCall::ReturnProto()
|
|||
|
||||
VMFunction *FxVMFunctionCall::GetDirectFunction()
|
||||
{
|
||||
// If this return statement calls a function with no arguments,
|
||||
// If this return statement calls a non-virtual function with no arguments,
|
||||
// then it can be a "direct" function. That is, the DECORATE
|
||||
// definition can call that function directly without wrapping
|
||||
// it inside VM code.
|
||||
if ((ArgList ? ArgList->Size() : 0) == 0 && (Function->Variants[0].Flags & VARF_Action))
|
||||
if ((ArgList ? ArgList->Size() : 0) == 0 && !(Function->Variants[0].Flags & VARF_Virtual))
|
||||
{
|
||||
return Function->Variants[0].Implementation;
|
||||
}
|
||||
|
@ -5222,10 +5222,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
auto proto = Function->Variants[0].Proto;
|
||||
auto argtypes = proto->ArgumentTypes;
|
||||
|
||||
int implicit;
|
||||
if (Function->Variants[0].Flags & VARF_Action) implicit = 3;
|
||||
else if (Function->Variants[0].Flags & VARF_Method) implicit = 1;
|
||||
else implicit = 0;
|
||||
int implicit = Function->GetImplicitArgs();
|
||||
|
||||
// This should never happen.
|
||||
if (Self == nullptr && !(Function->Variants[0].Flags & VARF_Static))
|
||||
|
|
|
@ -179,12 +179,12 @@ class VMFunction : public DObject
|
|||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
bool Native;
|
||||
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
||||
FName Name;
|
||||
|
||||
class PPrototype *Proto;
|
||||
|
||||
VMFunction() : Native(false), Name(NAME_None), Proto(NULL) {}
|
||||
VMFunction(FName name) : Native(false), Name(name), Proto(NULL) {}
|
||||
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {}
|
||||
};
|
||||
|
||||
enum EVMOpMode
|
||||
|
|
|
@ -665,6 +665,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c
|
|||
it.Code = code;
|
||||
it.PrintableName = name;
|
||||
it.Function = new VMScriptFunction;
|
||||
it.Function->ImplicitArgs = functype->GetImplicitArgs();
|
||||
it.Proto = nullptr;
|
||||
it.FromDecorate = fromdecorate;
|
||||
mItems.Push(it);
|
||||
|
|
|
@ -1951,14 +1951,15 @@ void ZCCCompiler::InitFunctions()
|
|||
f->Flags &= notallowed;
|
||||
}
|
||||
uint32_t varflags = VARF_Method;
|
||||
int implicitargs = 1;
|
||||
AFuncDesc *afd = nullptr;
|
||||
|
||||
// map to implementation flags.
|
||||
if (f->Flags & ZCC_Private) varflags |= VARF_Private;
|
||||
if (f->Flags & ZCC_Protected) varflags |= VARF_Protected;
|
||||
if (f->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated;
|
||||
if (f->Flags & ZCC_Action) varflags |= VARF_Action|VARF_Final; // Action implies Final.
|
||||
if (f->Flags & ZCC_Static) varflags = (varflags & ~VARF_Method) | VARF_Final; // Static implies Final.
|
||||
if (f->Flags & ZCC_Action) varflags |= VARF_Action|VARF_Final, implicitargs = 3; // Action implies Final.
|
||||
if (f->Flags & ZCC_Static) varflags = (varflags & ~VARF_Method) | VARF_Final, implicitargs = 0; // Static implies Final.
|
||||
if ((f->Flags & (ZCC_Action | ZCC_Static)) == (ZCC_Action | ZCC_Static))
|
||||
{
|
||||
Error(f, "%s: Action and Static on the same function is not allowed.", FName(f->Name).GetChars());
|
||||
|
@ -1973,6 +1974,7 @@ void ZCCCompiler::InitFunctions()
|
|||
{
|
||||
Error(f, "The function '%s' has not been exported from the executable.", FName(f->Name).GetChars());
|
||||
}
|
||||
(*afd->VMPointer)->ImplicitArgs = BYTE(implicitargs);
|
||||
}
|
||||
SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags);
|
||||
auto p = f->Params;
|
||||
|
@ -2063,7 +2065,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a
|
|||
PFunction *afd = dyn_cast<PFunction>(cls->Symbols.FindSymbol(id->Identifier, true));
|
||||
if (afd != nullptr)
|
||||
{
|
||||
if (fc->Parameters == nullptr && (afd->Variants[0].Flags & VARF_Action))
|
||||
if (fc->Parameters == nullptr && !(afd->Variants[0].Flags & VARF_Virtual))
|
||||
{
|
||||
// We can use this function directly without wrapping it in a caller.
|
||||
return new FxVMFunctionCall(new FxSelf(*af), afd, nullptr, *af, false);
|
||||
|
|
Loading…
Reference in a new issue