]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGExpression.cxx
Make subsystem group destruction explicit, so get_subsystem calls during destruction...
[simgear.git] / simgear / structure / SGExpression.cxx
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 #ifdef HAVE_CONFIG_H
23 #  include <simgear_config.h>
24 #endif
25
26 #include "SGExpression.hxx"
27 #include "Singleton.hxx"
28
29 #include <algorithm>
30 #include <functional>
31 #include <map>
32 #include <utility>
33 #include <string>
34 #include <sstream>
35 #include <boost/bind.hpp>
36 #include <cstring> // for strcmp
37
38 #include <simgear/props/props.hxx>
39
40 using namespace std;
41
42 namespace simgear
43 {
44 template<typename T>
45 const expression::Value evalValue(const Expression* exp,
46                                   const expression::Binding* b)
47 {
48     T val;
49     static_cast<const SGExpression<T>*>(exp)->eval(val, b);
50     return expression::Value(val);
51 }
52
53 const expression::Value eval(const Expression* exp,
54                              const expression::Binding* b)
55 {
56     using namespace expression;
57     switch (exp->getType()) {
58     case BOOL:
59         return evalValue<bool>(exp, b);
60     case INT:
61         return evalValue<int>(exp, b);
62     case FLOAT:
63         return evalValue<float>(exp, b);
64     case DOUBLE:
65         return evalValue<double>(exp, b);
66     default:
67         throw "invalid type.";
68     }
69 }
70 }
71
72 template<typename T>
73 static bool
74 SGReadValueFromString(const char* str, T& value)
75 {
76     if (!str) {
77         SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
78         return false;
79     }
80     std::stringstream s;
81     s.str(std::string(str));
82     s >> value;
83     if (s.fail()) {
84         SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
85         return false;
86     }
87     return true;
88 }
89
90 template<>
91 bool
92 SGReadValueFromString(const char* str, bool& value)
93 {
94     if (!str) {
95         SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
96         return false;
97     }
98     std::stringstream s;
99     s.str(std::string(str));
100     s >> value;
101     if (!s.fail())
102         return true;
103
104     std::string stdstr;
105     if (!SGReadValueFromString(str, stdstr))
106         return false;
107
108     if (stdstr == "true" || stdstr == "True" || stdstr == "TRUE") {
109         value = true;
110         return true;
111     }
112     if (stdstr == "false" || stdstr == "False" || stdstr == "FALSE") {
113         value = true;
114         return true;
115     }
116     return false;
117 }
118
119 template<typename T>
120 static bool
121 SGReadValueFromContent(const SGPropertyNode *node, T& value)
122 {
123     if (!node)
124         return false;
125     return SGReadValueFromString(node->getStringValue(), value);
126 }
127
128 template<typename T>
129 static SGExpression<T>*
130 SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression);
131
132 template<typename T>
133 static bool
134 SGReadNaryOperands(SGNaryExpression<T>* nary,
135                    SGPropertyNode *inputRoot, const SGPropertyNode *expression)
136 {
137     for (int i = 0; i < expression->nChildren(); ++i) {
138         SGExpression<T>* inputExpression;
139         inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
140         if (!inputExpression)
141             return false;
142         nary->addOperand(inputExpression);
143     }
144     return true;
145 }
146
147 // template<typename T>
148 // static SGExpression<T>*
149 // SGReadBExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
150 // {
151 //   if (!expression)
152 //     return 0;
153
154 //   std::string name = expression->getName();
155 //   if (name == "value") {
156 //     T value;
157 //     if (!SGReadValueFromContent(expression, value)) {
158 //       SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
159 //       return 0;
160 //     }
161 //     return new SGConstExpression<T>(value);
162 //   }
163
164 //   return 0;
165 // }
166
167 template<typename T>
168 static SGExpression<T>*
169 SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
170 {
171     if (!expression)
172         return 0;
173
174     std::string name = expression->getName();
175     if (name == "value") {
176         T value;
177         if (!SGReadValueFromContent(expression, value)) {
178             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
179             return 0;
180         }
181         return new SGConstExpression<T>(value);
182     }
183
184     if (name == "property") {
185         if (!inputRoot) {
186             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.\n"
187                    "No inputRoot argument given!");
188             return 0;
189         }
190         if (!expression->getStringValue()) {
191             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
192             return 0;
193         }
194         SGPropertyNode* inputNode;
195         inputNode = inputRoot->getNode(expression->getStringValue(), true);
196         return new SGPropertyExpression<T>(inputNode);
197     }
198
199     if (name == "abs" || name == "fabs") {
200         if (expression->nChildren() != 1) {
201             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
202             return 0;
203         }
204         SGSharedPtr<SGExpression<T> > inputExpression;
205         inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
206         if (!inputExpression) {
207             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
208             return 0;
209         }
210         return new SGAbsExpression<T>(inputExpression);
211     }
212
213     if (name == "sqr") {
214         if (expression->nChildren() != 1) {
215             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
216             return 0;
217         }
218         SGSharedPtr<SGExpression<T> > inputExpression;
219         inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
220         if (!inputExpression) {
221             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
222             return 0;
223         }
224         return new SGSqrExpression<T>(inputExpression);
225     }
226
227     if (name == "clip") {
228         if (expression->nChildren() != 3) {
229             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
230             return 0;
231         }
232         const SGPropertyNode* minProperty = expression->getChild("clipMin");
233         T clipMin;
234         if (!SGReadValueFromContent(minProperty, clipMin))
235             clipMin = SGMisc<T>::min(SGLimits<T>::min(), -SGLimits<T>::max());
236
237         const SGPropertyNode* maxProperty = expression->getChild("clipMax");
238         T clipMax;
239         if (!SGReadValueFromContent(maxProperty, clipMax))
240             clipMin = SGLimits<T>::max();
241
242         SGSharedPtr<SGExpression<T> > inputExpression;
243         for (int i = 0; !inputExpression && i < expression->nChildren(); ++i)
244             inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
245         if (!inputExpression) {
246             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
247             return 0;
248         }
249         return new SGClipExpression<T>(inputExpression, clipMin, clipMax);
250     }
251
252     if (name == "div") {
253         if (expression->nChildren() != 2) {
254             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
255             return 0;
256         }
257         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
258             SGReadIExpression<T>(inputRoot, expression->getChild(0)),
259             SGReadIExpression<T>(inputRoot, expression->getChild(1))
260         };
261         if (!inputExpressions[0] || !inputExpressions[1]) {
262             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
263             return 0;
264         }
265         return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
266     }
267     if (name == "mod") {
268         if (expression->nChildren() != 2) {
269             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
270             return 0;
271         }
272         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
273             SGReadIExpression<T>(inputRoot, expression->getChild(0)),
274             SGReadIExpression<T>(inputRoot, expression->getChild(1))
275         };
276         if (!inputExpressions[0] || !inputExpressions[1]) {
277             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
278             return 0;
279         }
280         return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
281     }
282
283     if (name == "sum") {
284         if (expression->nChildren() < 1) {
285             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
286             return 0;
287         }
288         SGSumExpression<T>* output = new SGSumExpression<T>;
289         if (!SGReadNaryOperands(output, inputRoot, expression)) {
290             delete output;
291             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
292             return 0;
293         }
294         return output;
295     }
296     if (name == "prod" || name == "product") {
297         if (expression->nChildren() < 1) {
298             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
299             return 0;
300         }
301         SGProductExpression<T>* output = new SGProductExpression<T>;
302         if (!SGReadNaryOperands(output, inputRoot, expression)) {
303             delete output;
304             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
305             return 0;
306         }
307         return output;
308     }
309     if (name == "min") {
310         if (expression->nChildren() < 1) {
311             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
312             return 0;
313         }
314         SGMinExpression<T>* output = new SGMinExpression<T>;
315         if (!SGReadNaryOperands(output, inputRoot, expression)) {
316             delete output;
317             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
318             return 0;
319         }
320         return output;
321     }
322     if (name == "max") {
323         if (expression->nChildren() < 1) {
324             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
325             return 0;
326         }
327         SGMaxExpression<T>* output = new SGMaxExpression<T>;
328         if (!SGReadNaryOperands(output, inputRoot, expression)) {
329             delete output;
330             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
331             return 0;
332         }
333         return output;
334     }
335
336     if (name == "table") {
337         SGInterpTable* tab = new SGInterpTable(expression);
338         if (!tab) {
339             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: malformed table");
340             return 0;
341         }
342         
343         // find input expression - i.e a child not named 'entry'
344         const SGPropertyNode* inputNode = NULL;
345         for (int i=0; (i<expression->nChildren()) && !inputNode; ++i) {
346             if (strcmp(expression->getChild(i)->getName(), "entry") == 0) {
347                 continue;
348             }
349             
350             inputNode = expression->getChild(i);
351         }
352         
353         if (!inputNode) {
354             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: no input found");
355             return 0;
356         }
357         
358         SGSharedPtr<SGExpression<T> > inputExpression;
359         inputExpression = SGReadIExpression<T>(inputRoot, inputNode);
360         if (!inputExpression) {
361             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
362             return 0;
363         }
364         
365         return new SGInterpTableExpression<T>(inputExpression, tab);
366     }
367     
368     return 0;
369 }
370
371
372 template<typename T>
373 static SGExpression<T>*
374 SGReadFExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
375 {
376     SGExpression<T>* r = SGReadIExpression<T>(inputRoot, expression);
377     if (r)
378         return r;
379
380     if (!expression)
381         return 0;
382
383     std::string name = expression->getName();
384     if (name == "acos") {
385         if (expression->nChildren() != 1) {
386             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
387             return 0;
388         }
389         SGSharedPtr<SGExpression<T> > inputExpression;
390         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
391         if (!inputExpression) {
392             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
393             return 0;
394         }
395         return new SGACosExpression<T>(inputExpression);
396     }
397
398     if (name == "asin") {
399         if (expression->nChildren() != 1) {
400             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
401             return 0;
402         }
403         SGSharedPtr<SGExpression<T> > inputExpression;
404         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
405         if (!inputExpression) {
406             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
407             return 0;
408         }
409         return new SGASinExpression<T>(inputExpression);
410     }
411
412     if (name == "atan") {
413         if (expression->nChildren() != 1) {
414             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
415             return 0;
416         }
417         SGSharedPtr<SGExpression<T> > inputExpression;
418         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
419         if (!inputExpression) {
420             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
421             return 0;
422         }
423         return new SGATanExpression<T>(inputExpression);
424     }
425
426     if (name == "ceil") {
427         if (expression->nChildren() != 1) {
428             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
429             return 0;
430         }
431         SGSharedPtr<SGExpression<T> > inputExpression;
432         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
433         if (!inputExpression) {
434             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
435             return 0;
436         }
437         return new SGCeilExpression<T>(inputExpression);
438     }
439
440     if (name == "cos") {
441         if (expression->nChildren() != 1) {
442             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
443             return 0;
444         }
445         SGSharedPtr<SGExpression<T> > inputExpression;
446         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
447         if (!inputExpression) {
448             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
449             return 0;
450         }
451         return new SGCosExpression<T>(inputExpression);
452     }
453
454     if (name == "cosh") {
455         if (expression->nChildren() != 1) {
456             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
457             return 0;
458         }
459         SGSharedPtr<SGExpression<T> > inputExpression;
460         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
461         if (!inputExpression) {
462             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
463             return 0;
464         }
465         return new SGCoshExpression<T>(inputExpression);
466     }
467
468     if (name == "deg2rad") {
469         if (expression->nChildren() != 1) {
470             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
471             return 0;
472         }
473         SGSharedPtr<SGExpression<T> > inputExpression;
474         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
475         if (!inputExpression) {
476             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
477             return 0;
478         }
479         return new SGScaleExpression<T>(inputExpression, SGMisc<T>::pi()/180);
480     }
481
482     if (name == "exp") {
483         if (expression->nChildren() != 1) {
484             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
485             return 0;
486         }
487         SGSharedPtr<SGExpression<T> > inputExpression;
488         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
489         if (!inputExpression) {
490             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
491             return 0;
492         }
493         return new SGExpExpression<T>(inputExpression);
494     }
495
496     if (name == "floor") {
497         if (expression->nChildren() != 1) {
498             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
499             return 0;
500         }
501         SGSharedPtr<SGExpression<T> > inputExpression;
502         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
503         if (!inputExpression) {
504             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
505             return 0;
506         }
507         return new SGFloorExpression<T>(inputExpression);
508     }
509
510     if (name == "log") {
511         if (expression->nChildren() != 1) {
512             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
513             return 0;
514         }
515         SGSharedPtr<SGExpression<T> > inputExpression;
516         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
517         if (!inputExpression) {
518             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
519             return 0;
520         }
521         return new SGLogExpression<T>(inputExpression);
522     }
523
524     if (name == "log10") {
525         if (expression->nChildren() != 1) {
526             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
527             return 0;
528         }
529         SGSharedPtr<SGExpression<T> > inputExpression;
530         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
531         if (!inputExpression) {
532             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
533             return 0;
534         }
535         return new SGLog10Expression<T>(inputExpression);
536     }
537
538     if (name == "rad2deg") {
539         if (expression->nChildren() != 1) {
540             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
541             return 0;
542         }
543         SGSharedPtr<SGExpression<T> > inputExpression;
544         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
545         if (!inputExpression) {
546             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
547             return 0;
548         }
549         return new SGScaleExpression<T>(inputExpression, 180/SGMisc<T>::pi());
550     }
551
552     if (name == "sin") {
553         if (expression->nChildren() != 1) {
554             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
555             return 0;
556         }
557         SGSharedPtr<SGExpression<T> > inputExpression;
558         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
559         if (!inputExpression) {
560             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
561             return 0;
562         }
563         return new SGSinExpression<T>(inputExpression);
564     }
565
566     if (name == "sinh") {
567         if (expression->nChildren() != 1) {
568             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
569             return 0;
570         }
571         SGSharedPtr<SGExpression<T> > inputExpression;
572         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
573         if (!inputExpression) {
574             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
575             return 0;
576         }
577         return new SGSinhExpression<T>(inputExpression);
578     }
579
580     if (name == "sqrt") {
581         if (expression->nChildren() != 1) {
582             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
583             return 0;
584         }
585         SGSharedPtr<SGExpression<T> > inputExpression;
586         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
587         if (!inputExpression) {
588             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
589             return 0;
590         }
591         return new SGSqrtExpression<T>(inputExpression);
592     }
593
594     if (name == "tan") {
595         if (expression->nChildren() != 1) {
596             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
597             return 0;
598         }
599         SGSharedPtr<SGExpression<T> > inputExpression;
600         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
601         if (!inputExpression) {
602             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
603             return 0;
604         }
605         return new SGTanExpression<T>(inputExpression);
606     }
607
608     if (name == "tanh") {
609         if (expression->nChildren() != 1) {
610             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
611             return 0;
612         }
613         SGSharedPtr<SGExpression<T> > inputExpression;
614         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
615         if (!inputExpression) {
616             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
617             return 0;
618         }
619         return new SGTanhExpression<T>(inputExpression);
620     }
621     
622 // if (name == "step") {
623 // }
624 // if (name == "condition") {
625 // }
626
627     if (name == "atan2") {
628         if (expression->nChildren() != 2) {
629             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
630             return 0;
631         }
632         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
633             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
634             SGReadFExpression<T>(inputRoot, expression->getChild(1))
635         };
636         if (!inputExpressions[0] || !inputExpressions[1]) {
637             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
638             return 0;
639         }
640         return new SGAtan2Expression<T>(inputExpressions[0], inputExpressions[1]);
641     }
642     if (name == "div") {
643         if (expression->nChildren() != 2) {
644             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
645             return 0;
646         }
647         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
648             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
649             SGReadFExpression<T>(inputRoot, expression->getChild(1))
650         };
651         if (!inputExpressions[0] || !inputExpressions[1]) {
652             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
653             return 0;
654         }
655         return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
656     }
657     if (name == "mod") {
658         if (expression->nChildren() != 2) {
659             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
660             return 0;
661         }
662         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
663             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
664             SGReadFExpression<T>(inputRoot, expression->getChild(1))
665         };
666         if (!inputExpressions[0] || !inputExpressions[1]) {
667             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
668             return 0;
669         }
670         return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
671     }
672     if (name == "pow") {
673         if (expression->nChildren() != 2) {
674             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
675             return 0;
676         }
677         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
678             SGReadIExpression<T>(inputRoot, expression->getChild(0)),
679             SGReadIExpression<T>(inputRoot, expression->getChild(1))
680         };
681         if (!inputExpressions[0] || !inputExpressions[1]) {
682             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
683             return 0;
684         }
685         return new SGPowExpression<T>(inputExpressions[0], inputExpressions[1]);
686     }
687
688     return 0;
689 }
690
691 SGExpression<int>*
692 SGReadIntExpression(SGPropertyNode *inputRoot,
693                     const SGPropertyNode *configNode)
694 { return SGReadIExpression<int>(inputRoot, configNode); }
695
696 SGExpression<float>*
697 SGReadFloatExpression(SGPropertyNode *inputRoot,
698                       const SGPropertyNode *configNode)
699 { return SGReadFExpression<float>(inputRoot, configNode); }
700
701 SGExpression<double>*
702 SGReadDoubleExpression(SGPropertyNode *inputRoot,
703                        const SGPropertyNode *configNode)
704 { return SGReadFExpression<double>(inputRoot, configNode); }
705
706 // SGExpression<bool>*
707 // SGReadBoolExpression(SGPropertyNode *inputRoot,
708 //                      const SGPropertyNode *configNode)
709 // { return SGReadBExpression<bool>(inputRoot, configNode); }
710
711 namespace simgear
712 {
713 namespace expression
714 {
715
716 bool Parser::readChildren(const SGPropertyNode* exp,
717                           vector<Expression*>& result)
718 {
719     for (int i = 0; i < exp->nChildren(); ++i)
720         result.push_back(read(exp->getChild(i)));
721     return true;
722 }
723
724 void ExpressionParser::addExpParser(const string& token, exp_parser parsefn)
725 {
726     ParserMapSingleton::instance()
727         ->_parserTable.insert(std::make_pair(token, parsefn));
728 }
729
730 Expression* valueParser(const SGPropertyNode* exp, Parser* parser)
731 {
732     switch (exp->getType()) {
733     case props::BOOL:
734         return new SGConstExpression<bool>(getValue<bool>(exp));        
735     case props::INT:
736         return new SGConstExpression<int>(getValue<int>(exp));        
737     case props::FLOAT:
738         return new SGConstExpression<float>(getValue<float>(exp));
739     case props::DOUBLE:
740         return new SGConstExpression<double>(getValue<double>(exp));
741     default:
742         return 0;
743     }
744 }
745
746 ExpParserRegistrar valueRegistrar("value", valueParser);
747
748 template<typename T, typename OpType>
749 inline Expression* makeConvert(Expression* e)
750 {
751     return new ConvertExpression<T,
752         OpType>(static_cast<SGExpression<OpType>*>(e));
753 }
754
755 Type promoteAndConvert(vector<Expression*>& exps, Type minType = BOOL)
756 {
757     vector<Expression*>::iterator maxElem
758         = max_element(exps.begin(), exps.end());
759     Type maxType = (*maxElem)->getType();
760     Type resultType = minType < maxType ? maxType : minType;
761     for (vector<Expression*>::iterator itr = exps.begin(), end = exps.end();
762          itr != end;
763          ++itr) {
764         if ((*itr)->getType() != resultType) {
765             switch ((*itr)->getType()) {
766             case BOOL:
767                 switch (resultType) {
768                 case INT:
769                     *itr = makeConvert<int, bool>(*itr);
770                     break;
771                 case FLOAT:
772                     *itr = makeConvert<float, bool>(*itr);
773                     break;
774                 case DOUBLE:
775                     *itr = makeConvert<double, bool>(*itr);
776                     break;
777                 default:
778                     break;
779                 }
780                 break;
781             case INT:
782                 switch (resultType) {
783                 case FLOAT:
784                     *itr = makeConvert<float, int>(*itr);
785                     break;
786                 case DOUBLE:
787                     *itr = makeConvert<double, int>(*itr);
788                     break;
789                 default:
790                     break;
791                 }
792                 break;
793             case FLOAT:
794                 *itr = makeConvert<double, float>(*itr);
795                 break;
796             default:
797                 break;
798             }
799         }
800     }
801     return resultType;
802 }
803
804 template<template<typename OpType> class Expr>
805 Expression* makeTypedOperandExp(Type operandType, vector<Expression*> children)
806 {
807     switch (operandType) {
808     case BOOL:
809     {
810         Expr<bool> *expr = new Expr<bool>();
811         expr->addOperands(children.begin(), children.end());
812         return expr;
813     }
814     case INT:
815     {
816         Expr<int> *expr = new Expr<int>();
817         expr->addOperands(children.begin(), children.end());
818         return expr;
819     }
820     case FLOAT:
821     {
822         Expr<float> *expr = new Expr<float>();
823         expr->addOperands(children.begin(), children.end());
824         return expr;
825     }
826     case DOUBLE:
827     {
828         Expr<double> *expr = new Expr<double>();
829         expr->addOperands(children.begin(), children.end());
830         return expr;
831     }
832     default:
833         return 0;
834     }
835 }
836
837 template<template<typename OpType> class PredExp>
838 Expression* predParser(const SGPropertyNode* exp, Parser* parser)
839 {
840     vector<Expression*> children;
841     parser->readChildren(exp, children);
842     Type operandType = promoteAndConvert(children);
843     return makeTypedOperandExp<PredExp>(operandType, children);
844 }
845
846 ExpParserRegistrar equalRegistrar("equal", predParser<EqualToExpression>);
847 ExpParserRegistrar lessRegistrar("less", predParser<LessExpression>);
848 ExpParserRegistrar leRegistrar("less-equal", predParser<LessEqualExpression>);
849
850 template<typename Logicop>
851 Expression* logicopParser(const SGPropertyNode* exp, Parser* parser)
852 {
853     using namespace boost;
854     vector<Expression*> children;
855     parser->readChildren(exp, children);
856     vector<Expression*>::iterator notBool =
857         find_if(children.begin(), children.end(),
858                 boost::bind(&Expression::getType, _1) != BOOL);
859     if (notBool != children.end())
860         throw("non boolean operand to logical expression");
861     Logicop *expr = new Logicop;
862     expr->addOperands(children.begin(), children.end());
863     return expr;
864 }
865
866 ExpParserRegistrar andRegistrar("and", logicopParser<AndExpression>);
867 ExpParserRegistrar orRegistrar("or", logicopParser<OrExpression>);
868
869 int BindingLayout::addBinding(const string& name, Type type)
870 {
871     //XXX error checkint
872     vector<VariableBinding>::iterator itr
873         = find_if(bindings.begin(), bindings.end(),
874                   boost::bind(&VariableBinding::name, _1) == name);
875     if (itr != bindings.end())
876         return itr->location;
877     int result = bindings.size();
878     bindings.push_back(VariableBinding(name, type, bindings.size()));
879     return result;
880 }
881
882 bool BindingLayout::findBinding(const std::string& name,
883                                 VariableBinding& result) const
884 {
885     using namespace std;
886     using namespace boost;
887     vector<VariableBinding>::const_iterator itr
888         = find_if(bindings.begin(), bindings.end(),
889                   boost::bind(&VariableBinding::name, _1) == name);
890     if (itr != bindings.end()) {
891         result = *itr;
892         return true;
893     } else {
894         return false;
895     }
896 }
897 }
898 }