]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGExpression.cxx
Boolean uniforms are now updatable by properties
[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 SGReadExpression(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 = SGReadExpression<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 SGReadExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
170 {
171     if (!expression)
172         return 0;
173
174     std::string name = expression->getName();
175
176     if (name == "value") {
177         T value;
178         if (!SGReadValueFromContent(expression, value)) {
179             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
180             return 0;
181         }
182         return new SGConstExpression<T>(value);
183     }
184
185     if (name == "property") {
186         if (!inputRoot) {
187             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.\n"
188                    "No inputRoot argument given!");
189             return 0;
190         }
191         if (!expression->getStringValue()) {
192             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
193             return 0;
194         }
195         SGPropertyNode* inputNode;
196         inputNode = inputRoot->getNode(expression->getStringValue(), true);
197         return new SGPropertyExpression<T>(inputNode);
198     }
199
200     if (name == "abs" || name == "fabs") {
201         if (expression->nChildren() != 1) {
202             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
203             return 0;
204         }
205         SGSharedPtr<SGExpression<T> > inputExpression;
206         inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
207         if (!inputExpression) {
208             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
209             return 0;
210         }
211         return new SGAbsExpression<T>(inputExpression);
212     }
213
214     if (name == "sqr") {
215         if (expression->nChildren() != 1) {
216             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
217             return 0;
218         }
219         SGSharedPtr<SGExpression<T> > inputExpression;
220         inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
221         if (!inputExpression) {
222             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
223             return 0;
224         }
225         return new SGSqrExpression<T>(inputExpression);
226     }
227
228     if (name == "clip") {
229         if (expression->nChildren() != 3) {
230             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
231             return 0;
232         }
233         const SGPropertyNode* minProperty = expression->getChild("clipMin");
234         T clipMin;
235         if (!SGReadValueFromContent(minProperty, clipMin))
236             clipMin = SGMisc<T>::min(SGLimits<T>::min(), -SGLimits<T>::max());
237
238         const SGPropertyNode* maxProperty = expression->getChild("clipMax");
239         T clipMax;
240         if (!SGReadValueFromContent(maxProperty, clipMax))
241             clipMin = SGLimits<T>::max();
242
243         SGSharedPtr<SGExpression<T> > inputExpression;
244         for (int i = 0; !inputExpression && i < expression->nChildren(); ++i)
245             inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(i));
246         if (!inputExpression) {
247             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
248             return 0;
249         }
250         return new SGClipExpression<T>(inputExpression, clipMin, clipMax);
251     }
252
253     if (name == "div") {
254         if (expression->nChildren() != 2) {
255             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
256             return 0;
257         }
258         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
259             SGReadExpression<T>(inputRoot, expression->getChild(0)),
260             SGReadExpression<T>(inputRoot, expression->getChild(1))
261         };
262         if (!inputExpressions[0] || !inputExpressions[1]) {
263             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
264             return 0;
265         }
266         return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
267     }
268     if (name == "mod") {
269         if (expression->nChildren() != 2) {
270             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
271             return 0;
272         }
273         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
274             SGReadExpression<T>(inputRoot, expression->getChild(0)),
275             SGReadExpression<T>(inputRoot, expression->getChild(1))
276         };
277         if (!inputExpressions[0] || !inputExpressions[1]) {
278             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
279             return 0;
280         }
281         return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
282     }
283
284     if (name == "sum") {
285         if (expression->nChildren() < 1) {
286             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
287             return 0;
288         }
289         SGSumExpression<T>* output = new SGSumExpression<T>;
290         if (!SGReadNaryOperands(output, inputRoot, expression)) {
291             delete output;
292             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
293             return 0;
294         }
295         return output;
296     }
297
298     if (name == "difference" || name == "dif" ) {
299         if (expression->nChildren() < 1) {
300             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
301             return 0;
302         }
303         SGDifferenceExpression<T>* output = new SGDifferenceExpression<T>;
304         if (!SGReadNaryOperands(output, inputRoot, expression)) {
305             delete output;
306             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
307             return 0;
308         }
309         return output;
310     }
311
312     if (name == "prod" || name == "product") {
313         if (expression->nChildren() < 1) {
314             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
315             return 0;
316         }
317         SGProductExpression<T>* output = new SGProductExpression<T>;
318         if (!SGReadNaryOperands(output, inputRoot, expression)) {
319             delete output;
320             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
321             return 0;
322         }
323         return output;
324     }
325     if (name == "min") {
326         if (expression->nChildren() < 1) {
327             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
328             return 0;
329         }
330         SGMinExpression<T>* output = new SGMinExpression<T>;
331         if (!SGReadNaryOperands(output, inputRoot, expression)) {
332             delete output;
333             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
334             return 0;
335         }
336         return output;
337     }
338     if (name == "max") {
339         if (expression->nChildren() < 1) {
340             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
341             return 0;
342         }
343         SGMaxExpression<T>* output = new SGMaxExpression<T>;
344         if (!SGReadNaryOperands(output, inputRoot, expression)) {
345             delete output;
346             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
347             return 0;
348         }
349         return output;
350     }
351
352     if (name == "table") {
353         SGInterpTable* tab = new SGInterpTable(expression);
354         if (!tab) {
355             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: malformed table");
356             return 0;
357         }
358         
359         // find input expression - i.e a child not named 'entry'
360         const SGPropertyNode* inputNode = NULL;
361         for (int i=0; (i<expression->nChildren()) && !inputNode; ++i) {
362             if (strcmp(expression->getChild(i)->getName(), "entry") == 0) {
363                 continue;
364             }
365             
366             inputNode = expression->getChild(i);
367         }
368         
369         if (!inputNode) {
370             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: no input found");
371             return 0;
372         }
373         
374         SGSharedPtr<SGExpression<T> > inputExpression;
375         inputExpression = SGReadExpression<T>(inputRoot, inputNode);
376         if (!inputExpression) {
377             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
378             return 0;
379         }
380         
381         return new SGInterpTableExpression<T>(inputExpression, tab);
382     }
383     
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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
634             SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
649             SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
664             SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
679             SGReadExpression<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 SGReadExpression<int>(inputRoot, configNode); }
695
696 SGExpression<float>*
697 SGReadFloatExpression(SGPropertyNode *inputRoot,
698                       const SGPropertyNode *configNode)
699 { return SGReadExpression<float>(inputRoot, configNode); }
700
701 SGExpression<double>*
702 SGReadDoubleExpression(SGPropertyNode *inputRoot,
703                        const SGPropertyNode *configNode)
704 { return SGReadExpression<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 }