mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 05:40:44 +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;
|
VMScriptFunction *sfunc = new VMScriptFunction;
|
||||||
buildit.MakeFunction(sfunc);
|
buildit.MakeFunction(sfunc);
|
||||||
sfunc->NumArgs = NAP;
|
sfunc->NumArgs = NAP;
|
||||||
|
sfunc->ImplicitArgs = NAP;
|
||||||
state->SetAction(sfunc);
|
state->SetAction(sfunc);
|
||||||
|
sfunc->PrintableName.Format("Dehacked.%s.%d.%d", MBFCodePointers[codepointer].name.GetChars(), value1, value2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -719,6 +719,12 @@ public:
|
||||||
PClass *OwningClass = nullptr;
|
PClass *OwningClass = nullptr;
|
||||||
|
|
||||||
unsigned AddVariant(PPrototype *proto, TArray<DWORD> &argflags, TArray<FName> &argnames, VMFunction *impl, int flags);
|
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();
|
size_t PropagateMark();
|
||||||
|
|
||||||
|
|
|
@ -94,13 +94,13 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
|
||||||
}
|
}
|
||||||
if (stateret == NULL)
|
if (stateret == NULL)
|
||||||
{
|
{
|
||||||
stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL);
|
stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VMReturn ret;
|
VMReturn ret;
|
||||||
ret.PointerAt((void **)stateret);
|
ret.PointerAt((void **)stateret);
|
||||||
stack.Call(ActionFunc, params, countof(params), &ret, 1, NULL);
|
stack.Call(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1, NULL);
|
||||||
}
|
}
|
||||||
ActionCycles.Unclock();
|
ActionCycles.Unclock();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -168,7 +168,7 @@ bool ACustomInventory::CallStateChain (AActor *actor, FState *state)
|
||||||
numret = 2;
|
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.
|
// 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".
|
// A state that wants to jump does not count as "succeeded".
|
||||||
if (nextstate == NULL)
|
if (nextstate == NULL)
|
||||||
|
|
|
@ -5196,11 +5196,11 @@ PPrototype *FxVMFunctionCall::ReturnProto()
|
||||||
|
|
||||||
VMFunction *FxVMFunctionCall::GetDirectFunction()
|
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
|
// then it can be a "direct" function. That is, the DECORATE
|
||||||
// definition can call that function directly without wrapping
|
// definition can call that function directly without wrapping
|
||||||
// it inside VM code.
|
// 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;
|
return Function->Variants[0].Implementation;
|
||||||
}
|
}
|
||||||
|
@ -5222,10 +5222,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
auto proto = Function->Variants[0].Proto;
|
auto proto = Function->Variants[0].Proto;
|
||||||
auto argtypes = proto->ArgumentTypes;
|
auto argtypes = proto->ArgumentTypes;
|
||||||
|
|
||||||
int implicit;
|
int implicit = Function->GetImplicitArgs();
|
||||||
if (Function->Variants[0].Flags & VARF_Action) implicit = 3;
|
|
||||||
else if (Function->Variants[0].Flags & VARF_Method) implicit = 1;
|
|
||||||
else implicit = 0;
|
|
||||||
|
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
if (Self == nullptr && !(Function->Variants[0].Flags & VARF_Static))
|
if (Self == nullptr && !(Function->Variants[0].Flags & VARF_Static))
|
||||||
|
|
|
@ -179,12 +179,12 @@ class VMFunction : public DObject
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
bool Native;
|
bool Native;
|
||||||
|
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
||||||
FName Name;
|
FName Name;
|
||||||
|
|
||||||
class PPrototype *Proto;
|
class PPrototype *Proto;
|
||||||
|
|
||||||
VMFunction() : Native(false), Name(NAME_None), Proto(NULL) {}
|
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {}
|
||||||
VMFunction(FName name) : Native(false), Name(name), Proto(NULL) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EVMOpMode
|
enum EVMOpMode
|
||||||
|
|
|
@ -665,6 +665,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c
|
||||||
it.Code = code;
|
it.Code = code;
|
||||||
it.PrintableName = name;
|
it.PrintableName = name;
|
||||||
it.Function = new VMScriptFunction;
|
it.Function = new VMScriptFunction;
|
||||||
|
it.Function->ImplicitArgs = functype->GetImplicitArgs();
|
||||||
it.Proto = nullptr;
|
it.Proto = nullptr;
|
||||||
it.FromDecorate = fromdecorate;
|
it.FromDecorate = fromdecorate;
|
||||||
mItems.Push(it);
|
mItems.Push(it);
|
||||||
|
|
|
@ -1951,14 +1951,15 @@ void ZCCCompiler::InitFunctions()
|
||||||
f->Flags &= notallowed;
|
f->Flags &= notallowed;
|
||||||
}
|
}
|
||||||
uint32_t varflags = VARF_Method;
|
uint32_t varflags = VARF_Method;
|
||||||
|
int implicitargs = 1;
|
||||||
AFuncDesc *afd = nullptr;
|
AFuncDesc *afd = nullptr;
|
||||||
|
|
||||||
// map to implementation flags.
|
// map to implementation flags.
|
||||||
if (f->Flags & ZCC_Private) varflags |= VARF_Private;
|
if (f->Flags & ZCC_Private) varflags |= VARF_Private;
|
||||||
if (f->Flags & ZCC_Protected) varflags |= VARF_Protected;
|
if (f->Flags & ZCC_Protected) varflags |= VARF_Protected;
|
||||||
if (f->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated;
|
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_Action) varflags |= VARF_Action|VARF_Final, implicitargs = 3; // Action implies Final.
|
||||||
if (f->Flags & ZCC_Static) varflags = (varflags & ~VARF_Method) | VARF_Final; // Static 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))
|
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());
|
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());
|
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);
|
SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags);
|
||||||
auto p = f->Params;
|
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));
|
PFunction *afd = dyn_cast<PFunction>(cls->Symbols.FindSymbol(id->Identifier, true));
|
||||||
if (afd != nullptr)
|
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.
|
// We can use this function directly without wrapping it in a caller.
|
||||||
return new FxVMFunctionCall(new FxSelf(*af), afd, nullptr, *af, false);
|
return new FxVMFunctionCall(new FxSelf(*af), afd, nullptr, *af, false);
|
||||||
|
|
Loading…
Reference in a new issue