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