diff --git a/src/namedef.h b/src/namedef.h index 323d6f29c4..83f4aca9b0 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -280,7 +280,10 @@ xx(Cast) // 'damage type' for the cast call // Special names for thingdef_exp.cpp xx(Random) +xx(FRandom) xx(Random2) +xx(RandomPick) +xx(FRandomPick) xx(Cos) xx(Sin) xx(Alpha) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 4a838f89a0..6ebd9a413b 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -185,14 +185,6 @@ std2: '#include' { RET(TK_Include); } 'fixed_t' { RET(TK_Fixed_t); } 'angle_t' { RET(TK_Angle_t); } - 'abs' { RET(TK_Abs); } - 'random' { RET(TK_Random); } - 'random2' { RET(TK_Random2); } - 'frandom' { RET(TK_FRandom); } - 'randompick' { RET(TK_RandomPick); } - 'frandompick' { RET(TK_FRandomPick); } - 'min' { RET(TK_Min); } - 'max' { RET(TK_Max); } L (L|D)* { RET(TK_Identifier); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 4dcddd3326..30a8201b9c 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -113,10 +113,6 @@ xx(TK_Stop, "'stop'") xx(TK_Include, "'include'") xx(TK_Fixed_t, "'fixed_t'") xx(TK_Angle_t, "'angle_t'") -xx(TK_Abs, "'abs'") -xx(TK_Random, "'random'") -xx(TK_Random2, "'random2'") -xx(TK_FRandom, "'frandom'") xx(TK_Is, "'is'") xx(TK_Replaces, "'replaces'") @@ -126,10 +122,6 @@ xx(TK_Array, "'array'") xx(TK_In, "'in'") xx(TK_SizeOf, "'sizeof'") xx(TK_AlignOf, "'alignof'") -xx(TK_RandomPick, "'randompick'") -xx(TK_FRandomPick, "'frandompick'") -xx(TK_Min, "'min'") -xx(TK_Max, "'max'") xx(TK_States, "'states'") xx(TK_Loop, "'loop'") xx(TK_Fail, "'fail'") diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index 2204a56527..7ef93563c1 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -52,6 +52,12 @@ FRandom pr_exrandom ("EX_Random"); +static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls); +static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls); +static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls); +static FxExpression *ParseAbs(FScanner &sc, PClassActor *cls); +static FxExpression *ParseMinMax(FScanner &sc, FName identifier, PClassActor *cls); + // // ParseExpression // [GRB] Parses an expression and stores it into Expression array @@ -349,161 +355,63 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) // a cheap way to get them working when people use "name" instead of 'name'. return new FxConstant(FName(sc.String), scpos); } - else if (sc.CheckToken(TK_Min) || sc.CheckToken(TK_Max)) - { - int type = sc.TokenType; - TArray list; - sc.MustGetToken('('); - for (;;) - { - FxExpression *expr = ParseExpressionM(sc, cls); - list.Push(expr); - if (sc.CheckToken(')')) - break; - sc.MustGetToken(','); - } - return new FxMinMax(list, type, sc); - } - else if (sc.CheckToken(TK_Random)) - { - FRandom *rng; - - if (sc.CheckToken('[')) - { - sc.MustGetToken(TK_Identifier); - rng = FRandom::StaticFindRNG(sc.String); - sc.MustGetToken(']'); - } - else - { - rng = &pr_exrandom; - } - sc.MustGetToken('('); - - FxExpression *min = ParseExpressionM (sc, cls); - sc.MustGetToken(','); - FxExpression *max = ParseExpressionM (sc, cls); - sc.MustGetToken(')'); - - return new FxRandom(rng, min, max, sc); - } - else if (sc.CheckToken(TK_RandomPick) || sc.CheckToken(TK_FRandomPick)) - { - bool floaty = sc.TokenType == TK_FRandomPick; - FRandom *rng; - TArray list; - list.Clear(); - int index = 0; - - if (sc.CheckToken('[')) - { - sc.MustGetToken(TK_Identifier); - rng = FRandom::StaticFindRNG(sc.String); - sc.MustGetToken(']'); - } - else - { - rng = &pr_exrandom; - } - sc.MustGetToken('('); - - for (;;) - { - FxExpression *expr = ParseExpressionM(sc, cls); - list.Push(expr); - if (sc.CheckToken(')')) - break; - sc.MustGetToken(','); - } - return new FxRandomPick(rng, list, floaty, sc); - } - else if (sc.CheckToken(TK_FRandom)) - { - FRandom *rng; - - if (sc.CheckToken('[')) - { - sc.MustGetToken(TK_Identifier); - rng = FRandom::StaticFindRNG(sc.String); - sc.MustGetToken(']'); - } - else - { - rng = &pr_exrandom; - } - sc.MustGetToken('('); - - FxExpression *min = ParseExpressionM (sc, cls); - sc.MustGetToken(','); - FxExpression *max = ParseExpressionM (sc, cls); - sc.MustGetToken(')'); - - return new FxFRandom(rng, min, max, sc); - } - else if (sc.CheckToken(TK_Random2)) - { - FRandom *rng; - - if (sc.CheckToken('[')) - { - sc.MustGetToken(TK_Identifier); - rng = FRandom::StaticFindRNG(sc.String); - sc.MustGetToken(']'); - } - else - { - rng = &pr_exrandom; - } - - sc.MustGetToken('('); - - FxExpression *mask = NULL; - - if (!sc.CheckToken(')')) - { - mask = ParseExpressionM(sc, cls); - sc.MustGetToken(')'); - } - return new FxRandom2(rng, mask, sc); - } - else if (sc.CheckToken(TK_Abs)) - { - sc.MustGetToken('('); - FxExpression *x = ParseExpressionM (sc, cls); - sc.MustGetToken(')'); - return new FxAbs(x); - } else if (sc.CheckToken(TK_Identifier)) { FName identifier = FName(sc.String); + FArgumentList *args; + PFunction *func; + + switch (identifier) + { + case NAME_Random: + case NAME_FRandom: + return ParseRandom(sc, identifier, cls); + case NAME_RandomPick: + case NAME_FRandomPick: + return ParseRandomPick(sc, identifier, cls); + case NAME_Random2: + return ParseRandom2(sc, cls); + default: + break; + } if (sc.CheckToken('(')) { - FArgumentList *args = new FArgumentList; - PFunction *func = dyn_cast(cls->Symbols.FindSymbol(identifier, true)); - try + switch (identifier) { - // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work. - if (func != NULL && identifier != NAME_ACS_NamedExecuteWithResult) + case NAME_Min: + case NAME_Max: + return ParseMinMax(sc, identifier, cls); + case NAME_Abs: + return ParseAbs(sc, cls); + default: + args = new FArgumentList; + func = dyn_cast(cls->Symbols.FindSymbol(identifier, true)); + try { - sc.UnGet(); - ParseFunctionParameters(sc, cls, *args, func, "", NULL); - return new FxVMFunctionCall(func, args, sc); - } - else if (!sc.CheckToken(')')) - { - do + // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work. + if (func != NULL && identifier != NAME_ACS_NamedExecuteWithResult) { - args->Push(ParseExpressionM (sc, cls)); + sc.UnGet(); + ParseFunctionParameters(sc, cls, *args, func, "", NULL); + return new FxVMFunctionCall(func, args, sc); } - while (sc.CheckToken(',')); - sc.MustGetToken(')'); + else if (!sc.CheckToken(')')) + { + do + { + args->Push(ParseExpressionM (sc, cls)); + } + while (sc.CheckToken(',')); + sc.MustGetToken(')'); + } + return new FxFunctionCall(NULL, identifier, args, sc); } - return new FxFunctionCall(NULL, identifier, args, sc); - } - catch (...) - { - delete args; - throw; + catch (...) + { + delete args; + throw; + } + break; } } else @@ -519,4 +427,97 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) return NULL; } +static FRandom *ParseRNG(FScanner &sc) +{ + FRandom *rng; + if (sc.CheckToken('[')) + { + sc.MustGetToken(TK_Identifier); + rng = FRandom::StaticFindRNG(sc.String); + sc.MustGetToken(']'); + } + else + { + rng = &pr_exrandom; + } + return rng; +} + +static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls) +{ + FRandom *rng = ParseRNG(sc); + + sc.MustGetToken('('); + FxExpression *min = ParseExpressionM (sc, cls); + sc.MustGetToken(','); + FxExpression *max = ParseExpressionM (sc, cls); + sc.MustGetToken(')'); + + if (identifier == NAME_Random) + { + return new FxRandom(rng, min, max, sc); + } + else + { + return new FxFRandom(rng, min, max, sc); + } +} + +static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls) +{ + bool floaty = identifier == NAME_FRandomPick; + FRandom *rng; + TArray list; + list.Clear(); + int index = 0; + + rng = ParseRNG(sc); + sc.MustGetToken('('); + + for (;;) + { + FxExpression *expr = ParseExpressionM(sc, cls); + list.Push(expr); + if (sc.CheckToken(')')) + break; + sc.MustGetToken(','); + } + return new FxRandomPick(rng, list, floaty, sc); +} + +static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls) +{ + FRandom *rng = ParseRNG(sc); + FxExpression *mask = NULL; + + sc.MustGetToken('('); + + if (!sc.CheckToken(')')) + { + mask = ParseExpressionM(sc, cls); + sc.MustGetToken(')'); + } + return new FxRandom2(rng, mask, sc); +} + +static FxExpression *ParseAbs(FScanner &sc, PClassActor *cls) +{ + FxExpression *x = ParseExpressionM (sc, cls); + sc.MustGetToken(')'); + return new FxAbs(x); +} + +static FxExpression *ParseMinMax(FScanner &sc, FName identifier, PClassActor *cls) +{ + TArray list; + for (;;) + { + FxExpression *expr = ParseExpressionM(sc, cls); + list.Push(expr); + if (sc.CheckToken(')')) + break; + sc.MustGetToken(','); + } + return new FxMinMax(list, identifier, sc); +} diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 330caf0a5f..294399d791 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -632,10 +632,10 @@ public: class FxMinMax : public FxExpression { TDeletingArray choices; - int Type; + FName Type; public: - FxMinMax(TArray &expr, int type, const FScriptPosition &pos); + FxMinMax(TArray &expr, FName type, const FScriptPosition &pos); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 8d0f158bab..833f3a3d5b 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -2043,11 +2043,11 @@ ExpEmit FxAbs::Emit(VMFunctionBuilder *build) // // //========================================================================== -FxMinMax::FxMinMax(TArray &expr, int type, const FScriptPosition &pos) +FxMinMax::FxMinMax(TArray &expr, FName type, const FScriptPosition &pos) : FxExpression(pos), Type(type) { assert(expr.Size() > 0); - assert(type == TK_Min || type == TK_Max); + assert(type == NAME_Min || type == NAME_Max); ValueType = VAL_Unknown; choices.Resize(expr.Size()); @@ -2132,7 +2132,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx) { ExpVal value = static_cast(choices[j])->GetValue(); assert(value.Type == ValueType.Type); - if (Type == TK_Min) + if (Type == NAME_Min) { if (value.Type == VAL_Float) { @@ -2213,7 +2213,7 @@ ExpEmit FxMinMax::Emit(VMFunctionBuilder *build) assert(OP_LEF_RK == OP_LEF_RR+1); assert(OP_LE_RK == OP_LE_RR+1); - if (Type == TK_Min) + if (Type == NAME_Min) { opcode = ValueType.Type == VAL_Float ? OP_LEF_RR : OP_LE_RR; opA = 1;