]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/SGExpression.hxx
Fix use count for deleted, reference counted objects.
[simgear.git] / simgear / structure / SGExpression.hxx
index c3e3bac5844e0fdd001897f8e8b839c0a826ca05..2cfa3dc8909d629959816210282535f3be13f37c 100644 (file)
 #ifndef _SG_EXPRESSION_HXX
 #define _SG_EXPRESSION_HXX 1
 
+#include <string>
+#include <vector>
+#include <functional>
+#include <set>
+#include <string>
+
 #include <simgear/props/condition.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/math/interpolater.hxx>
 #include <simgear/math/SGMath.hxx>
 #include <simgear/scene/model/persparam.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/structure/Singleton.hxx>
 
 /// Expression tree implementation.
 
+namespace simgear
+{
+  namespace expression
+  {
+    enum Type {
+      BOOL = 0,
+      INT,
+      FLOAT,
+      DOUBLE
+    };
+    template<typename T> struct TypeTraits;
+    template<> struct TypeTraits<bool> {
+      static const Type typeTag = BOOL;
+    };
+    template<> struct TypeTraits<int> {
+      static const Type typeTag = INT;
+    };
+    template<> struct TypeTraits<float> {
+      static const Type typeTag = FLOAT;
+    };
+    template<> struct TypeTraits<double> {
+      static const Type typeTag = DOUBLE;
+    };
+
+    struct Value
+    {
+      Type typeTag;
+      union {
+        bool boolVal;
+        int intVal;
+        float floatVal;
+        double doubleVal;
+      } val;
+
+      Value() : typeTag(DOUBLE)
+      {
+        val.doubleVal = 0.0;
+      }
+
+      Value(bool val_) : typeTag(BOOL)
+      {
+        val.boolVal = val_;
+      }
+
+      Value(int val_) : typeTag(INT)
+      {
+        val.intVal = val_;
+      }
+
+      Value(float val_) : typeTag(FLOAT)
+      {
+        val.floatVal = val_;
+      }
+
+      Value(double val_) : typeTag(DOUBLE)
+      {
+        val.doubleVal = val_;
+      }
+
+    };
+
+    class Binding;
+  }
+
+  class Expression : public SGReferenced
+  {
+  public:
+    virtual ~Expression() {}
+    virtual expression::Type getType() const = 0;
+  };
+
+  const expression::Value eval(const Expression* exp,
+                               const expression::Binding* binding = 0);
+
+}
+
 template<typename T>
-class SGExpression : public SGReferenced {
+class SGExpression : public simgear::Expression {
 public:
   virtual ~SGExpression() {}
-  virtual void eval(T&) const = 0;
+  typedef T result_type;
+  typedef T operand_type;
+  virtual void eval(T&, const simgear::expression::Binding*) const = 0;
 
-  T getValue() const
-  { T value; eval(value); return value; }
+  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
+  {
+    return simgear::expression::TypeTraits<T>::typeTag;
+  }
+  virtual simgear::expression::Type getOperandType() const
+  {
+    return simgear::expression::TypeTraits<T>::typeTag;
+  }
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  { }
 };
 
 /// Constant value expression
@@ -51,9 +150,9 @@ public:
   { }
   void setValue(const T& value)
   { _value = value; }
-  const T& getValue() const
+  const T& getValue(const simgear::expression::Binding* binding = 0) const
   { return _value; }
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding*) const
   { value = _value; }
   virtual bool isConst() const { return true; }
 private:
@@ -89,7 +188,9 @@ public:
     _expression = _expression->simplify();
     return SGExpression<T>::simplify();
   }
-
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+    { _expression->collectDependentProperties(props); }  
 protected:
   SGUnaryExpression(SGExpression<T>* expression = 0)
   { setOperand(expression); }
@@ -101,11 +202,11 @@ private:
 template<typename T>
 class SGBinaryExpression : public SGExpression<T> {
 public:
-  const SGExpression<T>* getOperand(unsigned i) const
+  const SGExpression<T>* getOperand(size_t i) const
   { return _expressions[i]; }
-  SGExpression<T>* getOperand(unsigned i)
+  SGExpression<T>* getOperand(size_t i)
   { return _expressions[i]; }
-  void setOperand(unsigned i, SGExpression<T>* expression)
+  void setOperand(size_t i, SGExpression<T>* expression)
   {
     if (!expression)
       expression = new SGConstExpression<T>(T());
@@ -123,6 +224,12 @@ public:
     return SGExpression<T>::simplify();
   }
 
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    _expressions[0]->collectDependentProperties(props);
+    _expressions[1]->collectDependentProperties(props); 
+  } 
+  
 protected:
   SGBinaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
   { setOperand(0, expr0); setOperand(1, expr1); }
