Package edu.cmu.cs.crystal.internal

Source Code of edu.cmu.cs.crystal.internal.ControlFlowVisitor

/**
* Copyright (c) 2006, 2007, 2008 Marwan Abi-Antoun, Jonathan Aldrich, Nels E. Beckman,
* Kevin Bierhoff, David Dickey, Ciera Jaspan, Thomas LaToza, Gabriel Zenarosa, and others.
*
* This file is part of Crystal.
*
* Crystal is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Crystal is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Crystal.  If not, see <http://www.gnu.org/licenses/>.
*/
package edu.cmu.cs.crystal.internal;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.AssertStatement;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BlockComment;
import org.eclipse.jdt.core.dom.BooleanLiteral;
import org.eclipse.jdt.core.dom.BreakStatement;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.CharacterLiteral;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.ContinueStatement;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EmptyStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.InstanceofExpression;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.LineComment;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MemberRef;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.MethodRefParameter;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.NullLiteral;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PostfixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.SynchronizedStatement;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TextElement;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.dom.WildcardType;

import edu.cmu.cs.crystal.internal.ControlFlowNode.Direction;

/**
* An ASTVisitor that traverses the ASTNode structure and connects ControlFlowNodes
* to form a control flow graph of the ASTNode.
*  
* @author David Dickey
*
*/
public class ControlFlowVisitor extends ASTVisitor {
  protected ControlFlowNode controlFlowNode;
  protected ControlFlowGraph controlFlowGraph;

  public ControlFlowVisitor(ControlFlowNode cfn) {
    if(cfn == null)
      throw new CrystalRuntimeException("Cannot create a ControlFlowVisitor for a null ControlFlowNode");
    controlFlowNode = cfn;
    controlFlowGraph = cfn.getControlFlowGraph();
    if(controlFlowGraph == null)
      throw new CrystalRuntimeException("ControlFlowNode was not part of a ControlFlowGraph");
  }
 
  /**
   * Carries out the visit to the stored node.
   */
  public void performVisit() {
    if(controlFlowNode.getASTNode() != null)
      controlFlowNode.getASTNode().accept(this);
    else
      throw new CrystalRuntimeException("Cannot visit a null ASTNode");
  }

  /**
   * Called before performing a visit
   */
  public void preVisit(ASTNode node) {
    // TEMP: Print out the visit
    // System.out.println(Utilities.ASTNodeToString(node));
  }
 
  /*
   * The visit methods follow the following steps
   * 1) Create Children Visitors
   * 2) Reroute Control Flow to first Child from Parent
   * 3) Add Edges between Children
   * 4) Evaluate Children
   */
 
  /**
   * AnnotationTypeDeclaration
   *
   * This node does not influence control flow.
   */
  public boolean visit(AnnotationTypeDeclaration node) {
    return false;
  }
  /**
   * AnnotationTypeMemberDeclaration
   *
   * This node does not influence control flow.
   */
  public boolean visit(AnnotationTypeMemberDeclaration node) {
    return false;
  }
  /**
   * AnonymousClassDeclaration
   *
   * This node does not influence control flow.
   */
  public boolean visit(AnonymousClassDeclaration node) {
    return false;
  }
  /**
   * Example: myArray[0]
   */
  public boolean visit(ArrayAccess node) {
    if(node.getArray() == null)
      throw new CrystalRuntimeException("null array");
    if(node.getIndex() == null)
        throw new CrystalRuntimeException("null array index");
    ControlFlowNode array = controlFlowNode.newControlFlowNode(node.getArray());
    ControlFlowNode index = controlFlowNode.newControlFlowNode(node.getIndex());

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, array);

