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