@@ -134,34 +241,48 @@ private:
 template<typename T>
 class SGNaryExpression : public SGExpression<T> {
 public:
-  unsigned getNumOperands() const
+  size_t getNumOperands() const
   { return _expressions.size(); }
-  const SGExpression<T>* getOperand(unsigned i) const
+  const SGExpression<T>* getOperand(size_t i) const
   { return _expressions[i]; }
-  SGExpression<T>* getOperand(unsigned i)
+  SGExpression<T>* getOperand(size_t i)
   { return _expressions[i]; }
-  unsigned addOperand(SGExpression<T>* expression)
+  size_t addOperand(SGExpression<T>* expression)
   {
     if (!expression)
-      return ~unsigned(0);
+      return ~size_t(0);
     _expressions.push_back(expression);
     return _expressions.size() - 1;
   }
 
+  template<typename Iter>
+  void addOperands(Iter begin, Iter end)
+  {
+    for (Iter iter = begin; iter != end; ++iter)
+      {
+        addOperand(static_cast< ::SGExpression<T>*>(*iter));
+      }
+  }
+
   virtual bool isConst() const
   {
-    for (unsigned i = 0; i < _expressions.size(); ++i)
+    for (size_t i = 0; i < _expressions.size(); ++i)
       if (!_expressions[i]->isConst())
         return false;
     return true;
   }
   virtual SGExpression<T>* simplify()
   {
-    for (unsigned i = 0; i < _expressions.size(); ++i)
+    for (size_t i = 0; i < _expressions.size(); ++i)
       _expressions[i] = _expressions[i]->simplify();
     return SGExpression<T>::simplify();
   }
 
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    for (size_t i = 0; i < _expressions.size(); ++i)
+      _expressions[i]->collectDependentProperties(props);
+  } 
 protected:
   SGNaryExpression()
   { }
@@ -182,8 +303,11 @@ public:
   { }
   void setPropertyNode(const SGPropertyNode* prop)
   { _prop = prop; }
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding*) const
   { doEval(value); }
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+    { props.insert(_prop.get()); }
 private:
   void doEval(float& value) const
   { if (_prop) value = _prop->getFloatValue(); }
@@ -205,8 +329,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = getOperand()->getValue(); if (value <= 0) value = -value; }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = getOperand()->getValue(b); if (value <= 0) value = -value; }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -218,8 +342,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = acos(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = acos((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -231,8 +355,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = asin(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = asin((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -244,8 +368,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = atan(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = atan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -257,8 +381,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = ceil(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = ceil(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -270,8 +394,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = cos(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = cos(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -283,8 +407,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = cosh(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = cosh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -296,8 +420,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = exp(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = exp(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -309,8 +433,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = floor(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = floor(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -322,8 +446,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = log(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = log(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -335,8 +459,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = log10(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = log10(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -348,8 +472,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = sin(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = sin(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -361,8 +485,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = sinh(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = sinh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -374,8 +498,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = getOperand()->getValue(); value = value*value; }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = getOperand()->getValue(b); value = value*value; }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -387,8 +511,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = sqrt(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = sqrt(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -400,8 +524,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = tan(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = tan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -413,8 +537,8 @@ public:
     : SGUnaryExpression<T>(expr)
   { }
 
-  virtual void eval(T& value) const
-  { value = tanh(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = tanh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -430,8 +554,8 @@ public:
   const T& getScale() const
   { return _scale; }
 
-  virtual void eval(T& value) const
-  { value = _scale * getOperand()->getValue(); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = _scale * getOperand()->getValue(b); }
 
   virtual SGExpression<T>* simplify()
   {
@@ -457,8 +581,8 @@ public:
   const T& getBias() const
   { return _bias; }
 
-  virtual void eval(T& value) const
-  { value = _bias + getOperand()->getValue(); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = _bias + getOperand()->getValue(b); }
 
   virtual SGExpression<T>* simplify()
   {
@@ -481,10 +605,10 @@ public:
     _interpTable(interpTable)
   { }
 
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     if (_interpTable)
-      value = _interpTable->interpolate(getOperand()->getValue());
+      value = _interpTable->interpolate(getOperand()->getValue(b));
   }
 
   using SGUnaryExpression<T>::getOperand;
@@ -517,9 +641,9 @@ public:
   const T& getClipMax() const
   { return _clipMax; }
 
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
-    value = SGMisc<T>::clip(getOperand()->getValue(), _clipMin, _clipMax);
+    value = SGMisc<T>::clip(getOperand()->getValue(b), _clipMin, _clipMax);
   }
 
   virtual SGExpression<T>* simplify()
@@ -554,32 +678,24 @@ public:
   const T& getScroll() const
   { return _scroll; }
 
-  virtual void eval(T& value) const
-  { value = apply_mods(getOperand()->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = apply_mods(getOperand()->getValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 
 private:
   T apply_mods(T property) const
   {
-    T modprop;
-    if (_step > 0) {
-      T scrollval = 0;
-      if(_scroll > 0) {
-        // calculate scroll amount (for odometer like movement)
-        T remainder  =  _step - fmod(fabs(property), _step);
-        if (remainder < _scroll) {
-          scrollval = (_scroll - remainder) / _scroll * _step;
-        }
-      }
-      // apply stepping of input value
-      if(property > 0)
-        modprop = ((floor(property/_step) * _step) + scrollval);
-      else
-        modprop = ((ceil(property/_step) * _step) + scrollval);
-    } else {
-      modprop = property;
-    }
+    if( _step <= SGLimits<T>::min() ) return property;
+
+    // apply stepping of input value
+    T modprop = floor(property/_step)*_step;
+
+    // calculate scroll amount (for odometer like movement)
+    T remainder = property <= SGLimits<T>::min() ? -fmod(property,_step) : (_step - fmod(property,_step));
+    if( remainder > SGLimits<T>::min() && remainder < _scroll )
+      modprop += (_scroll - remainder) / _scroll * _step;
+
     return modprop;
   }
 
@@ -603,10 +719,10 @@ public:
   void setDisabledValue(const T& disabledValue)
   { _disabledValue = disabledValue; }
 
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     if (_enable->test())
-      value = getOperand()->getValue();
+      value = getOperand()->getValue(b);
     else
       value = _disabledValue;
   }
@@ -617,6 +733,12 @@ public:
       return getOperand()->simplify();
     return SGUnaryExpression<T>::simplify();
   }
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    SGUnaryExpression<T>::collectDependentProperties(props);
+    _enable->collectDependentProperties(props);
+  }
 
   using SGUnaryExpression<T>::getOperand;
 private:
@@ -630,8 +752,8 @@ public:
   SGAtan2Expression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGBinaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
-  { value = atan2(getOperand(0)->getValue(), getOperand(1)->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = atan2(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -641,8 +763,8 @@ public:
   SGDivExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGBinaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
-  { value = getOperand(0)->getValue() / getOperand(1)->getValue(); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = getOperand(0)->getValue(b) / getOperand(1)->getValue(b); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -652,8 +774,8 @@ public:
   SGModExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGBinaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
-  { value = mod(getOperand(0)->getValue(), getOperand(1)->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = mod(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 private:
   int mod(const int& v0, const int& v1) const
@@ -670,8 +792,8 @@ public:
   SGPowExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGBinaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
-  { value = pow(getOperand(0)->getValue(), getOperand(1)->getValue()); }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  { value = pow(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -683,12 +805,31 @@ public:
   SGSumExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGNaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     value = T(0);
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
-    for (unsigned i = 0; i < sz; ++i)
-      value += getOperand(i)->getValue();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 0; i < sz; ++i)
+      value += getOperand(i)->getValue(b);
+  }
+  using SGNaryExpression<T>::getValue;
+  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);
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 1; i < sz; ++i)
+      value -= getOperand(i)->getValue(b);
   }
   using SGNaryExpression<T>::getValue;
   using SGNaryExpression<T>::getOperand;
@@ -702,12 +843,12 @@ public:
   SGProductExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGNaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     value = T(1);
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
-    for (unsigned i = 0; i < sz; ++i)
-      value *= getOperand(i)->getValue();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 0; i < sz; ++i)
+      value *= getOperand(i)->getValue(b);
   }
   using SGNaryExpression<T>::getValue;
   using SGNaryExpression<T>::getOperand;
@@ -721,15 +862,15 @@ public:
   SGMinExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGNaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
     if (sz < 1)
       return;
     
-    value = getOperand(0)->getValue();
-    for (unsigned i = 1; i < sz; ++i)
-      value = SGMisc<T>::min(value, getOperand(i)->getValue());
+    value = getOperand(0)->getValue(b);
+    for (size_t i = 1; i < sz; ++i)
+      value = SGMisc<T>::min(value, getOperand(i)->getValue(b));
   }
   using SGNaryExpression<T>::getOperand;
 };
@@ -742,15 +883,15 @@ public:
   SGMaxExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
     : SGNaryExpression<T>(expr0, expr1)
   { }
-  virtual void eval(T& value) const
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
     if (sz < 1)
       return;
     
-    value = getOperand(0)->getValue();
-    for (unsigned i = 1; i < sz; ++i)
-      value = SGMisc<T>::max(value, getOperand(i)->getValue());
+    value = getOperand(0)->getValue(b);
+    for (size_t i = 1; i < sz; ++i)
+      value = SGMisc<T>::max(value, getOperand(i)->getValue(b));
   }
   using SGNaryExpression<T>::getOperand;
 };
@@ -760,6 +901,11 @@ typedef SGExpression<float> SGExpressionf;
 typedef SGExpression<double> SGExpressiond;
 typedef SGExpression<bool> SGExpressionb;
 
+typedef SGSharedPtr<SGExpressioni> SGExpressioni_ref;
+typedef SGSharedPtr<SGExpressionf> SGExpressionf_ref;
+typedef SGSharedPtr<SGExpressiond> SGExpressiond_ref;
+typedef SGSharedPtr<SGExpressionb> SGExpressionb_ref;
+
 /**
  * Global function to make an expression out of properties.
 
@@ -798,4 +944,350 @@ SGExpression<bool>*
 SGReadBoolExpression(SGPropertyNode *inputRoot,
                      const SGPropertyNode *configNode);
 
+namespace simgear
+{
+  namespace expression
+  {
+  struct ParseError : public sg_exception
+  {
+      ParseError(const std::string& message = std::string())
+          : sg_exception(message) {}
+  };
+    
+  // 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:
+      const Value* getBindings() const
+      {
+          if (_bindings.empty())
+              return 0;
+          else
+              return &_bindings[0];
+      }
+      Value* getBindings()
+      {
+          if (_bindings.empty())
+              return 0;
+          else
+              return &_bindings[0];
+      }
+      std::vector<Value> _bindings;
+  };
+
+  template<int Size> class FixedLengthBinding : public Binding
+  {
+  public:
+      Value* getBindings()
+      {
+          return &_bindings[0];
+      }
+      const Value* getBindings() const
+      {
+          return &_bindings[0];
+      }
+      Value _bindings[Size];
+  };
+
+  struct VariableBinding
+  {
+      VariableBinding() : type(expression::DOUBLE), location(-1) {}
+
+      VariableBinding(const std::string& name_, expression::Type type_,
+                      int location_)
+          : name(name_), type(type_), location(location_)
+      {
+      }
+      std::string name;
+      expression::Type type;
+      int location;
+  };
+
+  class BindingLayout
+  {
+  public:
+      size_t addBinding(const std::string& name, expression::Type type);
+      bool findBinding(const std::string& name, VariableBinding& result) const;
+      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(std::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);
+      }
+  };
+
+  }
+
+  /**
+   * Access a variable definition. Use a location from a BindingLayout.
+   */
+  template<typename T>
+  class VariableExpression : public ::SGExpression<T> {
+  public:
+    VariableExpression(int location) : _location(location) {}
+    virtual ~VariableExpression() {}
+    virtual void eval(T& value, const simgear::expression::Binding* b) const
+    {
+      const expression::Value* values = b->getBindings();
+      value = *reinterpret_cast<const T *>(&values[_location].val);
+    }
+  protected:
+    int _location;
+
+  };
+
+  /**
+   * An n-ary expression where the types of the argument aren't the
+   * same as the return type.
+   */
+  template<typename T, typename OpType>
+  class GeneralNaryExpression : public ::SGExpression<T> {
+  public:
+    typedef OpType operand_type;
+    size_t getNumOperands() const
+    { return _expressions.size(); }
+    const ::SGExpression<OpType>* getOperand(size_t i) const
+    { return _expressions[i]; }
+    ::SGExpression<OpType>* getOperand(size_t i)
+    { return _expressions[i]; }
+    size_t addOperand(::SGExpression<OpType>* expression)
+    {
+      if (!expression)
+        return ~size_t(0);
+      _expressions.push_back(expression);
+      return _expressions.size() - 1;
+    }
+    
+    template<typename Iter>
+    void addOperands(Iter begin, Iter end)
+    {
+      for (Iter iter = begin; iter != end; ++iter)
+        {
+          addOperand(static_cast< ::SGExpression<OpType>*>(*iter));
+        }
+    }
+    
+    virtual bool isConst() const
+    {
+      for (size_t i = 0; i < _expressions.size(); ++i)
+        if (!_expressions[i]->isConst())
+          return false;
+      return true;
+    }
+    virtual ::SGExpression<T>* simplify()
+    {
+      for (size_t i = 0; i < _expressions.size(); ++i)
+        _expressions[i] = _expressions[i]->simplify();
+      return SGExpression<T>::simplify();
+    }
+
+    simgear::expression::Type getOperandType() const
+    {
+      return simgear::expression::TypeTraits<OpType>::typeTag;
+    }
+    
+  protected:
+    GeneralNaryExpression()
+    { }
+    GeneralNaryExpression(::SGExpression<OpType>* expr0,
+                          ::SGExpression<OpType>* expr1)
+    { addOperand(expr0); addOperand(expr1); }
+
+    std::vector<SGSharedPtr<SGExpression<OpType> > > _expressions;
+  };
+
+  /**
+   * A predicate that wraps, for example the STL template predicate
+   * expressions like std::equal_to.
+   */
+  template<typename OpType, template<typename PredOp> class Pred>
+  class PredicateExpression : public GeneralNaryExpression<bool, OpType> {
+  public:
+    PredicateExpression()
+    {
+    }
+    PredicateExpression(::SGExpression<OpType>* expr0,
+                        ::SGExpression<OpType>* expr1)
+      : GeneralNaryExpression<bool, OpType>(expr0, expr1)
+    {
+    }
+    virtual void eval(bool& value, const simgear::expression::Binding* b) const
+    {
+      size_t sz = this->getNumOperands();
+      if (sz != 2)
+        return;
+      value = _pred(this->getOperand(0)->getValue(b),
+                    this->getOperand(1)->getValue(b));
+    }
+  protected:
+    Pred<OpType> _pred;
+  };
+
+  template<template<typename OT> class Pred, typename OpType>
+  PredicateExpression<OpType, Pred>*
+  makePredicate(SGExpression<OpType>* op1, SGExpression<OpType>* op2)
+  {
+    return new PredicateExpression<OpType, Pred>(op1, op2);
+  }
+  
+  template<typename OpType>
+  class EqualToExpression : public PredicateExpression<OpType, std::equal_to>
+  {
+  public:
+    EqualToExpression() {}
+    EqualToExpression(::SGExpression<OpType>* expr0,
+                      ::SGExpression<OpType>* expr1)
+      : PredicateExpression<OpType, std::equal_to>(expr0, expr1)
+    {
+    }
+  };
+
+  template<typename OpType>
+  class LessExpression : public PredicateExpression<OpType, std::less>
+  {
+  public:
+    LessExpression() {}
+    LessExpression(::SGExpression<OpType>* expr0, ::SGExpression<OpType>* expr1)
+      : PredicateExpression<OpType, std::less>(expr0, expr1)
+    {
+    }
+  };
+
+  template<typename OpType>
+  class LessEqualExpression
+    : public PredicateExpression<OpType, std::less_equal>
+  {
+  public:
+    LessEqualExpression() {}
+    LessEqualExpression(::SGExpression<OpType>* expr0,
+                        ::SGExpression<OpType>* expr1)
+      : PredicateExpression<OpType, std::less_equal>(expr0, expr1)
+    {
+    }
+  };
+
+  class NotExpression : public ::SGUnaryExpression<bool>
+  {
+  public:
+    NotExpression(::SGExpression<bool>* expr = 0)
+      : ::SGUnaryExpression<bool>(expr)
+    {
+    }
+    void eval(bool& value, const expression::Binding* b) const
+    {
+      value = !getOperand()->getValue(b);
+    }
+  };
+
+  class OrExpression : public ::SGNaryExpression<bool>
+  {
+  public:
+    void eval(bool& value, const expression::Binding* b) const
+    {
+      value = false;
+      for (int i = 0; i < (int)getNumOperands(); ++i) {
+        value = value || getOperand(i)->getValue(b);
+        if (value)
+          return;
+      }
+    }
+  };
+
+  class AndExpression : public ::SGNaryExpression<bool>
+  {
+  public:
+    void eval(bool& value, const expression::Binding* b) const
+    {
+      value = true;
+      for (int i = 0; i < (int)getNumOperands(); ++i) {
+        value = value && getOperand(i)->getValue(b);
+        if (!value)
+          return;
+      }
+    }
+  };
+
+  /**
+   * Convert an operand from OpType to T.
+   */
+  template<typename T, typename OpType>
+  class ConvertExpression : public GeneralNaryExpression<T, OpType>
+  {
+  public:
+    ConvertExpression() {}
+    ConvertExpression(::SGExpression<OpType>* expr0)
+    {
+      this->addOperand(expr0);
+    }
+    virtual void eval(T& value, const simgear::expression::Binding* b) const
+    {
+      typename ConvertExpression::operand_type result;
+      this->_expressions.at(0)->eval(result, b);
+      value = result;
+    }
+  };
+}
 #endif // _SG_EXPRESSION_HXX