1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/libraries/libmbutil/evaluator_impl.h,v 1.4 2017/01/12 14:44:04 masarati Exp $ */
2 /*
3 * MBDyn (C) is a multibody analysis code.
4 * http://www.mbdyn.org
5 *
6 * Copyright (C) 1996-2017
7 *
8 * Pierangelo Masarati <masarati@aero.polimi.it>
9 * Paolo Mantegazza <mantegazza@aero.polimi.it>
10 *
11 * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12 * via La Masa, 34 - 20156 Milano, Italy
13 * http://www.aero.polimi.it
14 *
15 * Changing this copyright notice is forbidden.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation (version 2 of the License).
20 *
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */
31
32 /*
33 * With the contribution of Ankit Aggarwal <ankit.ankit.aggarwal@gmail.com>
34 * during Google Summer of Code 2015
35 */
36
37 #ifndef EVALUATOR_IMPL_H
38 #define EVALUATOR_IMPL_H
39
40 #include <iostream>
41 #include <sstream>
42 #include <cmath>
43 #include <limits>
44
45 // "evaluator.h" must be explicitly included
46
47 // for storing constant values like "1","1.23"
48 class EE_Value : public ExpressionElement {
49 private:
50 TypedValue m_Val;
51
52 public:
EE_Value(TypedValue Val)53 EE_Value(TypedValue Val) : m_Val(Val) { m_Val.SetConst(true); };
54 // nothing to destroy
~EE_Value(void)55 ~EE_Value(void) {};
56
57 TypedValue
Eval(void)58 Eval(void) const
59 {
60 return m_Val;
61 };
62
63 std::ostream&
Output(std::ostream & out)64 Output(std::ostream& out) const
65 {
66 return out << m_Val;
67 };
68 };
69
70 // for storing non const variable like "a", "b"
71 // FIXME: probably needs to know about its namespace
72 class EE_Var : public ExpressionElement {
73 private:
74 NamedValue *m_Var;
75 // NOTE: probably the string would suffice, but just in case...
76 MathParser::NameSpace *m_ns;
77
78 public:
m_Var(var)79 EE_Var(NamedValue *var, MathParser::NameSpace *ns = 0) : m_Var(var), m_ns(ns) {};
80 // nothing to destroy (Var belongs to the symbol table)
~EE_Var(void)81 virtual ~EE_Var(void) {};
82
83 virtual TypedValue
Eval(void)84 Eval(void) const
85 {
86 // NOTE: this should not be const,
87 // otherwise it would have been turned into a EE_Value
88 return m_Var->GetVal();
89 };
90
91 virtual std::ostream&
Output(std::ostream & out)92 Output(std::ostream& out) const
93 {
94 if (m_ns) {
95 out << m_ns->sGetName() << "::";
96 }
97
98 return out << m_Var->GetName();
99 };
100 };
101
102 class EE_Plus : public ExpressionElement {
103 private:
104 ExpressionElement *m_pEE1, *m_pEE2;
105
106 public:
EE_Plus(ExpressionElement * pEE1,ExpressionElement * pEE2)107 EE_Plus(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Plus(void)108 ~EE_Plus(void) { delete m_pEE1; delete m_pEE2; };
109
110 TypedValue
Eval(void)111 Eval(void) const
112 {
113 // FIXME: check integer overflow?
114 return m_pEE1->Eval() + m_pEE2->Eval();
115 };
116
117 std::ostream&
Output(std::ostream & out)118 Output(std::ostream& out) const
119 {
120 return out << "(", m_pEE1->Output(out) << " + ", m_pEE2->Output(out) << ")";
121 };
122 };
123
124 class EE_Minus : public ExpressionElement {
125 private:
126 ExpressionElement *m_pEE1, *m_pEE2;
127
128 public:
EE_Minus(ExpressionElement * pEE1,ExpressionElement * pEE2)129 EE_Minus(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Minus(void)130 ~EE_Minus(void) { delete m_pEE1; delete m_pEE2; };
131
132 TypedValue
Eval(void)133 Eval(void) const
134 {
135 // FIXME: check integer overflow?
136 return m_pEE1->Eval() - m_pEE2->Eval();
137 };
138
139 std::ostream&
Output(std::ostream & out)140 Output(std::ostream& out) const
141 {
142 return out << "(", m_pEE1->Output(out) << " - ", m_pEE2->Output(out) << ")";
143 };
144 };
145
146 class EE_Modulus : public ExpressionElement {
147 private:
148 ExpressionElement *m_pEE1, *m_pEE2;
149
150 #if 0 // TODO: check correctness whenever possible
151 bool
152 Check_int(const TypedValue& value)
153 {
154 switch (value.GetType()) {
155 case TypedValue::VAR_BOOL:
156 case TypedValue::VAR_INT:
157 if (value.GetInt() == 0) {
158 return false;
159 }
160 break;
161
162 default:
163 return false;
164 }
165 };
166 #endif
167
168 public:
EE_Modulus(ExpressionElement * pEE1,ExpressionElement * pEE2)169 EE_Modulus(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Modulus(void)170 ~EE_Modulus(void) { delete m_pEE1; delete m_pEE2; };
171
172 #if 0 // TODO: check correctness whenever possible
173 bool
174 Check(void) const
175 {
176 if (dynamic_cast<EE_Value *>(m_pEE2)) {
177 return Check_int(m_pEE2->Eval());
178 }
179 return true;
180 };
181 #endif
182
183 TypedValue
Eval(void)184 Eval(void) const
185 {
186 // FIXME: the check on types should be done while parsing, if possible...
187 TypedValue a = m_pEE2->Eval();
188 if (a.GetType() == TypedValue::VAR_INT || a.GetType() == TypedValue::VAR_BOOL) {
189 ASSERT(a.GetInt() != 0);
190 return m_pEE1->Eval() % a;
191 }
192 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
193 };
194
195 std::ostream&
Output(std::ostream & out)196 Output(std::ostream& out) const
197 {
198 return out << "(", m_pEE1->Output(out) << " % ", m_pEE2->Output(out) << ")";
199 };
200 };
201
202 class EE_Multiply : public ExpressionElement {
203 private:
204 ExpressionElement *m_pEE1, *m_pEE2;
205
206 public:
EE_Multiply(ExpressionElement * pEE1,ExpressionElement * pEE2)207 EE_Multiply(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Multiply(void)208 ~EE_Multiply(void) { delete m_pEE1; delete m_pEE2; };
209
210 TypedValue
Eval(void)211 Eval(void) const
212 {
213 return m_pEE1->Eval() * m_pEE2->Eval();
214 };
215
216 std::ostream&
Output(std::ostream & out)217 Output(std::ostream& out) const
218 {
219 return out << "(", m_pEE1->Output(out) << " * ", m_pEE2->Output(out) << ")";
220 };
221 };
222
223 class EE_Divide : public ExpressionElement {
224 private:
225 ExpressionElement *m_pEE1, *m_pEE2;
226
227 public:
EE_Divide(ExpressionElement * pEE1,ExpressionElement * pEE2)228 EE_Divide(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Divide(void)229 ~EE_Divide(void) { delete m_pEE1; delete m_pEE2; };
230 // need to take care of zero denominator
231
232 TypedValue
Eval(void)233 Eval(void) const
234 {
235 TypedValue den = m_pEE2->Eval();
236 if (den.GetType() == TypedValue::VAR_BOOL) {
237 ASSERT(den.GetBool() != 0);
238
239 } else if (den.GetType() == TypedValue::VAR_INT) {
240 ASSERT(den.GetInt() != 0);
241
242 } else if (den.GetType() == TypedValue::VAR_REAL) {
243 Real value = den.GetReal();
244 if (std::abs(value) < std::numeric_limits<double>::epsilon()) {
245 // need to throw exception over here
246 std::cout << "denominator cannot be zero" << std::endl;
247 }
248 }
249
250 return m_pEE1->Eval() / den;
251 };
252
253 std::ostream&
Output(std::ostream & out)254 Output(std::ostream& out) const
255 {
256 return out << "(", m_pEE1->Output(out) << " / ", m_pEE2->Output(out) << ")";
257 };
258 };
259
260 class EE_Unary_minus : public ExpressionElement {
261 private:
262 ExpressionElement *m_pEE1;
263
264 public:
EE_Unary_minus(ExpressionElement * pEE1)265 EE_Unary_minus(ExpressionElement *pEE1) : m_pEE1(pEE1) {};
~EE_Unary_minus(void)266 ~EE_Unary_minus(void) { delete m_pEE1; };
267
268 TypedValue
Eval(void)269 Eval(void) const
270 {
271 return -m_pEE1->Eval();
272 };
273
274 std::ostream&
Output(std::ostream & out)275 Output(std::ostream& out) const
276 {
277 return out << "(-", m_pEE1->Output(out) << ")";
278 };
279 };
280
281 class EE_AND : public ExpressionElement {
282 private:
283 ExpressionElement *m_pEE1, *m_pEE2;
284
285 public:
EE_AND(ExpressionElement * pEE1,ExpressionElement * pEE2)286 EE_AND(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_AND(void)287 ~EE_AND(void) { delete m_pEE1; delete m_pEE2; };
288
289 TypedValue
Eval(void)290 Eval(void) const
291 {
292 return m_pEE1->Eval() && m_pEE2->Eval();
293 };
294
295 std::ostream&
Output(std::ostream & out)296 Output(std::ostream& out) const
297 {
298 return out << "(", m_pEE1->Output(out) << " && ", m_pEE2->Output(out) << ")";
299 };
300 };
301
302 class EE_OR : public ExpressionElement {
303 private:
304 ExpressionElement *m_pEE1, *m_pEE2;
305
306 public:
EE_OR(ExpressionElement * pEE1,ExpressionElement * pEE2)307 EE_OR(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_OR(void)308 ~EE_OR(void) { delete m_pEE1; delete m_pEE2; };
309
310 TypedValue
Eval(void)311 Eval(void) const
312 {
313 return m_pEE1->Eval() || m_pEE2->Eval();
314 };
315
316 std::ostream&
Output(std::ostream & out)317 Output(std::ostream& out) const
318 {
319 return out << "(", m_pEE1->Output(out) << " || ", m_pEE2->Output(out) << ")";
320 };
321 };
322
323 class EE_NOT : public ExpressionElement {
324 private:
325 ExpressionElement *m_pEE1;
326
327 public:
EE_NOT(ExpressionElement * pEE1)328 EE_NOT(ExpressionElement *pEE1) : m_pEE1(pEE1) {};
~EE_NOT(void)329 ~EE_NOT(void) { delete m_pEE1; };
330
331 TypedValue
Eval(void)332 Eval(void) const
333 {
334 return !(m_pEE1->Eval());
335 };
336
337 std::ostream&
Output(std::ostream & out)338 Output(std::ostream& out) const
339 {
340 return out << "(!", m_pEE1->Output(out) << ")";
341 };
342 };
343
344 // need to implement ~= as overloaded operator in mathp.cc
345 class EE_XOR : public ExpressionElement {
346 private:
347 ExpressionElement *m_pEE1, *m_pEE2;
348
349 public:
EE_XOR(ExpressionElement * pEE1,ExpressionElement * pEE2)350 EE_XOR(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_XOR(void)351 ~EE_XOR(void) { delete m_pEE1; delete m_pEE2; };
352
353 TypedValue
Eval(void)354 Eval(void) const
355 {
356 TypedValue v1 = m_pEE1->Eval();
357 TypedValue v2 = m_pEE2->Eval();
358 return ((!(v1 && v2)) && (v1 || v2));
359 };
360
361 std::ostream&
Output(std::ostream & out)362 Output(std::ostream& out) const
363 {
364 return out << "(", m_pEE1->Output(out) << " ~| ", m_pEE2->Output(out) << ")";
365 };
366 };
367
368 class EE_Greater : public ExpressionElement {
369 private:
370 ExpressionElement *m_pEE1, *m_pEE2;
371
372 public:
EE_Greater(ExpressionElement * pEE1,ExpressionElement * pEE2)373 EE_Greater(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Greater(void)374 ~EE_Greater(void) { delete m_pEE1; delete m_pEE2; };
375
376 TypedValue
Eval(void)377 Eval(void) const
378 {
379 return m_pEE1->Eval() > m_pEE2->Eval();
380 };
381
382 std::ostream&
Output(std::ostream & out)383 Output(std::ostream& out) const
384 {
385 return out << "(", m_pEE1->Output(out) << " > ", m_pEE2->Output(out) << ")";
386 };
387 };
388
389 class EE_Greater_Equal : public ExpressionElement {
390 private:
391 ExpressionElement *m_pEE1, *m_pEE2;
392
393 public:
EE_Greater_Equal(ExpressionElement * pEE1,ExpressionElement * pEE2)394 EE_Greater_Equal(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Greater_Equal(void)395 ~EE_Greater_Equal(void) { delete m_pEE1; delete m_pEE2; };
396
397 TypedValue
Eval(void)398 Eval(void) const
399 {
400 return m_pEE1->Eval() >= m_pEE2->Eval();
401 };
402
403 std::ostream&
Output(std::ostream & out)404 Output(std::ostream& out) const
405 {
406 return out << "(", m_pEE1->Output(out) << " >= ", m_pEE2->Output(out) << ")";
407 };
408 };
409
410 class EE_Lesser : public ExpressionElement {
411 private:
412 ExpressionElement *m_pEE1, *m_pEE2;
413
414 public:
EE_Lesser(ExpressionElement * pEE1,ExpressionElement * pEE2)415 EE_Lesser(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Lesser(void)416 ~EE_Lesser(void) { delete m_pEE1; delete m_pEE2; };
417
418 TypedValue
Eval(void)419 Eval(void) const
420 {
421 return m_pEE1->Eval() < m_pEE2->Eval();
422 };
423
424 std::ostream&
Output(std::ostream & out)425 Output(std::ostream& out) const
426 {
427 return out << "(", m_pEE1->Output(out) << " < ", m_pEE2->Output(out) << ")";
428 };
429 };
430
431 class EE_Lesser_Equal : public ExpressionElement {
432 private:
433 ExpressionElement *m_pEE1, *m_pEE2;
434
435 public:
EE_Lesser_Equal(ExpressionElement * pEE1,ExpressionElement * pEE2)436 EE_Lesser_Equal(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Lesser_Equal(void)437 ~EE_Lesser_Equal(void) { delete m_pEE1; delete m_pEE2; };
438
439 TypedValue
Eval(void)440 Eval(void) const
441 {
442 return m_pEE1->Eval() <= m_pEE2->Eval();
443 };
444
445 std::ostream&
Output(std::ostream & out)446 Output(std::ostream& out) const
447 {
448 return out << "(", m_pEE1->Output(out) << " <= ", m_pEE2->Output(out) << ")";
449 };
450 };
451
452 class EE_Equal_Equal : public ExpressionElement {
453 private:
454 ExpressionElement *m_pEE1, *m_pEE2;
455
456 public:
EE_Equal_Equal(ExpressionElement * pEE1,ExpressionElement * pEE2)457 EE_Equal_Equal(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Equal_Equal(void)458 ~EE_Equal_Equal(void) { delete m_pEE1; delete m_pEE2; };
459
460 TypedValue
Eval(void)461 Eval(void) const
462 {
463 return (m_pEE1->Eval()) == (m_pEE2->Eval());
464 };
465
466 std::ostream&
Output(std::ostream & out)467 Output(std::ostream& out) const
468 {
469 return out << "(", m_pEE1->Output(out) << " == ", m_pEE2->Output(out) << ")";
470 };
471 };
472
473 class EE_Not_Equal : public ExpressionElement {
474 private:
475 ExpressionElement *m_pEE1, *m_pEE2;
476
477 public:
EE_Not_Equal(ExpressionElement * pEE1,ExpressionElement * pEE2)478 EE_Not_Equal(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Not_Equal(void)479 ~EE_Not_Equal(void) { delete m_pEE1; delete m_pEE2; };
480
481 TypedValue
Eval(void)482 Eval(void) const
483 {
484 return (m_pEE1->Eval()) != (m_pEE2->Eval());
485 };
486
487 std::ostream&
Output(std::ostream & out)488 Output(std::ostream& out) const
489 {
490 return out << "(", m_pEE1->Output(out) << " != ", m_pEE2->Output(out) << ")";
491 };
492 };
493
494 class EE_Power : public ExpressionElement {
495 private:
496 ExpressionElement *m_pEE1, *m_pEE2;
497
498 public:
EE_Power(ExpressionElement * pEE1,ExpressionElement * pEE2)499 EE_Power(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_Power(void)500 ~EE_Power(void) { delete m_pEE1; delete m_pEE2; };
501
502 TypedValue
Eval(void)503 Eval(void) const
504 {
505 TypedValue a = m_pEE1->Eval();
506 TypedValue b = m_pEE2->Eval();
507 if (a.GetType() == TypedValue::VAR_STRING || b.GetType() == TypedValue::VAR_STRING) {
508 silent_cerr(" power undefined between string " << a << " and " << b << std::endl);
509 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
510
511 } else if ((a.GetType() == TypedValue::VAR_INT && b.GetType() == TypedValue::VAR_INT)
512 || (a.GetType() == TypedValue::VAR_BOOL && b.GetType() == TypedValue::VAR_BOOL))
513 {
514 Real value = std::pow(a.GetInt(), b.GetInt());
515 if (Real(Int(value)) != value) {
516 silent_cerr(" power(" << a.GetInt() << ", " << b.GetInt() << ") overflows (use explicit/implicit cast?)" << std::endl);
517 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
518 }
519 return value;
520
521 } else {
522 return std::pow(a.GetReal(), b.GetReal());
523 }
524 };
525
526 std::ostream&
Output(std::ostream & out)527 Output(std::ostream& out) const
528 {
529 return out << "(", m_pEE1->Output(out) << " ^ ", m_pEE2->Output(out) << ")";
530 };
531 };
532
533 #if 1
534 // FIXME: needs review
535 // for storing value that is which is evaluated first then assigned
536
537 class EE_Assign : public ExpressionElement {
538 private:
539 mutable Var *m_Var;
540 MathParser::NameSpace *m_ns;
541 const ExpressionElement *m_pEE;
542
543 public:
EE_Assign(Var * var,MathParser::NameSpace * ns,ExpressionElement * pEE)544 EE_Assign(Var *var, MathParser::NameSpace *ns, ExpressionElement *pEE) : m_Var(var), m_ns(ns), m_pEE(pEE) {};
~EE_Assign(void)545 ~EE_Assign(void) { delete m_pEE; };
546
547 TypedValue
Eval(void)548 Eval(void) const
549 {
550 TypedValue v(m_pEE->Eval());
551 m_Var->SetVal(v);
552 return v;
553 };
554
555 std::ostream&
Output(std::ostream & out)556 Output(std::ostream& out) const
557 {
558 out << "(";
559 if (m_ns) {
560 out << m_ns->sGetName() << "::";
561 }
562
563 return out << m_Var->GetName() << " = ", m_pEE->Output(out) << ")";
564 };
565 };
566
567 /* the variable is pre-declared */
568 class EE_DeclareAssign : public ExpressionElement {
569 private:
570 mutable Var *m_Var;
571 MathParser::NameSpace *m_ns;
572 const ExpressionElement *m_pEE;
573 mutable bool m_bEvaluated;
574
575 public:
m_Var(var)576 EE_DeclareAssign(Var *var, MathParser::NameSpace *ns, ExpressionElement *pEE = 0) : m_Var(var), m_ns(ns), m_pEE(pEE), m_bEvaluated(false) {};
~EE_DeclareAssign(void)577 ~EE_DeclareAssign(void) { if (m_pEE) { delete m_pEE; } };
578
579 TypedValue
Eval(void)580 Eval(void) const
581 {
582 if (m_bEvaluated) {
583 silent_cerr(" variable " << m_Var->GetName() << " already declared" << std::endl);
584 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
585 }
586
587 m_bEvaluated = true;
588
589 if (m_pEE) {
590 TypedValue v(m_pEE->Eval());
591 m_Var->SetVal(v);
592 return v;
593 }
594
595 return TypedValue(0, true);
596 };
597
598 std::ostream&
Output(std::ostream & out)599 Output(std::ostream& out) const
600 {
601 out << "(";
602 if (m_Var->Const()) {
603 out << "const ";
604 }
605
606 out << m_Var->GetTypeName() << " ";
607
608 if (m_ns) {
609 out << m_ns->sGetName() << "::";
610 }
611
612 return out << m_Var->GetName() << " = ", m_pEE->Output(out) << ")";
613 };
614 };
615 #endif
616
617 // for storing like <stmt>;<stmt>
618 class EE_StmtList : public ExpressionElement {
619 private:
620 ExpressionElement *m_pEE1, *m_pEE2;
621
622 public:
EE_StmtList(ExpressionElement * pEE1,ExpressionElement * pEE2)623 EE_StmtList(ExpressionElement *pEE1, ExpressionElement *pEE2) : m_pEE1(pEE1), m_pEE2(pEE2) {};
~EE_StmtList(void)624 ~EE_StmtList(void) { delete m_pEE1; delete m_pEE2; };
625
626 TypedValue
Eval(void)627 Eval(void) const
628 {
629 // FIXME: the first expression must exist
630 ASSERT(m_pEE1 != 0);
631
632 if (m_pEE1 != 0) {
633 m_pEE1->Eval();
634 }
635
636 return m_pEE2->Eval();
637 };
638
639 std::ostream&
Output(std::ostream & out)640 Output(std::ostream& out) const
641 {
642 return out << "(", m_pEE1->Output(out) << " ; ", m_pEE2->Output(out) << ")";
643 };
644 };
645
646 class EE_Func : public ExpressionElement {
647 private:
648 // pointer to MathParser only needed for exception handling
649 MathParser *m_p;
650 MathParser::MathFunc_t *m_f;
651
652 public:
EE_Func(MathParser * p,MathParser::MathFunc_t * f)653 EE_Func(MathParser *p, MathParser::MathFunc_t *f)
654 : m_p(p), m_f(f)
655 {
656 };
657
~EE_Func(void)658 ~EE_Func(void)
659 {
660 for (unsigned i = 0; i < m_f->args.size(); ++i) {
661 const ExpressionElement *ee = m_f->args[i]->GetExpr();
662 if (ee) {
663 delete ee;
664 }
665 }
666 delete m_f;
667 };
668
669 TypedValue
Eval(void)670 Eval(void) const
671 {
672 // sure args[0] does not need to be evaluated: it's the return value
673 for (unsigned i = 1; i < m_f->args.size(); i++) {
674 m_f->args[i]->Eval();
675 }
676
677 if (m_f->t != 0) {
678 if (m_f->t(m_f->args)) {
679 DEBUGCERR("error in function "
680 << m_f->ns->sGetName() << "::" << m_f->fname
681 << " " "(msg: " << m_f->errmsg << ")"
682 << " in EE_Func()" << std::endl);
683 throw MathParser::ErrGeneric(m_p, MBDYN_EXCEPT_ARGS,
684 m_f->fname + ": error " + m_f->errmsg);
685 }
686 }
687
688 TypedValue val = m_f->ns->EvalFunc(m_f);
689
690 return val;
691 };
692
693 std::ostream&
Output(std::ostream & out)694 Output(std::ostream& out) const
695 {
696 if (m_f->ns) {
697 out << m_f->ns->sGetName() << "::";
698 }
699
700 out << m_f->fname << "(";
701 const ExpressionElement *ee = m_f->args[1]->GetExpr();
702 if (ee != 0) {
703 ee->Output(out);
704 for (unsigned i = 2; i < m_f->args.size(); ++i) {
705 ee = m_f->args[i]->GetExpr();
706 if (ee == 0) {
707 break;
708 }
709 out << ", ", ee->Output(out);
710 }
711 }
712 out << ")";
713
714 return out;
715 };
716 };
717
718 // unary operator construction helper with optimization
719 template <class T>
720 ExpressionElement *
EECreate(ExpressionElement * e1)721 EECreate(ExpressionElement *e1)
722 {
723 ExpressionElement *out = new T(e1);
724 if (ExpressionElement::IsFlag(ExpressionElement::EE_CONSTIFY)) {
725 if (dynamic_cast<EE_Value *>(e1)) {
726 ExpressionElement *tmp = new EE_Value(out->Eval());
727 delete out;
728 return tmp;
729 }
730 }
731 return out;
732 }
733
734 // binary operator construction helper with optimization
735 template <class T>
736 ExpressionElement *
EECreate(ExpressionElement * e1,ExpressionElement * e2)737 EECreate(ExpressionElement *e1, ExpressionElement *e2)
738 {
739 ExpressionElement *out = new T(e1, e2);
740 if (ExpressionElement::IsFlag(ExpressionElement::EE_CONSTIFY)) {
741 if (dynamic_cast<EE_Value *>(e1) && dynamic_cast<EE_Value *>(e2)) {
742 ExpressionElement *tmp = new EE_Value(out->Eval());
743 delete out;
744 return tmp;
745 }
746 }
747 return out;
748 }
749
750 // ternary operator construction helper with optimization
751 template <class T>
752 ExpressionElement *
EECreate(ExpressionElement * e1,ExpressionElement * e2,ExpressionElement * e3)753 EECreate(ExpressionElement *e1, ExpressionElement *e2, ExpressionElement *e3)
754 {
755 ExpressionElement *out = new T(e1, e2, e3);
756 if (ExpressionElement::IsFlag(ExpressionElement::EE_CONSTIFY)) {
757 if (dynamic_cast<EE_Value *>(e1) && dynamic_cast<EE_Value *>(e2) && dynamic_cast<EE_Value *>(e3)) {
758 ExpressionElement *tmp = new EE_Value(out->Eval());
759 delete out;
760 return tmp;
761 }
762 }
763 return out;
764 }
765
766 #endif // EVALUATOR_IMPL_H
767