1    	/*
2    	 Basic expression visitor
3    	
4    	 Copyright (C) 2014 AMPL Optimization Inc
5    	
6    	 Permission to use, copy, modify, and distribute this software and its
7    	 documentation for any purpose and without fee is hereby granted,
8    	 provided that the above copyright notice appear in all copies and that
9    	 both that the copyright notice and this permission notice and warranty
10   	 disclaimer appear in supporting documentation.
11   	
12   	 The author and AMPL Optimization Inc disclaim all warranties with
13   	 regard to this software, including all implied warranties of
14   	 merchantability and fitness.  In no event shall the author be liable
15   	 for any special, indirect or consequential damages or any damages
16   	 whatsoever resulting from loss of use, data or profits, whether in an
17   	 action of contract, negligence or other tortious action, arising out
18   	 of or in connection with the use or performance of this software.
19   	
20   	 Author: Victor Zverovich
21   	 */
22   	
23   	#ifndef MP_BASIC_EXPR_VISITOR_H_
24   	#define MP_BASIC_EXPR_VISITOR_H_
25   	
26   	#include "mp/common.h"
27   	#include "mp/error.h"
28   	
29   	#define MP_DEFINE_EXPR_TYPES(ExprTypes) \
30   	  typedef typename ExprTypes::Expr Expr; \
31   	  typedef typename ExprTypes::NumericExpr NumericExpr; \
32   	  typedef typename ExprTypes::LogicalExpr LogicalExpr; \
33   	  typedef typename ExprTypes::NumericConstant NumericConstant; \
34   	  typedef typename ExprTypes::Variable Variable; \
35   	  typedef typename ExprTypes::CommonExpr CommonExpr; \
36   	  typedef typename ExprTypes::UnaryExpr UnaryExpr; \
37   	  typedef typename ExprTypes::BinaryExpr BinaryExpr; \
38   	  typedef typename ExprTypes::IfExpr IfExpr; \
39   	  typedef typename ExprTypes::PLTerm PLTerm; \
40   	  typedef typename ExprTypes::CallExpr CallExpr; \
41   	  typedef typename ExprTypes::VarArgExpr VarArgExpr; \
42   	  typedef typename ExprTypes::SumExpr SumExpr; \
43   	  typedef typename ExprTypes::CountExpr CountExpr; \
44   	  typedef typename ExprTypes::NumberOfExpr NumberOfExpr; \
45   	  typedef typename ExprTypes::SymbolicNumberOfExpr SymbolicNumberOfExpr; \
46   	  typedef typename ExprTypes::LogicalConstant LogicalConstant; \
47   	  typedef typename ExprTypes::NotExpr NotExpr; \
48   	  typedef typename ExprTypes::BinaryLogicalExpr BinaryLogicalExpr; \
49   	  typedef typename ExprTypes::RelationalExpr RelationalExpr; \
50   	  typedef typename ExprTypes::LogicalCountExpr LogicalCountExpr; \
51   	  typedef typename ExprTypes::ImplicationExpr ImplicationExpr; \
52   	  typedef typename ExprTypes::IteratedLogicalExpr IteratedLogicalExpr; \
53   	  typedef typename ExprTypes::PairwiseExpr PairwiseExpr; \
54   	  typedef typename ExprTypes::StringLiteral StringLiteral; \
55   	  typedef typename ExprTypes::SymbolicIfExpr SymbolicIfExpr
56   	
57   	namespace mp {
58   	
59   	// A basic expression visitor that can be used with different expression
60   	// hierarchies described by ExprTypes.
61   	//
62   	// BasicExprVisitor uses the curiously recurring template pattern:
63   	// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
64   	template <typename Impl, typename Result, typename ExprTypes>
65   	class BasicExprVisitor {
66   	 public:
67   	  MP_DEFINE_EXPR_TYPES(ExprTypes);
68   	
69   	  Result Visit(Expr e);
70   	
71   	  Result VisitUnsupported(Expr e) {
72   	    throw MakeUnsupportedError(str(e.kind()));
73   	  }
74   	
75   	  Result VisitNumeric(NumericExpr e) {
76   	    return VisitUnsupported(e);
77   	  }
78   	
79   	  Result VisitLogical(LogicalExpr e) {
80   	    return VisitUnsupported(e);
81   	  }
82   	
83   	  Result VisitNumericConstant(NumericConstant c) {
84   	    return MP_DISPATCH(VisitNumeric(c));
85   	  }
86   	
87   	  Result VisitVariable(Variable v) {
88   	    return MP_DISPATCH(VisitNumeric(v));
89   	  }
90   	
91   	  Result VisitCommonExpr(CommonExpr e) {
92   	    return MP_DISPATCH(VisitNumeric(e));
93   	  }
94   	
95   	  // Visits a unary expression or a function taking one argument.
96   	  Result VisitUnary(UnaryExpr e) {
97   	    return MP_DISPATCH(VisitNumeric(e));
98   	  }
99   	
100  	  Result VisitMinus(UnaryExpr e) {
101  	    return MP_DISPATCH(VisitUnary(e));
102  	  }
103  	
104  	  Result VisitAbs(UnaryExpr e) {
105  	    return MP_DISPATCH(VisitUnary(e));
106  	  }
107  	
108  	  Result VisitFloor(UnaryExpr e) {
109  	    return MP_DISPATCH(VisitUnary(e));
110  	  }
111  	
112  	  Result VisitCeil(UnaryExpr e) {
113  	    return MP_DISPATCH(VisitUnary(e));
114  	  }
115  	
116  	  Result VisitSqrt(UnaryExpr e) {
117  	    return MP_DISPATCH(VisitUnary(e));
118  	  }
119  	
120  	  Result VisitPow2(UnaryExpr e) {
121  	    return MP_DISPATCH(VisitUnary(e));
122  	  }
123  	
124  	  Result VisitExp(UnaryExpr e) {
125  	    return MP_DISPATCH(VisitUnary(e));
126  	  }
127  	
128  	  Result VisitLog(UnaryExpr e) {
129  	    return MP_DISPATCH(VisitUnary(e));
130  	  }
131  	
132  	  Result VisitLog10(UnaryExpr e) {
133  	    return MP_DISPATCH(VisitUnary(e));
134  	  }
135  	
136  	  Result VisitSin(UnaryExpr e) {
137  	    return MP_DISPATCH(VisitUnary(e));
138  	  }
139  	
140  	  Result VisitSinh(UnaryExpr e) {
141  	    return MP_DISPATCH(VisitUnary(e));
142  	  }
143  	
144  	  Result VisitCos(UnaryExpr e) {
145  	    return MP_DISPATCH(VisitUnary(e));
146  	  }
147  	
148  	  Result VisitCosh(UnaryExpr e) {
149  	    return MP_DISPATCH(VisitUnary(e));
150  	  }
151  	
152  	  Result VisitTan(UnaryExpr e) {
153  	    return MP_DISPATCH(VisitUnary(e));
154  	  }
155  	
156  	  Result VisitTanh(UnaryExpr e) {
157  	    return MP_DISPATCH(VisitUnary(e));
158  	  }
159  	
160  	  Result VisitAsin(UnaryExpr e) {
161  	    return MP_DISPATCH(VisitUnary(e));
162  	  }
163  	
164  	  Result VisitAsinh(UnaryExpr e) {
165  	    return MP_DISPATCH(VisitUnary(e));
166  	  }
167  	
168  	  Result VisitAcos(UnaryExpr e) {
169  	    return MP_DISPATCH(VisitUnary(e));
170  	  }
171  	
172  	  Result VisitAcosh(UnaryExpr e) {
173  	    return MP_DISPATCH(VisitUnary(e));
174  	  }
175  	
176  	  Result VisitAtan(UnaryExpr e) {
177  	    return MP_DISPATCH(VisitUnary(e));
178  	  }
179  	
180  	  Result VisitAtanh(UnaryExpr e) {
181  	    return MP_DISPATCH(VisitUnary(e));
182  	  }
183  	
184  	  // Visits a binary expression or a function taking two arguments.
185  	  Result VisitBinary(BinaryExpr e) {
186  	    return MP_DISPATCH(VisitNumeric(e));
187  	  }
188  	
189  	  Result VisitAdd(BinaryExpr e) {
190  	    return MP_DISPATCH(VisitBinary(e));
191  	  }
192  	
193  	  Result VisitSub(BinaryExpr e) {
194  	    return MP_DISPATCH(VisitBinary(e));
195  	  }
196  	
197  	  Result VisitLess(BinaryExpr e) {
198  	    return MP_DISPATCH(VisitBinary(e));
199  	  }
200  	
201  	  Result VisitMul(BinaryExpr e) {
202  	    return MP_DISPATCH(VisitBinary(e));
203  	  }
204  	
205  	  Result VisitDiv(BinaryExpr e) {
206  	    return MP_DISPATCH(VisitBinary(e));
207  	  }
208  	
209  	  Result VisitTruncDiv(BinaryExpr e) {
210  	    return MP_DISPATCH(VisitBinary(e));
211  	  }
212  	
213  	  Result VisitMod(BinaryExpr e) {
214  	    return MP_DISPATCH(VisitBinary(e));
215  	  }
216  	
217  	  Result VisitPow(BinaryExpr e) {
218  	    return MP_DISPATCH(VisitBinary(e));
219  	  }
220  	
221  	  Result VisitPowConstBase(BinaryExpr e) {
222  	    return MP_DISPATCH(VisitBinary(e));
223  	  }
224  	
225  	  Result VisitPowConstExp(BinaryExpr e) {
226  	    return MP_DISPATCH(VisitBinary(e));
227  	  }
228  	
229  	  // Visits a function taking two arguments.
230  	  Result VisitBinaryFunc(BinaryExpr e) {
231  	    return MP_DISPATCH(VisitBinary(e));
232  	  }
233  	
234  	  Result VisitAtan2(BinaryExpr e) {
235  	    return MP_DISPATCH(VisitBinaryFunc(e));
236  	  }
237  	
238  	  Result VisitPrecision(BinaryExpr e) {
239  	    return MP_DISPATCH(VisitBinaryFunc(e));
240  	  }
241  	
242  	  Result VisitRound(BinaryExpr e) {
243  	    return MP_DISPATCH(VisitBinaryFunc(e));
244  	  }
245  	
246  	  Result VisitTrunc(BinaryExpr e) {
247  	    return MP_DISPATCH(VisitBinaryFunc(e));
248  	  }
249  	
250  	  Result VisitIf(IfExpr e) {
251  	    return MP_DISPATCH(VisitNumeric(e));
252  	  }
253  	
254  	  Result VisitPLTerm(PLTerm e) {
255  	    return MP_DISPATCH(VisitNumeric(e));
256  	  }
257  	
258  	  Result VisitCall(CallExpr e) {
259  	    return MP_DISPATCH(VisitNumeric(e));
260  	  }
261  	
262  	  Result VisitVarArg(VarArgExpr e) {
263  	    return MP_DISPATCH(VisitNumeric(e));
264  	  }
265  	
266  	  Result VisitMin(VarArgExpr e) {
267  	    return MP_DISPATCH(VisitVarArg(e));
268  	  }
269  	
270  	  Result VisitMax(VarArgExpr e) {
271  	    return MP_DISPATCH(VisitVarArg(e));
272  	  }
273  	
274  	  Result VisitSum(SumExpr e) {
275  	    return MP_DISPATCH(VisitNumeric(e));
276  	  }
277  	
278  	  Result VisitNumberOf(NumberOfExpr e) {
279  	    return MP_DISPATCH(VisitNumeric(e));
280  	  }
281  	
282  	  Result VisitNumberOfSym(SymbolicNumberOfExpr e) {
283  	    return MP_DISPATCH(VisitNumeric(e));
284  	  }
285  	
286  	  Result VisitCount(CountExpr e) {
287  	    return MP_DISPATCH(VisitNumeric(e));
288  	  }
289  	
290  	  Result VisitLogicalConstant(LogicalConstant c) {
291  	    return MP_DISPATCH(VisitLogical(c));
292  	  }
293  	
294  	  Result VisitNot(NotExpr e) {
295  	    return MP_DISPATCH(VisitLogical(e));
296  	  }
297  	
298  	  Result VisitBinaryLogical(BinaryLogicalExpr e) {
299  	    return MP_DISPATCH(VisitLogical(e));
300  	  }
301  	
302  	  Result VisitOr(BinaryLogicalExpr e) {
303  	    return MP_DISPATCH(VisitBinaryLogical(e));
304  	  }
305  	
306  	  Result VisitAnd(BinaryLogicalExpr e) {
307  	    return MP_DISPATCH(VisitBinaryLogical(e));
308  	  }
309  	
310  	  Result VisitIff(BinaryLogicalExpr e) {
311  	    return MP_DISPATCH(VisitBinaryLogical(e));
312  	  }
313  	
314  	  Result VisitRelational(RelationalExpr e) {
315  	    return MP_DISPATCH(VisitLogical(e));
316  	  }
317  	
318  	  Result VisitLT(RelationalExpr e) {
319  	    return MP_DISPATCH(VisitRelational(e));
320  	  }
321  	
322  	  Result VisitLE(RelationalExpr e) {
323  	    return MP_DISPATCH(VisitRelational(e));
324  	  }
325  	
326  	  Result VisitEQ(RelationalExpr e) {
327  	    return MP_DISPATCH(VisitRelational(e));
328  	  }
329  	
330  	  Result VisitGE(RelationalExpr e) {
331  	    return MP_DISPATCH(VisitRelational(e));
332  	  }
333  	
334  	  Result VisitGT(RelationalExpr e) {
335  	    return MP_DISPATCH(VisitRelational(e));
336  	  }
337  	
338  	  Result VisitNE(RelationalExpr e) {
339  	    return MP_DISPATCH(VisitRelational(e));
340  	  }
341  	
342  	  Result VisitLogicalCount(LogicalCountExpr e) {
343  	    return MP_DISPATCH(VisitLogical(e));
344  	  }
345  	
346  	  Result VisitAtLeast(LogicalCountExpr e) {
347  	    return MP_DISPATCH(VisitLogicalCount(e));
348  	  }
349  	
350  	  Result VisitAtMost(LogicalCountExpr e) {
351  	    return MP_DISPATCH(VisitLogicalCount(e));
352  	  }
353  	
354  	  Result VisitExactly(LogicalCountExpr e) {
355  	    return MP_DISPATCH(VisitLogicalCount(e));
356  	  }
357  	
358  	  Result VisitNotAtLeast(LogicalCountExpr e) {
359  	    return MP_DISPATCH(VisitLogicalCount(e));
360  	  }
361  	
362  	  Result VisitNotAtMost(LogicalCountExpr e) {
363  	    return MP_DISPATCH(VisitLogicalCount(e));
364  	  }
365  	
366  	  Result VisitNotExactly(LogicalCountExpr e) {
367  	    return MP_DISPATCH(VisitLogicalCount(e));
368  	  }
369  	
370  	  Result VisitImplication(ImplicationExpr e) {
371  	    return MP_DISPATCH(VisitLogical(e));
372  	  }
373  	
374  	  Result VisitIteratedLogical(IteratedLogicalExpr e) {
375  	    return MP_DISPATCH(VisitLogical(e));
376  	  }
377  	
378  	  Result VisitExists(IteratedLogicalExpr e) {
379  	    return MP_DISPATCH(VisitIteratedLogical(e));
380  	  }
381  	
382  	  Result VisitForAll(IteratedLogicalExpr e) {
383  	    return MP_DISPATCH(VisitIteratedLogical(e));
384  	  }
385  	
386  	  Result VisitAllDiff(PairwiseExpr e) {
387  	    return MP_DISPATCH(VisitLogical(e));
388  	  }
389  	
390  	  Result VisitNotAllDiff(PairwiseExpr e) {
391  	    return MP_DISPATCH(VisitLogical(e));
392  	  }
393  	
394  	  Result VisitStringLiteral(StringLiteral e) {
395  	    return VisitUnsupported(e);
396  	  }
397  	
398  	  Result VisitSymbolicIf(SymbolicIfExpr e) {
399  	    return VisitUnsupported(e);
400  	  }
401  	};
402  	
403  	template <typename Impl, typename Result, typename ET>
404  	Result BasicExprVisitor<Impl, Result, ET>::Visit(Expr e) {
405  	  // All expressions except OPNUMBEROFs and OPIFSYM are supported.
406  	  switch (e.kind()) {
407  	  default:
408  	    MP_ASSERT(false, "invalid expression");
409  	    // Fall through.
410  	  case expr::NUMBER:
411  	    return MP_DISPATCH(VisitNumericConstant(
412  	                         ET::template UncheckedCast<NumericConstant>(e)));
413  	  case expr::VARIABLE:
414  	    return MP_DISPATCH(VisitVariable(ET::template UncheckedCast<Variable>(e)));
415  	  case expr::COMMON_EXPR:
416  	    return MP_DISPATCH(VisitCommonExpr(
417  	                         ET::template UncheckedCast<CommonExpr>(e)));
418  	
419  	  // Unary expressions.
420  	  case expr::MINUS:
421  	    return MP_DISPATCH(VisitMinus(ET::template UncheckedCast<UnaryExpr>(e)));
422  	  case expr::ABS:
423  	    return MP_DISPATCH(VisitAbs(ET::template UncheckedCast<UnaryExpr>(e)));
424  	  case expr::FLOOR:
425  	    return MP_DISPATCH(VisitFloor(ET::template UncheckedCast<UnaryExpr>(e)));
426  	  case expr::CEIL:
427  	    return MP_DISPATCH(VisitCeil(ET::template UncheckedCast<UnaryExpr>(e)));
428  	  case expr::SQRT:
429  	    return MP_DISPATCH(VisitSqrt(ET::template UncheckedCast<UnaryExpr>(e)));
430  	  case expr::POW2:
431  	    return MP_DISPATCH(VisitPow2(ET::template UncheckedCast<UnaryExpr>(e)));
432  	  case expr::EXP:
433  	    return MP_DISPATCH(VisitExp(ET::template UncheckedCast<UnaryExpr>(e)));
434  	  case expr::LOG:
435  	    return MP_DISPATCH(VisitLog(ET::template UncheckedCast<UnaryExpr>(e)));
436  	  case expr::LOG10:
437  	    return MP_DISPATCH(VisitLog10(ET::template UncheckedCast<UnaryExpr>(e)));
438  	  case expr::SIN:
439  	    return MP_DISPATCH(VisitSin(ET::template UncheckedCast<UnaryExpr>(e)));
440  	  case expr::SINH:
441  	    return MP_DISPATCH(VisitSinh(ET::template UncheckedCast<UnaryExpr>(e)));
442  	  case expr::COS:
443  	    return MP_DISPATCH(VisitCos(ET::template UncheckedCast<UnaryExpr>(e)));
444  	  case expr::COSH:
445  	    return MP_DISPATCH(VisitCosh(ET::template UncheckedCast<UnaryExpr>(e)));
446  	  case expr::TAN:
447  	    return MP_DISPATCH(VisitTan(ET::template UncheckedCast<UnaryExpr>(e)));
448  	  case expr::TANH:
449  	    return MP_DISPATCH(VisitTanh(ET::template UncheckedCast<UnaryExpr>(e)));
450  	  case expr::ASIN:
451  	    return MP_DISPATCH(VisitAsin(ET::template UncheckedCast<UnaryExpr>(e)));
452  	  case expr::ASINH:
453  	    return MP_DISPATCH(VisitAsinh(ET::template UncheckedCast<UnaryExpr>(e)));
454  	  case expr::ACOS:
455  	    return MP_DISPATCH(VisitAcos(ET::template UncheckedCast<UnaryExpr>(e)));
456  	  case expr::ACOSH:
457  	    return MP_DISPATCH(VisitAcosh(ET::template UncheckedCast<UnaryExpr>(e)));
458  	  case expr::ATAN:
459  	    return MP_DISPATCH(VisitAtan(ET::template UncheckedCast<UnaryExpr>(e)));
460  	  case expr::ATANH:
461  	    return MP_DISPATCH(VisitAtanh(ET::template UncheckedCast<UnaryExpr>(e)));
462  	
463  	  // Binary expressions.
464  	  case expr::ADD:
465  	    return MP_DISPATCH(VisitAdd(ET::template UncheckedCast<BinaryExpr>(e)));
466  	  case expr::SUB:
467  	    return MP_DISPATCH(VisitSub(ET::template UncheckedCast<BinaryExpr>(e)));
468  	  case expr::LESS:
469  	    return MP_DISPATCH(VisitLess(ET::template UncheckedCast<BinaryExpr>(e)));
470  	  case expr::MUL:
471  	    return MP_DISPATCH(VisitMul(ET::template UncheckedCast<BinaryExpr>(e)));
472  	  case expr::DIV:
473  	    return MP_DISPATCH(VisitDiv(ET::template UncheckedCast<BinaryExpr>(e)));
474  	  case expr::TRUNC_DIV:
475  	    return MP_DISPATCH(VisitTruncDiv(
476  	                         ET::template UncheckedCast<BinaryExpr>(e)));
477  	  case expr::MOD:
478  	    return MP_DISPATCH(VisitMod(ET::template UncheckedCast<BinaryExpr>(e)));
479  	  case expr::POW:
480  	    return MP_DISPATCH(VisitPow(ET::template UncheckedCast<BinaryExpr>(e)));
481  	  case expr::POW_CONST_BASE:
482  	    return MP_DISPATCH(VisitPowConstBase(
483  	                         ET::template UncheckedCast<BinaryExpr>(e)));
484  	  case expr::POW_CONST_EXP:
485  	    return MP_DISPATCH(VisitPowConstExp(
486  	                         ET::template UncheckedCast<BinaryExpr>(e)));
487  	  case expr::ATAN2:
488  	    return MP_DISPATCH(VisitAtan2(ET::template UncheckedCast<BinaryExpr>(e)));
489  	  case expr::PRECISION:
490  	    return MP_DISPATCH(VisitPrecision(
491  	                         ET::template UncheckedCast<BinaryExpr>(e)));
492  	  case expr::ROUND:
493  	    return MP_DISPATCH(VisitRound(ET::template UncheckedCast<BinaryExpr>(e)));
494  	  case expr::TRUNC:
495  	    return MP_DISPATCH(VisitTrunc(ET::template UncheckedCast<BinaryExpr>(e)));
496  	
497  	  case expr::IF:
498  	    return MP_DISPATCH(VisitIf(ET::template UncheckedCast<IfExpr>(e)));
499  	  case expr::PLTERM:
500  	    return MP_DISPATCH(VisitPLTerm(ET::template UncheckedCast<PLTerm>(e)));
501  	  case expr::CALL:
502  	    return MP_DISPATCH(VisitCall(ET::template UncheckedCast<CallExpr>(e)));
503  	  case expr::MIN:
504  	    return MP_DISPATCH(VisitMin(ET::template UncheckedCast<VarArgExpr>(e)));
505  	  case expr::MAX:
506  	    return MP_DISPATCH(VisitMax(ET::template UncheckedCast<VarArgExpr>(e)));
507  	  case expr::SUM:
508  	    return MP_DISPATCH(VisitSum(ET::template UncheckedCast<SumExpr>(e)));
509  	  case expr::NUMBEROF:
510  	    return MP_DISPATCH(VisitNumberOf(
511  	                         ET::template UncheckedCast<NumberOfExpr>(e)));
512  	  case expr::NUMBEROF_SYM:
513  	    return MP_DISPATCH(VisitNumberOfSym(
514  	                         ET::template UncheckedCast<SymbolicNumberOfExpr>(e)));
515  	  case expr::COUNT:
516  	    return MP_DISPATCH(VisitCount(ET::template UncheckedCast<CountExpr>(e)));
517  	
518  	    // Logical expressions.
519  	  case expr::BOOL:
520  	    return MP_DISPATCH(VisitLogicalConstant(
521  	                         ET::template UncheckedCast<LogicalConstant>(e)));
522  	  case expr::NOT:
523  	    return MP_DISPATCH(VisitNot(ET::template UncheckedCast<NotExpr>(e)));
524  	  case expr::OR:
525  	    return MP_DISPATCH(VisitOr(
526  	                         ET::template UncheckedCast<BinaryLogicalExpr>(e)));
527  	  case expr::AND:
528  	    return MP_DISPATCH(VisitAnd(
529  	                         ET::template UncheckedCast<BinaryLogicalExpr>(e)));
530  	  case expr::IFF:
531  	    return MP_DISPATCH(VisitIff(
532  	                         ET::template UncheckedCast<BinaryLogicalExpr>(e)));
533  	  case expr::LT:
534  	    return MP_DISPATCH(VisitLT(ET::template UncheckedCast<RelationalExpr>(e)));
535  	  case expr::LE:
536  	    return MP_DISPATCH(VisitLE(ET::template UncheckedCast<RelationalExpr>(e)));
537  	  case expr::EQ:
538  	    return MP_DISPATCH(VisitEQ(ET::template UncheckedCast<RelationalExpr>(e)));
539  	  case expr::GE:
540  	    return MP_DISPATCH(VisitGE(ET::template UncheckedCast<RelationalExpr>(e)));
541  	  case expr::GT:
542  	    return MP_DISPATCH(VisitGT(ET::template UncheckedCast<RelationalExpr>(e)));
543  	  case expr::NE:
544  	    return MP_DISPATCH(VisitNE(ET::template UncheckedCast<RelationalExpr>(e)));
545  	  case expr::ATLEAST:
546  	    return MP_DISPATCH(VisitAtLeast(
547  	                         ET::template UncheckedCast<LogicalCountExpr>(e)));
548  	  case expr::ATMOST:
549  	    return MP_DISPATCH(VisitAtMost(
550  	                         ET::template UncheckedCast<LogicalCountExpr>(e)));
551  	  case expr::EXACTLY:
552  	    return MP_DISPATCH(VisitExactly(
553  	                         ET::template UncheckedCast<LogicalCountExpr>(e)));
554  	  case expr::NOT_ATLEAST:
555  	    return MP_DISPATCH(VisitNotAtLeast(
556  	                         ET::template UncheckedCast<LogicalCountExpr>(e)));
557  	  case expr::NOT_ATMOST:
558  	    return MP_DISPATCH(VisitNotAtMost(
559  	                         ET::template UncheckedCast<LogicalCountExpr>(e)));
560  	  case expr::NOT_EXACTLY:
561  	    return MP_DISPATCH(VisitNotExactly(
562  	                         ET::template UncheckedCast<LogicalCountExpr>(e)));
563  	  case expr::IMPLICATION:
564  	    return MP_DISPATCH(VisitImplication(
565  	                         ET::template UncheckedCast<ImplicationExpr>(e)));
566  	  case expr::EXISTS:
567  	    return MP_DISPATCH(VisitExists(
568  	                         ET::template UncheckedCast<IteratedLogicalExpr>(e)));
569  	  case expr::FORALL:
570  	    return MP_DISPATCH(VisitForAll(
571  	                         ET::template UncheckedCast<IteratedLogicalExpr>(e)));
572  	  case expr::ALLDIFF:
573  	    return MP_DISPATCH(VisitAllDiff(
574  	                         ET::template UncheckedCast<PairwiseExpr>(e)));
575  	  case expr::NOT_ALLDIFF:
576  	    return MP_DISPATCH(VisitNotAllDiff(
577  	                         ET::template UncheckedCast<PairwiseExpr>(e)));
578  	
579  	    // String expressions.
580  	  case expr::STRING:
581  	    return MP_DISPATCH(VisitStringLiteral(
582  	                         ET::template UncheckedCast<StringLiteral>(e)));
583  	  case expr::IFSYM:
584  	    return MP_DISPATCH(VisitSymbolicIf(
585  	                         ET::template UncheckedCast<SymbolicIfExpr>(e)));
586  	  }
587  	}
588  	}  // namespace mp
589  	
590  	#endif  // MP_BASIC_EXPR_VISITOR_H_
591