diff --git a/reusablecfg/src/main/jastadd/CFG.ast b/reusablecfg/src/main/jastadd/CFG.ast
deleted file mode 100644
index b1e7cbe5349021cc8790f4a6ee2613ee6b1eb168..0000000000000000000000000000000000000000
--- a/reusablecfg/src/main/jastadd/CFG.ast
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/** A node in a Control Flow Graph (CFG). */
-abstract CfgNode;
-
-/** The CFG entry node. */
-CfgEntry : CfgNode ::= <Succ:CfgNode>;
-
-/** The CFG exit node. */
-CfgExit : CfgNode;
-
-/** A method call in the CFG. */
-CfgMethodCall : CfgNode;
-
-/** A conditional branch in the CFG.  */
-CfgBranch : CfgNode;
-
-/** A branch in the CFG caused by potential thrown exceptions.  */
-CfgException : CfgNode;
-
-/** A marker node used to mark try block entry points or the end of if-statement branches.  */
-CfgMarker : CfgNode;
diff --git a/reusablecfg/src/main/jastadd/CFG.relast b/reusablecfg/src/main/jastadd/CFG.relast
new file mode 100644
index 0000000000000000000000000000000000000000..f34de746a7373ea0c4defeb1b10e9288eae4f002
--- /dev/null
+++ b/reusablecfg/src/main/jastadd/CFG.relast
@@ -0,0 +1,26 @@
+CFG ::= CfgNode*;
+
+/** A node in a Control Flow Graph (CFG). */
+abstract CfgNode;
+
+/** The CFG entry node. */
+CfgEntry : CfgNode ::= <Succ:CfgNode>;
+
+/** The CFG exit node. */
+CfgExit : CfgNode;
+
+/** A method call in the CFG. */
+CfgMethodCall : CfgNode;
+
+/** A conditional branch in the CFG.  */
+CfgBranch : CfgNode;
+
+/** A branch in the CFG caused by potential thrown exceptions.  */
+CfgException : CfgNode;
+
+/** A marker node used to mark try block entry points or the end of if-statement branches.  */
+CfgMarker : CfgNode;
+
+rel CfgNode.successor <-> CfgNode.predecessor ;
+
+rel CfgEntry ->
diff --git a/reusablecfg/src/main/jastadd/ReusableCFG.jadd b/reusablecfg/src/main/jastadd/ReusableCFG.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..ecc7306b3e23f541a7d183692011d27624e68fbc
--- /dev/null
+++ b/reusablecfg/src/main/jastadd/ReusableCFG.jadd
@@ -0,0 +1,103 @@
+aspect ReusableCfg {
+
+  /**
+   * Set that contains either one or two unique objects. The objects are
+   * compared with reference equality.
+   */
+  class IdentityTupleSet<E> implements Set<E> {
+    final E a, b;
+
+    public IdentityTupleSet(E a, E b) {
+      this.a = a;
+      this.b = b;
+    }
+
+    @Override
+    public boolean add(E e) {
+      throw new UnsupportedOperationException();
+    }
+    @Override
+    public boolean addAll(Collection<? extends E> e) {
+      throw new UnsupportedOperationException();
+    }
+    @Override
+    public void clear() {
+      throw new UnsupportedOperationException();
+    }
+    @Override
+    public boolean contains(Object o) {
+      return o == a || o == b;
+    }
+    @Override
+    public boolean containsAll(Collection<?> c) {
+      for (Object o : c) {
+        if (!contains(o)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    @Override
+    public int hashCode() {
+      return a.hashCode() + b.hashCode();
+    }
+    @Override
+    public boolean isEmpty() {
+      return false;
+    }
+    @Override
+    public Iterator<E> iterator() {
+      return new Iterator<E>() {
+        int index = 0;
+        @Override
+        public boolean hasNext() {
+          return (a == b && index < 1)
+              || (a != b && index < 2);
+        }
+        @Override
+        public E next() {
+          return ++index == 1 ? a : b;
+        }
+        @Override
+        public void remove() {
+          throw new UnsupportedOperationException();
+        }
+      };
+    }
+    @Override
+    public boolean remove(Object o) {
+      throw new UnsupportedOperationException();
+    }
+    @Override
+    public boolean removeAll(Collection<?> c) {
+      throw new UnsupportedOperationException();
+    }
+    @Override
+    public boolean retainAll(Collection<?> c) {
+      throw new UnsupportedOperationException();
+    }
+    @Override
+    public int size() {
+      return a == b ? 1 : 2;
+    }
+    @Override
+    public Object[] toArray() {
+      return new Object[] { a, b };
+    }
+    @Override
+    public <T> T[] toArray(T[] array) {
+      array[0] = (T) a;
+      array[1] = (T) b;
+      return array;
+    }
+    @Override
+    public String toString() {
+      if (a == b) {
+        return "[" + a + "]";
+      } else {
+        return "[" + a + ", " + b + "]";
+      }
+    }
+  }
+
+}
diff --git a/reusablecfg/src/main/jastadd/ReusableCfg.jrag b/reusablecfg/src/main/jastadd/ReusableCfg.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..0e700ba7233991ee498ad35c7d9abf7387984345
--- /dev/null
+++ b/reusablecfg/src/main/jastadd/ReusableCfg.jrag
@@ -0,0 +1,138 @@
+class ReusableCfg {
+  /**
+   * Find the next CFG node representing the next branch, or the next
+   * method access following this statement.
+   */
+  inh CfgNode Stmt.follow();
+  inh CfgNode Expr.follow();
+
+  // Needed for completeness, but never used by anything relevant.
+  eq Program.getChild().follow() = new CfgExit();
+
+
+  eq TryStmt.getBlock().follow() =
+      hasNonEmptyFinally()
+      ? getFinally().entry()
+      : follow();
+
+  eq TryStmt.getCatchClause(int index).follow() =
+      hasNonEmptyFinally()
+      ? getFinally().entry()
+      : follow();
+
+  eq BreakStmt.marker().follow() =
+      hasFinally()
+      ? getFinally().entry()
+      : targetStmt().follow();
+
+  eq ReturnStmt.marker().follow() =
+      hasResult()
+      ? getResult().entry()
+      : returnTarget();
+
+  eq ReturnStmt.getResult().follow() = returnTarget();
+
+  eq ReturnStmt.getFinally().follow() = methodExit();
+
+  // Since we not have precise type lookups we need to approximate the possible
+  // exception branches.
+  eq ThrowStmt.getExpr().follow() = exceptionNode();
+
+  eq ClassInstanceExpr.getArg(int index).follow() =
+      index+1 < getNumArg()
+      ? getArg(index+1).entry()
+      : getAccess().entry();
+
+  // If we have arguments the CfgMethodCall is placed after the last argument.
+  eq MethodAccess.getArg(int index).follow() =
+      index+1 < getNumArg()
+      ? getArg(index+1).entry()
+      : call();
+
+  // If we have arguments the CfgMethodCall is placed after the last argument.
+  eq ConstructorAccess.getArg(int index).follow() =
+      index+1 < getNumArg()
+      ? getArg(index+1).entry()
+      : follow();
+
+  eq ArrayInit.getInit(int index).follow() =
+      index+1 < getNumInit()
+      ? getInit(index+1).entry()
+      : follow();
+
+  eq AssignExpr.getSource().follow() = getDest().entry();
+
+
+  eq Binary.getLeftOperand().follow() = getRightOperand().entry();
+
+
+  eq Dot.getLeft().follow() = getRight().entry();
+
+
+  eq ConditionalExpr.getCondition().follow() = branch();
+  eq ConditionalExpr.getTrueExpr().follow() = thenEndMarker();
+  eq ConditionalExpr.getFalseExpr().follow() = elseEndMarker();
+  eq ConditionalExpr.thenEndMarker().follow() = follow();
+  eq ConditionalExpr.elseEndMarker().follow() = follow();
+
+
+  eq IfStmt.getCondition().follow() = branch();
+  eq IfStmt.getThen().follow() = thenEndMarker();
+  eq IfStmt.getElse().follow() = elseEndMarker();
+  eq IfStmt.thenEndMarker().follow() = follow();
+  eq IfStmt.elseEndMarker().follow() = follow();
+
+  eq ForStmt.getInitStmt(int index).follow() =
+      index+1 < getNumInitStmt()
+      ? getInitStmt(index+1).entry()
+      : getCondition().entry();
+
+  eq ForStmt.getCondition().follow() = branch();
+
+  eq ForStmt.getUpdateStmt(int index).follow() =
+      index+1 < getNumUpdateStmt()
+      ? getUpdateStmt(index+1).entry()
+      : getCondition().entry();
+
+  eq ForStmt.getStmt().follow() = loopEndMarker();
+
+  eq ForStmt.loopEndMarker().follow() =
+      getNumUpdateStmt() > 0
+      ? getUpdateStmt(0).entry()
+      : getCondition().entry();
+
+
+  eq EnhancedForStmt.getExpr().follow() = branch();
+
+  eq EnhancedForStmt.getStmt().follow() = loopEndMarker();
+
+  eq EnhancedForStmt.loopEndMarker().follow() = entry(); // Loop back.
+
+  eq WhileStmt.getCondition().follow() = branch();
+
+  eq WhileStmt.getStmt().follow() = loopEndMarker();
+
+  eq WhileStmt.loopEndMarker().follow() = entry(); // Loop back.
+
+
+  eq DoStmt.doEntryMarker().follow() = getStmt().entry();
+
+  eq DoStmt.getStmt().follow() = getCondition().entry();
+
+  eq DoStmt.getCondition().follow() = branch();
+
+
+  eq SwitchStmt.getExpr().follow() = branch();
+
+  eq BodyDecl.getChild().follow() = exit();
+
+  eq Block.getStmt(int index).follow() =
+      index+1 < getNumStmt()
+      ? getStmt(index+1).entry()
+      : follow();
+
+
+  eq BlockLambdaBody.getBlock().follow() = exit();
+  eq ExprLambdaBody.getExpr().follow() = exit();
+
+}
diff --git a/reusablecfg/src/main/jastadd/SimpleCFG.jrag b/reusablecfg/src/main/jastadd/SimpleCFG.jrag
index 162622bb10fa429e861076736a12e726958f7378..68474b5db41cd395175968d2a444dd0d60ca3880 100644
--- a/reusablecfg/src/main/jastadd/SimpleCFG.jrag
+++ b/reusablecfg/src/main/jastadd/SimpleCFG.jrag
@@ -59,106 +59,6 @@ aspect SimpleCFG {
 
   eq CfgMarker.successors() = succ();
 
-  /**
-   * Set that contains either one or two unique objects. The objects are
-   * compared with reference equality.
-   */
-  class IdentityTupleSet<E> implements Set<E> {
-    final E a, b;
-
-    public IdentityTupleSet(E a, E b) {
-      this.a = a;
-      this.b = b;
-    }
-
-    @Override
-    public boolean add(E e) {
-      throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean addAll(Collection<? extends E> e) {
-      throw new UnsupportedOperationException();
-    }
-    @Override
-    public void clear() {
-      throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean contains(Object o) {
-      return o == a || o == b;
-    }
-    @Override
-    public boolean containsAll(Collection<?> c) {
-      for (Object o : c) {
-        if (!contains(o)) {
-          return false;
-        }
-      }
-      return true;
-    }
-    @Override
-    public int hashCode() {
-      return a.hashCode() + b.hashCode();
-    }
-    @Override
-    public boolean isEmpty() {
-      return false;
-    }
-    @Override
-    public Iterator<E> iterator() {
-      return new Iterator<E>() {
-        int index = 0;
-        @Override
-        public boolean hasNext() {
-          return (a == b && index < 1)
-              || (a != b && index < 2);
-        }
-        @Override
-        public E next() {
-          return ++index == 1 ? a : b;
-        }
-        @Override
-        public void remove() {
-          throw new UnsupportedOperationException();
-        }
-      };
-    }
-    @Override
-    public boolean remove(Object o) {
-      throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean removeAll(Collection<?> c) {
-      throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean retainAll(Collection<?> c) {
-      throw new UnsupportedOperationException();
-    }
-    @Override
-    public int size() {
-      return a == b ? 1 : 2;
-    }
-    @Override
-    public Object[] toArray() {
-      return new Object[] { a, b };
-    }
-    @Override
-    public <T> T[] toArray(T[] array) {
-      array[0] = (T) a;
-      array[1] = (T) b;
-      return array;
-    }
-    @Override
-    public String toString() {
-      if (a == b) {
-        return "[" + a + "]";
-      } else {
-        return "[" + a + ", " + b + "]";
-      }
-    }
-  }
-
   /** Successors to this branch node. */
   inh Set<? extends CfgNode> CfgBranch.succ();
 
@@ -181,16 +81,9 @@ aspect SimpleCFG {
    */
   syn CfgNode Stmt.entry() = follow();
 
-  /**
-   * Find the next CFG node representing the next branch, or the next
-   * method access following this statement.
-   */
-  inh CfgNode Stmt.follow();
 
-  inh CfgNode Expr.follow();
 
-  // Needed for completeness, but never used by anything relevant.
-  eq Program.getChild().follow() = new CfgExit();
+
 
   /**
    * The entry node in a filtered CFG.
@@ -327,15 +220,6 @@ aspect SimpleCFG {
     return set;
   }
 
-  eq TryStmt.getBlock().follow() =
-      hasNonEmptyFinally()
-      ? getFinally().entry()
-      : follow();
-
-  eq TryStmt.getCatchClause(int index).follow() =
-      hasNonEmptyFinally()
-      ? getFinally().entry()
-      : follow();
 
   /** The CFG marker for this break statement.  */
   syn nta CfgMarker BreakStmt.marker() = new CfgMarker();
@@ -345,10 +229,6 @@ aspect SimpleCFG {
       hasFinally()
       ? Collections.singleton(getFinally().entry())
       : Collections.singleton(targetStmt().follow());
-  eq BreakStmt.marker().follow() =
-      hasFinally()
-      ? getFinally().entry()
-      : targetStmt().follow();
 
   eq BreakStmt.getFinally().follow() = targetStmt().follow();
 
@@ -375,12 +255,6 @@ aspect SimpleCFG {
       hasResult()
       ? Collections.singleton(getResult().entry())
       : Collections.singleton(returnTarget());
-  eq ReturnStmt.marker().follow() =
-      hasResult()
-      ? getResult().entry()
-      : returnTarget();
-
-  eq ReturnStmt.getResult().follow() = returnTarget();
 
   inh CompilationUnit ReturnStmt.compilationUnit();
 
@@ -389,8 +263,6 @@ aspect SimpleCFG {
       ? getFinally().entry()
       : methodExit();
 
-  eq ReturnStmt.getFinally().follow() = methodExit();
-
   /**
    * Finds the CFG exit node for the enclosing method, constructor, or
    * initializer.
@@ -403,10 +275,6 @@ aspect SimpleCFG {
 
   eq ThrowStmt.entry() = getExpr().entry();
 
-  // Since we not have precise type lookups we need to approximate the possible
-  // exception branches.
-  eq ThrowStmt.getExpr().follow() = exceptionNode();
-
   /**
    * This node represents the control flow path taken when an exception
    * interrupts the call.
@@ -468,44 +336,22 @@ aspect SimpleCFG {
       ? getArg(0).entry()
       : call();
 
-  // If we have arguments the CfgMethodCall is placed after the last argument.
-  eq MethodAccess.getArg(int index).follow() =
-      index+1 < getNumArg()
-      ? getArg(index+1).entry()
-      : call();
-
   // If there are arguments control flow passes to the arguments first.
   eq ConstructorAccess.entry() =
       getNumArg() > 0
       ? getArg(0).entry()
       : follow();
 
-  // If we have arguments the CfgMethodCall is placed after the last argument.
-  eq ConstructorAccess.getArg(int index).follow() =
-      index+1 < getNumArg()
-      ? getArg(index+1).entry()
-      : follow();
-
   eq ClassInstanceExpr.entry() =
       getNumArg() > 0
       ? getArg(0).entry()
       : getAccess().entry();
 
-  eq ClassInstanceExpr.getArg(int index).follow() =
-      index+1 < getNumArg()
-      ? getArg(index+1).entry()
-      : getAccess().entry();
-
   eq ArrayInit.entry() =
       getNumInit() > 0
       ? getInit(0).entry()
       : follow();
 
-  eq ArrayInit.getInit(int index).follow() =
-      index+1 < getNumInit()
-      ? getInit(index+1).entry()
-      : follow();
-
   /** @return {@code true} if this statement is inside a try block. */
   inh boolean MethodAccess.isInsideTryBlockOrResource();
   inh boolean Stmt.isInsideTryBlockOrResource();
@@ -524,8 +370,6 @@ aspect SimpleCFG {
 
   eq AssignExpr.entry() = getSource().entry();
 
-  eq AssignExpr.getSource().follow() = getDest().entry();
-
   eq Literal.entry() = follow();
 
   eq ArrayCreationExpr.entry() =
@@ -534,10 +378,8 @@ aspect SimpleCFG {
       : follow();
 
   eq Binary.entry() = getLeftOperand().entry();
-  eq Binary.getLeftOperand().follow() = getRightOperand().entry();
 
   eq Dot.entry() = getLeft().entry();
-  eq Dot.getLeft().follow() = getRight().entry();
 
   /** The branch node for this conditional expression. */
   syn nta CfgBranch ConditionalExpr.branch() = new CfgBranch();
@@ -555,11 +397,6 @@ aspect SimpleCFG {
   syn nta CfgMarker ConditionalExpr.elseEndMarker() = new CfgMarker();
 
   eq ConditionalExpr.entry() = getCondition().entry();
-  eq ConditionalExpr.getCondition().follow() = branch();
-  eq ConditionalExpr.getTrueExpr().follow() = thenEndMarker();
-  eq ConditionalExpr.getFalseExpr().follow() = elseEndMarker();
-  eq ConditionalExpr.thenEndMarker().follow() = follow();
-  eq ConditionalExpr.elseEndMarker().follow() = follow();
   eq ConditionalExpr.thenEndMarker().succ() = Collections.singleton(follow());
   eq ConditionalExpr.elseEndMarker().succ() = Collections.singleton(follow());
 
@@ -577,11 +414,6 @@ aspect SimpleCFG {
 
   eq IfStmt.entry() = getCondition().entry();
 
-  eq IfStmt.getCondition().follow() = branch();
-  eq IfStmt.getThen().follow() = thenEndMarker();
-  eq IfStmt.getElse().follow() = elseEndMarker();
-  eq IfStmt.thenEndMarker().follow() = follow();
-  eq IfStmt.elseEndMarker().follow() = follow();
   eq IfStmt.thenEndMarker().succ() = Collections.singleton(follow());
   eq IfStmt.elseEndMarker().succ() = Collections.singleton(follow());
 
@@ -601,25 +433,6 @@ aspect SimpleCFG {
       ? getInitStmt(0).entry()
       : getCondition().entry();
 
-  eq ForStmt.getInitStmt(int index).follow() =
-      index+1 < getNumInitStmt()
-      ? getInitStmt(index+1).entry()
-      : getCondition().entry();
-
-  eq ForStmt.getCondition().follow() = branch();
-
-  eq ForStmt.getUpdateStmt(int index).follow() =
-      index+1 < getNumUpdateStmt()
-      ? getUpdateStmt(index+1).entry()
-      : getCondition().entry();
-
-  eq ForStmt.getStmt().follow() = loopEndMarker();
-
-  eq ForStmt.loopEndMarker().follow() =
-      getNumUpdateStmt() > 0
-      ? getUpdateStmt(0).entry()
-      : getCondition().entry();
-
   eq ForStmt.loopEndMarker().succ() =
       getNumUpdateStmt() > 0
       ? Collections.singleton(getUpdateStmt(0).entry())
@@ -646,12 +459,6 @@ aspect SimpleCFG {
 
   eq EnhancedForStmt.entry() = getExpr().entry();
 
-  eq EnhancedForStmt.getExpr().follow() = branch();
-
-  eq EnhancedForStmt.getStmt().follow() = loopEndMarker();
-
-  eq EnhancedForStmt.loopEndMarker().follow() = entry(); // Loop back.
-
   eq EnhancedForStmt.loopEndMarker().succ() = Collections.singleton(entry());
 
   /** The branch node for this statement. */
@@ -662,12 +469,6 @@ aspect SimpleCFG {
 
   eq WhileStmt.entry() = getCondition().entry();
 
-  eq WhileStmt.getCondition().follow() = branch();
-
-  eq WhileStmt.getStmt().follow() = loopEndMarker();
-
-  eq WhileStmt.loopEndMarker().follow() = entry(); // Loop back.
-
   eq WhileStmt.loopEndMarker().succ() = Collections.singleton(entry());
 
   eq WhileStmt.branch().succ() {
@@ -688,14 +489,9 @@ aspect SimpleCFG {
 
   eq DoStmt.entry() = doEntryMarker();
 
-  eq DoStmt.doEntryMarker().follow() = getStmt().entry();
 
   eq DoStmt.doEntryMarker().succ() = Collections.singleton(getStmt().entry());
 
-  eq DoStmt.getStmt().follow() = getCondition().entry();
-
-  eq DoStmt.getCondition().follow() = branch();
-
   // Loop back.
   eq DoStmt.branch().succ() {
     if (getCondition().isTrue()) {
@@ -711,8 +507,6 @@ aspect SimpleCFG {
 
   eq SwitchStmt.entry() = getExpr().entry();
 
-  eq SwitchStmt.getExpr().follow() = branch();
-
   eq SwitchStmt.branch().succ() {
     Set<CfgNode> set = Collections.newSetFromMap(
         new IdentityHashMap<CfgNode, Boolean>());
@@ -731,22 +525,12 @@ aspect SimpleCFG {
     return set;
   }
 
-  eq BodyDecl.getChild().follow() = exit();
-
-  eq Block.getStmt(int index).follow() =
-      index+1 < getNumStmt()
-      ? getStmt(index+1).entry()
-      : follow();
-
   syn lazy CfgEntry LambdaBody.entry();
   eq BlockLambdaBody.entry() = new CfgEntry(getBlock().entry());
   eq ExprLambdaBody.entry() = new CfgEntry(getExpr().entry());
 
   syn nta CfgExit LambdaBody.exit() = new CfgExit();
 
-  eq BlockLambdaBody.getBlock().follow() = exit();
-  eq ExprLambdaBody.getExpr().follow() = exit();
-
   /** Find the method access which this call node is associated with. */
   inh MethodAccess CfgMethodCall.methodAccess();
   eq MethodAccess.call().methodAccess() = this;