    array.addEdge(ControlFlowNode.Direction.FORWARDS, index);
    index.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);

    array.evaluate();
    index.evaluate();
   
    return false;
  }
  /**
   * Example: new int[10]{1,2,3,4,5,6,7,8,9,10};
   */
  public boolean visit(ArrayCreation node) {
    List dimensions = node.dimensions();
    ArrayInitializer arrayInitializer = node.getInitializer();
    List<ControlFlowNode> cfns = null;

    if(dimensions != null && dimensions.size() > 0) {
      // Handle dimension expressions
      cfns = createCFNListFromASTNodeList(dimensions);
      ControlFlowNode cfn = cfns.get(0);
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
      cfn = cfns.get(cfns.size() - 1);
      cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
      evaluate(cfns);
    } else if (arrayInitializer != null) {
      // Handle initializer if there is one
      ControlFlowNode initializer = controlFlowNode.newControlFlowNode(arrayInitializer);
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, initializer);
      initializer.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
      initializer.evaluate();
    }
    return false;
  }
  /**
   * Example: {1.2f, 2.3f, 3.4f}
   */
  public boolean visit(ArrayInitializer node) {
    List expressions = node.expressions();
    if(expressions == null || expressions.size() == 0)
      return false;
    // Take the expression list and make more visitors from them.
    List<ControlFlowNode> cfns = createCFNListFromASTNodeList(expressions);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    evaluate(cfns);
   
    return false;
  }
  /**
   * ArrayType
   *
   * This node does not influence control flow.
   */
  public boolean visit(ArrayType node) {
    return false;
  }
  /**
   * Example: assert (x != 0) : "x is " + x + " which is not 0";
   */
  public boolean visit(AssertStatement node) {
    ControlFlowNode expression = controlFlowNode.newControlFlowNode(node.getExpression());
    Expression message = node.getMessage();
   
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expression);

    if(message != null) {
      ControlFlowNode cfnMessage = controlFlowNode.newControlFlowNode(message);
      expression.addEdge(ControlFlowNode.Direction.FORWARDS, cfnMessage);
      cfnMessage.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
     
      expression.evaluate();
      cfnMessage.evaluate();
    } else {
      expression.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
      expression.evaluate();
    }
   
    return false;
  }
  /**
   * Example: x = y
   */
  public boolean visit(Assignment node) {
    ControlFlowNode leftCFN = controlFlowNode.newControlFlowNode(node.getLeftHandSide());
    ControlFlowNode rightCFN = controlFlowNode.newControlFlowNode(node.getRightHandSide());

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, leftCFN);

    leftCFN.addEdge(ControlFlowNode.Direction.FORWARDS, rightCFN);
    rightCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);

    leftCFN.evaluate();
    rightCFN.evaluate();
       
    return false;
  }
  /**
   * Example: { int x = 1; x++; }   or  {}
   */
  public boolean visit(Block node) {
    List statements = node.statements();
   
    if(statements == null || statements.size() == 0) {
      // controlFlowNode.remove();
      return false;
    }
   
    List<ControlFlowNode> cfns = createCFNListFromASTNodeList(statements);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    // Remove the block node from the graph
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    //controlFlowNode.moveEdges(ControlFlowNode.Direction.FORWARDS, cfn);
    //controlFlowNode.remove();
   
    evaluate(cfns);
   
    return false;
  }
  /**
   * BlockComment
   *
   * This node does not influence control flow.
   */
  public boolean visit(BlockComment node) {
    return false;
  }
  /**
   * BooleanLiteral
   *
   * This node does not influence control flow.
   */
  public boolean visit(BooleanLiteral node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * Example: break;   or   break ToHere;
   */
  public boolean visit(BreakStatement node) {
    SimpleName simpleName = node.getLabel();
    String label;
    if(simpleName == null)
      label = null;
    else
      label = simpleName.getIdentifier();
   
    controlFlowNode.breaking(label, true);

    return false;
  }
  /**
   * Example: (Square) myShape
   */
  public boolean visit(CastExpression node) {
    ControlFlowNode expression = controlFlowNode.newControlFlowNode(node.getExpression());

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expression);

    expression.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);

    expression.evaluate();
    return false;
  }
  /**
   * Example: catch (RuntimeException re) { System.out.println("RE: " + re); }
   */
  public boolean visit(CatchClause node) {
    ControlFlowNode exception = controlFlowNode.newControlFlowNode(node.getException());
    ControlFlowNode body = controlFlowNode.newControlFlowNode(node.getBody());

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, exception);
    exception.addEdge(ControlFlowNode.Direction.FORWARDS, body);
    body.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);

    exception.evaluate();
    body.evaluate();
    return false;
  }
  /**
   * CharacterLiteral
   *
   * This node does not influence control flow.
   */
  public boolean visit(CharacterLiteral node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * Example: new MyClass(5, "hello");
   */
  public boolean visit(ClassInstanceCreation node) {
    Expression expression = node.getExpression();
    List arguments = node.arguments();
    ControlFlowNode expressioncfn = null, last = null;
    List<ControlFlowNode> cfns = null;
   
    if(expression != null) {
      expressioncfn = controlFlowNode.newControlFlowNode(expression);
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressioncfn);
      last = expressioncfn;
    }

    if(arguments != null && arguments.size() > 0) {
      // Take the argument list and make more CFNs from them.
      cfns = createCFNListFromASTNodeList(arguments);
      if(expression == null)
        controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfns.get(0));
      else
        expressioncfn.addEdge(ControlFlowNode.Direction.FORWARDS, cfns.get(0));
      last = cfns.get(cfns.size() - 1);
    }
   
    if(last == null)
      return false;
    last.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    if(expressioncfn != null)
      expressioncfn.evaluate();
    if(cfns != null)
      evaluate(cfns);
   
    return false;
  }
  /**
   * CompilationUnit
   *
   * This node does not influence control flow.
   */
  public boolean visit(CompilationUnit node) {
    return false;
  }
  /**
   * Example: (isTrue) ? "yep" : "nope";
   */
  public boolean visit(ConditionalExpression node) {
    ControlFlowNode conditionCFN = controlFlowNode.newControlFlowNode(node.getExpression());
    ControlFlowNode thenCFN = controlFlowNode.newControlFlowNode(node.getThenExpression());
    ControlFlowNode elseCFN = controlFlowNode.newControlFlowNode(node.getElseExpression());

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, conditionCFN);

    conditionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, thenCFN);
    conditionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, elseCFN);
    thenCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    elseCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);

    conditionCFN.evaluate();
    thenCFN.evaluate();
    elseCFN.evaluate();
   
    return false;
  }
  /**
   * Example: this(1, 23, 2005);
   */
  public boolean visit(ConstructorInvocation node) {
    List arguments = node.arguments();
   
    if(arguments == null || arguments.size() == 0) {
      return false;
    }
   
    // Handle dimension expressions
    List<ControlFlowNode> cfns = createCFNListFromASTNodeList(arguments);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    evaluate(cfns);
   
    return false;
  }
  /**
   * Example: continue;   or   continue ToHere;
   */
  public boolean visit(ContinueStatement node) {
    SimpleName simpleName = node.getLabel();
    String label;
    if(simpleName == null)
      label = null;
    else
      label = simpleName.getIdentifier();
   
    controlFlowNode.continuing(label, true);
   
    return false;
  }
  /**
   * Example: do { int x = 5; method(x++); } while(x < 10);
   */
  public boolean visit(DoStatement node) {
//      do Statement while ( Expression ) ;
//         --- 1 ---         --- 2 ----
//      ------------- 3 -> 1 --------------
//      ------------- 3 -> exit -----------
     
    ControlFlowNode exit = controlFlowNode.getNode(ControlFlowNode.Direction.FORWARDS);
    ControlFlowNode expressionCFN = controlFlowNode.newControlFlowNode(node.getExpression());
    ControlFlowNode bodyCFN = controlFlowNode.newControlFlowNode(node.getBody());
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, bodyCFN);

    bodyCFN.addEdge(ControlFlowNode.Direction.FORWARDS, expressionCFN);
    expressionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    controlFlowNode.addEdge(ControlFlowNode.Direction.FORWARDS, bodyCFN);
    controlFlowNode.setLoopPaths(expressionCFN, exit);
   
    bodyCFN.evaluate();
    expressionCFN.evaluate();
   
    return false;
  }
  /**
   * Example:  ;
   */
  public boolean visit(EmptyStatement node) {
    return false;
  }

  public boolean visit(EnhancedForStatement node) {
//      for ( FormalParameter : Expression ) Statement
//                              ---- 1 ---   --- 3 ---
//    ------------------- 2 -> 3 -------------------
//    ------------------- 2 -> exit ----------------

    // TODO: Add formal parameter, so a continue; makes more sense
    Expression expression = node.getExpression();
    Statement body = node.getBody();
    ControlFlowNode expressionCFN = null;
    ControlFlowNode bodyCFN = null;
    ControlFlowNode exit = controlFlowNode.getNode(ControlFlowNode.Direction.FORWARDS);
   
    if(expression == null)
      throw new CrystalRuntimeException("enchancedForStatement did not have an expression");
    if(body == null)
      throw new CrystalRuntimeException("No body defined for an EnhancedForStatment");
     
    expressionCFN = controlFlowNode.newControlFlowNode(expression);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressionCFN);
    expressionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    bodyCFN = controlFlowNode.newControlFlowNode(body);
    controlFlowNode.addEdge(ControlFlowNode.Direction.FORWARDS, bodyCFN);
    bodyCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    controlFlowNode.setLoopPaths(bodyCFN, exit);
   
    expressionCFN.evaluate();
    bodyCFN.evaluate();
   
    return false;
  }
  /**
   * Example: enum MyEnum { CONST_1, CONST_2, CONST_2 }
   */
  public boolean visit(EnumConstantDeclaration node) {
    List arguments = node.arguments();
   
    if(arguments == null || arguments.size() == 0) {
      return false;
    }
   
    // Handle dimension expressions
    List<ControlFlowNode> cfns = createCFNListFromASTNodeList(arguments);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    evaluate(cfns);
   
    return false;
  }
  /**
   * Example: enum MyEnum { CONST_1, CONST_2 }
   */
  public boolean visit(EnumDeclaration node) {
    return false;
  }
  /**
   * Example: x = 5;
   */
  public boolean visit(ExpressionStatement node) {
    // Candidate for Removal
    ControlFlowNode expressionCFN = controlFlowNode.newControlFlowNode(node.getExpression());
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressionCFN);
    expressionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    expressionCFN.evaluate();
    return false;
  }
  /**
   * Example: x = this.myField;
   */
  public boolean visit(FieldAccess node) {
    Expression expression = node.getExpression();
   
    if(expression == null)
      return false;

    ControlFlowNode expressioncfn = controlFlowNode.newControlFlowNode(expression);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressioncfn);

    expressioncfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);

    expressioncfn.evaluate();
    return false;
  }
  /**
   * Example: protected int myField = 18;
   */
  public boolean visit(FieldDeclaration node) {
    List fragments = node.fragments();
    if(fragments == null || fragments.size() == 0)
      return false;
    List<ControlFlowNode> cfns = createCFNListFromASTNodeList(fragments);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    evaluate(cfns);
   
    return false;
  }

  public boolean visit(ForStatement node) {
//      for ( [ ForInit ]; [ Expression ] ; [ ForUpdate ] ) Statement
//           ---- 1 ----   ----- 2 ---    --- 5 -> 2 --   --- 4 ---
//    -------------------------- 3 -> 4 --------------------------
//    -------------------------- 3 -> exit -----------------------

    List initializers = node.initializers();
    Expression expression = node.getExpression();
    List updaters = node.updaters();
    Statement body = node.getBody();
    List<ControlFlowNode> initializercfns = null, updatercfns = null;
    ControlFlowNode expressioncfn = null, bodycfn = null, tempcfn;
    ControlFlowNode exit = controlFlowNode.getNode(ControlFlowNode.Direction.FORWARDS);
    ControlFlowNode first = controlFlowNode;
   
    // Initialize all CFNs AND setup CFG edges
    if(initializers != null && initializers.size() > 0) {
      initializercfns = createCFNListFromASTNodeList(initializers);
      first = initializercfns.get(0);
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, first);
    }
    if(expression != null) {
      expressioncfn = controlFlowNode.newControlFlowNode(expression);
      if(initializercfns == null) {
        controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressioncfn);
        first = expressioncfn;
      } else {
        tempcfn = initializercfns.get(initializercfns.size() - 1);
        tempcfn.addEdge(ControlFlowNode.Direction.FORWARDS, expressioncfn);
      }
      expressioncfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    } else if(initializercfns != null) {
      tempcfn = initializercfns.get(initializercfns.size() - 1);
      tempcfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    }
    if(updaters != null && updaters.size() > 0) {
      updatercfns = createCFNListFromASTNodeList(updaters);
      tempcfn = updatercfns.get(updatercfns.size() - 1);
      if(expressioncfn == null)
        tempcfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
      else
        tempcfn.addEdge(ControlFlowNode.Direction.FORWARDS, expressioncfn);
    }
    if(body == null)
      throw new CrystalRuntimeException("for statement with no body");
   
    bodycfn = controlFlowNode.newControlFlowNode(body);
    controlFlowNode.addEdge(ControlFlowNode.Direction.FORWARDS, bodycfn);
    if(updatercfns != null)
      bodycfn.addEdge(ControlFlowNode.Direction.FORWARDS, updatercfns.get(0));
    else if (expressioncfn != null)
      bodycfn.addEdge(ControlFlowNode.Direction.FORWARDS, expressioncfn);
    else
      bodycfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    if(updatercfns != null)
      controlFlowNode.setLoopPaths(updatercfns.get(0), exit);
    else if(expressioncfn != null)
      controlFlowNode.setLoopPaths(expressioncfn, exit);
    else
      controlFlowNode.setLoopPaths(bodycfn, exit);

    // Do visits
   
    if(initializercfns != null)
      evaluate(initializercfns)
    if(expressioncfn != null)
      expressioncfn.evaluate();
    if(updatercfns != null)
        evaluate(updatercfns);
    if(bodycfn != null)
      bodycfn.evaluate();
   
   
    return false;
  }
  /**
   * Example: if(bool) x = 5; else x = 7;
   */
  public boolean visit(IfStatement node) {
    Expression expression = node.getExpression();
    Statement thenStatement = node.getThenStatement();
    Statement elseStatement = node.getElseStatement();

    ControlFlowNode conditionCFN = controlFlowNode.newControlFlowNode(expression);
    // conditionCFN.copyLabelsFrom(controlFlowNode);
    ControlFlowNode thenCFN = controlFlowNode.newControlFlowNode(thenStatement);
    ControlFlowNode elseCFN = null;
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, conditionCFN);
    // THEN
    conditionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, thenCFN);
    thenCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
 
    // ELSE
    if(elseStatement != null) {
      elseCFN = controlFlowNode.newControlFlowNode(elseStatement);
      conditionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, elseCFN);
      elseCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    } else {
      conditionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    }

    // Perform visits
    conditionCFN.evaluate();

    thenCFN.evaluate();
    if(elseCFN != null)
      elseCFN.evaluate();
    return false;
  }
  /**
   * ImportDeclaration
   *
   * This node does not influence control flow.
   */
  public boolean visit(ImportDeclaration node) {
    return false;
  }
  /**
   * Example: "Hello " + "World " + "How " + "Are " + "You?"
   *          left + right + extOp1 + extOp2 + extOp3
   */
  public boolean visit(InfixExpression node) {
    List<ControlFlowNode> cfns = null;
    ControlFlowNode leftCFN = controlFlowNode.newControlFlowNode(node.getLeftOperand());
    ControlFlowNode rightCFN = controlFlowNode.newControlFlowNode(node.getRightOperand());
    // Connect the back edges to the first operand (ie. left)
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, leftCFN);
    leftCFN.addEdge(ControlFlowNode.Direction.FORWARDS, rightCFN);
   
    // Add all extended operands
    if(node.hasExtendedOperands()) {
      cfns = createCFNListFromASTNodeList(node.extendedOperands());
      ControlFlowNode cfn = cfns.get(0);
      rightCFN.addEdge(ControlFlowNode.Direction.FORWARDS, cfn);
      cfn = cfns.get(cfns.size() - 1);
      cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    } else
      rightCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    leftCFN.evaluate();
    rightCFN.evaluate();
    if(cfns != null)
      evaluate(cfns);

    return false;
  }

  public boolean visit(Initializer node) {
    return false;
  }
  /**
   * Example: myVar instanceof MyClass
   */
  public boolean visit(InstanceofExpression node) {
    Expression expression = node.getLeftOperand();
    if(expression == null)
      return false;

    ControlFlowNode expressioncfn = controlFlowNode.newControlFlowNode(expression);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressioncfn);
    expressioncfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    expressioncfn.evaluate();
    return false;
  }
  /**
   * Javadoc
   *
   * This node does not influence control flow.
   */
  public boolean visit(Javadoc node) {
    return false;
  }
  /**
   * Example: MyLabel: { int x = 5; }
   */
  public boolean visit(LabeledStatement node) {
    SimpleName label = node.getLabel();
    if(label == null)
      throw new CrystalRuntimeException("labeled statement had no label");
    ControlFlowNode body = controlFlowNode.newControlFlowNode(node.getBody());
    if(body == null)
      throw new CrystalRuntimeException("labeled statement had no body");

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, body);
    body.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    // body.copyLabelsFrom(controlFlowNode);
    // body.addLabel(label.getIdentifier());
    body.evaluate();
   
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(LineComment node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(MarkerAnnotation node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(MemberRef node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(MemberValuePair node) {
    return false;
  }
  /**
   * Example: public void myMethod(int x) { return x * x; }
   */
  public boolean visit(MethodDeclaration node) {
    // If method has no body, then nothing to traverse.
    if(node.getBody() == null)
      return false;
   
    ControlFlowNode blockCFN = controlFlowNode.newControlFlowNode(node.getBody());
    controlFlowNode.insertNode(ControlFlowNode.Direction.BACKWARDS, blockCFN);
    blockCFN.evaluate();
    return false;
  }
  /**
   * Example: var.getRef.myMethod(1, "two", true);
   */
  public boolean visit(MethodInvocation node) {   
    Expression expression = node.getExpression();
    List arguments = node.arguments();
    ControlFlowNode expressioncfn = null, last = null;
    List<ControlFlowNode> cfns = null;
   
    if(expression != null) {
      expressioncfn = controlFlowNode.newControlFlowNode(expression);
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressioncfn);
      last = expressioncfn;
    }

    if(arguments != null && arguments.size() > 0) {
      // Take the argument list and make more CFNs from them.
      cfns = createCFNListFromASTNodeList(arguments);
      if(expression == null)
        controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfns.get(0));
      else
        expressioncfn.addEdge(ControlFlowNode.Direction.FORWARDS, cfns.get(0));
      last = cfns.get(cfns.size() - 1);
    }
   
    if(last == null)
      return false;
    last.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    if(expressioncfn != null)
      expressioncfn.evaluate();
    if(cfns != null)
      evaluate(cfns);
   
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(MethodRef node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(MethodRefParameter node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(Modifier node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(NormalAnnotation node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(NullLiteral node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(NumberLiteral node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(PackageDeclaration node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(ParameterizedType node) {
    return false;
  }
  /**
   * Example: (5 + 3)
   */
  public boolean visit(ParenthesizedExpression node) {
    // Candidate for Removal
    ControlFlowNode expressionCFN = controlFlowNode.newControlFlowNode(node.getExpression());
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressionCFN);
    expressionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    expressionCFN.evaluate();
   
    return false;
  }
  /**
   * Example: x++;
   */
  public boolean visit(PostfixExpression node) {
    ControlFlowNode operandCFN = controlFlowNode.newControlFlowNode(node.getOperand());
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, operandCFN);
    operandCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    operandCFN.evaluate();
    return false;
  }
  /**
   * Example: ++x;
   */
  public boolean visit(PrefixExpression node) {
    ControlFlowNode operandCFN = controlFlowNode.newControlFlowNode(node.getOperand());
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, operandCFN);
    operandCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    operandCFN.evaluate();
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(PrimitiveType node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * Example: (2 in 1)  java.lang.System.out.println("Hello");
   */
  public boolean visit(QualifiedName node) {
    SimpleName name = node.getName();
    Name qualifier = node.getQualifier();
    IBinding nameBinding = name.resolveBinding();
    // If this is a Field access, then add children to CFG
    if(nameBinding.getKind() == IBinding.VARIABLE) {
      IVariableBinding variableBinding = (IVariableBinding) nameBinding;
      if(variableBinding.isField()) {
        ControlFlowNode nameCFN = controlFlowNode.newControlFlowNode(name);
        ControlFlowNode qualifierCFN = controlFlowNode.newControlFlowNode(qualifier);
        controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, qualifierCFN);
        qualifierCFN.addEdge(ControlFlowNode.Direction.FORWARDS, nameCFN);
        nameCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
        qualifierCFN.evaluate();
        nameCFN.evaluate();
      }
    }
    // If it is NOT a field access, then do not add children to CFG
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(QualifiedType node) {
    // Leaf in CFG, has children in AST
    return false;
  }
  /**
   * Example: return "goodbye";
   */
  public boolean visit(ReturnStatement node) {
   
    controlFlowNode.returning();
   
    Expression expression = node.getExpression();
    if(expression != null) {
      ControlFlowNode expressionCFN = controlFlowNode.newControlFlowNode(expression);
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressionCFN);
      expressionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
      expressionCFN.evaluate();
    }

    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(SimpleName node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(SimpleType node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(SingleMemberAnnotation node) {
    return false;
  }

  public boolean visit(SingleVariableDeclaration node) {
    Expression initializer = node.getInitializer();
    if(initializer == null)
      return false;
    ControlFlowNode initializercfn = controlFlowNode.newControlFlowNode(initializer);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, initializercfn);
    initializercfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    initializercfn.evaluate();
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(StringLiteral node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * Example: super(arg1);
   */
  public boolean visit(SuperConstructorInvocation node) {
    Expression expression = node.getExpression();
    List arguments = node.arguments();
    ControlFlowNode expressioncfn = null, last = null;
    List<ControlFlowNode> cfns = null;
   
    if(expression != null) {
      expressioncfn = controlFlowNode.newControlFlowNode(expression);
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressioncfn);
      last = expressioncfn;
    }

    if(arguments != null && arguments.size() > 0) {
      // Take the argument list and make more CFNs from them.
      cfns = createCFNListFromASTNodeList(arguments);
      if(expression == null)
        controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfns.get(0));
      else
        expressioncfn.addEdge(ControlFlowNode.Direction.FORWARDS, cfns.get(0));
      last = cfns.get(cfns.size() - 1);
    }
   
    if(last == null)
      return false;
    last.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    if(expressioncfn != null)
      expressioncfn.evaluate();
    if(cfns != null)
      evaluate(cfns);
   
    return false;
  }

  public boolean visit(SuperFieldAccess node) {
    return false;
  }

  public boolean visit(SuperMethodInvocation node) {
    List arguments = node.arguments();
    if(arguments == null || arguments.size() == 0)
      return false;
    List<ControlFlowNode> cfns = createCFNListFromASTNodeList(arguments);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    evaluate(cfns);
    return false;
  }

  public boolean visit(SwitchCase node) {
    Expression expression = node.getExpression();
    if(expression == null)
      return false;
   
    ControlFlowNode expressioncfn = controlFlowNode.newControlFlowNode(expression);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressioncfn);
    expressioncfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    expressioncfn.evaluate();
    return false;
  }

  public boolean visit(SwitchStatement node) {
    Expression expression = node.getExpression();
    List statements = node.statements();
    if(expression == null)
      throw new CrystalRuntimeException("Switch statement without an expression?");
    if(statements == null || statements.size() == 0)
      throw new CrystalRuntimeException("Switch statements without any statements?");

    ControlFlowNode expressionCFN = controlFlowNode.newControlFlowNode(expression);

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressionCFN);
   
    Iterator i = statements.iterator();
    List<ControlFlowNode> statementCFNs = new LinkedList<ControlFlowNode>();
    ControlFlowNode cfn = null, previous = null;
    Statement astNode;
    boolean haveSeenDefault = false;
    while(i.hasNext()) {
      astNode = (Statement) i.next();
      cfn = controlFlowNode.newControlFlowNode(astNode);
      statementCFNs.add(cfn);
      if(previous != null)
        previous.addEdge(Direction.FORWARDS, cfn);
      if(astNode.getNodeType() == ASTNode.SWITCH_CASE) {
        expressionCFN.addEdge(Direction.FORWARDS, cfn);
        SwitchCase sc = (SwitchCase) astNode;
        if(sc.isDefault()) {
          if(haveSeenDefault)
            throw new CrystalRuntimeException("cannot have more than one default in a switch");
          haveSeenDefault = true;
        }
      }
      previous = cfn;
    }
    if(cfn == null)
      throw new CrystalRuntimeException("no statements in switch");
    // if we never saw a default, then add an edge to the switch statement
    if(!haveSeenDefault)
      expressionCFN.addEdge(Direction.FORWARDS, controlFlowNode);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
 
    expressionCFN.evaluate();
    if(statementCFNs != null)
      evaluate(statementCFNs);

    return false;
  }
  /**
   * Example: synchronized (myVar) { myMethod(); }
   */
  public boolean visit(SynchronizedStatement node) {
    ControlFlowNode expression = controlFlowNode.newControlFlowNode(node.getExpression());
    ControlFlowNode body = controlFlowNode.newControlFlowNode(node.getBody());

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expression);

    expression.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    controlFlowNode.addEdge(ControlFlowNode.Direction.FORWARDS, body);

    expression.evaluate();
    body.evaluate();
   
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(TagElement node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(TextElement node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(ThisExpression node) {
    return false;
  }
  /**
   *
   * The throw statement will either be caught locally or
   * be thrown up the stack (ie leave the method).
   */
  public boolean visit(ThrowStatement node) {
    return false;
  }
  /**
   * Example: try { int x; }
   */
  public boolean visit(TryStatement node) {
    Block body = node.getBody();
    Block finalBody = node.getFinally();
    List catches = node.catchClauses();

    ControlFlowNode cfnBody = controlFlowNode.newControlFlowNode(body);
    ControlFlowNode cfnFinalBody = null;

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfnBody);
   
    List<ControlFlowNode> cfns = new ArrayList<ControlFlowNode>();
    ControlFlowNode cfn = cfnBody, prev = cfnBody;
    Iterator i = catches.iterator();
    CatchClause cc;
    for(;i.hasNext();) {
      cc = (CatchClause) i.next();
      cfn = controlFlowNode.newControlFlowNode(cc);
      prev.addEdge(ControlFlowNode.Direction.FORWARDS, cfn);
      prev = cfn;
      cfns.add(cfn);
    }
   
    if(finalBody != null) {
      cfnFinalBody = controlFlowNode.newControlFlowNode(finalBody);
      cfn.addEdge(ControlFlowNode.Direction.FORWARDS, cfnFinalBody);
      cfnFinalBody.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    } else {
      cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    }
   
    // Peform Visits
    cfnBody.evaluate();
    Iterator<ControlFlowNode> j = cfns.iterator();
    for(;j.hasNext();)
      j.next().evaluate();
    if(finalBody != null)
      cfnFinalBody.evaluate();
   
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(TypeDeclaration node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(TypeDeclarationStatement node) {
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(TypeLiteral node) {
    // Leaf, no action necessary
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(TypeParameter node) {
    return false;
  }

  public boolean visit(VariableDeclarationExpression node) {
    List fragments = node.fragments();
    if(fragments == null || fragments.size() == 0)
      return false;
    List<ControlFlowNode>cfns = createCFNListFromASTNodeList(fragments);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    evaluate(cfns);
   
    return false;
  }

  /**
   * Example: int a[] = {5, 4}, x = 5, y;
   * VariableDeclarationFragments: (a[] = {5, 4}), (x = 5), & (y) 
   */
  public boolean visit(VariableDeclarationFragment node) {
    // Similar to Assignment
    ControlFlowNode nameCFN = controlFlowNode.newControlFlowNode(node.getName());

    // Empty Initializer
    if(node.getInitializer() == null) {
      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, nameCFN);
      nameCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
      nameCFN.evaluate();
    } else {
      ControlFlowNode initializerCFN = controlFlowNode.newControlFlowNode(node.getInitializer());

      controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, initializerCFN);

      initializerCFN.addEdge(ControlFlowNode.Direction.FORWARDS, nameCFN);
      nameCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);

      initializerCFN.evaluate();
      nameCFN.evaluate();
    }
   
    return false;
  }

  public boolean visit(VariableDeclarationStatement node) {
    List fragments = node.fragments();
    if(fragments == null || fragments.size() == 0)
      return false;

    List<ControlFlowNode> cfns = createCFNListFromASTNodeList(fragments);
    ControlFlowNode cfn = cfns.get(0);
    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, cfn);
    cfn = cfns.get(cfns.size() - 1);
    cfn.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
   
    evaluate(cfns);
   
    return false;
  }
  /*
   * Example: while (x < 10) { x++; run(x); };
   */
  public boolean visit(WhileStatement node) {
//      while ( Expression ) Statement
//             ----- 1 ---  -- 3 -> 1 --
//      -------------- 2 -> 3 ----------
//     -------------- 2 -> exit -------

    ControlFlowNode exit = controlFlowNode.getNode(ControlFlowNode.Direction.FORWARDS);
    ControlFlowNode expressionCFN = controlFlowNode.newControlFlowNode(node.getExpression());
    // expressionCFN.copyLabelsFrom(controlFlowNode);
    ControlFlowNode bodyCFN = controlFlowNode.newControlFlowNode(node.getBody());

    controlFlowNode.moveEdges(ControlFlowNode.Direction.BACKWARDS, expressionCFN);

    expressionCFN.addEdge(ControlFlowNode.Direction.FORWARDS, controlFlowNode);
    controlFlowNode.addEdge(ControlFlowNode.Direction.FORWARDS, bodyCFN);
    bodyCFN.addEdge(ControlFlowNode.Direction.FORWARDS, expressionCFN);
   
    controlFlowNode.setLoopPaths(expressionCFN, exit);
   
    expressionCFN.evaluate();
    bodyCFN.evaluate();
   
    return false;
  }
  /**
   * This node does not influence control flow.
   */
  public boolean visit(WildcardType node) {
    return false;
  }
 
 
  /*
   * Helper Methods
   *
   */
 
 
  /**
   * Takes a list of ASTNodes and creates ControlFlowNodes for each and connects them.
   * The first element will not have any back edges and the last element will not
   * have any forward edges.
   */
  protected List<ControlFlowNode> createCFNListFromASTNodeList(List nodes) {
    if(nodes == null)
      return null;
    List<ControlFlowNode> cfns = new ArrayList<ControlFlowNode>();
    ControlFlowNode current, previous = null;
    Iterator i = nodes.iterator();
    ASTNode node;
    for(;i.hasNext();) {
      node = (ASTNode) i.next();
      current = controlFlowNode.newControlFlowNode(node);
      cfns.add(current);
      if(previous != null)
        previous.addEdge(ControlFlowNode.Direction.FORWARDS, current);
      previous = current;
    }
    return cfns;
  }
 
  protected void evaluate(List<ControlFlowNode> list) {
    if(list == null)
      return;
    Iterator<ControlFlowNode> i = list.iterator();
    ControlFlowNode cfn;
    for(;i.hasNext();) {
      cfn = i.next();
      cfn.evaluate();
    }
  }
}
TOP

Related Classes of edu.cmu.cs.crystal.internal.ControlFlowVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.