- fixed and cleaned up state index jump handling

* use the function build list instead of the function to pass the info. The function is permanent so not the best place for compile-time info.
 * pass along the current state index which is needed to calculate the target state.
This commit is contained in:
Christoph Oelckers 2016-11-06 13:14:46 +01:00
parent c354000f1c
commit 2ac0046cda
9 changed files with 24 additions and 18 deletions

View file

@ -719,7 +719,6 @@ public:
}; };
TArray<Variant> Variants; TArray<Variant> Variants;
PClass *OwningClass = nullptr; PClass *OwningClass = nullptr;
int StateCount = 0; // needed to process state indices later.
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() int GetImplicitArgs()

View file

@ -93,12 +93,14 @@ static const FLOP FxFlops[] =
// //
//========================================================================== //==========================================================================
FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate) : ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate) FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount)
: ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount)
{ {
if (fnc != nullptr) Class = fnc->OwningClass; if (fnc != nullptr) Class = fnc->OwningClass;
} }
FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate) FCompileContext::FCompileContext(PClass *cls, bool fromdecorate)
: ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0)
{ {
} }
@ -1426,13 +1428,13 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
} }
else if (basex->IsNumeric() && basex->ValueType != TypeSound && basex->ValueType != TypeColor) else if (basex->IsNumeric() && basex->ValueType != TypeSound && basex->ValueType != TypeColor)
{ {
if (ctx.Function->SymbolName != NAME_None || !(ctx.Function->Variants[0].Flags & VARF_Action)) if (ctx.StateIndex < 0)
{ {
ScriptPosition.Message(MSG_ERROR, "State jumps with index can only be used in anonymous state functions."); ScriptPosition.Message(MSG_ERROR, "State jumps with index can only be used in anonymous state functions.");
delete this; delete this;
return nullptr; return nullptr;
} }
if (ctx.Function->StateCount != 1) if (ctx.StateCount != 1)
{ {
ScriptPosition.Message(MSG_ERROR, "State jumps with index cannot be used on multistate definitions"); ScriptPosition.Message(MSG_ERROR, "State jumps with index cannot be used on multistate definitions");
delete this; delete this;
@ -1447,7 +1449,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
delete this; delete this;
return nullptr; return nullptr;
} }
FxExpression *x = new FxStateByIndex(i, ScriptPosition); FxExpression *x = new FxStateByIndex(ctx.StateIndex + i, ScriptPosition);
x = x->Resolve(ctx); x = x->Resolve(ctx);
basex = nullptr; basex = nullptr;
delete this; delete this;

View file

@ -73,10 +73,12 @@ struct FCompileContext
PPrototype *ReturnProto; PPrototype *ReturnProto;
PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.)
PClass *Class; // The type of the owning class. PClass *Class; // The type of the owning class.
bool FromDecorate; bool FromDecorate; // DECORATE must silence some warnings and demote some errors.
int StateIndex; // index in actor's state table for anonymous functions, otherwise -1 (not used by DECORATE which pre-resolves state indices)
int StateCount; // amount of states an anoymous function is being used on (must be 1 for state indices to be allowed.)
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs; TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate); FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount);
FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants! FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants!
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);

View file

@ -324,7 +324,7 @@ do_stop:
endofstate: endofstate:
if (ScriptCode != nullptr) if (ScriptCode != nullptr)
{ {
auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action, (int)statestring.Len()); auto funcsym = CreateAnonymousFunction(actor, nullptr, VARF_Method | VARF_Action);
state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true); state.ActionFunc = FunctionBuildList.AddFunction(funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true);
} }
int count = bag.statedef.AddStates(&state, statestring); int count = bag.statedef.AddStates(&state, statestring);

View file

@ -132,7 +132,7 @@ void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FNam
// //
//========================================================================== //==========================================================================
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags, int statecount) PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags)
{ {
TArray<PType *> rets(1); TArray<PType *> rets(1);
TArray<PType *> args; TArray<PType *> args;
@ -143,7 +143,6 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i
SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags); SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags);
PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names. PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names.
sym->StateCount = statecount;
sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, flags); sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, flags);
return sym; return sym;
} }
@ -202,7 +201,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id,
else else
{ {
auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition); auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition);
auto funcsym = CreateAnonymousFunction(info, TypeSInt32, VARF_Method, 0); auto funcsym = CreateAnonymousFunction(info, TypeSInt32, VARF_Method);
defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate); defaults->DamageFunc = FunctionBuildList.AddFunction(funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate);
} }
} }

View file

@ -153,7 +153,7 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg
class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag); class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag);
FName CheckCastKludges(FName in); FName CheckCastKludges(FName in);
void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FName> *argnames, PClass *cls, DWORD funcflags); void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FName> *argnames, PClass *cls, DWORD funcflags);
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags, int statecount); PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags);
PFunction *FindClassMemberFunction(PClass *cls, PClass *funccls, FName name, FScriptPosition &sc, bool *error); PFunction *FindClassMemberFunction(PClass *cls, PClass *funccls, FName name, FScriptPosition &sc, bool *error);
void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate); void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate);

View file

@ -653,7 +653,7 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc)
//========================================================================== //==========================================================================
FFunctionBuildList FunctionBuildList; FFunctionBuildList FunctionBuildList;
VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate) VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount)
{ {
auto func = code->GetDirectFunction(); auto func = code->GetDirectFunction();
if (func != nullptr) if (func != nullptr)
@ -673,6 +673,8 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c
it.Function->ImplicitArgs = functype->GetImplicitArgs(); it.Function->ImplicitArgs = functype->GetImplicitArgs();
it.Proto = nullptr; it.Proto = nullptr;
it.FromDecorate = fromdecorate; it.FromDecorate = fromdecorate;
it.StateIndex = stateindex;
it.StateCount = statecount;
// set prototype for named functions. // set prototype for named functions.
if (it.Func->SymbolName != NAME_None) if (it.Func->SymbolName != NAME_None)
@ -698,7 +700,7 @@ void FFunctionBuildList::Build()
assert(item.Code != NULL); assert(item.Code != NULL);
// We don't know the return type in advance for anonymous functions. // We don't know the return type in advance for anonymous functions.
FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate); FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate, item.StateIndex, item.StateCount);
// Allocate registers for the function's arguments and create local variable nodes before starting to resolve it. // Allocate registers for the function's arguments and create local variable nodes before starting to resolve it.
VMFunctionBuilder buildit(item.Func->GetImplicitArgs()); VMFunctionBuilder buildit(item.Func->GetImplicitArgs());

View file

@ -106,13 +106,15 @@ class FFunctionBuildList
PPrototype *Proto = nullptr; PPrototype *Proto = nullptr;
VMScriptFunction *Function = nullptr; VMScriptFunction *Function = nullptr;
FString PrintableName; FString PrintableName;
int StateIndex;
int StateCount;
bool FromDecorate; bool FromDecorate;
}; };
TArray<Item> mItems; TArray<Item> mItems;
public: public:
VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate); VMFunction *AddFunction(PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate = -1, int statecnt = 0);
void Build(); void Build();
}; };

View file

@ -2349,8 +2349,8 @@ void ZCCCompiler::CompileStates()
auto code = SetupActionFunction(static_cast<PClassActor *>(c->Type()), sl->Action); auto code = SetupActionFunction(static_cast<PClassActor *>(c->Type()), sl->Action);
if (code != nullptr) if (code != nullptr)
{ {
auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action, (int)sl->Frames->Len()); auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action);
state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false); state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len());
} }
} }