Use action function return value to make state jumps happen
- The A_Jump family of action functions now return the state to jump
to (NULL if no jump is to be taken) instead of jumping directly.
It is the caller's responsibility to handle the jump. This will
make it possible to use their results in if statements and
do something other than jump.
- DECORATE return statements can now return the result of a function
(but not any random expression--it must be a function call). To
make a jump happen from inside a multi-action block, you must
return the value of an A_Jump function. e.g.:
{ return A_Jump(128, "SomeState"); }
- The VMFunction class now contains its prototype instead of storing
it at a higher level in PFunction. This is so that
FState::CallAction can easily tell if a function returns a state.
- Removed the FxTailable class because with explicit return
statements, it's not useful anymore.
This commit is contained in:
parent
0f70d10521
commit
b2ccd0bd28
18 changed files with 662 additions and 534 deletions
|
|
@ -277,11 +277,11 @@ static void FinishThingdef()
|
|||
|
||||
// Can we call this function directly without wrapping it in an
|
||||
// anonymous function? e.g. Are we passing any parameters to it?
|
||||
func = tcall->Code->GetDirectFunction();
|
||||
func = NULL;//tcall->Code->GetDirectFunction();
|
||||
if (func == NULL)
|
||||
{
|
||||
FCompileContext ctx(tcall->ActorClass);
|
||||
tcall->Code = static_cast<FxTailable *>(tcall->Code->Resolve(ctx));
|
||||
tcall->Code = tcall->Code->Resolve(ctx);
|
||||
|
||||
// Make sure resolving it didn't obliterate it.
|
||||
if (tcall->Code != NULL)
|
||||
|
|
@ -292,11 +292,25 @@ static void FinishThingdef()
|
|||
// self, stateowner, state (all are pointers)
|
||||
buildit.Registers[REGT_POINTER].Get(3);
|
||||
|
||||
// Emit a tail call via FxVMFunctionCall
|
||||
tcall->Code->Emit(&buildit, true);
|
||||
// Emit code
|
||||
tcall->Code->Emit(&buildit);
|
||||
|
||||
VMScriptFunction *sfunc = buildit.MakeFunction();
|
||||
sfunc->NumArgs = NAP;
|
||||
|
||||
// Generate prototype for this anonymous function
|
||||
TArray<PType *> args(3);
|
||||
SetImplicitArgs(&args, NULL, tcall->ActorClass, VARF_Method | VARF_Action);
|
||||
if (tcall->Proto != NULL)
|
||||
{
|
||||
sfunc->Proto = NewPrototype(tcall->Proto->ReturnTypes, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
TArray<PType *> norets(0);
|
||||
sfunc->Proto = NewPrototype(norets, args);
|
||||
}
|
||||
|
||||
func = sfunc;
|
||||
|
||||
if (dump != NULL)
|
||||
|
|
@ -354,6 +368,7 @@ static void FinishThingdef()
|
|||
dmg->Emit(&buildit);
|
||||
sfunc = buildit.MakeFunction();
|
||||
sfunc->NumArgs = 1;
|
||||
sfunc->Proto = NULL; ///FIXME: Need a proper prototype here
|
||||
// Save this function in case this damage value was reused
|
||||
// (which happens quite easily with inheritance).
|
||||
dmg->SetFunction(sfunc);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue