1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.ir.visitor;
  27 
  28 import jdk.nashorn.internal.ir.AccessNode;
  29 import jdk.nashorn.internal.ir.BinaryNode;
  30 import jdk.nashorn.internal.ir.Block;
  31 import jdk.nashorn.internal.ir.BlockStatement;
  32 import jdk.nashorn.internal.ir.BreakNode;
  33 import jdk.nashorn.internal.ir.CallNode;
  34 import jdk.nashorn.internal.ir.CaseNode;
  35 import jdk.nashorn.internal.ir.CatchNode;
  36 import jdk.nashorn.internal.ir.ContinueNode;
  37 import jdk.nashorn.internal.ir.DebuggerNode;
  38 import jdk.nashorn.internal.ir.EmptyNode;
  39 import jdk.nashorn.internal.ir.ErrorNode;
  40 import jdk.nashorn.internal.ir.ExpressionStatement;
  41 import jdk.nashorn.internal.ir.ForNode;
  42 import jdk.nashorn.internal.ir.FunctionNode;
  43 import jdk.nashorn.internal.ir.GetSplitState;
  44 import jdk.nashorn.internal.ir.IdentNode;
  45 import jdk.nashorn.internal.ir.IfNode;
  46 import jdk.nashorn.internal.ir.IndexNode;
  47 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
  48 import jdk.nashorn.internal.ir.JumpToInlinedFinally;
  49 import jdk.nashorn.internal.ir.LabelNode;
  50 import jdk.nashorn.internal.ir.LexicalContext;
  51 import jdk.nashorn.internal.ir.LiteralNode;
  52 import jdk.nashorn.internal.ir.Node;
  53 import jdk.nashorn.internal.ir.ObjectNode;
  54 import jdk.nashorn.internal.ir.PropertyNode;
  55 import jdk.nashorn.internal.ir.ReturnNode;
  56 import jdk.nashorn.internal.ir.RuntimeNode;
  57 import jdk.nashorn.internal.ir.SetSplitState;
  58 import jdk.nashorn.internal.ir.SplitNode;
  59 import jdk.nashorn.internal.ir.SplitReturn;
  60 import jdk.nashorn.internal.ir.SwitchNode;
  61 import jdk.nashorn.internal.ir.TernaryNode;
  62 import jdk.nashorn.internal.ir.ThrowNode;
  63 import jdk.nashorn.internal.ir.TryNode;
  64 import jdk.nashorn.internal.ir.UnaryNode;
  65 import jdk.nashorn.internal.ir.VarNode;
  66 import jdk.nashorn.internal.ir.WhileNode;
  67 import jdk.nashorn.internal.ir.WithNode;
  68 
  69 /**
  70  * Visitor used to navigate the IR.
  71  * @param <T> lexical context class used by this visitor
  72  */
  73 public abstract class NodeVisitor<T extends LexicalContext> {
  74     /** lexical context in use */
  75     protected final T lc;
  76 
  77     /**
  78      * Constructor
  79      *
  80      * @param lc a custom lexical context
  81      */
  82     public NodeVisitor(final T lc) {
  83         this.lc = lc;
  84     }
  85 
  86     /**
  87      * Get the lexical context of this node visitor
  88      * @return lexical context
  89      */
  90     public T getLexicalContext() {
  91         return lc;
  92     }
  93 
  94     /**
  95      * Override this method to do a double inheritance pattern, e.g. avoid
  96      * using
  97      * <p>
  98      * if (x instanceof NodeTypeA) {
  99      *    ...
 100      * } else if (x instanceof NodeTypeB) {
 101      *    ...
 102      * } else {
 103      *    ...
 104      * }
 105      * <p>
 106      * Use a NodeVisitor instead, and this method contents forms the else case.
 107      *
 108      * @see NodeVisitor#leaveDefault(Node)
 109      * @param node the node to visit
 110      * @return true if traversal should continue and node children be traversed, false otherwise
 111      */
 112     protected boolean enterDefault(final Node node) {
 113         return true;
 114     }
 115 
 116     /**
 117      * Override this method to do a double inheritance pattern, e.g. avoid
 118      * using
 119      * <p>
 120      * if (x instanceof NodeTypeA) {
 121      *    ...
 122      * } else if (x instanceof NodeTypeB) {
 123      *    ...
 124      * } else {
 125      *    ...
 126      * }
 127      * <p>
 128      * Use a NodeVisitor instead, and this method contents forms the else case.
 129      *
 130      * @see NodeVisitor#enterDefault(Node)
 131      * @param node the node to visit
 132      * @return the node
 133      */
 134     protected Node leaveDefault(final Node node) {
 135         return node;
 136     }
 137 
 138     /**
 139      * Callback for entering an AccessNode
 140      *
 141      * @param  accessNode the node
 142      * @return true if traversal should continue and node children be traversed, false otherwise
 143      */
 144     public boolean enterAccessNode(final AccessNode accessNode) {
 145         return enterDefault(accessNode);
 146     }
 147 
 148     /**
 149      * Callback for entering an AccessNode
 150      *
 151      * @param  accessNode the node
 152      * @return processed node, null if traversal should end
 153      */
 154     public Node leaveAccessNode(final AccessNode accessNode) {
 155         return leaveDefault(accessNode);
 156     }
 157 
 158     /**
 159      * Callback for entering a Block
 160      *
 161      * @param  block     the node
 162      * @return true if traversal should continue and node children be traversed, false otherwise
 163      */
 164     public boolean enterBlock(final Block block) {
 165         return enterDefault(block);
 166     }
 167 
 168     /**
 169      * Callback for leaving a Block
 170      *
 171      * @param  block the node
 172      * @return processed node, which will replace the original one, or the original node
 173      */
 174     public Node leaveBlock(final Block block) {
 175         return leaveDefault(block);
 176     }
 177 
 178     /**
 179      * Callback for entering a BinaryNode
 180      *
 181      * @param  binaryNode  the node
 182      * @return processed   node
 183      */
 184     public boolean enterBinaryNode(final BinaryNode binaryNode) {
 185         return enterDefault(binaryNode);
 186     }
 187 
 188     /**
 189      * Callback for leaving a BinaryNode
 190      *
 191      * @param  binaryNode the node
 192      * @return processed node, which will replace the original one, or the original node
 193      */
 194     public Node leaveBinaryNode(final BinaryNode binaryNode) {
 195         return leaveDefault(binaryNode);
 196     }
 197 
 198     /**
 199      * Callback for entering a BreakNode
 200      *
 201      * @param  breakNode the node
 202      * @return true if traversal should continue and node children be traversed, false otherwise
 203      */
 204     public boolean enterBreakNode(final BreakNode breakNode) {
 205         return enterDefault(breakNode);
 206     }
 207 
 208     /**
 209      * Callback for leaving a BreakNode
 210      *
 211      * @param  breakNode the node
 212      * @return processed node, which will replace the original one, or the original node
 213      */
 214     public Node leaveBreakNode(final BreakNode breakNode) {
 215         return leaveDefault(breakNode);
 216     }
 217 
 218     /**
 219      * Callback for entering a CallNode
 220      *
 221      * @param  callNode  the node
 222      * @return true if traversal should continue and node children be traversed, false otherwise
 223      */
 224     public boolean enterCallNode(final CallNode callNode) {
 225         return enterDefault(callNode);
 226     }
 227 
 228     /**
 229      * Callback for leaving a CallNode
 230      *
 231      * @param  callNode the node
 232      * @return processed node, which will replace the original one, or the original node
 233      */
 234     public Node leaveCallNode(final CallNode callNode) {
 235         return leaveDefault(callNode);
 236     }
 237 
 238     /**
 239      * Callback for entering a CaseNode
 240      *
 241      * @param  caseNode  the node
 242      * @return true if traversal should continue and node children be traversed, false otherwise
 243      */
 244     public boolean enterCaseNode(final CaseNode caseNode) {
 245         return enterDefault(caseNode);
 246     }
 247 
 248     /**
 249      * Callback for leaving a CaseNode
 250      *
 251      * @param  caseNode the node
 252      * @return processed node, which will replace the original one, or the original node
 253      */
 254     public Node leaveCaseNode(final CaseNode caseNode) {
 255         return leaveDefault(caseNode);
 256     }
 257 
 258     /**
 259      * Callback for entering a CatchNode
 260      *
 261      * @param  catchNode the node
 262      * @return true if traversal should continue and node children be traversed, false otherwise
 263      */
 264     public boolean enterCatchNode(final CatchNode catchNode) {
 265         return enterDefault(catchNode);
 266     }
 267 
 268     /**
 269      * Callback for leaving a CatchNode
 270      *
 271      * @param  catchNode the node
 272      * @return processed node, which will replace the original one, or the original node
 273      */
 274     public Node leaveCatchNode(final CatchNode catchNode) {
 275         return leaveDefault(catchNode);
 276     }
 277 
 278     /**
 279      * Callback for entering a ContinueNode
 280      *
 281      * @param  continueNode the node
 282      * @return true if traversal should continue and node children be traversed, false otherwise
 283      */
 284     public boolean enterContinueNode(final ContinueNode continueNode) {
 285         return enterDefault(continueNode);
 286     }
 287 
 288     /**
 289      * Callback for leaving a ContinueNode
 290      *
 291      * @param  continueNode the node
 292      * @return processed node, which will replace the original one, or the original node
 293      */
 294     public Node leaveContinueNode(final ContinueNode continueNode) {
 295         return leaveDefault(continueNode);
 296     }
 297 
 298  
 299     /**
 300      * Callback for entering a DebuggerNode
 301      *
 302      * @param  debuggerNode the node
 303      * @return true if traversal should continue and node children be traversed, false otherwise
 304      */
 305     public boolean enterDebuggerNode(final DebuggerNode debuggerNode) {
 306         return enterDefault(debuggerNode);
 307     }
 308  
 309     /**
 310      * Callback for leaving a DebuggerNode
 311      *
 312      * @param  debuggerNode the node
 313      * @return processed node, which will replace the original one, or the original node
 314      */
 315     public Node leaveDebuggerNode(final DebuggerNode debuggerNode) {
 316         return leaveDefault(debuggerNode);
 317     }
 318  
 319     /**
 320      * Callback for entering an EmptyNode
 321      *
 322      * @param  emptyNode   the node
 323      * @return true if traversal should continue and node children be traversed, false otherwise
 324      */
 325     public boolean enterEmptyNode(final EmptyNode emptyNode) {
 326         return enterDefault(emptyNode);
 327     }
 328 
 329     /**
 330      * Callback for leaving an EmptyNode
 331      *
 332      * @param  emptyNode the node
 333      * @return processed node, which will replace the original one, or the original node
 334      */
 335     public Node leaveEmptyNode(final EmptyNode emptyNode) {
 336         return leaveDefault(emptyNode);
 337     }
 338 
 339     /**
 340      * Callback for entering an ErrorNode
 341      *
 342      * @param  errorNode   the node
 343      * @return true if traversal should continue and node children be traversed, false otherwise
 344      */
 345     public boolean enterErrorNode(final ErrorNode errorNode) {
 346         return enterDefault(errorNode);
 347     }
 348 
 349     /**
 350      * Callback for leaving an ErrorNode
 351      *
 352      * @param  errorNode the node
 353      * @return processed node, which will replace the original one, or the original node
 354      */
 355     public Node leaveErrorNode(final ErrorNode errorNode) {
 356         return leaveDefault(errorNode);
 357     }
 358 
 359     /**
 360      * Callback for entering an ExpressionStatement
 361      *
 362      * @param  expressionStatement the node
 363      * @return true if traversal should continue and node children be traversed, false otherwise
 364      */
 365     public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
 366         return enterDefault(expressionStatement);
 367     }
 368 
 369     /**
 370      * Callback for leaving an ExpressionStatement
 371      *
 372      * @param  expressionStatement the node
 373      * @return processed node, which will replace the original one, or the original node
 374      */
 375     public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
 376         return leaveDefault(expressionStatement);
 377     }
 378 
 379     /**
 380      * Callback for entering a BlockStatement
 381      *
 382      * @param  blockStatement the node
 383      * @return true if traversal should continue and node children be traversed, false otherwise
 384      */
 385     public boolean enterBlockStatement(final BlockStatement blockStatement) {
 386         return enterDefault(blockStatement);
 387     }
 388 
 389     /**
 390      * Callback for leaving a BlockStatement
 391      *
 392      * @param  blockStatement the node
 393      * @return processed node, which will replace the original one, or the original node
 394      */
 395     public Node leaveBlockStatement(final BlockStatement blockStatement) {
 396         return leaveDefault(blockStatement);
 397     }
 398 
 399     /**
 400      * Callback for entering a ForNode
 401      *
 402      * @param  forNode   the node
 403      * @return true if traversal should continue and node children be traversed, false otherwise
 404      */
 405     public boolean enterForNode(final ForNode forNode) {
 406         return enterDefault(forNode);
 407     }
 408 
 409     /**
 410      * Callback for leaving a ForNode
 411      *
 412      * @param  forNode the node
 413      * @return processed node, which will replace the original one, or the original node
 414      */
 415     public Node leaveForNode(final ForNode forNode) {
 416         return leaveDefault(forNode);
 417     }
 418 
 419     /**
 420      * Callback for entering a FunctionNode
 421      *
 422      * @param  functionNode the node
 423      * @return true if traversal should continue and node children be traversed, false otherwise
 424      */
 425     public boolean enterFunctionNode(final FunctionNode functionNode) {
 426         return enterDefault(functionNode);
 427     }
 428 
 429     /**
 430      * Callback for leaving a FunctionNode
 431      *
 432      * @param  functionNode the node
 433      * @return processed node, which will replace the original one, or the original node
 434      */
 435     public Node leaveFunctionNode(final FunctionNode functionNode) {
 436         return leaveDefault(functionNode);
 437     }
 438 
 439     /**
 440      * Callback for entering a {@link GetSplitState}.
 441      *
 442      * @param  getSplitState the get split state expression
 443      * @return true if traversal should continue and node children be traversed, false otherwise
 444      */
 445     public boolean enterGetSplitState(final GetSplitState getSplitState) {
 446         return enterDefault(getSplitState);
 447     }
 448 
 449     /**
 450      * Callback for leaving a {@link GetSplitState}.
 451      *
 452      * @param  getSplitState the get split state expression
 453      * @return processed node, which will replace the original one, or the original node
 454      */
 455     public Node leaveGetSplitState(final GetSplitState getSplitState) {
 456         return leaveDefault(getSplitState);
 457     }
 458 
 459     /**
 460      * Callback for entering an IdentNode
 461      *
 462      * @param  identNode the node
 463      * @return true if traversal should continue and node children be traversed, false otherwise
 464      */
 465     public boolean enterIdentNode(final IdentNode identNode) {
 466         return enterDefault(identNode);
 467     }
 468 
 469     /**
 470      * Callback for leaving an IdentNode
 471      *
 472      * @param  identNode the node
 473      * @return processed node, which will replace the original one, or the original node
 474      */
 475     public Node leaveIdentNode(final IdentNode identNode) {
 476         return leaveDefault(identNode);
 477     }
 478 
 479     /**
 480      * Callback for entering an IfNode
 481      *
 482      * @param  ifNode the node
 483      * @return true if traversal should continue and node children be traversed, false otherwise
 484      */
 485     public boolean enterIfNode(final IfNode ifNode) {
 486         return enterDefault(ifNode);
 487     }
 488 
 489     /**
 490      * Callback for leaving an IfNode
 491      *
 492      * @param  ifNode the node
 493      * @return processed node, which will replace the original one, or the original node
 494      */
 495     public Node leaveIfNode(final IfNode ifNode) {
 496         return leaveDefault(ifNode);
 497     }
 498 
 499     /**
 500      * Callback for entering an IndexNode
 501      *
 502      * @param  indexNode  the node
 503      * @return true if traversal should continue and node children be traversed, false otherwise
 504      */
 505     public boolean enterIndexNode(final IndexNode indexNode) {
 506         return enterDefault(indexNode);
 507     }
 508 
 509     /**
 510      * Callback for leaving an IndexNode
 511      *
 512      * @param  indexNode the node
 513      * @return processed node, which will replace the original one, or the original node
 514      */
 515     public Node leaveIndexNode(final IndexNode indexNode) {
 516         return leaveDefault(indexNode);
 517     }
 518 
 519     /**
 520      * Callback for entering a JumpToInlinedFinally
 521      *
 522      * @param  jumpToInlinedFinally the node
 523      * @return true if traversal should continue and node children be traversed, false otherwise
 524      */
 525     public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
 526         return enterDefault(jumpToInlinedFinally);
 527     }
 528 
 529     /**
 530      * Callback for leaving a JumpToInlinedFinally
 531      *
 532      * @param  jumpToInlinedFinally the node
 533      * @return processed node, which will replace the original one, or the original node
 534      */
 535     public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
 536         return leaveDefault(jumpToInlinedFinally);
 537     }
 538 
 539     /**
 540      * Callback for entering a LabelNode
 541      *
 542      * @param  labelNode the node
 543      * @return true if traversal should continue and node children be traversed, false otherwise
 544      */
 545     public boolean enterLabelNode(final LabelNode labelNode) {
 546         return enterDefault(labelNode);
 547     }
 548 
 549     /**
 550      * Callback for leaving a LabelNode
 551      *
 552      * @param  labelNode the node
 553      * @return processed node, which will replace the original one, or the original node
 554      */
 555     public Node leaveLabelNode(final LabelNode labelNode) {
 556         return leaveDefault(labelNode);
 557     }
 558 
 559     /**
 560      * Callback for entering a LiteralNode
 561      *
 562      * @param  literalNode the node
 563      * @return true if traversal should continue and node children be traversed, false otherwise
 564      */
 565     public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
 566         return enterDefault(literalNode);
 567     }
 568 
 569     /**
 570      * Callback for leaving a LiteralNode
 571      *
 572      * @param  literalNode the node
 573      * @return processed node, which will replace the original one, or the original node
 574      */
 575     public Node leaveLiteralNode(final LiteralNode<?> literalNode) {
 576         return leaveDefault(literalNode);
 577     }
 578 
 579     /**
 580      * Callback for entering an ObjectNode
 581      *
 582      * @param  objectNode the node
 583      * @return true if traversal should continue and node children be traversed, false otherwise
 584      */
 585     public boolean enterObjectNode(final ObjectNode objectNode) {
 586         return enterDefault(objectNode);
 587     }
 588 
 589     /**
 590      * Callback for leaving an ObjectNode
 591      *
 592      * @param  objectNode the node
 593      * @return processed node, which will replace the original one, or the original node
 594      */
 595     public Node leaveObjectNode(final ObjectNode objectNode) {
 596         return leaveDefault(objectNode);
 597     }
 598 
 599     /**
 600      * Callback for entering a PropertyNode
 601      *
 602      * @param  propertyNode the node
 603      * @return true if traversal should continue and node children be traversed, false otherwise
 604      */
 605     public boolean enterPropertyNode(final PropertyNode propertyNode) {
 606         return enterDefault(propertyNode);
 607     }
 608 
 609     /**
 610      * Callback for leaving a PropertyNode
 611      *
 612      * @param  propertyNode the node
 613      * @return processed node, which will replace the original one, or the original node
 614      */
 615     public Node leavePropertyNode(final PropertyNode propertyNode) {
 616         return leaveDefault(propertyNode);
 617     }
 618 
 619     /**
 620      * Callback for entering a ReturnNode
 621      *
 622      * @param  returnNode the node
 623      * @return true if traversal should continue and node children be traversed, false otherwise
 624      */
 625     public boolean enterReturnNode(final ReturnNode returnNode) {
 626         return enterDefault(returnNode);
 627     }
 628 
 629     /**
 630      * Callback for leaving a ReturnNode
 631      *
 632      * @param  returnNode the node
 633      * @return processed node, which will replace the original one, or the original node
 634      */
 635     public Node leaveReturnNode(final ReturnNode returnNode) {
 636         return leaveDefault(returnNode);
 637     }
 638 
 639     /**
 640      * Callback for entering a RuntimeNode
 641      *
 642      * @param  runtimeNode the node
 643      * @return true if traversal should continue and node children be traversed, false otherwise
 644      */
 645     public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
 646         return enterDefault(runtimeNode);
 647     }
 648 
 649     /**
 650      * Callback for leaving a RuntimeNode
 651      *
 652      * @param  runtimeNode the node
 653      * @return processed node, which will replace the original one, or the original node
 654      */
 655     public Node leaveRuntimeNode(final RuntimeNode runtimeNode) {
 656         return leaveDefault(runtimeNode);
 657     }
 658 
 659     /**
 660      * Callback for entering a {@link SetSplitState}.
 661      *
 662      * @param  setSplitState the set split state statement
 663      * @return true if traversal should continue and node children be traversed, false otherwise
 664      */
 665     public boolean enterSetSplitState(final SetSplitState setSplitState) {
 666         return enterDefault(setSplitState);
 667     }
 668 
 669     /**
 670      * Callback for leaving a {@link SetSplitState}.
 671      *
 672      * @param  setSplitState the set split state expression
 673      * @return processed node, which will replace the original one, or the original node
 674      */
 675     public Node leaveSetSplitState(final SetSplitState setSplitState) {
 676         return leaveDefault(setSplitState);
 677     }
 678 
 679     /**
 680      * Callback for entering a SplitNode
 681      *
 682      * @param  splitNode the node
 683      * @return true if traversal should continue and node children be traversed, false otherwise
 684      */
 685     public boolean enterSplitNode(final SplitNode splitNode) {
 686         return enterDefault(splitNode);
 687     }
 688 
 689     /**
 690      * Callback for leaving a SplitNode
 691      *
 692      * @param  splitNode the node
 693      * @return processed node, which will replace the original one, or the original node
 694      */
 695     public Node leaveSplitNode(final SplitNode splitNode) {
 696         return leaveDefault(splitNode);
 697     }
 698 
 699     /**
 700      * Callback for entering a SplitReturn
 701      *
 702      * @param  splitReturn the node
 703      * @return true if traversal should continue and node children be traversed, false otherwise
 704      */
 705     public boolean enterSplitReturn(final SplitReturn splitReturn) {
 706         return enterDefault(splitReturn);
 707     }
 708 
 709     /**
 710      * Callback for leaving a SplitReturn
 711      *
 712      * @param  splitReturn the node
 713      * @return processed node, which will replace the original one, or the original node
 714      */
 715     public Node leaveSplitReturn(final SplitReturn splitReturn) {
 716         return leaveDefault(splitReturn);
 717     }
 718 
 719     /**
 720      * Callback for entering a SwitchNode
 721      *
 722      * @param  switchNode the node
 723      * @return true if traversal should continue and node children be traversed, false otherwise
 724      */
 725     public boolean enterSwitchNode(final SwitchNode switchNode) {
 726         return enterDefault(switchNode);
 727     }
 728 
 729     /**
 730      * Callback for leaving a SwitchNode
 731      *
 732      * @param  switchNode the node
 733      * @return processed node, which will replace the original one, or the original node
 734      */
 735     public Node leaveSwitchNode(final SwitchNode switchNode) {
 736         return leaveDefault(switchNode);
 737     }
 738 
 739     /**
 740      * Callback for entering a TernaryNode
 741      *
 742      * @param  ternaryNode the node
 743      * @return true if traversal should continue and node children be traversed, false otherwise
 744      */
 745     public boolean enterTernaryNode(final TernaryNode ternaryNode) {
 746         return enterDefault(ternaryNode);
 747     }
 748 
 749     /**
 750      * Callback for leaving a TernaryNode
 751      *
 752      * @param  ternaryNode the node
 753      * @return processed node, which will replace the original one, or the original node
 754      */
 755     public Node leaveTernaryNode(final TernaryNode ternaryNode) {
 756         return leaveDefault(ternaryNode);
 757     }
 758 
 759     /**
 760      * Callback for entering a ThrowNode
 761      *
 762      * @param  throwNode the node
 763      * @return true if traversal should continue and node children be traversed, false otherwise
 764      */
 765     public boolean enterThrowNode(final ThrowNode throwNode) {
 766         return enterDefault(throwNode);
 767     }
 768 
 769     /**
 770      * Callback for leaving a ThrowNode
 771      *
 772      * @param  throwNode the node
 773      * @return processed node, which will replace the original one, or the original node
 774      */
 775     public Node leaveThrowNode(final ThrowNode throwNode) {
 776         return leaveDefault(throwNode);
 777     }
 778 
 779     /**
 780      * Callback for entering a TryNode
 781      *
 782      * @param  tryNode the node
 783      * @return true if traversal should continue and node children be traversed, false otherwise
 784      */
 785     public boolean enterTryNode(final TryNode tryNode) {
 786         return enterDefault(tryNode);
 787     }
 788 
 789     /**
 790      * Callback for leaving a TryNode
 791      *
 792      * @param  tryNode the node
 793      * @return processed node, which will replace the original one, or the original node
 794      */
 795     public Node leaveTryNode(final TryNode tryNode) {
 796         return leaveDefault(tryNode);
 797     }
 798 
 799     /**
 800      * Callback for entering a UnaryNode
 801      *
 802      * @param  unaryNode the node
 803      * @return true if traversal should continue and node children be traversed, false otherwise
 804      */
 805     public boolean enterUnaryNode(final UnaryNode unaryNode) {
 806         return enterDefault(unaryNode);
 807     }
 808 
 809     /**
 810      * Callback for leaving a UnaryNode
 811      *
 812      * @param  unaryNode the node
 813      * @return processed node, which will replace the original one, or the original node
 814      */
 815     public Node leaveUnaryNode(final UnaryNode unaryNode) {
 816         return leaveDefault(unaryNode);
 817     }
 818 
 819     /**
 820      * Callback for entering a {@link JoinPredecessorExpression}.
 821      *
 822      * @param  expr the join predecessor expression
 823      * @return true if traversal should continue and node children be traversed, false otherwise
 824      */
 825     public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression expr) {
 826         return enterDefault(expr);
 827     }
 828 
 829     /**
 830      * Callback for leaving a {@link JoinPredecessorExpression}.
 831      *
 832      * @param  expr the join predecessor expression
 833      * @return processed node, which will replace the original one, or the original node
 834      */
 835     public Node leaveJoinPredecessorExpression(final JoinPredecessorExpression expr) {
 836         return leaveDefault(expr);
 837     }
 838 
 839 
 840     /**
 841      * Callback for entering a VarNode
 842      *
 843      * @param  varNode   the node
 844      * @return true if traversal should continue and node children be traversed, false otherwise
 845      */
 846     public boolean enterVarNode(final VarNode varNode) {
 847         return enterDefault(varNode);
 848     }
 849 
 850     /**
 851      * Callback for leaving a VarNode
 852      *
 853      * @param  varNode the node
 854      * @return processed node, which will replace the original one, or the original node
 855      */
 856     public Node leaveVarNode(final VarNode varNode) {
 857         return leaveDefault(varNode);
 858     }
 859 
 860     /**
 861      * Callback for entering a WhileNode
 862      *
 863      * @param  whileNode the node
 864      * @return true if traversal should continue and node children be traversed, false otherwise
 865      */
 866     public boolean enterWhileNode(final WhileNode whileNode) {
 867         return enterDefault(whileNode);
 868     }
 869 
 870     /**
 871      * Callback for leaving a WhileNode
 872      *
 873      * @param  whileNode the node
 874      * @return processed node, which will replace the original one, or the original node
 875      */
 876     public Node leaveWhileNode(final WhileNode whileNode) {
 877         return leaveDefault(whileNode);
 878     }
 879 
 880     /**
 881      * Callback for entering a WithNode
 882      *
 883      * @param  withNode  the node
 884      * @return true if traversal should continue and node children be traversed, false otherwise
 885      */
 886     public boolean enterWithNode(final WithNode withNode) {
 887         return enterDefault(withNode);
 888     }
 889 
 890     /**
 891      * Callback for leaving a WithNode
 892      *
 893      * @param  withNode  the node
 894      * @return processed node, which will replace the original one, or the original node
 895      */
 896     public Node leaveWithNode(final WithNode withNode) {
 897         return leaveDefault(withNode);
 898     }
 899 
 900 
 901 }