mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-12-04 09:22:17 +00:00
Use PFunction instead of PSymbolActionFunction in DECORATE parser
This commit is contained in:
parent
aba691ad72
commit
cf87d0f1e9
8 changed files with 169 additions and 172 deletions
|
@ -81,7 +81,7 @@ static void UnloadDehSupp ();
|
||||||
|
|
||||||
|
|
||||||
// This is a list of all the action functions used by each of Doom's states.
|
// This is a list of all the action functions used by each of Doom's states.
|
||||||
static TArray<PSymbolActionFunction *> Actions;
|
static TArray<PFunction *> Actions;
|
||||||
|
|
||||||
// These are the original heights of every Doom 2 thing. They are used if a patch
|
// These are the original heights of every Doom 2 thing. They are used if a patch
|
||||||
// specifies that a thing should be hanging from the ceiling but doesn't specify
|
// specifies that a thing should be hanging from the ceiling but doesn't specify
|
||||||
|
@ -788,8 +788,8 @@ void SetDehParams(FState *state, int codepointer)
|
||||||
FScriptPosition *pos = new FScriptPosition(FString("DEHACKED"), 0);
|
FScriptPosition *pos = new FScriptPosition(FString("DEHACKED"), 0);
|
||||||
|
|
||||||
// Let's identify the codepointer we're dealing with.
|
// Let's identify the codepointer we're dealing with.
|
||||||
PSymbolActionFunction *sym;
|
PFunction *sym;
|
||||||
sym = dyn_cast<PSymbolActionFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true));
|
sym = dyn_cast<PFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true));
|
||||||
if (sym == NULL) return;
|
if (sym == NULL) return;
|
||||||
|
|
||||||
if (codepointer < 0 || codepointer >= countof(MBFCodePointerFactories))
|
if (codepointer < 0 || codepointer >= countof(MBFCodePointerFactories))
|
||||||
|
@ -809,7 +809,7 @@ void SetDehParams(FState *state, int codepointer)
|
||||||
buildit.Emit(OP_PARAM, 0, REGT_POINTER, 2);
|
buildit.Emit(OP_PARAM, 0, REGT_POINTER, 2);
|
||||||
// Emit code for action parameters.
|
// Emit code for action parameters.
|
||||||
int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2);
|
int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2);
|
||||||
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Function, ATAG_OBJECT), NAP + argcount, 0);
|
buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), NAP + argcount, 0);
|
||||||
// Attach it to the state.
|
// Attach it to the state.
|
||||||
VMScriptFunction *sfunc = buildit.MakeFunction();
|
VMScriptFunction *sfunc = buildit.MakeFunction();
|
||||||
sfunc->NumArgs = NAP;
|
sfunc->NumArgs = NAP;
|
||||||
|
@ -1711,7 +1711,7 @@ static int PatchWeapon (int weapNum)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetPointer(FState *state, PSymbolActionFunction *sym, int frame = 0)
|
static void SetPointer(FState *state, PFunction *sym, int frame = 0)
|
||||||
{
|
{
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1720,7 +1720,7 @@ static void SetPointer(FState *state, PSymbolActionFunction *sym, int frame = 0)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state->SetAction(sym->Function);
|
state->SetAction(sym->Variants[0].Implementation);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < MBFCodePointers.Size(); i++)
|
for (unsigned int i = 0; i < MBFCodePointers.Size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -2103,15 +2103,15 @@ static int PatchCodePtrs (int dummy)
|
||||||
|
|
||||||
// This skips the action table and goes directly to the internal symbol table
|
// This skips the action table and goes directly to the internal symbol table
|
||||||
// DEH compatible functions are easy to recognize.
|
// DEH compatible functions are easy to recognize.
|
||||||
PSymbolActionFunction *sym = dyn_cast<PSymbolActionFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(symname, true));
|
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(symname, true));
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
{
|
{
|
||||||
Printf("Frame %d: Unknown code pointer '%s'\n", frame, Line2);
|
Printf("Frame %d: Unknown code pointer '%s'\n", frame, Line2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FString &args = sym->Arguments;
|
TArray<DWORD> &args = sym->Variants[0].ArgFlags;
|
||||||
if (args.Len() != 0 && (args[0] < 'a' || args[0] > 'z'))
|
if (args.Size() != 0 && !(args[0] & VARF_Optional))
|
||||||
{
|
{
|
||||||
Printf("Frame %d: Incompatible code pointer '%s'\n", frame, Line2);
|
Printf("Frame %d: Incompatible code pointer '%s'\n", frame, Line2);
|
||||||
sym = NULL;
|
sym = NULL;
|
||||||
|
@ -2680,15 +2680,15 @@ static bool LoadDehSupp ()
|
||||||
// or AActor so this will find all of them.
|
// or AActor so this will find all of them.
|
||||||
FString name = "A_";
|
FString name = "A_";
|
||||||
name << sc.String;
|
name << sc.String;
|
||||||
PSymbolActionFunction *sym = dyn_cast<PSymbolActionFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(name, true));
|
PFunction *sym = dyn_cast<PFunction>(RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(name, true));
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
{
|
{
|
||||||
sc.ScriptError("Unknown code pointer '%s'", sc.String);
|
sc.ScriptError("Unknown code pointer '%s'", sc.String);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FString &args = sym->Arguments;
|
TArray<DWORD> &args = sym->Variants[0].ArgFlags;
|
||||||
if (args.Len() != 0 && (args[0] < 'a' || args[0] > 'z'))
|
if (args.Size() != 0 && !(args[0] & VARF_Optional))
|
||||||
{
|
{
|
||||||
sc.ScriptError("Incompatible code pointer '%s'", sc.String);
|
sc.ScriptError("Incompatible code pointer '%s'", sc.String);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1145,6 +1145,25 @@ size_t PFunction::PropagateMark()
|
||||||
return Variants.Size() * sizeof(Variants[0]) + Super::PropagateMark();
|
return Variants.Size() * sizeof(Variants[0]) + Super::PropagateMark();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PFunction :: AddVariant
|
||||||
|
//
|
||||||
|
// Adds a new variant for this function. Does not check if a matching
|
||||||
|
// variant already exists.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
unsigned PFunction::AddVariant(PPrototype *proto, TArray<DWORD> &argflags, VMFunction *impl)
|
||||||
|
{
|
||||||
|
Variant variant;
|
||||||
|
|
||||||
|
variant.Proto = proto;
|
||||||
|
variant.ArgFlags = argflags;
|
||||||
|
variant.Implementation = impl;
|
||||||
|
return Variants.Push(variant);
|
||||||
|
}
|
||||||
|
|
||||||
/* PClass *****************************************************************/
|
/* PClass *****************************************************************/
|
||||||
|
|
||||||
IMPLEMENT_POINTY_CLASS(PClass)
|
IMPLEMENT_POINTY_CLASS(PClass)
|
||||||
|
@ -1814,9 +1833,6 @@ CCMD(typetable)
|
||||||
IMPLEMENT_ABSTRACT_CLASS(PSymbol);
|
IMPLEMENT_ABSTRACT_CLASS(PSymbol);
|
||||||
IMPLEMENT_CLASS(PSymbolConst);
|
IMPLEMENT_CLASS(PSymbolConst);
|
||||||
IMPLEMENT_CLASS(PSymbolVariable);
|
IMPLEMENT_CLASS(PSymbolVariable);
|
||||||
IMPLEMENT_POINTY_CLASS(PSymbolActionFunction)
|
|
||||||
DECLARE_POINTER(Function)
|
|
||||||
END_POINTERS
|
|
||||||
IMPLEMENT_POINTY_CLASS(PSymbolVMFunction)
|
IMPLEMENT_POINTY_CLASS(PSymbolVMFunction)
|
||||||
DECLARE_POINTER(Function)
|
DECLARE_POINTER(Function)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
|
@ -64,23 +64,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// An action function -------------------------------------------------------
|
// An action function -------------------------------------------------------
|
||||||
//
|
|
||||||
// The Arguments string is a string of characters as understood by
|
|
||||||
// the DECORATE parser:
|
|
||||||
//
|
|
||||||
// If the letter is uppercase, it is required. Lowercase letters are optional.
|
|
||||||
// i = integer
|
|
||||||
// f = fixed point
|
|
||||||
// s = sound name
|
|
||||||
// m = actor name
|
|
||||||
// t = string
|
|
||||||
// l = jump label
|
|
||||||
// c = color
|
|
||||||
// x = expression
|
|
||||||
// y = expression
|
|
||||||
// If the final character is a +, the previous parameter is repeated indefinitely,
|
|
||||||
// and an "imaginary" first parameter is inserted containing the total number of
|
|
||||||
// parameters passed.
|
|
||||||
struct FState;
|
struct FState;
|
||||||
struct StateCallData;
|
struct StateCallData;
|
||||||
class VMFrameStack;
|
class VMFrameStack;
|
||||||
|
@ -89,18 +73,6 @@ struct VMReturn;
|
||||||
typedef int (*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
typedef int (*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
||||||
class VMFunction;
|
class VMFunction;
|
||||||
|
|
||||||
class PSymbolActionFunction : public PSymbol
|
|
||||||
{
|
|
||||||
DECLARE_CLASS(PSymbolActionFunction, PSymbol);
|
|
||||||
HAS_OBJECT_POINTERS;
|
|
||||||
public:
|
|
||||||
FString Arguments;
|
|
||||||
VMFunction *Function;
|
|
||||||
|
|
||||||
PSymbolActionFunction(FName name) : PSymbol(name) {}
|
|
||||||
PSymbolActionFunction() : PSymbol(NAME_None) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// A VM function ------------------------------------------------------------
|
// A VM function ------------------------------------------------------------
|
||||||
|
|
||||||
class PSymbolVMFunction : public PSymbol
|
class PSymbolVMFunction : public PSymbol
|
||||||
|
@ -469,6 +441,7 @@ public:
|
||||||
TArray<Variant> Variants;
|
TArray<Variant> Variants;
|
||||||
DWORD Flags;
|
DWORD Flags;
|
||||||
|
|
||||||
|
unsigned AddVariant(PPrototype *proto, TArray<DWORD> &argflags, VMFunction *impl);
|
||||||
|
|
||||||
size_t PropagateMark();
|
size_t PropagateMark();
|
||||||
|
|
||||||
|
|
|
@ -233,24 +233,24 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
|
||||||
{
|
{
|
||||||
if (extra.bExplosive)
|
if (extra.bExplosive)
|
||||||
{
|
{
|
||||||
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Explode")->Function);
|
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Explode")->Variants[0].Implementation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The first frame plays the death sound and
|
// The first frame plays the death sound and
|
||||||
// the second frame makes it nonsolid.
|
// the second frame makes it nonsolid.
|
||||||
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Scream")->Function);
|
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_Scream")->Variants[0].Implementation);
|
||||||
if (extra.bSolidOnDeath)
|
if (extra.bSolidOnDeath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (extra.DeathStart + 1 < extra.DeathEnd)
|
else if (extra.DeathStart + 1 < extra.DeathEnd)
|
||||||
{
|
{
|
||||||
type->OwnedStates[extra.DeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking")->Function);
|
type->OwnedStates[extra.DeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking")->Variants[0].Implementation);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_ScreamAndUnblock")->Function);
|
type->OwnedStates[extra.DeathStart].SetAction(FindGlobalActionFunction("A_ScreamAndUnblock")->Variants[0].Implementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra.DeathHeight == 0)
|
if (extra.DeathHeight == 0)
|
||||||
|
@ -282,17 +282,17 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
|
||||||
|
|
||||||
// The first frame plays the burn sound and
|
// The first frame plays the burn sound and
|
||||||
// the second frame makes it nonsolid.
|
// the second frame makes it nonsolid.
|
||||||
type->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveSound")->Function);
|
type->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveSound")->Variants[0].Implementation);
|
||||||
if (extra.bSolidOnBurn)
|
if (extra.bSolidOnBurn)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (extra.FireDeathStart + 1 < extra.FireDeathEnd)
|
else if (extra.FireDeathStart + 1 < extra.FireDeathEnd)
|
||||||
{
|
{
|
||||||
type->OwnedStates[extra.FireDeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking")->Function);
|
type->OwnedStates[extra.FireDeathStart+1].SetAction(FindGlobalActionFunction("A_NoBlocking")->Variants[0].Implementation);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveAndUnblock")->Function);
|
type->OwnedStates[extra.FireDeathStart].SetAction(FindGlobalActionFunction("A_ActiveAndUnblock")->Variants[0].Implementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
|
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
|
||||||
|
@ -313,14 +313,14 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
|
||||||
type->OwnedStates[i].Tics = 5;
|
type->OwnedStates[i].Tics = 5;
|
||||||
type->OwnedStates[i].TicRange = 0;
|
type->OwnedStates[i].TicRange = 0;
|
||||||
type->OwnedStates[i].Misc1 = 0;
|
type->OwnedStates[i].Misc1 = 0;
|
||||||
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeath")->Function);
|
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeath")->Variants[0].Implementation);
|
||||||
|
|
||||||
i = type->NumOwnedStates - 1;
|
i = type->NumOwnedStates - 1;
|
||||||
type->OwnedStates[i].NextState = &type->OwnedStates[i];
|
type->OwnedStates[i].NextState = &type->OwnedStates[i];
|
||||||
type->OwnedStates[i].Tics = 1;
|
type->OwnedStates[i].Tics = 1;
|
||||||
type->OwnedStates[i].TicRange = 0;
|
type->OwnedStates[i].TicRange = 0;
|
||||||
type->OwnedStates[i].Misc1 = 0;
|
type->OwnedStates[i].Misc1 = 0;
|
||||||
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeathChunks")->Function);
|
type->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeathChunks")->Variants[0].Implementation);
|
||||||
bag.statedef.SetStateLabel("Ice", &type->OwnedStates[extra.IceDeathStart]);
|
bag.statedef.SetStateLabel("Ice", &type->OwnedStates[extra.IceDeathStart]);
|
||||||
}
|
}
|
||||||
else if (extra.bGenericIceDeath)
|
else if (extra.bGenericIceDeath)
|
||||||
|
|
|
@ -188,7 +188,7 @@ AFuncDesc *FindFunction(const char * string);
|
||||||
|
|
||||||
void ParseStates(FScanner &sc, PClassActor *actor, AActor *defaults, Baggage &bag);
|
void ParseStates(FScanner &sc, PClassActor *actor, AActor *defaults, Baggage &bag);
|
||||||
|
|
||||||
PSymbolActionFunction *FindGlobalActionFunction(const char *name);
|
PFunction *FindGlobalActionFunction(const char *name);
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -201,7 +201,7 @@ void SetReplacement(FScanner &sc, PClassActor *info, FName replaceName);
|
||||||
|
|
||||||
void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
|
void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
|
||||||
void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag);
|
void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag);
|
||||||
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, char type, bool constant);
|
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant);
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
|
|
@ -553,9 +553,9 @@ FVariableInfo *FindVariable(const char * string, const PClass *cls)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PSymbolActionFunction *FindGlobalActionFunction(const char *name)
|
PFunction *FindGlobalActionFunction(const char *name)
|
||||||
{
|
{
|
||||||
return dyn_cast<PSymbolActionFunction>(RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false));
|
return dyn_cast<PFunction>(RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,35 +67,46 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def);
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, char type, bool constant)
|
FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant)
|
||||||
{
|
{
|
||||||
FxExpression *x = NULL;
|
FxExpression *x = NULL;
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
switch(type)
|
if (type == TypeSound)
|
||||||
{
|
{
|
||||||
case 'S':
|
|
||||||
case 's': // Sound name
|
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
x = new FxConstant(FSoundID(sc.String), sc);
|
x = new FxConstant(FSoundID(sc.String), sc);
|
||||||
break;
|
}
|
||||||
|
else if (type == TypeSInt32 || type == TypeFloat64)
|
||||||
case 'M':
|
{
|
||||||
case 'm': // Actor name
|
x = ParseExpression (sc, cls);
|
||||||
|
if (constant && !x->isConstant())
|
||||||
|
{
|
||||||
|
sc.ScriptMessage("Default parameter must be constant.");
|
||||||
|
FScriptPosition::ErrorCounter++;
|
||||||
|
}
|
||||||
|
// Do automatic coercion between ints and floats.
|
||||||
|
if (type == TypeSInt32)
|
||||||
|
{
|
||||||
|
if (x->ValueType != VAL_Int)
|
||||||
|
{
|
||||||
|
x = new FxIntCast(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x->ValueType != VAL_Float)
|
||||||
|
{
|
||||||
|
x = new FxFloatCast(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == TypeName || type == TypeString)
|
||||||
|
{
|
||||||
sc.SetEscape(true);
|
sc.SetEscape(true);
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
sc.SetEscape(false);
|
sc.SetEscape(false);
|
||||||
x = new FxClassTypeCast(RUNTIME_CLASS(AActor), new FxConstant(FName(sc.String), sc));
|
if (type == TypeName)
|
||||||
break;
|
|
||||||
|
|
||||||
case 'N':
|
|
||||||
case 'n': // name
|
|
||||||
case 'T':
|
|
||||||
case 't': // String
|
|
||||||
sc.SetEscape(true);
|
|
||||||
sc.MustGetString();
|
|
||||||
sc.SetEscape(false);
|
|
||||||
if (type == 'n' || type == 'N')
|
|
||||||
{
|
{
|
||||||
x = new FxConstant(sc.String[0] ? FName(sc.String) : NAME_None, sc);
|
x = new FxConstant(sc.String[0] ? FName(sc.String) : NAME_None, sc);
|
||||||
}
|
}
|
||||||
|
@ -103,10 +114,9 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, char type, bool con
|
||||||
{
|
{
|
||||||
x = new FxConstant(strbin1(sc.String), sc);
|
x = new FxConstant(strbin1(sc.String), sc);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
else if (type == TypeColor)
|
||||||
case 'C':
|
{
|
||||||
case 'c': // Color
|
|
||||||
sc.MustGetString ();
|
sc.MustGetString ();
|
||||||
if (sc.Compare("none"))
|
if (sc.Compare("none"))
|
||||||
{
|
{
|
||||||
|
@ -122,16 +132,12 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, char type, bool con
|
||||||
// 0 needs to be the default so we have to mark the color.
|
// 0 needs to be the default so we have to mark the color.
|
||||||
v = MAKEARGB(1, RPART(c), GPART(c), BPART(c));
|
v = MAKEARGB(1, RPART(c), GPART(c), BPART(c));
|
||||||
}
|
}
|
||||||
{
|
ExpVal val;
|
||||||
ExpVal val;
|
val.Type = VAL_Color;
|
||||||
val.Type = VAL_Color;
|
val.Int = v;
|
||||||
val.Int = v;
|
x = new FxConstant(val, sc);
|
||||||
x = new FxConstant(val, sc);
|
}
|
||||||
break;
|
else if (type == TypeState)
|
||||||
}
|
|
||||||
|
|
||||||
case 'L':
|
|
||||||
case 'l':
|
|
||||||
{
|
{
|
||||||
// This forces quotation marks around the state name.
|
// This forces quotation marks around the state name.
|
||||||
sc.MustGetToken(TK_StringConst);
|
sc.MustGetToken(TK_StringConst);
|
||||||
|
@ -151,39 +157,18 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, char type, bool con
|
||||||
{
|
{
|
||||||
x = new FxMultiNameState(sc.String, sc);
|
x = new FxMultiNameState(sc.String, sc);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if (type->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||||
case 'X':
|
{ // Actor name
|
||||||
case 'x':
|
sc.SetEscape(true);
|
||||||
case 'Y':
|
sc.MustGetString();
|
||||||
case 'y':
|
sc.SetEscape(false);
|
||||||
x = ParseExpression (sc, cls);
|
x = new FxClassTypeCast(static_cast<PClassPointer *>(type)->ClassRestriction, new FxConstant(FName(sc.String), sc));
|
||||||
if (constant && !x->isConstant())
|
}
|
||||||
{
|
else
|
||||||
sc.ScriptMessage("Default parameter must be constant.");
|
{
|
||||||
FScriptPosition::ErrorCounter++;
|
assert(false && "Unknown parameter type");
|
||||||
}
|
x = NULL;
|
||||||
// Do automatic coercion between ints and floats.
|
|
||||||
if (type == 'x' || type == 'X')
|
|
||||||
{
|
|
||||||
if (x->ValueType != VAL_Int)
|
|
||||||
{
|
|
||||||
x = new FxIntCast(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (x->ValueType != VAL_Float)
|
|
||||||
{
|
|
||||||
x = new FxFloatCast(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -917,15 +902,12 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag)
|
||||||
|
|
||||||
static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
||||||
{
|
{
|
||||||
enum
|
|
||||||
{
|
|
||||||
OPTIONAL = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
const AFuncDesc *afd;
|
const AFuncDesc *afd;
|
||||||
FName funcname;
|
FName funcname;
|
||||||
FString args;
|
TArray<PType *> rets;
|
||||||
|
TArray<PType *> args;
|
||||||
|
TArray<DWORD> argflags;
|
||||||
|
|
||||||
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
|
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
|
||||||
{
|
{
|
||||||
|
@ -934,6 +916,11 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
||||||
}
|
}
|
||||||
|
|
||||||
sc.MustGetToken(TK_Native);
|
sc.MustGetToken(TK_Native);
|
||||||
|
// check for a return value
|
||||||
|
if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Bool))
|
||||||
|
{
|
||||||
|
rets.Push(TypeSInt32);
|
||||||
|
}
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
funcname = sc.String;
|
funcname = sc.String;
|
||||||
afd = FindFunction(sc.String);
|
afd = FindFunction(sc.String);
|
||||||
|
@ -942,13 +929,18 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
||||||
sc.ScriptMessage ("The function '%s' has not been exported from the executable.", sc.String);
|
sc.ScriptMessage ("The function '%s' has not been exported from the executable.", sc.String);
|
||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
|
args.Push(NewClassPointer(cls)), argflags.Push(0); // implied self pointer
|
||||||
|
args.Push(NewClassPointer(RUNTIME_CLASS(AActor))), argflags.Push(0); // implied stateowner pointer
|
||||||
|
args.Push(TypeState), argflags.Push(0); // implied callingstate pointer
|
||||||
|
|
||||||
sc.MustGetToken('(');
|
sc.MustGetToken('(');
|
||||||
if (!sc.CheckToken(')'))
|
if (!sc.CheckToken(')'))
|
||||||
{
|
{
|
||||||
while (sc.TokenType != ')')
|
while (sc.TokenType != ')')
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
char type = '@';
|
PType *type = NULL;
|
||||||
|
PClass *restrict = NULL;
|
||||||
|
|
||||||
// Retrieve flags before type name
|
// Retrieve flags before type name
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -967,32 +959,42 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
||||||
{
|
{
|
||||||
case TK_Bool:
|
case TK_Bool:
|
||||||
case TK_Int:
|
case TK_Int:
|
||||||
type = 'x';
|
type = TypeSInt32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TK_Float:
|
case TK_Float:
|
||||||
type = 'y';
|
type = TypeFloat64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TK_Sound: type = 's'; break;
|
case TK_Sound: type = TypeSound; break;
|
||||||
case TK_String: type = 't'; break;
|
case TK_String: type = TypeString; break;
|
||||||
case TK_Name: type = 'n'; break;
|
case TK_Name: type = TypeName; break;
|
||||||
case TK_State: type = 'l'; break;
|
case TK_State: type = TypeState; break;
|
||||||
case TK_Color: type = 'c'; break;
|
case TK_Color: type = TypeColor; break;
|
||||||
case TK_Class:
|
case TK_Class:
|
||||||
sc.MustGetToken('<');
|
sc.MustGetToken('<');
|
||||||
sc.MustGetToken(TK_Identifier); // Skip class name, since the parser doesn't care
|
sc.MustGetToken(TK_Identifier); // Get class name
|
||||||
|
restrict = PClass::FindClass(sc.String);
|
||||||
|
if (restrict == NULL)
|
||||||
|
{
|
||||||
|
sc.ScriptMessage("Unknown class type %s", sc.String);
|
||||||
|
FScriptPosition::ErrorCounter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = NewClassPointer(restrict);
|
||||||
|
}
|
||||||
sc.MustGetToken('>');
|
sc.MustGetToken('>');
|
||||||
type = 'm';
|
|
||||||
break;
|
break;
|
||||||
case TK_Ellipsis:
|
case TK_Ellipsis:
|
||||||
type = '+';
|
// Making the final type NULL signals a varargs function.
|
||||||
|
type = NULL;
|
||||||
sc.MustGetToken(')');
|
sc.MustGetToken(')');
|
||||||
sc.UnGet();
|
sc.UnGet();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc.ScriptMessage ("Unknown variable type %s", sc.TokenName(sc.TokenType, sc.String).GetChars());
|
sc.ScriptMessage ("Unknown variable type %s", sc.TokenName(sc.TokenType, sc.String).GetChars());
|
||||||
type = 'x';
|
type = TypeSInt32;
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1008,16 +1010,13 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
||||||
|
|
||||||
if (sc.CheckToken('='))
|
if (sc.CheckToken('='))
|
||||||
{
|
{
|
||||||
flags |= OPTIONAL;
|
flags |= VARF_Optional;
|
||||||
FxExpression *def = ParseParameter(sc, cls, type, true);
|
FxExpression *def = ParseParameter(sc, cls, type, true);
|
||||||
delete def;
|
delete def;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & OPTIONAL) && type != '+')
|
args.Push(type);
|
||||||
{
|
argflags.Push(flags);
|
||||||
type -= 'a' - 'A';
|
|
||||||
}
|
|
||||||
args += type;
|
|
||||||
sc.MustGetAnyToken();
|
sc.MustGetAnyToken();
|
||||||
if (sc.TokenType != ',' && sc.TokenType != ')')
|
if (sc.TokenType != ',' && sc.TokenType != ')')
|
||||||
{
|
{
|
||||||
|
@ -1028,14 +1027,14 @@ static void ParseActionDef (FScanner &sc, PClassActor *cls)
|
||||||
sc.MustGetToken(';');
|
sc.MustGetToken(';');
|
||||||
if (afd != NULL)
|
if (afd != NULL)
|
||||||
{
|
{
|
||||||
PSymbolActionFunction *sym = new PSymbolActionFunction(funcname);
|
PFunction *sym = new PFunction(funcname);
|
||||||
sym->Arguments = args;
|
sym->AddVariant(NewPrototype(rets, args), argflags, *(afd->VMPointer));
|
||||||
sym->Function = *(afd->VMPointer);
|
sym->Flags = VARF_Method | VARF_Action;
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
}
|
}
|
||||||
else if (cls->Symbols.AddSymbol (sym) == NULL)
|
else if (cls->Symbols.AddSymbol(sym) == NULL)
|
||||||
{
|
{
|
||||||
delete sym;
|
delete sym;
|
||||||
sc.ScriptMessage ("'%s' is already defined in class '%s'.",
|
sc.ScriptMessage ("'%s' is already defined in class '%s'.",
|
||||||
|
|
|
@ -100,7 +100,7 @@ bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag, FStateTempCall
|
||||||
sc.ScriptError ("Too many arguments to %s", specname.GetChars());
|
sc.ScriptError ("Too many arguments to %s", specname.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
tcall->Function = FindGlobalActionFunction("A_CallSpecial")->Function;
|
tcall->Function = FindGlobalActionFunction("A_CallSpecial")->Variants[0].Implementation;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -312,18 +312,29 @@ do_stop:
|
||||||
goto endofstate;
|
goto endofstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
PSymbolActionFunction *afd = dyn_cast<PSymbolActionFunction>(bag.Info->Symbols.FindSymbol (FName(sc.String, true), true));
|
PFunction *afd = dyn_cast<PFunction>(bag.Info->Symbols.FindSymbol(FName(sc.String, true), true));
|
||||||
if (afd != NULL)
|
if (afd != NULL)
|
||||||
{
|
{
|
||||||
tcall->Function = afd->Function;
|
tcall->Function = afd->Variants[0].Implementation;
|
||||||
if (!afd->Arguments.IsEmpty())
|
const TArray<PType *> ¶ms = afd->Variants[0].Proto->ArgumentTypes;
|
||||||
|
const TArray<DWORD> ¶mflags = afd->Variants[0].ArgFlags;
|
||||||
|
int numparams = (int)params.Size();
|
||||||
|
int pnum = 0;
|
||||||
|
if (afd->Flags & VARF_Method)
|
||||||
|
{
|
||||||
|
numparams--;
|
||||||
|
pnum++;
|
||||||
|
}
|
||||||
|
if (afd->Flags & VARF_Action)
|
||||||
|
{
|
||||||
|
numparams -= 2;
|
||||||
|
pnum += 2;
|
||||||
|
}
|
||||||
|
if (numparams > 0)
|
||||||
{
|
{
|
||||||
const char *params = afd->Arguments.GetChars();
|
|
||||||
int numparams = (int)afd->Arguments.Len();
|
|
||||||
|
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
if (!islower(*params))
|
if (!(paramflags[pnum] & VARF_Optional))
|
||||||
{
|
{
|
||||||
sc.MustGetStringName("(");
|
sc.MustGetStringName("(");
|
||||||
}
|
}
|
||||||
|
@ -335,13 +346,10 @@ do_stop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool varargs = params[numparams - 1] == '+';
|
while (numparams > 0)
|
||||||
int varargcount = 0;
|
|
||||||
|
|
||||||
while (*params)
|
|
||||||
{
|
{
|
||||||
FxExpression *x;
|
FxExpression *x;
|
||||||
if ((*params == 'l' || *params == 'L') && sc.CheckNumber())
|
if (params[pnum] == TypeState && sc.CheckNumber())
|
||||||
{
|
{
|
||||||
// Special case: State label as an offset
|
// Special case: State label as an offset
|
||||||
if (sc.Number > 0 && statestring.Len() > 1)
|
if (sc.Number > 0 && statestring.Len() > 1)
|
||||||
|
@ -349,7 +357,7 @@ do_stop:
|
||||||
sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n");
|
sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
v=sc.Number;
|
v = sc.Number;
|
||||||
if (v<0)
|
if (v<0)
|
||||||
{
|
{
|
||||||
sc.ScriptError("Negative jump offsets are not allowed");
|
sc.ScriptError("Negative jump offsets are not allowed");
|
||||||
|
@ -367,22 +375,23 @@ do_stop:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Use the generic parameter parser for everything else
|
// Use the generic parameter parser for everything else
|
||||||
x = ParseParameter(sc, bag.Info, *params, false);
|
x = ParseParameter(sc, bag.Info, params[pnum], false);
|
||||||
}
|
}
|
||||||
tcall->Parameters.Push(new FxParameter(x));
|
tcall->Parameters.Push(new FxParameter(x));
|
||||||
params++;
|
pnum++;
|
||||||
varargcount++;
|
numparams--;
|
||||||
if (*params)
|
if (numparams > 0)
|
||||||
{
|
{
|
||||||
if (*params == '+')
|
if (params[pnum] == NULL)
|
||||||
{
|
{ // varargs function
|
||||||
if (sc.CheckString(")"))
|
if (sc.CheckString(")"))
|
||||||
{
|
{
|
||||||
goto endofstate;
|
goto endofstate;
|
||||||
}
|
}
|
||||||
params--;
|
pnum--;
|
||||||
|
numparams++;
|
||||||
}
|
}
|
||||||
else if ((islower(*params) || *params=='!') && sc.CheckString(")"))
|
else if ((paramflags[pnum] & VARF_Optional) && sc.CheckString(")"))
|
||||||
{
|
{
|
||||||
goto endofstate;
|
goto endofstate;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue