]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGExpression.hxx
82dd8bbdc70138e67f49be47768e4cb005eab022
[simgear.git] / simgear / structure / SGExpression.hxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2006-2007 Mathias Froehlich 
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21
22 #ifndef _SG_EXPRESSION_HXX
23 #define _SG_EXPRESSION_HXX 1
24
25 #include <string>
26 #include <vector>
27
28 #include <simgear/props/condition.hxx>
29 #include <simgear/props/props.hxx>
30 #include <simgear/math/interpolater.hxx>
31 #include <simgear/math/SGMath.hxx>
32 #include <simgear/scene/model/persparam.hxx>
33 #include <simgear/structure/exception.hxx>
34
35 /// Expression tree implementation.
36
37 namespace simgear
38 {
39   namespace expression
40   {
41     enum Type {
42       BOOL = 0,
43       INT,
44       FLOAT,
45       DOUBLE
46     };
47     template<typename T> struct TypeTraits;
48     template<> struct TypeTraits<bool> {
49       static const Type typeTag = BOOL;
50     };
51     template<> struct TypeTraits<int> {
52       static const Type typeTag = INT;
53     };
54     template<> struct TypeTraits<float> {
55       static const Type typeTag = FLOAT;
56     };
57     template<> struct TypeTraits<double> {
58       static const Type typeTag = DOUBLE;
59     };
60
61     struct Value
62     {
63       Type typeTag;
64       union {
65         bool boolVal;
66         int intVal;
67         float floatVal;
68         double doubleVal;
69       } val;
70
71       Value() : typeTag(DOUBLE)
72       {
73         val.doubleVal = 0.0;
74       }
75
76       Value(bool val_) : typeTag(BOOL)
77       {
78         val.boolVal = val_;
79       }
80
81       Value(int val_) : typeTag(INT)
82       {
83         val.intVal = val_;
84       }
85
86       Value(float val_) : typeTag(FLOAT)
87       {
88         val.floatVal = val_;
89       }
90
91       Value(double val_) : typeTag(DOUBLE)
92       {
93         val.doubleVal = val_;
94       }
95
96     };
97
98     class Binding;
99   }
100
101   class Expression : public SGReferenced
102   {
103   public:
104     virtual ~Expression() {}
105     virtual expression::Type getType() const = 0;
106   };
107
108   const expression::Value eval(const Expression* exp,
109                                const expression::Binding* binding = 0);
110
111 }
112
113 template<typename T>
114 class SGExpression : public simgear::Expression {
115 public:
116   virtual ~SGExpression() {}
117   typedef T result_type;
118   typedef T operand_type;
119   virtual void eval(T&, const simgear::expression::Binding*) const = 0;
120
121   T getValue(const simgear::expression::Binding* binding = 0) const
122   { T value; eval(value, binding); return value; }
123
124   virtual bool isConst() const { return false; }
125   virtual SGExpression* simplify();
126   virtual simgear::expression::Type getType() const
127   {
128     return simgear::expression::TypeTraits<T>::typeTag;
129   }
130   virtual simgear::expression::Type getOperandType() const
131   {
132     return simgear::expression::TypeTraits<T>::typeTag;
133   }
134 };
135
136 /// Constant value expression
137 template<typename T>
138 class SGConstExpression : public SGExpression<T> {
139 public:
140   SGConstExpression(const T& value = T()) : _value(value)
141   { }
142   void setValue(const T& value)
143   { _value = value; }
144   const T& getValue(const simgear::expression::Binding* binding = 0) const
145   { return _value; }
146   virtual void eval(T& value, const simgear::expression::Binding*) const
147   { value = _value; }
148   virtual bool isConst() const { return true; }
149 private:
150   T _value;
151 };
152
153 template<typename T>
154 SGExpression<T>*
155 SGExpression<T>::simplify()
156 {
157   if (isConst())
158     return new SGConstExpression<T>(getValue());
159   return this;
160 }
161
162 template<typename T>
163 class SGUnaryExpression : public SGExpression<T> {
164 public:
165   const SGExpression<T>* getOperand() const
166   { return _expression; }
167   SGExpression<T>* getOperand()
168   { return _expression; }
169   void setOperand(SGExpression<T>* expression)
170   {
171     if (!expression)
172       expression = new SGConstExpression<T>(T());
173     _expression = expression;
174   }
175   virtual bool isConst() const
176   { return getOperand()->isConst(); }
177   virtual SGExpression<T>* simplify()
178   {
179     _expression = _expression->simplify();
180     return SGExpression<T>::simplify();
181   }
182
183 protected:
184   SGUnaryExpression(SGExpression<T>* expression = 0)
185   { setOperand(expression); }
186
187 private:
188   SGSharedPtr<SGExpression<T> > _expression;
189 };
190
191 template<typename T>
192 class SGBinaryExpression : public SGExpression<T> {
193 public:
194   const SGExpression<T>* getOperand(unsigned i) const
195   { return _expressions[i]; }
196   SGExpression<T>* getOperand(unsigned i)
197   { return _expressions[i]; }
198   void setOperand(unsigned i, SGExpression<T>* expression)
199   {
200     if (!expression)
201       expression = new SGConstExpression<T>(T());
202     if (2 <= i)
203       i = 0;
204     _expressions[i] = expression;
205   }
206
207   virtual bool isConst() const
208   { return getOperand(0)->isConst() && getOperand(1)->isConst(); }
209   virtual SGExpression<T>* simplify()
210   {
211     _expressions[0] = _expressions[0]->simplify();
212     _expressions[1] = _expressions[1]->simplify();
213     return SGExpression<T>::simplify();
214   }
215
216 protected:
217   SGBinaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
218   { setOperand(0, expr0); setOperand(1, expr1); }
219   
220 private:
221   SGSharedPtr<SGExpression<T> > _expressions[2];
222 };
223
224 template<typename T>
225 class SGNaryExpression : public SGExpression<T> {
226 public:
227   unsigned getNumOperands() const
228   { return _expressions.size(); }
229   const SGExpression<T>* getOperand(unsigned i) const
230   { return _expressions[i]; }
231   SGExpression<T>* getOperand(unsigned i)
232   { return _expressions[i]; }
233   unsigned addOperand(SGExpression<T>* expression)
234   {
235     if (!expression)
236       return ~unsigned(0);
237     _expressions.push_back(expression);
238     return _expressions.size() - 1;
239   }
240
241   template<typename Iter>
242   void addOperands(Iter begin, Iter end)
243   {
244     for (Iter iter = begin; iter != end; ++iter)
245       {
246         addOperand(static_cast< ::SGExpression<T>*>(*iter));
247       }
248   }
249
250   virtual bool isConst() const
251   {
252     for (unsigned i = 0; i < _expressions.size(); ++i)
253       if (!_expressions[i]->isConst())
254         return false;
255     return true;
256   }
257   virtual SGExpression<T>* simplify()
258   {
259     for (unsigned i = 0; i < _expressions.size(); ++i)
260       _expressions[i] = _expressions[i]->simplify();
261     return SGExpression<T>::simplify();
262   }
263
264 protected:
265   SGNaryExpression()
266   { }
267   SGNaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
268   { addOperand(expr0); addOperand(expr1); }
269   
270 private:
271   std::vector<SGSharedPtr<SGExpression<T> > > _expressions;
272 };
273
274
275
276
277 template<typename T>
278 class SGPropertyExpression : public SGExpression<T> {
279 public:
280   SGPropertyExpression(const SGPropertyNode* prop) : _prop(prop)
281   { }
282   void setPropertyNode(const SGPropertyNode* prop)
283   { _prop = prop; }
284   virtual void eval(T& value, const simgear::expression::Binding*) const
285   { doEval(value); }
286 private:
287   void doEval(float& value) const
288   { if (_prop) value = _prop->getFloatValue(); }
289   void doEval(double& value) const
290   { if (_prop) value = _prop->getDoubleValue(); }
291   void doEval(int& value) const
292   { if (_prop) value = _prop->getIntValue(); }
293   void doEval(long& value) const
294   { if (_prop) value = _prop->getLongValue(); }
295   void doEval(bool& value) const
296   { if (_prop) value = _prop->getBoolValue(); }
297   SGSharedPtr<const SGPropertyNode> _prop;
298 };
299
300 template<typename T>
301 class SGAbsExpression : public SGUnaryExpression<T> {
302 public:
303   SGAbsExpression(SGExpression<T>* expr = 0)
304     : SGUnaryExpression<T>(expr)
305   { }
306
307   virtual void eval(T& value, const simgear::expression::Binding* b) const
308   { value = getOperand()->getValue(b); if (value <= 0) value = -value; }
309
310   using SGUnaryExpression<T>::getOperand;
311 };
312
313 template<typename T>
314 class SGACosExpression : public SGUnaryExpression<T> {
315 public:
316   SGACosExpression(SGExpression<T>* expr = 0)
317     : SGUnaryExpression<T>(expr)
318   { }
319
320   virtual void eval(T& value, const simgear::expression::Binding* b) const
321   { value = acos(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
322
323   using SGUnaryExpression<T>::getOperand;
324 };
325
326 template<typename T>
327 class SGASinExpression : public SGUnaryExpression<T> {
328 public:
329   SGASinExpression(SGExpression<T>* expr = 0)
330     : SGUnaryExpression<T>(expr)
331   { }
332
333   virtual void eval(T& value, const simgear::expression::Binding* b) const
334   { value = asin(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
335
336   using SGUnaryExpression<T>::getOperand;
337 };
338
339 template<typename T>
340 class SGATanExpression : public SGUnaryExpression<T> {
341 public:
342   SGATanExpression(SGExpression<T>* expr = 0)
343     : SGUnaryExpression<T>(expr)
344   { }
345
346   virtual void eval(T& value, const simgear::expression::Binding* b) const
347   { value = atan(getOperand()->getValue(b)); }
348
349   using SGUnaryExpression<T>::getOperand;
350 };
351
352 template<typename T>
353 class SGCeilExpression : public SGUnaryExpression<T> {
354 public:
355   SGCeilExpression(SGExpression<T>* expr = 0)
356     : SGUnaryExpression<T>(expr)
357   { }
358
359   virtual void eval(T& value, const simgear::expression::Binding* b) const
360   { value = ceil(getOperand()->getValue(b)); }
361
362   using SGUnaryExpression<T>::getOperand;
363 };
364
365 template<typename T>
366 class SGCosExpression : public SGUnaryExpression<T> {
367 public:
368   SGCosExpression(SGExpression<T>* expr = 0)
369     : SGUnaryExpression<T>(expr)
370   { }
371
372   virtual void eval(T& value, const simgear::expression::Binding* b) const
373   { value = cos(getOperand()->getValue(b)); }
374
375   using SGUnaryExpression<T>::getOperand;
376 };
377
378 template<typename T>
379 class SGCoshExpression : public SGUnaryExpression<T> {
380 public:
381   SGCoshExpression(SGExpression<T>* expr = 0)
382     : SGUnaryExpression<T>(expr)
383   { }
384
385   virtual void eval(T& value, const simgear::expression::Binding* b) const
386   { value = cosh(getOperand()->getValue(b)); }
387
388   using SGUnaryExpression<T>::getOperand;
389 };
390
391 template<typename T>
392 class SGExpExpression : public SGUnaryExpression<T> {
393 public:
394   SGExpExpression(SGExpression<T>* expr = 0)
395     : SGUnaryExpression<T>(expr)
396   { }
397
398   virtual void eval(T& value, const simgear::expression::Binding* b) const
399   { value = exp(getOperand()->getValue(b)); }
400
401   using SGUnaryExpression<T>::getOperand;
402 };
403
404 template<typename T>
405 class SGFloorExpression : public SGUnaryExpression<T> {
406 public:
407   SGFloorExpression(SGExpression<T>* expr = 0)
408     : SGUnaryExpression<T>(expr)
409   { }
410
411   virtual void eval(T& value, const simgear::expression::Binding* b) const
412   { value = floor(getOperand()->getValue(b)); }
413
414   using SGUnaryExpression<T>::getOperand;
415 };
416
417 template<typename T>
418 class SGLogExpression : public SGUnaryExpression<T> {
419 public:
420   SGLogExpression(SGExpression<T>* expr = 0)
421     : SGUnaryExpression<T>(expr)
422   { }
423
424   virtual void eval(T& value, const simgear::expression::Binding* b) const
425   { value = log(getOperand()->getValue(b)); }
426
427   using SGUnaryExpression<T>::getOperand;
428 };
429
430 template<typename T>
431 class SGLog10Expression : public SGUnaryExpression<T> {
432 public:
433   SGLog10Expression(SGExpression<T>* expr = 0)
434     : SGUnaryExpression<T>(expr)
435   { }
436
437   virtual void eval(T& value, const simgear::expression::Binding* b) const
438   { value = log10(getOperand()->getValue(b)); }
439
440   using SGUnaryExpression<T>::getOperand;
441 };
442
443 template<typename T>
444 class SGSinExpression : public SGUnaryExpression<T> {
445 public:
446   SGSinExpression(SGExpression<T>* expr = 0)
447     : SGUnaryExpression<T>(expr)
448   { }
449
450   virtual void eval(T& value, const simgear::expression::Binding* b) const
451   { value = sin(getOperand()->getValue(b)); }
452
453   using SGUnaryExpression<T>::getOperand;
454 };
455
456 template<typename T>
457 class SGSinhExpression : public SGUnaryExpression<T> {
458 public:
459   SGSinhExpression(SGExpression<T>* expr = 0)
460     : SGUnaryExpression<T>(expr)
461   { }
462
463   virtual void eval(T& value, const simgear::expression::Binding* b) const
464   { value = sinh(getOperand()->getValue(b)); }
465
466   using SGUnaryExpression<T>::getOperand;
467 };
468
469 template<typename T>
470 class SGSqrExpression : public SGUnaryExpression<T> {
471 public:
472   SGSqrExpression(SGExpression<T>* expr = 0)
473     : SGUnaryExpression<T>(expr)
474   { }
475
476   virtual void eval(T& value, const simgear::expression::Binding* b) const
477   { value = getOperand()->getValue(b); value = value*value; }
478
479   using SGUnaryExpression<T>::getOperand;
480 };
481
482 template<typename T>
483 class SGSqrtExpression : public SGUnaryExpression<T> {
484 public:
485   SGSqrtExpression(SGExpression<T>* expr = 0)
486     : SGUnaryExpression<T>(expr)
487   { }
488
489   virtual void eval(T& value, const simgear::expression::Binding* b) const
490   { value = sqrt(getOperand()->getValue(b)); }
491
492   using SGUnaryExpression<T>::getOperand;
493 };
494
495 template<typename T>
496 class SGTanExpression : public SGUnaryExpression<T> {
497 public:
498   SGTanExpression(SGExpression<T>* expr = 0)
499     : SGUnaryExpression<T>(expr)
500   { }
501
502   virtual void eval(T& value, const simgear::expression::Binding* b) const
503   { value = tan(getOperand()->getValue(b)); }
504
505   using SGUnaryExpression<T>::getOperand;
506 };
507
508 template<typename T>
509 class SGTanhExpression : public SGUnaryExpression<T> {
510 public:
511   SGTanhExpression(SGExpression<T>* expr = 0)
512     : SGUnaryExpression<T>(expr)
513   { }
514
515   virtual void eval(T& value, const simgear::expression::Binding* b) const
516   { value = tanh(getOperand()->getValue(b)); }
517
518   using SGUnaryExpression<T>::getOperand;
519 };
520
521 template<typename T>
522 class SGScaleExpression : public SGUnaryExpression<T> {
523 public:
524   SGScaleExpression(SGExpression<T>* expr = 0, const T& scale = T(1))
525     : SGUnaryExpression<T>(expr), _scale(scale)
526   { }
527   void setScale(const T& scale)
528   { _scale = scale; }
529   const T& getScale() const
530   { return _scale; }
531
532   virtual void eval(T& value, const simgear::expression::Binding* b) const
533   { value = _scale * getOperand()->getValue(b); }
534
535   virtual SGExpression<T>* simplify()
536   {
537     if (_scale == 1)
538       return getOperand()->simplify();
539     return SGUnaryExpression<T>::simplify();
540   }
541
542   using SGUnaryExpression<T>::getOperand;
543 private:
544   T _scale;
545 };
546
547 template<typename T>
548 class SGBiasExpression : public SGUnaryExpression<T> {
549 public:
550   SGBiasExpression(SGExpression<T>* expr = 0, const T& bias = T(0))
551     : SGUnaryExpression<T>(expr), _bias(bias)
552   { }
553
554   void setBias(const T& bias)
555   { _bias = bias; }
556   const T& getBias() const
557   { return _bias; }
558
559   virtual void eval(T& value, const simgear::expression::Binding* b) const
560   { value = _bias + getOperand()->getValue(b); }
561
562   virtual SGExpression<T>* simplify()
563   {
564     if (_bias == 0)
565       return getOperand()->simplify();
566     return SGUnaryExpression<T>::simplify();
567   }
568
569   using SGUnaryExpression<T>::getOperand;
570 private:
571   T _bias;
572 };
573
574 template<typename T>
575 class SGInterpTableExpression : public SGUnaryExpression<T> {
576 public:
577   SGInterpTableExpression(SGExpression<T>* expr,
578                           const SGInterpTable* interpTable) :
579     SGUnaryExpression<T>(expr),
580     _interpTable(interpTable)
581   { }
582
583   virtual void eval(T& value, const simgear::expression::Binding* b) const
584   {
585     if (_interpTable)
586       value = _interpTable->interpolate(getOperand()->getValue(b));
587   }
588
589   using SGUnaryExpression<T>::getOperand;
590 private:
591   SGSharedPtr<SGInterpTable const> _interpTable;
592 };
593
594 template<typename T>
595 class SGClipExpression : public SGUnaryExpression<T> {
596 public:
597   SGClipExpression(SGExpression<T>* expr)
598     : SGUnaryExpression<T>(expr),
599       _clipMin(SGMisc<T>::min(-SGLimits<T>::max(), SGLimits<T>::min())),
600       _clipMax(SGLimits<T>::max())
601   { }
602   SGClipExpression(SGExpression<T>* expr,
603                    const T& clipMin, const T& clipMax)
604     : SGUnaryExpression<T>(expr),
605       _clipMin(clipMin),
606       _clipMax(clipMax)
607   { }
608
609   void setClipMin(const T& clipMin)
610   { _clipMin = clipMin; }
611   const T& getClipMin() const
612   { return _clipMin; }
613
614   void setClipMax(const T& clipMax)
615   { _clipMax = clipMax; }
616   const T& getClipMax() const
617   { return _clipMax; }
618
619   virtual void eval(T& value, const simgear::expression::Binding* b) const
620   {
621     value = SGMisc<T>::clip(getOperand()->getValue(b), _clipMin, _clipMax);
622   }
623
624   virtual SGExpression<T>* simplify()
625   {
626     if (_clipMin <= SGMisc<T>::min(-SGLimits<T>::max(), SGLimits<T>::min()) &&
627         _clipMax >= SGLimits<T>::max())
628       return getOperand()->simplify();
629     return SGUnaryExpression<T>::simplify();
630   }
631
632   using SGUnaryExpression<T>::getOperand;
633 private:
634   T _clipMin;
635   T _clipMax;
636 };
637
638 template<typename T>
639 class SGStepExpression : public SGUnaryExpression<T> {
640 public:
641   SGStepExpression(SGExpression<T>* expr = 0,
642                    const T& step = T(1), const T& scroll = T(0))
643     : SGUnaryExpression<T>(expr), _step(step), _scroll(scroll)
644   { }
645
646   void setStep(const T& step)
647   { _step = step; }
648   const T& getStep() const
649   { return _step; }
650
651   void setScroll(const T& scroll)
652   { _scroll = scroll; }
653   const T& getScroll() const
654   { return _scroll; }
655
656   virtual void eval(T& value, const simgear::expression::Binding* b) const
657   { value = apply_mods(getOperand()->getValue(b)); }
658
659   using SGUnaryExpression<T>::getOperand;
660
661 private:
662   T apply_mods(T property) const
663   {
664     T modprop;
665     if (_step > 0) {
666       T scrollval = 0;
667       if(_scroll > 0) {
668         // calculate scroll amount (for odometer like movement)
669         T remainder  =  _step - fmod(fabs(property), _step);
670         if (remainder < _scroll) {
671           scrollval = (_scroll - remainder) / _scroll * _step;
672         }
673       }
674       // apply stepping of input value
675       if(property > 0)
676         modprop = ((floor(property/_step) * _step) + scrollval);
677       else
678         modprop = ((ceil(property/_step) * _step) + scrollval);
679     } else {
680       modprop = property;
681     }
682     return modprop;
683   }
684
685   T _step;
686   T _scroll;
687 };
688
689 template<typename T>
690 class SGEnableExpression : public SGUnaryExpression<T> {
691 public:
692   SGEnableExpression(SGExpression<T>* expr = 0,
693                      SGCondition* enable = 0,
694                      const T& disabledValue = T(0))
695     : SGUnaryExpression<T>(expr),
696       _enable(enable),
697       _disabledValue(disabledValue)
698   { }
699
700   const T& getDisabledValue() const
701   { return _disabledValue; }
702   void setDisabledValue(const T& disabledValue)
703   { _disabledValue = disabledValue; }
704
705   virtual void eval(T& value, const simgear::expression::Binding* b) const
706   {
707     if (_enable->test())
708       value = getOperand()->getValue(b);
709     else
710       value = _disabledValue;
711   }
712
713   virtual SGExpression<T>* simplify()
714   {
715     if (!_enable)
716       return getOperand()->simplify();
717     return SGUnaryExpression<T>::simplify();
718   }
719
720   using SGUnaryExpression<T>::getOperand;
721 private:
722   SGSharedPtr<SGCondition> _enable;
723   T _disabledValue;
724 };
725
726 template<typename T>
727 class SGAtan2Expression : public SGBinaryExpression<T> {
728 public:
729   SGAtan2Expression(SGExpression<T>* expr0, SGExpression<T>* expr1)
730     : SGBinaryExpression<T>(expr0, expr1)
731   { }
732   virtual void eval(T& value, const simgear::expression::Binding* b) const
733   { value = atan2(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
734   using SGBinaryExpression<T>::getOperand;
735 };
736
737 template<typename T>
738 class SGDivExpression : public SGBinaryExpression<T> {
739 public:
740   SGDivExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
741     : SGBinaryExpression<T>(expr0, expr1)
742   { }
743   virtual void eval(T& value, const simgear::expression::Binding* b) const
744   { value = getOperand(0)->getValue(b) / getOperand(1)->getValue(b); }
745   using SGBinaryExpression<T>::getOperand;
746 };
747
748 template<typename T>
749 class SGModExpression : public SGBinaryExpression<T> {
750 public:
751   SGModExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
752     : SGBinaryExpression<T>(expr0, expr1)
753   { }
754   virtual void eval(T& value, const simgear::expression::Binding* b) const
755   { value = mod(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
756   using SGBinaryExpression<T>::getOperand;
757 private:
758   int mod(const int& v0, const int& v1) const
759   { return v0 % v1; }
760   float mod(const float& v0, const float& v1) const
761   { return fmod(v0, v1); }
762   double mod(const double& v0, const double& v1) const
763   { return fmod(v0, v1); }
764 };
765
766 template<typename T>
767 class SGPowExpression : public SGBinaryExpression<T> {
768 public:
769   SGPowExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
770     : SGBinaryExpression<T>(expr0, expr1)
771   { }
772   virtual void eval(T& value, const simgear::expression::Binding* b) const
773   { value = pow(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
774   using SGBinaryExpression<T>::getOperand;
775 };
776
777 template<typename T>
778 class SGSumExpression : public SGNaryExpression<T> {
779 public:
780   SGSumExpression()
781   { }
782   SGSumExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
783     : SGNaryExpression<T>(expr0, expr1)
784   { }
785   virtual void eval(T& value, const simgear::expression::Binding* b) const
786   {
787     value = T(0);
788     unsigned sz = SGNaryExpression<T>::getNumOperands();
789     for (unsigned i = 0; i < sz; ++i)
790       value += getOperand(i)->getValue(b);
791   }
792   using SGNaryExpression<T>::getValue;
793   using SGNaryExpression<T>::getOperand;
794 };
795
796 template<typename T>
797 class SGProductExpression : public SGNaryExpression<T> {
798 public:
799   SGProductExpression()
800   { }
801   SGProductExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
802     : SGNaryExpression<T>(expr0, expr1)
803   { }
804   virtual void eval(T& value, const simgear::expression::Binding* b) const
805   {
806     value = T(1);
807     unsigned sz = SGNaryExpression<T>::getNumOperands();
808     for (unsigned i = 0; i < sz; ++i)
809       value *= getOperand(i)->getValue(b);
810   }
811   using SGNaryExpression<T>::getValue;
812   using SGNaryExpression<T>::getOperand;
813 };
814
815 template<typename T>
816 class SGMinExpression : public SGNaryExpression<T> {
817 public:
818   SGMinExpression()
819   { }
820   SGMinExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
821     : SGNaryExpression<T>(expr0, expr1)
822   { }
823   virtual void eval(T& value, const simgear::expression::Binding* b) const
824   {
825     unsigned sz = SGNaryExpression<T>::getNumOperands();
826     if (sz < 1)
827       return;
828     
829     value = getOperand(0)->getValue(b);
830     for (unsigned i = 1; i < sz; ++i)
831       value = SGMisc<T>::min(value, getOperand(i)->getValue(b));
832   }
833   using SGNaryExpression<T>::getOperand;
834 };
835
836 template<typename T>
837 class SGMaxExpression : public SGNaryExpression<T> {
838 public:
839   SGMaxExpression()
840   { }
841   SGMaxExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
842     : SGNaryExpression<T>(expr0, expr1)
843   { }
844   virtual void eval(T& value, const simgear::expression::Binding* b) const
845   {
846     unsigned sz = SGNaryExpression<T>::getNumOperands();
847     if (sz < 1)
848       return;
849     
850     value = getOperand(0)->getValue(b);
851     for (unsigned i = 1; i < sz; ++i)
852       value = SGMisc<T>::max(value, getOperand(i)->getValue(b));
853   }
854   using SGNaryExpression<T>::getOperand;
855 };
856
857 typedef SGExpression<int> SGExpressioni;
858 typedef SGExpression<float> SGExpressionf;
859 typedef SGExpression<double> SGExpressiond;
860 typedef SGExpression<bool> SGExpressionb;
861
862 /**
863  * Global function to make an expression out of properties.
864
865   <clip>
866     <clipMin>0</clipMin>
867     <clipMax>79</clipMax>
868     <abs>
869       <sum>
870         <rad2deg>
871           <property>sim/model/whatever-rad</property>
872         </rad2deg>
873         <property>sim/model/someother-deg</property>
874         <value>-90</value>
875       </sum>
876     </abs>
877   <clip>
878
879 will evaluate to an expression:
880
881 SGMisc<T>::clip(abs(deg2rad*sim/model/whatever-rad + sim/model/someother-deg - 90), clipMin, clipMax);
882
883  */
884 SGExpression<int>*
885 SGReadIntExpression(SGPropertyNode *inputRoot,
886                     const SGPropertyNode *configNode);
887
888 SGExpression<float>*
889 SGReadFloatExpression(SGPropertyNode *inputRoot,
890                       const SGPropertyNode *configNode);
891
892 SGExpression<double>*
893 SGReadDoubleExpression(SGPropertyNode *inputRoot,
894                        const SGPropertyNode *configNode);
895
896 SGExpression<bool>*
897 SGReadBoolExpression(SGPropertyNode *inputRoot,
898                      const SGPropertyNode *configNode);
899
900 namespace simgear
901 {
902   namespace expression
903   {
904     class Parser;
905     /**
906      * Function that parses a property tree, producing an expression.
907      */
908     typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
909                                      Parser* parser);
910     void addExpParser(const std::string&, exp_parser);
911     Expression* read(const SGPropertyNode* exp, Parser* parser = 0);
912     /**
913      * Constructor for registering parser functions.
914      */
915     struct ExpParserRegistrar
916     {
917       ExpParserRegistrar(const std::string& token, exp_parser parser)
918       {
919         addExpParser(token, parser);
920       }
921     };
922
923     struct ParseError : public sg_exception
924     {
925       ParseError(const string& message = std::string())
926         : sg_exception(message) {}
927     };
928     
929     // Support for binding variables around an expression.
930     class Binding
931     {
932     public:
933       virtual ~Binding() {}
934       const virtual Value* getBindings() const = 0;
935       virtual Value* getBindings() = 0;
936     };
937
938     class VariableLengthBinding : public Binding
939     {
940     public:
941       const Value* getBindings() const
942       {
943         if (_bindings.empty())
944           return 0;
945         else
946           return &_bindings[0];
947       }
948       Value* getBindings()
949       {
950         if (_bindings.empty())
951           return 0;
952         else
953           return &_bindings[0];
954       }
955       std::vector<Value> _bindings;
956     };
957
958     template<int Size> class FixedLengthBinding : public Binding
959     {
960     public:
961       Value* getBindings()
962       {
963         return &_bindings[0];
964       }
965       const Value* getBindings() const
966       {
967         return &_bindings[0];
968       }
969       Value _bindings[Size];
970     };
971
972     struct VariableBinding
973     {
974       VariableBinding() : type(expression::DOUBLE), location(-1) {}
975
976       VariableBinding(const std::string& name_, expression::Type type_,
977                       int location_)
978         : name(name_), type(type_), location(location_)
979       {
980       }
981       std::string name;
982       expression::Type type;
983       int location;
984     };
985
986     class BindingLayout
987     {
988     public:
989       int addBinding(const std::string& name, expression::Type type);
990       bool findBinding(const string& name, VariableBinding& result) const;
991     protected:
992       std::vector<VariableBinding> bindings;
993     };
994   }
995
996   /**
997    * Access a variable definition. Use a location from a BindingLayout.
998    */
999   template<typename T>
1000   class VariableExpression : public ::SGExpression<T> {
1001   public:
1002     VariableExpression(int location) : _location(location) {}
1003     virtual ~VariableExpression() {}
1004     virtual void eval(T& value, const simgear::expression::Binding* b) const
1005     {
1006       const expression::Value* values = b->getBindings();
1007       value = *reinterpret_cast<const T *>(&values[_location].val);
1008     }
1009   protected:
1010     int _location;
1011
1012   };
1013
1014   /**
1015    * An n-ary expression where the types of the argument aren't the
1016    * same as the return type.
1017    */
1018   template<typename T, typename OpType>
1019   class GeneralNaryExpression : public ::SGExpression<T> {
1020   public:
1021     typedef OpType operand_type;
1022     unsigned getNumOperands() const
1023     { return _expressions.size(); }
1024     const ::SGExpression<OpType>* getOperand(unsigned i) const
1025     { return _expressions[i]; }
1026     ::SGExpression<OpType>* getOperand(unsigned i)
1027     { return _expressions[i]; }
1028     unsigned addOperand(::SGExpression<OpType>* expression)
1029     {
1030       if (!expression)
1031         return ~unsigned(0);
1032       _expressions.push_back(expression);
1033       return _expressions.size() - 1;
1034     }
1035     
1036     template<typename Iter>
1037     void addOperands(Iter begin, Iter end)
1038     {
1039       for (Iter iter = begin; iter != end; ++iter)
1040         {
1041           addOperand(static_cast< ::SGExpression<OpType>*>(*iter));
1042         }
1043     }
1044     
1045     virtual bool isConst() const
1046     {
1047       for (unsigned i = 0; i < _expressions.size(); ++i)
1048         if (!_expressions[i]->isConst())
1049           return false;
1050       return true;
1051     }
1052     virtual ::SGExpression<T>* simplify()
1053     {
1054       for (unsigned i = 0; i < _expressions.size(); ++i)
1055         _expressions[i] = _expressions[i]->simplify();
1056       return SGExpression<T>::simplify();
1057     }
1058
1059     simgear::expression::Type getOperandType() const
1060     {
1061       return simgear::expression::TypeTraits<OpType>::typeTag;
1062     }
1063     
1064   protected:
1065     GeneralNaryExpression()
1066     { }
1067     GeneralNaryExpression(::SGExpression<OpType>* expr0,
1068                           ::SGExpression<OpType>* expr1)
1069     { addOperand(expr0); addOperand(expr1); }
1070
1071     std::vector<SGSharedPtr<SGExpression<OpType> > > _expressions;
1072   };
1073
1074   /**
1075    * A predicate that wraps, for example the STL template predicate
1076    * expressions like std::equal_to.
1077    */
1078   template<typename OpType, template<typename PredOp> class Pred>
1079   class PredicateExpression : public GeneralNaryExpression<bool, OpType> {
1080   public:
1081     PredicateExpression()
1082     {
1083     }
1084     PredicateExpression(::SGExpression<OpType>* expr0,
1085                         ::SGExpression<OpType>* expr1)
1086       : GeneralNaryExpression<bool, OpType>(expr0, expr1)
1087     {
1088     }
1089     virtual void eval(bool& value, const simgear::expression::Binding* b) const
1090     {
1091       unsigned sz = this->getNumOperands();
1092       if (sz != 2)
1093         return;
1094       value = _pred(this->getOperand(0)->getValue(b),
1095                     this->getOperand(1)->getValue(b));
1096     }
1097   protected:
1098     Pred<OpType> _pred;
1099   };
1100
1101   template<template<typename OT> class Pred, typename OpType>
1102   PredicateExpression<OpType, Pred>*
1103   makePredicate(SGExpression<OpType>* op1, SGExpression<OpType>* op2)
1104   {
1105     return new PredicateExpression<OpType, Pred>(op1, op2);
1106   }
1107   
1108   template<typename OpType>
1109   class EqualToExpression : public PredicateExpression<OpType, std::equal_to>
1110   {
1111   public:
1112     EqualToExpression() {}
1113     EqualToExpression(::SGExpression<OpType>* expr0,
1114                       ::SGExpression<OpType>* expr1)
1115       : PredicateExpression<OpType, std::equal_to>(expr0, expr1)
1116     {
1117     }
1118   };
1119
1120   template<typename OpType>
1121   class LessExpression : public PredicateExpression<OpType, std::less>
1122   {
1123   public:
1124     LessExpression() {}
1125     LessExpression(::SGExpression<OpType>* expr0, ::SGExpression<OpType>* expr1)
1126       : PredicateExpression<OpType, std::less>(expr0, expr1)
1127     {
1128     }
1129   };
1130
1131   template<typename OpType>
1132   class LessEqualExpression
1133     : public PredicateExpression<OpType, std::less_equal>
1134   {
1135   public:
1136     LessEqualExpression() {}
1137     LessEqualExpression(::SGExpression<OpType>* expr0,
1138                         ::SGExpression<OpType>* expr1)
1139       : PredicateExpression<OpType, std::less_equal>(expr0, expr1)
1140     {
1141     }
1142   };
1143
1144   class NotExpression : public ::SGUnaryExpression<bool>
1145   {
1146   public:
1147     NotExpression(::SGExpression<bool>* expr = 0)
1148       : ::SGUnaryExpression<bool>(expr)
1149     {
1150     }
1151     void eval(bool& value, const expression::Binding* b) const
1152     {
1153       value = !getOperand()->getValue(b);
1154     }
1155   };
1156
1157   class OrExpression : public ::SGNaryExpression<bool>
1158   {
1159   public:
1160     void eval(bool& value, const expression::Binding* b) const
1161     {
1162       value = false;
1163       for (int i = 0; i < getNumOperands(); ++i) {
1164         value = value || getOperand(i)->getValue(b);
1165         if (value)
1166           return;
1167       }
1168     }
1169   };
1170
1171   class AndExpression : public ::SGNaryExpression<bool>
1172   {
1173   public:
1174     void eval(bool& value, const expression::Binding* b) const
1175     {
1176       value = true;
1177       for (int i = 0; i < getNumOperands(); ++i) {
1178         value = value && getOperand(i)->getValue(b);
1179         if (!value)
1180           return;
1181       }
1182     }
1183   };
1184
1185   /**
1186    * Convert an operand from OpType to T.
1187    */
1188   template<typename T, typename OpType>
1189   class ConvertExpression : public GeneralNaryExpression<T, OpType>
1190   {
1191   public:
1192     ConvertExpression() {}
1193     ConvertExpression(::SGExpression<OpType>* expr0)
1194     {
1195       addOperand(expr0);
1196     }
1197     virtual void eval(T& value, const simgear::expression::Binding* b) const
1198     {
1199       typename ConvertExpression::operand_type result;
1200       this->_expressions.at(0)->eval(result, b);
1201       value = result;
1202     }
1203   };
1204 }
1205 #endif // _SG_EXPRESSION_HXX