diff --git a/src/dobjtype.h b/src/dobjtype.h index 9cf663983..fd8bfb60a 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -719,7 +719,6 @@ public: }; TArray Variants; PClass *OwningClass = nullptr; - int StateCount = 0; // needed to process state indices later. unsigned AddVariant(PPrototype *proto, TArray &argflags, TArray &argnames, VMFunction *impl, int flags); int GetImplicitArgs() diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index f296ac6e7..ea61d42df 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -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; } -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) { - 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."); delete this; 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"); delete this; @@ -1447,7 +1449,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return nullptr; } - FxExpression *x = new FxStateByIndex(i, ScriptPosition); + FxExpression *x = new FxStateByIndex(ctx.StateIndex + i, ScriptPosition); x = x->Resolve(ctx); basex = nullptr; delete this; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index f4426da90..3cc86d1e6 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -73,10 +73,12 @@ struct FCompileContext PPrototype *ReturnProto; PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.) 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 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! PSymbol *FindInClass(FName identifier, PSymbolTable *&symt); diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 3b9930928..d17cb5d4d 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -324,7 +324,7 @@ do_stop: endofstate: 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); } int count = bag.statedef.AddStates(&state, statestring); diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 6f30f8add..8c42e8987 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -132,7 +132,7 @@ void SetImplicitArgs(TArray *args, TArray *argflags, TArray rets(1); TArray args; @@ -143,7 +143,6 @@ PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, i SetImplicitArgs(&args, &argflags, &argnames, containingclass, flags); 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); return sym; } @@ -202,7 +201,7 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, else { 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); } } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 3511d1ee1..b2d34231d 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -153,7 +153,7 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg class FxVMFunctionCall *ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag); FName CheckCastKludges(FName in); void SetImplicitArgs(TArray *args, TArray *argflags, TArray *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); void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate); diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index f8ca44ba6..0d517b6ef 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -653,7 +653,7 @@ void VMFunctionBuilder::BackpatchToHere(size_t loc) //========================================================================== 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(); if (func != nullptr) @@ -673,6 +673,8 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c it.Function->ImplicitArgs = functype->GetImplicitArgs(); it.Proto = nullptr; it.FromDecorate = fromdecorate; + it.StateIndex = stateindex; + it.StateCount = statecount; // set prototype for named functions. if (it.Func->SymbolName != NAME_None) @@ -698,7 +700,7 @@ void FFunctionBuildList::Build() assert(item.Code != NULL); // 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. VMFunctionBuilder buildit(item.Func->GetImplicitArgs()); diff --git a/src/scripting/vm/vmbuilder.h b/src/scripting/vm/vmbuilder.h index 9a97c216d..452a7882c 100644 --- a/src/scripting/vm/vmbuilder.h +++ b/src/scripting/vm/vmbuilder.h @@ -106,13 +106,15 @@ class FFunctionBuildList PPrototype *Proto = nullptr; VMScriptFunction *Function = nullptr; FString PrintableName; + int StateIndex; + int StateCount; bool FromDecorate; }; TArray mItems; 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(); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 44b2f489c..f52976512 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2349,8 +2349,8 @@ void ZCCCompiler::CompileStates() auto code = SetupActionFunction(static_cast(c->Type()), sl->Action); if (code != nullptr) { - auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, VARF_Method | VARF_Action, (int)sl->Frames->Len()); - state.ActionFunc = FunctionBuildList.AddFunction(funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false); + 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, statedef.GetStateCount(), (int)sl->Frames->Len()); } }