MADARA  3.4.1
EvaluationVisitor.cpp
Go to the documentation of this file.
1 /* -*- C++ -*- */
2 #ifndef _EVALUATION_VISITOR_CPP_
3 #define _EVALUATION_VISITOR_CPP_
4 
5 #ifdef _USE_VISITORS_
6 
7 #include <iostream>
8 #include <typeinfo>
9 #include <algorithm>
10 
42 
44 
46 void madara::expression::EvaluationVisitor::visit(
47  const madara::expression::LeafNode& node)
48 {
49  stack_.push(node.item());
50 }
51 
53 void madara::expression::EvaluationVisitor::visit(
55 {
56  stack_.push(node.item());
57 }
58 
60 void madara::expression::EvaluationVisitor::visit(
62 {
63  stack_.push(node.item());
64 }
65 
67 void madara::expression::EvaluationVisitor::visit(
69 {
70  stack_.push(node.item());
71 }
72 
74 void madara::expression::EvaluationVisitor::visit(
76 {
77  stack_.push(node.item());
78 }
79 
81 void madara::expression::EvaluationVisitor::visit(
83 {
84  stack_.push(node.item());
85 }
86 
88 void madara::expression::EvaluationVisitor::visit(
90 {
91  stack_.push(node.item());
92 }
93 
95 void madara::expression::EvaluationVisitor::visit(
96  const madara::expression::ListNode& node)
97 {
98 }
99 
101 void madara::expression::EvaluationVisitor::visit(
103 {
104  if (stack_.size() >= 1)
105  stack_.push(-stack_.pop());
106  else
107  {
108  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
109  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Negate"
110  " requires a right expression"));
111 
112  throw exceptions::KarlException("madara::expression::CompositeNegateNode: "
113  "KARL COMPILE ERROR: "
114  "Node has no right expression\n");
115  }
116 }
117 
119 void madara::expression::EvaluationVisitor::visit(
121 {
122  if (stack_.size() >= 1)
123  {
124  madara::knowledge::KnowledgeRecord old_value = stack_.pop();
125  try
126  {
127  VariableNode* right = dynamic_cast<VariableNode*>(node.right());
128 
129  madara::knowledge::KnowledgeRecord new_value = --old_value;
130  if (right)
131  {
132  new_value = right->dec();
133  }
134  stack_.push(new_value);
135  }
136  catch (::std::bad_cast&)
137  {
138  stack_.push(--old_value);
139  }
140  }
141  else
142  {
143  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
144  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Predecrement"
145  " requires a right expression"));
146  exit(-1);
147  }
148 }
149 
151 void madara::expression::EvaluationVisitor::visit(
153 {
154  if (stack_.size() >= 1)
155  {
156  madara::knowledge::KnowledgeRecord old_value = stack_.pop();
157  try
158  {
159  VariableNode* right = dynamic_cast<VariableNode*>(node.right());
160 
161  madara::knowledge::KnowledgeRecord new_value = ++old_value;
162  if (right)
163  {
164  new_value = right->inc();
165  }
166  stack_.push(new_value);
167  }
168  catch (::std::bad_cast&)
169  {
170  stack_.push(++old_value);
171  }
172  }
173  else
174  {
175  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
176  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Preincrement"
177  " requires a right expression"));
178  exit(-1);
179  }
180 }
181 
183 void madara::expression::EvaluationVisitor::visit(
185 {
186  if (stack_.size() >= 1)
187  stack_.push(!stack_.pop());
188  else
189  {
190  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
191  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Not"
192  " requires a right expression"));
193  exit(-1);
194  }
195 }
196 
198 void madara::expression::EvaluationVisitor::visit(
200 {
201  if (stack_.size() >= 2)
202  stack_.push(stack_.pop() + stack_.pop());
203  else
204  {
205  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
206  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Add"
207  " requires both a left and right expression"));
208  exit(-1);
209  }
210 }
211 
213 void madara::expression::EvaluationVisitor::visit(
215 {
216  if (stack_.size() >= 2)
217  {
218  // for an assignment to be valid, we need a variable to the left
219  // and an expression tree to the right.
220  try
221  {
222  // this is really backwards logic, but it was the only way I could think
223  // of to allow for a = b = c with this type of tree and post-order flow
224  madara::knowledge::KnowledgeRecord right = stack_.pop();
225  stack_.pop();
226  VariableNode* left = dynamic_cast<VariableNode*>(node.left());
227  left->set(right.to_integer());
228  stack_.push(right);
229  }
230  catch (::std::bad_cast&)
231  {
232  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
233  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Assignment"
234  " must have a variable as the left expression\n"));
235  exit(-1);
236  }
237  }
238  // ::std::cout << "add current top: " << stack_.top () << ::std::endl;
239 }
240 
242 void madara::expression::EvaluationVisitor::visit(
244 {
245  if (stack_.size() >= 2)
246  {
247  madara::knowledge::KnowledgeRecord right = stack_.pop();
248  madara::knowledge::KnowledgeRecord left = stack_.pop();
249 
250  stack_.push(left && right);
251  }
252  else
253  {
254  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
255  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: And"
256  " requires both a left and right expression\n"));
257  exit(-1);
258  }
259 }
260 
262 void madara::expression::EvaluationVisitor::visit(
264 {
265  if (stack_.size() >= 2)
266  {
267  madara::knowledge::KnowledgeRecord right = stack_.pop();
268  madara::knowledge::KnowledgeRecord left = stack_.pop();
269 
270  stack_.push(left || right);
271  }
272  else
273  {
274  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
275  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Or"
276  " requires both a left and right expression\n"));
277  exit(-1);
278  }
279 }
280 
282 void madara::expression::EvaluationVisitor::visit(
284 {
285  if (stack_.size() >= 2)
286  {
287  madara::knowledge::KnowledgeRecord right_v = stack_.pop();
288  madara::knowledge::KnowledgeRecord left_v = stack_.pop();
289 
290  // I was trying to use std::max, but it was giving me
291  // some grief, so I just implemented it as is
292  stack_.push(left_v > right_v ? left_v : right_v);
293  }
294  else
295  {
296  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
297  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: And"
298  " requires both a left and right expression\n"));
299  exit(-1);
300  }
301 }
302 
304 void madara::expression::EvaluationVisitor::visit(
306 {
307  if (stack_.size() >= 2)
308  {
309  madara::knowledge::KnowledgeRecord right_v = stack_.pop();
310  madara::knowledge::KnowledgeRecord left_v = stack_.pop();
311 
312  // I was trying to use std::max, but it was giving me
313  // some grief, so I just implemented it as is
314  stack_.push(left_v > right_v ? right_v : left_v);
315  }
316  else
317  {
318  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
319  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: And"
320  " requires both a left and right expression\n"));
321  exit(-1);
322  }
323 }
324 
326 void madara::expression::EvaluationVisitor::visit(
328 {
329 }
330 
332 void madara::expression::EvaluationVisitor::visit(
334 {
335 }
336 
338 void madara::expression::EvaluationVisitor::visit(
340 {
341  if (stack_.size() >= 2)
342  {
343  madara::knowledge::KnowledgeRecord right = stack_.pop();
344  madara::knowledge::KnowledgeRecord left = stack_.pop();
345 
346  stack_.push(left == right);
347  }
348  else
349  {
350  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
351  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Equality"
352  " requires both a left and right expression\n"));
353  exit(-1);
354  }
355 }
356 
358 void madara::expression::EvaluationVisitor::visit(
360 {
361  if (stack_.size() >= 2)
362  {
363  madara::knowledge::KnowledgeRecord right = stack_.pop();
364  madara::knowledge::KnowledgeRecord left = stack_.pop();
365 
366  stack_.push(left != right);
367  }
368  else
369  {
370  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
371  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Inequality"
372  " requires both a left and right expression\n"));
373  exit(-1);
374  }
375 }
376 
379 void madara::expression::EvaluationVisitor::visit(
381 {
382  if (stack_.size() >= 2)
383  {
384  madara::knowledge::KnowledgeRecord right = stack_.pop();
385  madara::knowledge::KnowledgeRecord left = stack_.pop();
386 
387  stack_.push(left >= right);
388  }
389  else
390  {
391  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
392  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Greater-than-equal"
393  " requires both a left and right expression\n"));
394  exit(-1);
395  }
396 }
397 
399 void madara::expression::EvaluationVisitor::visit(
401 {
402  if (stack_.size() >= 2)
403  {
404  madara::knowledge::KnowledgeRecord right = stack_.pop();
405  madara::knowledge::KnowledgeRecord left = stack_.pop();
406 
407  stack_.push(left > right);
408  }
409  else
410  {
411  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
412  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Greater-than"
413  " requires both a left and right expression\n"));
414  exit(-1);
415  }
416 }
417 
419 void madara::expression::EvaluationVisitor::visit(
421 {
422  if (stack_.size() >= 2)
423  {
424  madara::knowledge::KnowledgeRecord right = stack_.pop();
425  madara::knowledge::KnowledgeRecord left = stack_.pop();
426 
427  stack_.push(left <= right);
428  }
429  else
430  {
431  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
432  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Less-than-equal"
433  " requires both a left and right expression\n"));
434  exit(-1);
435  }
436 }
437 
439 void madara::expression::EvaluationVisitor::visit(
441 {
442  if (stack_.size() >= 2)
443  {
444  madara::knowledge::KnowledgeRecord right = stack_.pop();
445  madara::knowledge::KnowledgeRecord left = stack_.pop();
446 
447  stack_.push(left < right);
448  }
449  else
450  {
451  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
452  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Less-than"
453  " requires both a left and right expression\n"));
454  exit(-1);
455  }
456 }
457 
459 void madara::expression::EvaluationVisitor::visit(
461 {
462  if (stack_.size() >= 2)
463  {
464  madara::knowledge::KnowledgeRecord rhs = stack_.pop();
465  stack_.push(stack_.pop() - rhs);
466  }
467  else
468  {
469  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
470  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Subtract"
471  " requires both a left and right expression\n"));
472  exit(-1);
473  }
474 }
475 
477 void madara::expression::EvaluationVisitor::visit(
479 {
480  if (stack_.size() >= 2 && stack_.top())
481  {
482  madara::knowledge::KnowledgeRecord rhs = stack_.pop();
483  stack_.push(stack_.pop() / rhs);
484  }
485  else
486  {
487  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
488  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Division"
489  " requires both a left and right expression"
490  " (and right must not be 0)\n"));
491  exit(-1);
492  }
493 }
494 
496 void madara::expression::EvaluationVisitor::visit(
498 {
499  if (stack_.size() >= 2)
500  stack_.push(stack_.pop() * stack_.pop());
501  else
502  {
503  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
504  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Multiply"
505  " requires both a left and right expression\n"));
506  exit(-1);
507  }
508 }
509 
511 void madara::expression::EvaluationVisitor::visit(
513 {
514  if (stack_.size() >= 2 && stack_.top())
515  {
516  madara::knowledge::KnowledgeRecord rhs = stack_.pop();
517  stack_.push(stack_.pop() / rhs);
518  }
519  else
520  {
521  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
522  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Modulus"
523  " requires both a left and right expression"
524  " (and right must not be 0)\n"));
525  exit(-1);
526  }
527 }
528 
530 void madara::expression::EvaluationVisitor::visit(
532 {
533  if (stack_.size() >= 2)
534  stack_.push(stack_.pop() ? stack_.pop() : 0);
535  else
536  {
537  MADARA_ERROR(MADARA_LOG_TERMINAL_ERROR,
538  (LM_ERROR, DLINFO "\nKARL EVAL ERROR: Implies"
539  " requires both a left and right expression"));
540  exit(-1);
541  }
542 }
543 
545 int64_t madara::expression::EvaluationVisitor::total(void)
546 {
547  if (!stack_.is_empty())
548  return stack_.top();
549  else
550  return 0;
551 }
552 
554 void madara::expression::EvaluationVisitor::reset(void)
555 {
556  stack_.erase();
557 }
558 
559 #endif // _USE_VISITORS_
560 
561 #endif /* _EVALUATION_VISITOR_CPP_ */
virtual ComponentNode * left(void) const
Returns the left expression.
A composite node that encompasses addition of two expressions.
A composite node that performs a logical and.
A composite node that allows for variable assignment.
A composite node that evaluates both left and right expressions regardless of their evaluations.
A composite node that divides a left expression by a right one.
A composite node that compares left and right expressions for equality.
A composite node that iterates until a condition is met.
A composite node that calls a function.
A composite node that compares left and right expressions for greater than or equal to.
A composite node that compares left and right children for greater than.
A composite node that performs an implication (inference rule)
A composite node that compares left and right children for inequality.
A composite node that compares left and right children for less than or equal to.
A composite node that compares left and right children for less than.
A composite node that divides a left expression by a right expression and returns the remainder of th...
A composite node that multiplies a left expression by a right expression.
A composite node that integrally negates a right expression.
A composite node that logically nots a right expression.
A composite node that performs a logical or.
A composite node that decrements a right expression.
A composite node that increments a right expression.
A composite node that evaluates both left and right expressions regardless of their evaluations.
A composite node that encompasses subtraction of a right expression from a left expression.
virtual ComponentNode * right(void) const
Returns the right expression.
Defines a node that contains a madara::knowledge::KnowledgeRecord::Integer value.
Definition: LeafNode.h:25
virtual madara::knowledge::KnowledgeRecord item(void) const
Returns the printable value of the node.
Definition: LeafNode.cpp:47
Defines a terminal node that contains a list.
Definition: ListNode.h:28
Defines a terminal node of that references the current value stored in a variable.
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
Composite node that subtracts a variable by some right hand side.
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
Composite node that divides a variable by some right hand side.
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
Defines a terminal node of that references the current value stored in a variable.
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
Composite node that multiplies a variable by some right hand side.
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
Defines a terminal node of that references the current value stored in a variable.
Definition: VariableNode.h:29
virtual madara::knowledge::KnowledgeRecord item(void) const
Return the item stored in the node.
This class encapsulates an entry in a KnowledgeBase.
Integer to_integer(void) const
converts the value to an integer.