From 4df1ea63b57ec7b517678834ed8ae9efb2bbb835 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 22 Apr 2012 08:17:27 +0000 Subject: [PATCH] - added DavidPH's sqrt for DECORATE submission. SVN r3586 (trunk) --- src/CMakeLists.txt | 1 + src/namedef.h | 1 + src/thingdef/thingdef_exp.h | 32 +- src/thingdef/thingdef_expression.cpp | 83 +-- src/thingdef/thingdef_function.cpp | 187 +++++++ zdoom.vcproj | 754 ++++++++++++++------------- 6 files changed, 609 insertions(+), 449 deletions(-) create mode 100644 src/thingdef/thingdef_function.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 18ed5d91b0..780f1f9ccc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -873,6 +873,7 @@ add_executable( zdoom WIN32 thingdef/thingdef_data.cpp thingdef/thingdef_exp.cpp thingdef/thingdef_expression.cpp + thingdef/thingdef_function.cpp thingdef/thingdef_parse.cpp thingdef/thingdef_properties.cpp thingdef/thingdef_states.cpp diff --git a/src/namedef.h b/src/namedef.h index b69f1fb3f0..8a68f50e3f 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -274,6 +274,7 @@ xx(MomZ) xx(Abs) xx(ACS_NamedExecuteWithResult) xx(CallACS) +xx(Sqrt) // Various actor names which are used internally xx(MapSpot) diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 5ef7b9bccb..77af37f539 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -710,17 +710,41 @@ public: class FxGlobalFunctionCall : public FxExpression { +public: + typedef FxExpression *(*Creator)(FName, FArgumentList *, const FScriptPosition &); + struct CreatorAdder + { + CreatorAdder(FName methodname, Creator creator) + { + FxGlobalFunctionCall::AddCreator(methodname, creator); + } + }; + + static void AddCreator(FName methodname, Creator creator); + static FxExpression *StaticCreate(FName methodname, FArgumentList *args, const FScriptPosition &pos); + +protected: FName Name; FArgumentList *ArgList; -public: - FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos); ~FxGlobalFunctionCall(); - FxExpression *Resolve(FCompileContext&); - ExpVal EvalExpression (AActor *self); + + FxExpression *ResolveArgs(FCompileContext &, unsigned min, unsigned max, bool numeric); }; +#define GLOBALFUNCTION_DEFINE(CLASS) \ +FxGlobalFunctionCall_##CLASS(FName methodname, FArgumentList *args, const FScriptPosition &pos) \ +: FxGlobalFunctionCall(methodname, args, pos) {} \ +static FxExpression *StaticCreate(FName methodname, FArgumentList *args, const FScriptPosition &pos) \ + {return new FxGlobalFunctionCall_##CLASS(methodname, args, pos);} + +#define GLOBALFUNCTION_ADDER(CLASS) GLOBALFUNCTION_ADDER_NAMED(CLASS, CLASS) + +#define GLOBALFUNCTION_ADDER_NAMED(CLASS,NAME) \ +static FxGlobalFunctionCall::CreatorAdder FxGlobalFunctionCall_##NAME##Adder \ +(NAME_##NAME, FxGlobalFunctionCall_##CLASS::StaticCreate) + //========================================================================== // diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index e18e0fba97..64f5c9a4fc 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -2279,22 +2279,6 @@ FxFunctionCall::~FxFunctionCall() FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) { - // There's currently only 2 global functions. - // This will have to change later! - if (MethodName == NAME_Sin || MethodName == NAME_Cos) - { - if (Self != NULL) - { - ScriptPosition.Message(MSG_ERROR, "Global variables cannot have a self pointer"); - delete this; - return NULL; - } - FxExpression *x = new FxGlobalFunctionCall(MethodName, ArgList, ScriptPosition); - ArgList = NULL; - delete this; - return x->Resolve(ctx); - } - int min, max, special; if (MethodName == NAME_ACS_NamedExecuteWithResult || MethodName == NAME_CallACS) { @@ -2328,6 +2312,19 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) delete this; return x->Resolve(ctx); } + else + { + if (Self != NULL) + { + ScriptPosition.Message(MSG_ERROR, "Global variables cannot have a self pointer"); + delete this; + return NULL; + } + FxExpression *x = FxGlobalFunctionCall::StaticCreate(MethodName, ArgList, ScriptPosition); + ArgList = NULL; + delete this; + return x->Resolve(ctx); + } ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); delete this; @@ -2474,60 +2471,6 @@ FxGlobalFunctionCall::~FxGlobalFunctionCall() SAFE_DELETE(ArgList); } -//========================================================================== -// -// // so far just a quick hack to handle sin and cos -// -//========================================================================== - -FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx) -{ - CHECKRESOLVED(); - - if (ArgList == NULL || ArgList->Size() != 1) - { - ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", Name.GetChars()); - delete this; - return NULL; - } - - (*ArgList)[0] = (*ArgList)[0]->Resolve(ctx); - if ((*ArgList)[0] == NULL) - { - delete this; - return NULL; - } - - if (!(*ArgList)[0]->ValueType.isNumeric()) - { - ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); - delete this; - return NULL; - } - ValueType = VAL_Float; - return this; -} - - -//========================================================================== -// -// -// -//========================================================================== - -ExpVal FxGlobalFunctionCall::EvalExpression (AActor *self) -{ - double v = (*ArgList)[0]->EvalExpression(self).GetFloat(); - ExpVal ret; - ret.Type = VAL_Float; - - // shall we use the CRT's sin and cos functions? - angle_t angle = angle_t(v * ANGLE_90/90.); - if (Name == NAME_Sin) ret.Float = FIXED2FLOAT (finesine[angle>>ANGLETOFINESHIFT]); - else ret.Float = FIXED2FLOAT (finecosine[angle>>ANGLETOFINESHIFT]); - return ret; -} - //========================================================================== // diff --git a/src/thingdef/thingdef_function.cpp b/src/thingdef/thingdef_function.cpp new file mode 100644 index 0000000000..2858e9a86e --- /dev/null +++ b/src/thingdef/thingdef_function.cpp @@ -0,0 +1,187 @@ +/* +** thingdef_function.cpp +** +** Expression function evaluation. +** +**--------------------------------------------------------------------------- +** Copyright 2012 David Hill +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be +** covered by the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or (at +** your option) any later version. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include + +#include "tables.h" +#include "tarray.h" +#include "thingdef.h" +#include "thingdef_exp.h" + +static TMap CreatorMap; + +//========================================================================== +// +// FxGlobalFunctionCall::AddCreator +// +//========================================================================== + +void FxGlobalFunctionCall::AddCreator(FName methodname, Creator creator) +{ + CreatorMap.Insert(methodname, creator); +} + + +//========================================================================== +// +// FxGlobalFunctionCall::ResolveArgs +// +// Handles common Resolve processing of args. +// +//========================================================================== + +FxExpression *FxGlobalFunctionCall::ResolveArgs(FCompileContext &ctx, unsigned min, unsigned max, bool numeric) +{ + unsigned i = ArgList ? ArgList->Size() : 0; + + if (i < min || i > max) + { + ScriptPosition.Message(MSG_ERROR, "%s expects %u to %u parameters", Name.GetChars(), min, max); + delete this; + return NULL; + } + + while (i--) + { + if (!((*ArgList)[i] = (*ArgList)[i]->Resolve(ctx))) + { + delete this; + return NULL; + } + + if (numeric && !(*ArgList)[i]->ValueType.isNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter"); + delete this; + return NULL; + } + } + + return this; +} + +//========================================================================== +// +// FxGlobalFunctionCall::StaticCreate +// +//========================================================================== + +FxExpression *FxGlobalFunctionCall::StaticCreate +(FName methodname, FArgumentList *args, const FScriptPosition &pos) +{ + Creator *creator = CreatorMap.CheckKey(methodname); + + if (!creator) + { + pos.Message(MSG_ERROR, "Call to unknown function '%s'", methodname.GetChars()); + return NULL; + } + + return (*creator)(methodname, args, pos); +} + +//========================================================================== +// +// Function: cos/sin +// +//========================================================================== + +class FxGlobalFunctionCall_Cos : public FxGlobalFunctionCall +{ +public: + GLOBALFUNCTION_DEFINE(Cos); + + FxExpression *Resolve(FCompileContext& ctx) + { + CHECKRESOLVED(); + + ValueType = VAL_Float; + return ResolveArgs(ctx, 1, 1, true); + } + + ExpVal EvalExpression(AActor *self) + { + double v = (*ArgList)[0]->EvalExpression(self).GetFloat(); + ExpVal ret; + ret.Type = VAL_Float; + + // shall we use the CRT's sin and cos functions? + angle_t angle = angle_t(v * ANGLE_90/90.); + if (Name == NAME_Sin) ret.Float = FIXED2DBL (finesine[angle>>ANGLETOFINESHIFT]); + else ret.Float = FIXED2DBL (finecosine[angle>>ANGLETOFINESHIFT]); + return ret; + } +}; + +GLOBALFUNCTION_ADDER(Cos); +GLOBALFUNCTION_ADDER_NAMED(Cos, Sin); + +//========================================================================== +// +// Function: sqrt +// +//========================================================================== + +class FxGlobalFunctionCall_Sqrt : public FxGlobalFunctionCall +{ +public: + GLOBALFUNCTION_DEFINE(Sqrt); + + FxExpression *Resolve(FCompileContext& ctx) + { + CHECKRESOLVED(); + + if (!ResolveArgs(ctx, 1, 1, true)) + return NULL; + + ValueType = VAL_Float; + return this; + } + + ExpVal EvalExpression(AActor *self) + { + ExpVal ret; + ret.Type = VAL_Float; + ret.Float = sqrt((*ArgList)[0]->EvalExpression(self).GetFloat()); + return ret; + } +}; + +GLOBALFUNCTION_ADDER(Sqrt); + diff --git a/zdoom.vcproj b/zdoom.vcproj index 4601991fa3..ba01a82343 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -1840,14 +1848,6 @@ Outputs="$(IntDir)/$(InputName).obj" /> - - - @@ -2037,14 +2037,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -2055,6 +2047,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - @@ -2485,6 +2477,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -2783,7 +2783,7 @@ /> + + @@ -3746,7 +3750,7 @@ /> - - - + + +