]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/SGExpression.hxx
Fix wrong difference calculation in SGExpression
[simgear.git] / simgear / structure / SGExpression.hxx
index 82dd8bbdc70138e67f49be47768e4cb005eab022..ffb9dd1ded2408b43797160ab597e6820cb0fa9f 100644 (file)
@@ -31,6 +31,7 @@
 #include <simgear/math/SGMath.hxx>
 #include <simgear/scene/model/persparam.hxx>
 #include <simgear/structure/exception.hxx>
+#include <simgear/structure/Singleton.hxx>
 
 /// Expression tree implementation.
 
@@ -121,6 +122,9 @@ public:
   T getValue(const simgear::expression::Binding* binding = 0) const
   { T value; eval(value, binding); return value; }
 
+  double getDoubleValue(const simgear::expression::Binding* binding = 0) const
+  { T value; eval(value, binding); return value; }
+
   virtual bool isConst() const { return false; }
   virtual SGExpression* simplify();
   virtual simgear::expression::Type getType() const
@@ -318,7 +322,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = acos(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+  { value = acos((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -331,7 +335,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = asin(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+  { value = asin((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -344,7 +348,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = atan(getOperand()->getValue(b)); }
+  { value = atan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -357,7 +361,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = ceil(getOperand()->getValue(b)); }
+  { value = ceil(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -370,7 +374,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = cos(getOperand()->getValue(b)); }
+  { value = cos(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -383,7 +387,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = cosh(getOperand()->getValue(b)); }
+  { value = cosh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -396,7 +400,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = exp(getOperand()->getValue(b)); }
+  { value = exp(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -409,7 +413,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = floor(getOperand()->getValue(b)); }
+  { value = floor(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -422,7 +426,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = log(getOperand()->getValue(b)); }
+  { value = log(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -435,7 +439,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = log10(getOperand()->getValue(b)); }
+  { value = log10(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -448,7 +452,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sin(getOperand()->getValue(b)); }
+  { value = sin(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -461,7 +465,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sinh(getOperand()->getValue(b)); }
+  { value = sinh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -487,7 +491,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sqrt(getOperand()->getValue(b)); }
+  { value = sqrt(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -500,7 +504,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = tan(getOperand()->getValue(b)); }
+  { value = tan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -513,7 +517,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = tanh(getOperand()->getValue(b)); }
+  { value = tanh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -730,7 +734,7 @@ public:
     : SGBinaryExpression<T>(expr0, expr1)
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = atan2(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+  { value = atan2(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -770,7 +774,7 @@ public:
     : SGBinaryExpression<T>(expr0, expr1)
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = pow(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+  { value = pow(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -793,6 +797,25 @@ public:
   using SGNaryExpression<T>::getOperand;
 };
 
+template<typename T>
+class SGDifferenceExpression : public SGNaryExpression<T> {
+public:
+  SGDifferenceExpression()
+  { }
+  SGDifferenceExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
+    : SGNaryExpression<T>(expr0, expr1)
+  { }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  {
+    value = getOperand(0)->getValue(b);
+    unsigned sz = SGNaryExpression<T>::getNumOperands();
+    for (unsigned i = 1; i < sz; ++i)
+      value -= getOperand(i)->getValue(b);
+  }
+  using SGNaryExpression<T>::getValue;
+  using SGNaryExpression<T>::getOperand;
+};
+
 template<typename T>
 class SGProductExpression : public SGNaryExpression<T> {
 public:
@@ -901,96 +924,137 @@ namespace simgear
 {
   namespace expression
   {
-    class Parser;
-    /**
-     * Function that parses a property tree, producing an expression.
-     */
-    typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
-                                     Parser* parser);
-    void addExpParser(const std::string&, exp_parser);
-    Expression* read(const SGPropertyNode* exp, Parser* parser = 0);
-    /**
-     * Constructor for registering parser functions.
-     */
-    struct ExpParserRegistrar
-    {
-      ExpParserRegistrar(const std::string& token, exp_parser parser)
-      {
-        addExpParser(token, parser);
-      }
-    };
-
-    struct ParseError : public sg_exception
-    {
+  struct ParseError : public sg_exception
+  {
       ParseError(const string& message = std::string())
-        : sg_exception(message) {}
-    };
+          : sg_exception(message) {}
+  };
     
-    // Support for binding variables around an expression.
-    class Binding
-    {
-    public:
+  // Support for binding variables around an expression.
+  class Binding
+  {
+  public:
       virtual ~Binding() {}
       const virtual Value* getBindings() const = 0;
       virtual Value* getBindings() = 0;
-    };
+  };
 
-    class VariableLengthBinding : public Binding
-    {
-    public:
+  class VariableLengthBinding : public Binding
+  {
+  public:
       const Value* getBindings() const
       {
-        if (_bindings.empty())
-          return 0;
-        else
-          return &_bindings[0];
+          if (_bindings.empty())
+              return 0;
+          else
+              return &_bindings[0];
       }
       Value* getBindings()
       {
-        if (_bindings.empty())
-          return 0;
-        else
-          return &_bindings[0];
+          if (_bindings.empty())
+              return 0;
+          else
+              return &_bindings[0];
       }
       std::vector<Value> _bindings;
-    };
+  };
 
-    template<int Size> class FixedLengthBinding : public Binding
-    {
-    public:
+  template<int Size> class FixedLengthBinding : public Binding
+  {
+  public:
       Value* getBindings()
       {
-        return &_bindings[0];
+          return &_bindings[0];
       }
       const Value* getBindings() const
       {
-        return &_bindings[0];
+          return &_bindings[0];
       }
       Value _bindings[Size];
-    };
+  };
 
-    struct VariableBinding
-    {
+  struct VariableBinding
+  {
       VariableBinding() : type(expression::DOUBLE), location(-1) {}
 
       VariableBinding(const std::string& name_, expression::Type type_,
                       int location_)
-        : name(name_), type(type_), location(location_)
+          : name(name_), type(type_), location(location_)
       {
       }
       std::string name;
       expression::Type type;
       int location;
-    };
+  };
 
-    class BindingLayout
-    {
-    public:
+  class BindingLayout
+  {
+  public:
       int addBinding(const std::string& name, expression::Type type);
       bool findBinding(const string& name, VariableBinding& result) const;
-    protected:
       std::vector<VariableBinding> bindings;
-    };
+  };
+
+  class Parser {
+  public:
+      typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
+                                        Parser* parser);
+      void addParser(const std::string& name, exp_parser parser)
+      {
+          getParserMap().insert(std::make_pair(name, parser));
+      }
+      Expression* read(const SGPropertyNode* exp)
+      {
+          ParserMap& map = getParserMap();
+          ParserMap::iterator itr = map.find(exp->getName());
+          if (itr == map.end())
+              throw ParseError(string("unknown expression ") + exp->getName());
+          exp_parser parser = itr->second;
+          return (*parser)(exp, this);
+      }
+      // XXX vector of SGSharedPtr?
+      bool readChildren(const SGPropertyNode* exp,
+                        std::vector<Expression*>& result);
+      /**
+       * Function that parses a property tree, producing an expression.
+       */
+      typedef std::map<const std::string, exp_parser> ParserMap;
+      virtual ParserMap& getParserMap() = 0;
+      /**
+       * After an expression is parsed, the binding layout may contain
+       * references that need to be bound during evaluation.
+       */
+      BindingLayout& getBindingLayout() { return _bindingLayout; }
+  protected:
+      BindingLayout _bindingLayout;
+  };
+
+  class ExpressionParser : public Parser
+  {
+  public:
+      ParserMap& getParserMap()
+      {
+          return ParserMapSingleton::instance()->_parserTable;
+      }
+      static void addExpParser(const std::string&, exp_parser);
+  protected:
+      struct ParserMapSingleton : public simgear::Singleton<ParserMapSingleton>
+      {
+          ParserMap _parserTable;
+      };
+  };
+
+  /**
+   * Constructor for registering parser functions.
+   */
+  struct ExpParserRegistrar
+  {
+      ExpParserRegistrar(const std::string& token, Parser::exp_parser parser)
+      {
+          ExpressionParser::addExpParser(token, parser);
+      }
+  };
+
   }
 
   /**
@@ -1160,7 +1224,7 @@ namespace simgear
     void eval(bool& value, const expression::Binding* b) const
     {
       value = false;
-      for (int i = 0; i < getNumOperands(); ++i) {
+      for (int i = 0; i < (int)getNumOperands(); ++i) {
         value = value || getOperand(i)->getValue(b);
         if (value)
           return;
@@ -1174,7 +1238,7 @@ namespace simgear
     void eval(bool& value, const expression::Binding* b) const
     {
       value = true;
-      for (int i = 0; i < getNumOperands(); ++i) {
+      for (int i = 0; i < (int)getNumOperands(); ++i) {
         value = value && getOperand(i)->getValue(b);
         if (!value)
           return;