diff --git a/ChangeLog b/ChangeLog
index 12767c1dac8dccf8bec936e76ce6f86d9a3874d8..836d2fbecc3305a169e3282958e4af7716167fee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2016-03-16  Jesper Öqvist <jesper.oqvist@cs.lth.se>
+
+    * Improved circular NTA rewrite implementation: implicit rewrite
+    attributes are now generated only for node types that have a rewrite, and
+    the attribute relies on the rewrite condition to decide when the rewrite
+    has reached a final result.
+    * Removed list rewrites. List rewrites were an undocumented feature that
+    caused problems for attribute correctness by allowing nodes to change
+    position in a list after the AST was constructed.
+    * Removed staged rewrites. Rewrite stages were an undocumented,
+    unsupported, and mostly unused feature. Removing staged rewrites
+    simplifies code generation.
+    * Rewrites no longer trigger on child count access.
+
+    Removed list rewrites. Removed rewrite limit. Removed staged rewrites.
+
 2016-02-02  Jesper Öqvist <jesper.oqvist@cs.lth.se>
 
     * Fixed repeated error message reported for multiple production rules for
diff --git a/src/jastadd/ast/ASTNodeAnnotations.jrag b/src/jastadd/ast/ASTNodeAnnotations.jrag
index 87fbb57c905f2d8c6b430ec7a7bcbfb3d1b4f3fd..6a0209da85b4c86c27716a5032768750bd63828e 100644
--- a/src/jastadd/ast/ASTNodeAnnotations.jrag
+++ b/src/jastadd/ast/ASTNodeAnnotations.jrag
@@ -28,10 +28,15 @@
 
 aspect ASTNodeAnnotations {
   syn String AttrDecl.annotationKind();
+
   eq SynDecl.annotationKind() = "kind=ASTNodeAnnotation.Kind.SYN";
+
   eq InhDecl.annotationKind() = "kind=ASTNodeAnnotation.Kind.INH";
+
   eq CollDecl.annotationKind() = "kind=ASTNodeAnnotation.Kind.COLL";
 
+  eq CircularRewriteDecl.annotationKind() = "kind=ASTNodeAnnotation.Kind.SYN";
+
   syn String AttrDecl.attributeAnnotationValue() {
     StringBuilder sb = new StringBuilder();
     sb.append(annotationKind());
diff --git a/src/jastadd/ast/Ast.ast b/src/jastadd/ast/Ast.ast
index 8ab56234bf0a146a797ea5697b64e9977cc6345e..16c35bb5feefc8131099f16a6691d50c1f47e7ac 100644
--- a/src/jastadd/ast/Ast.ast
+++ b/src/jastadd/ast/Ast.ast
@@ -16,7 +16,7 @@ EnumDecl : TypeDecl;
 ASTDecl : TypeDecl ::= [Abstract] IdDecl [SuperClass:IdUse] Component*
     SynDecl* SynEq* InhDecl* InhEq* ClassBodyDecl* Rewrite* CollDecl* CollEq*
     <FileName> <StartLine:int> <EndLine:int> <Comment:String>
-    SynthesizedNta*;
+    SynthesizedNta* /CircularRewriteDecl/;
 
 Abstract;
 
@@ -27,6 +27,14 @@ abstract AttrDecl ::= Parameter* <Name> <Type> <CacheMode:CacheMode> <FileName>
 
 SynDecl : AttrDecl;
 
+/**
+ * Only used to generate code for implicit circular rewrite NTAs.
+ * The reason a separate node type is used for this is because we need to
+ * change the code generation for the implicit circular NTA slightly.
+ * The changes in code generation affect parent attachment and update condition.
+ */
+CircularRewriteDecl : AttrDecl;
+
 InhDecl : AttrDecl;
 
 CollDecl : AttrDecl ::= <Target>;
@@ -50,8 +58,6 @@ ClassBodyDecl ::= <Name> <FileName> <StartLine:int> <EndLine:int> <AspectName:St
 
 Rewrite ::= <FileName> <StartLine:int> <EndLine:int> <AspectName>;
 
-RewriteList : Rewrite;
-
 /** A component of an AST node type declaration. */
 abstract Component;
 
diff --git a/src/jastadd/ast/Attributes.jrag b/src/jastadd/ast/Attributes.jrag
index 28306eaff07e2a62c57733b493e6693ea04e11dd..6d374556fee31780a89cbef856a348e8de525706 100644
--- a/src/jastadd/ast/Attributes.jrag
+++ b/src/jastadd/ast/Attributes.jrag
@@ -85,45 +85,6 @@ public aspect Attributes {
     aspectMap.put(name, comment);
   }
 
-  // Add attributes to AST.
-  public void Grammar.addRewriteList(
-      String className,
-      org.jastadd.jrag.AST.SimpleNode condition,
-      org.jastadd.jrag.AST.SimpleNode result,
-      String type,
-      String fileName,
-      int startLine,
-      int endLine,
-      String parentName,
-      String childName,
-      String aspectName) {
-
-    if (!config().rewriteEnabled()) {
-      error("can not use rewrites while rewrites are disabled (enable with --rewrite=regular)",
-          fileName, startLine);
-      return;
-    }
-
-    TypeDecl c = lookup(className);
-    if (c != null && c instanceof ASTDecl) {
-      RewriteList r = new RewriteList();
-      r.setFileName(fileName);
-      r.setStartLine(startLine);
-      r.setEndLine(endLine);
-      r.setCondition(condition);
-      r.setResult(result);
-      r.setReturnType(type);
-      r.setParentName(parentName);
-      r.setChildName(childName);
-      r.setAspectName(aspectName);
-      ((ASTDecl)c).addRewrite(r);
-    } else if (c != null) {
-      error("can not rewrite to non AST class '" + className + "'", fileName, startLine);
-    } else {
-      error("can not rewrite to unknown class '" + className + "'", fileName, startLine);
-    }
-  }
-
   public void Grammar.addRewrite(
       String className,
       org.jastadd.jrag.AST.SimpleNode condition,
@@ -1209,24 +1170,4 @@ public aspect Attributes {
   public void Rewrite.setReturnType(String type) {
     returnType = type;
   }
-
-  public String RewriteList.parentName;
-
-  public String RewriteList.getParentName() {
-    return parentName;
-  }
-
-  public void RewriteList.setParentName(String name) {
-    parentName = name;
-  }
-
-  public String RewriteList.childName;
-
-  public String RewriteList.getChildName() {
-    return childName;
-  }
-
-  public void RewriteList.setChildName(String name) {
-    childName = name;
-  }
 }
diff --git a/src/jastadd/ast/Circular.jrag b/src/jastadd/ast/Circular.jrag
index bdf31200403ed13f889ab5774160280807b01763..769dd8c8df9de1951b9bb701403ab122aa04411e 100644
--- a/src/jastadd/ast/Circular.jrag
+++ b/src/jastadd/ast/Circular.jrag
@@ -32,10 +32,19 @@ aspect Circular {
 
   syn boolean AttrDecl.isCircular() = hasBottomValue();
 
+  eq CircularRewriteDecl.isCircular() = true;
+
   syn boolean AttrDecl.hasBottomValue() = bottomValue != null && !bottomValue.isEmpty();
 
   syn String AttrDecl.getBottomValue() = bottomValue;
 
+  eq CircularRewriteDecl.getBottomValue() = "this";
+
+  /** The parent to attach an NTA value to during circular evaluation. */
+  syn String AttrDecl.ntaParent() = "this";
+
+  eq CircularRewriteDecl.ntaParent() = "getParent()";
+
   public void AttrDecl.setBottomValue(String expression) {
     bottomValue = expression;
   }
diff --git a/src/jastadd/ast/Flush.jrag b/src/jastadd/ast/Flush.jrag
index 343581277151a7a5b8c95b24467bd4d10b2a6b1e..3492554132b4d436d6d270cb02af36fb6faa354b 100644
--- a/src/jastadd/ast/Flush.jrag
+++ b/src/jastadd/ast/Flush.jrag
@@ -38,21 +38,13 @@ aspect Flush {
     //tt.bind("FlushNTACache", emitFlushNTACacheString());
 
     StringBuilder sb = new StringBuilder();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       sb.append(attr.signature() + "_reset();\n");
     }
-    if (config().rewriteCircularNTA() && isASTNodeDecl()) {
-      sb.append("rewritten_int_reset();\n");
-    }
+
     tt.bind("FlushAttrCacheBody", sb.toString());
     tt.expand("ASTDecl.flushAttrCacheMethod", out);
-
     tt.expand("ASTDecl.flushCollectionCacheMethod", out);
-
-    tt.expand("ASTDecl.flushRewriteCacheMethod", out);
-    tt.expand("ASTNode.getChild_initValue", out);
-    tt.expand("ASTNode.getChild_hasEnclosingInitValueMethod", out);
   }
 
   syn String AttrDecl.resetCache() = templateContext().expand("AttrDecl.resetAttrCache");
diff --git a/src/jastadd/ast/InheritedAttributes.jrag b/src/jastadd/ast/InheritedAttributes.jrag
index e2264096d3004a0ca398556ea51ca611f9b88ca9..1fd622ee294ae293de5b94a1a9f60e77db058a48 100644
--- a/src/jastadd/ast/InheritedAttributes.jrag
+++ b/src/jastadd/ast/InheritedAttributes.jrag
@@ -393,7 +393,7 @@ aspect InheritedAttributeCodeGen {
     // Have we already generated a component equation?
     boolean hasComponentEq = false;
 
-    for (InhEq equ: inhEqs) {
+    for (InhEq equ : inhEqs) {
       if (hasComponentEq) {
         sb.append("else ");
       }
diff --git a/src/jastadd/ast/JaddCodeGen.jrag b/src/jastadd/ast/JaddCodeGen.jrag
index 6eae1de2fdd0b24d625e4354fb0fde3d07665a73..089facb2803a3daf8a1e2224a09f400d49a0a29d 100644
--- a/src/jastadd/ast/JaddCodeGen.jrag
+++ b/src/jastadd/ast/JaddCodeGen.jrag
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005-2013, The JastAdd Team
+/* Copyright (c) 2005-2016, The JastAdd Team
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -110,20 +110,12 @@ aspect JaddCodeGen {
    * all list and opt children. Initializes NTAs.
    */
   public void ASTDecl.emitDefaultConstructor(PrintWriter out) {
-
     TemplateContext tt = templateContext();
-
     String finalInit = "";
-    if (config().rewriteEnabled() && isRootNode()) {
-      if (config().stagedRewrites()) {
-        finalInit = "is$Final(state().rewritePhase);";
-      } else {
-        finalInit = "is$Final(true);";
-      }
+    if (config().legacyRewrite() && isRootNode()) {
+      finalInit = "is$Final(true);";
     }
-
     tt.bind("FinalInit", finalInit);
-
     tt.expand("ASTDecl.emitDefaultConstructor", out);
   }
 
@@ -184,19 +176,15 @@ aspect JaddCodeGen {
         }
         param += 1;
       } else {
-        if (c instanceof ListComponent ||
-          c instanceof OptionalComponent ||
-          c instanceof AggregateComponent) {
-        childIndex++;
+        if (c instanceof ListComponent
+            || c instanceof OptionalComponent
+            || c instanceof AggregateComponent) {
+          childIndex++;
         }
       }
     }
-    if (config().rewriteEnabled() && isRootNode()) {
-      if (config().stagedRewrites()) {
-        out.println(config().ind(2) + "is$Final(java.lang.Integer.MAX_VALUE);");
-      } else {
-        out.println(config().ind(2) + "is$Final(true);");
-      }
+    if (config().legacyRewrite() && isRootNode()) {
+      out.println(config().ind(2) + "is$Final(true);");
     }
 
     tt.expand("State.incHookConstructionEnd", out);
@@ -237,18 +225,19 @@ aspect JaddCodeGen {
         stringArg = true;
       }
     }
-    if (!stringArg) return;
-
-    out.print(config().indent + "public " + name() + "." + name() + "(");
+    if (!stringArg) {
+      return;
+    }
+    out.format("%spublic %s.%s(", config().indent, name(), name());
     int paramIndex = 0;
     for (Component c : components()) {
       if (!c.isNTA()) {
         if (paramIndex != 0) out.print(", ");
         if (c instanceof TokenComponent && c.constrParmType().equals("String")
             || c.constrParmType().equals("java.lang.String")) {
-          out.print("beaver.Symbol p" + paramIndex);
+          out.format("beaver.Symbol p%d", paramIndex);
         } else {
-          out.print(c.constrParmType() + " p" + paramIndex);
+          out.format("%s p%d", c.constrParmType(), paramIndex);
         }
         paramIndex++;
       }
@@ -306,8 +295,8 @@ aspect JaddCodeGen {
    * array size.
    */
   syn String ASTDecl.initialChildArraySize() {
-    return "(i+1>" + config().minListSize() + " || !(this instanceof " + config().listType()
-      + "))?i+1:" + config().minListSize();
+    return String.format("(i + 1 > %d || !(this instanceof %s)) ? i + 1 : %d",
+        config().minListSize(), config().listType(), config().minListSize());
   }
 
   /**
@@ -345,7 +334,6 @@ aspect JaddCodeGen {
     TemplateContext tt = templateContext();
     tt.expand("ASTNode.declarations", out);
     tt.expand("ASTNode.getChild", out);
-    tt.expand("ASTNode.rewrittenAttr", out);
     tt.expand("ASTNode.addChild", out);
     tt.expand("ASTNode.getChildNoTransform", out);
     tt.expand("ASTNode.numChildren", out);
@@ -361,12 +349,6 @@ aspect JaddCodeGen {
     }
   }
 
-  /**
-   * @return <code>true</code> if the list$touched field is needed for this
-   * ASTDecl.
-   */
-  syn boolean ASTDecl.needsListTouched() = !(config().incremental() || config().flushRewrite());
-
   /**
    * Generate implicit aspect declarations for the List type.
    *
@@ -458,9 +440,7 @@ aspect JaddCodeGen {
   }
 
   public void ASTDecl.emitConstructor(PrintWriter out) {
-
     emitDefaultConstructor(out);
-
     emitChildInitMethod(out);
 
     if (numNonNTAComponent() != 0) {
@@ -482,7 +462,7 @@ aspect JaddCodeGen {
   }
 
   /**
-   * Emit aspect declaration for the mayHaveRewrite method
+   * Emit aspect declaration for the mayHaveRewrite method.
    *
    * @param out Aspect output stream
    */
@@ -493,24 +473,9 @@ aspect JaddCodeGen {
     out.println(ind + " * @apilevel internal");
     out.println(ind + " */");
     out.println(ind + "public boolean " + name() + ".mayHaveRewrite() {");
-    if (name().equals(config().listType())) {
-
-      // Avoiding list touch rewrite.
-      if (!(config().incremental() || config().flushRewrite())) {
-        out.println(ind2 + "return true;");  // Old code.
-      } else {
-        out.println(ind2 + "return false;");
-      }
-
-    } else if (!hasRewrites()) {
-      out.println(ind2 + "return false;");
-    } else if (!config().stagedRewrites() || rewriteWithNoPhaseCondition()) {
+    if (hasRewrites()) {
       out.println(ind2 + "return true;");
     } else {
-      for (Iterator iter = rewritePhaseConditions().iterator(); iter.hasNext(); ) {
-        String condition = (String)iter.next();
-        out.println(ind2 + "if (" + condition + ") return true;");
-      }
       out.println(ind2 + "return false;");
     }
     out.println(ind + "}");
@@ -556,7 +521,6 @@ aspect JaddCodeGen {
     emitCopyNode(out);
     emitFullCopy(out);
     emitIsEqualMethods(out);
-
     genIncremental(out);
   }
 
@@ -571,25 +535,6 @@ aspect JaddCodeGen {
     return superClass() instanceof ASTDecl && ((ASTDecl)superClass()).rewriteWithNoPhaseCondition();
   }
 
-  syn java.util.Set ASTDecl.rewritePhaseConditions() {
-    java.util.Set set = new java.util.LinkedHashSet();
-    Pattern p = Pattern.compile("inRewritePhase\\([\\w\\.]*\\)|inExactRewritePhase\\([\\w\\.]*\\)");
-    for (int i = 0; i < getNumRewrite(); i++) {
-      if (getRewrite(i).getCondition() != null) {
-        String condition = Unparser.unparse(getRewrite(i).getCondition());
-        Matcher m = p.matcher(condition);
-        while (m.find()) {
-          String match = m.group();
-          set.add(match);
-        }
-      }
-    }
-    if (superClass() instanceof ASTDecl) {
-      set.addAll(((ASTDecl)superClass()).rewritePhaseConditions());
-    }
-    return set;
-  }
-
   public abstract void Component.jaddGen(int index, boolean publicModifier, ASTDecl decl);
 
   public void ListComponent.jaddGen(int index, boolean publicModifier, ASTDecl decl) {
@@ -655,11 +600,6 @@ aspect JaddCodeGen {
     // from a node type specification
     jp.setFileName("");
 
-    // EMMA_2011-09-08: Adding this to give .ast generated methods an enclosing
-    // aspect "Ast" which allows for refinement of these methods. For example,
-    // "getA" generated from "B ::= A" can be refined using the "Ast" aspect.
-    //jp.enclosingAspect = "Ast";
-
     try {
       jp.AspectBodyDeclarationsEOF();
     } catch (Exception e) {
diff --git a/src/jastadd/ast/JastAddCodeGen.jadd b/src/jastadd/ast/JastAddCodeGen.jadd
index a8010bacaf475965b85459ce06659e9d11a73b08..2ac7cdb8d4b7752fd3281ea62d045bf80f3ee770 100644
--- a/src/jastadd/ast/JastAddCodeGen.jadd
+++ b/src/jastadd/ast/JastAddCodeGen.jadd
@@ -399,5 +399,6 @@ aspect JastAddCodeGen {
     emitCollDecls(out);
     emitCollContributions(out);
     emitInhEqSignatures(out);
+    emitRewriteAttribute(out);
   }
 }
diff --git a/src/jastadd/ast/JragCodeGen.jrag b/src/jastadd/ast/JragCodeGen.jrag
index eaf12b6eb7199fa55fe054f7fe844e3ed9cfd49c..bb240e0d5a31f2ecad6c0fbd6d27a26b7c953335 100644
--- a/src/jastadd/ast/JragCodeGen.jrag
+++ b/src/jastadd/ast/JragCodeGen.jrag
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005-2015, The JastAdd Team
+/* Copyright (c) 2005-2016, The JastAdd Team
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,6 +44,8 @@ aspect AttributeKind {
   eq InhDecl.attributeKind() = "inh";
 
   eq CollDecl.attributeKind() = "coll";
+
+  eq CircularRewriteDecl.attributeKind() = "syn nta";
 }
 
 aspect JragCodeGen {
@@ -81,8 +83,6 @@ aspect JragCodeGen {
 
   syn String Rewrite.declaredat() = ASTNode.declaredat(getFileName(), getStartLine());
 
-  syn String RewriteList.declaredat() = ASTNode.declaredat(getFileName(), getStartLine());
-
   syn String Rewrite.sourceLocation() = ASTNode.sourceLocation(getFileName(), getStartLine());
 
   /**
@@ -103,13 +103,13 @@ aspect JragCodeGen {
     throw new Error("unhandled cache mode");
   }
 
-  syn boolean AttrDecl.isLazy() = declaredNTA() || shouldCache(getCacheMode());
+  syn boolean AttrDecl.isLazy() = declaredNTA() || isCircular() || shouldCache(getCacheMode());
 
-  eq SynDecl.isLazy() = declaredNTA() || shouldCache(getCacheMode());
+  eq SynDecl.isLazy() = declaredNTA() || isCircular() || shouldCache(getCacheMode());
 
-  eq InhDecl.isLazy() = declaredNTA() || shouldCache(getCacheMode());
+  eq InhDecl.isLazy() = declaredNTA() || isCircular() || shouldCache(getCacheMode());
 
-  eq CollDecl.isLazy() = declaredNTA() || shouldCache(getCacheMode());
+  eq CollDecl.isLazy() = declaredNTA() || isCircular() || shouldCache(getCacheMode());
 
   public String Grammar.genImportsList() {
     Set imports = new LinkedHashSet();
@@ -219,7 +219,7 @@ aspect JragCodeGen {
     StringBuilder sb = new StringBuilder();
     if (config().lazyMaps()) {
       if (!isCircular()) {
-        if (getNumParameter() != 0 && config().visitCheckEnabled() && config().rewriteEnabled()) {
+        if (getNumParameter() != 0 && config().visitCheckEnabled() && config().legacyRewrite()) {
           sb.append(String.format("if (%s_visited == null) %s_visited = %s;\n",
               signature(), signature(), config().createDefaultMap()));
         } else if (getNumParameter() != 0 && config().visitCheckEnabled()) {
@@ -327,50 +327,13 @@ aspect JragCodeGen {
   }
 
   public String AttrDecl.cacheStoreCondition() {
-    /* BEGIN INCORRECT legacy cache store condition */
-    /* TODO remove this */
+    // This cache store condition is only used with the old (legacy) rewrite implementation.
+    // It is kept for backward compatibility.
     if (!config().rewriteEnabled() || getFinal()) {
       return "true";
     } else {
       return "isFinal && _boundaries == state().boundariesCrossed";
     }
-    /* END INCORRECT legacy cache store condition */
-
-    /* BEGIN CORRECT cache store condition.
-     * TODO use this instead of above condition in 2.2.0!!
-    StringBuilder cacheCond = new StringBuilder();
-    cacheCond.append(cacheStoreRewrite());
-    String circularCond = (!isCircular() ? cacheStoreCircular() : "");
-    if (cacheCond.length() != 0 && !circularCond.isEmpty()) {
-      cacheCond.append(" && ");
-    }
-    cacheCond.append(circularCond);
-    if (cacheCond.length() == 0) {
-      cacheCond.append("true");
-    }
-    return cacheCond;
-    END CORRECT cache store condition
-    */
-  }
-
-  public String AttrDecl.cacheStoreCircular() {
-    if (config().cacheCycle()) {
-      return "(!state.IN_CIRCLE || (state.IN_CIRCLE && (!state.INTERMEDIATE_VALUE "
-          + "|| state.LAST_CYCLE)))";
-    }
-    return "!state.INTERMEDIATE_VALUE";
-  }
-
-  public String AttrDecl.cacheStoreRewrite() {
-    if (config().rewriteEnabled() && !config().rewriteCircularNTA()) {
-      // TODO: Should final on attributes be allowed?
-      if (getFinal()) {
-        return "(_boundaries == state().boundariesCrossed)";
-      }
-      return "(isFinal && _boundaries == state().boundariesCrossed)";
-    } else {
-      return "";
-    }
   }
 
   syn boolean AttrEq.hasComputeBlock() = true;
@@ -535,17 +498,12 @@ aspect JragCodeGen {
   /**
    * Generate code to test if two attribute values differ based on the type of the attribute.
    */
-  public String AttrDecl.valueComparisonExpr(String s1, String s2) {
-    if (isPrimitive()) {
-      return s1 + " != " + s2;
-    } else if (declaredNTA() && isCircular()) {
-      if (isRewriteCircularNtaAttr()) {
-        return "rewriteState != " + config().stateClassName() + ".REWRITE_NOCHANGE";
-      }
-      return String.format("!is$Equal(%s, %s)", s1, s2);
+  public String AttrDecl.valueComparisonExpr(String oldValue, String newValue) {
+    if (isPrimitive() || (declaredNTA() && isCircular())) {
+      return String.format("%s != %s", oldValue, newValue);
     } else {
       return String.format("(%s == null && %s != null) || (%s != null && !%s.equals(%s))",
-          s1, s2, s1, s1, s2);
+          oldValue, newValue, oldValue, oldValue, newValue);
     }
   }
 
@@ -674,11 +632,7 @@ aspect JragCodeGen {
       return "";
     } else if (declaredNTA()) { // Check if attribute equation is declared NTA.
       if (config().rewriteEnabled()) {
-        if (config().stagedRewrites()) {
-          return templateContext().expand("SynDecl.higherOrderAttributeCode:stagedrewrites");
-        } else {
-          return templateContext().expand("SynDecl.higherOrderAttributeCode:nostagedrewrites");
-        }
+        return templateContext().expand("SynDecl.higherOrderAttributeCode:rewritesEnabled");
       } else {
         return templateContext().expand("SynDecl.higherOrderAttributeCode:norewrite");
       }
diff --git a/src/jastadd/ast/Rewrites.jrag b/src/jastadd/ast/Rewrites.jrag
index 357e6f416640dfa341c3f72415dcfd00bc7f41c1..1a84c52702d97d77d3837365a9babb2818a822e3 100644
--- a/src/jastadd/ast/Rewrites.jrag
+++ b/src/jastadd/ast/Rewrites.jrag
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005-2013, The JastAdd Team
+/* Copyright (c) 2005-2016, The JastAdd Team
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,14 +35,8 @@ aspect Rewrites {
     TemplateContext tt = templateContext();
     boolean unconditional = false;
 
-    tt.expand("ASTDecl.emitRewrites.begin", out);
+    tt.expand("ASTDecl.rewriteTo:begin", out);
 
-    if (name().equals(config().listType())) {
-      // ES_2011-10-10: Code generation for incremental evaluation, avoiding list touch rewrite.
-      if (!(config().incremental() || config().flushRewrite())) {
-        tt.expand("ASTDecl.emitRewrites.touch_list", out);
-      }
-    }
     for (int i = 0; i < getNumRewrite(); i++) {
       Rewrite r = getRewrite(i);
       if (r.genRewrite(out, i)) {
@@ -51,23 +45,38 @@ aspect Rewrites {
     }
 
     if (name().equals(config().astNodeType())) {
-      tt.expand("ASTDecl.emitRewrites.end:ASTNode", out);
+      tt.expand("ASTDecl.rewriteTo:end:ASTNode", out);
     } else if (!unconditional) {
-      tt.expand("ASTDecl.emitRewrites.end:!unconditional", out);
+      tt.expand("ASTDecl.rewriteTo:end:conditional", out);
     } else {
-      tt.expand("ASTDecl.emitRewrites.end", out);
+      tt.expand("ASTDecl.rewriteTo:end:unconditional", out);
     }
 
     for (int i = 0; i < getNumRewrite(); i++) {
       Rewrite r = getRewrite(i);
       r.genRewritesExtra(out, i);
     }
+
+    if (config().rewriteCircularNTA()) {
+      // Generate the canRewrite method.
+      tt.expand("ASTDecl.canRewrite:begin", out);
+
+      if (unconditional) {
+        tt.expand("ASTDecl.canRewrite:end:unconditional", out);
+      } else {
+        for (int i = 0; i < getNumRewrite(); i++) {
+          Rewrite r = getRewrite(i);
+          r.genRewriteCondition(out, i);
+        }
+        tt.expand("ASTDecl.canRewrite:end", out);
+      }
+    }
   }
 
   public boolean Rewrite.genRewrite(PrintStream out, int index) {
     TemplateContext tt = templateContext();
     tt.bind("RewriteIndex", "" + index);
-    tt.expand("Rewrite.genRewrite.declaredat", out);
+    tt.expand("Rewrite.declaredat", out);
     if (getCondition() != null) {
       tt.bind("Condition", Unparser.unparse(getCondition()));
       tt.expand("Rewrite.genRewrite:conditional", out);
@@ -77,18 +86,15 @@ aspect Rewrites {
       return true;
     }
   }
-  public boolean RewriteList.genRewrite(PrintStream out, int index) {
-    TemplateContext tt = templateContext();
-    tt.expand("Rewrite.genRewrite.declaredat", out);
 
+  public void Rewrite.genRewriteCondition(PrintStream out, int index) {
+    TemplateContext tt = templateContext();
+    tt.bind("RewriteIndex", "" + index);
+    tt.expand("Rewrite.declaredat", out);
     if (getCondition() != null) {
-      tt.bind("Condition", " && " + Unparser.unparse(getCondition()));
-    } else {
-      tt.bind("Condition", "");
+      tt.bind("Condition", Unparser.unparse(getCondition()));
+      tt.expand("Rewrite.condition", out);
     }
-
-    tt.expand("RewriteList.genRewrite", out);
-    return false;
   }
 
   public void Rewrite.genRewritesExtra(PrintStream out, int index) {
@@ -98,52 +104,11 @@ aspect Rewrites {
       templateContext().expand("Rewrite.javaDoc:internal", out);
       out.println();
       out.println(ind + "private " + getReturnType() + " rewriteRule" + index + "() {");
-      if (config().rewriteLimit() > 0) {
-        out.println(ind2
-            + "debugRewrite(\"Rewriting \" + getClass().getName() + \" "
-            + "using rule in " + getFileNameEscaped() + " at line "
-            + getStartLine() + "\");");
-      }
       out.print(Unparser.unparse(getResult()));
       out.println(ind + "}");
     } else {
       templateContext().expand("Rewrite.javaDoc:internal", out);
       out.println(ind + "private " + getReturnType() + " rewriteRule" + index + "() {");
-      if (config().rewriteLimit() > 0) {
-        out.println(ind2
-            + "debugRewrite(\"Rewriting \" + getClass().getName() + \" "
-            + "using rule in " + getFileNameEscaped() + " at line "
-            + getStartLine() + "\");");
-      }
-      out.println(ind2 + "return " + Unparser.unparse(getResult()) + ";");
-      out.println(ind + "}");
-    }
-  }
-
-  public void RewriteList.genRewritesExtra(PrintStream out, int index) {
-    String ind = config().indent;
-    String ind2 = config().ind(2);
-    if (getResult() instanceof org.jastadd.jrag.AST.ASTBlock) {
-      templateContext().expand("Rewrite.javaDoc:internal", out);
-      out.println(ind + "private " + getReturnType() + " rewrite"
-          + getParentName() + "_" + getChildName() + "() {");
-      if (config().rewriteLimit() > 0) {
-        out.println(ind2
-            + "debugRewrite(\"Rewriting \" + getClass().getName() + \" "
-            + "using rule in " + getFileNameEscaped() + " at line "
-            + getStartLine() + "\");");
-      }
-      out.print(Unparser.unparse(getResult()));
-      out.println(ind + "}");
-    } else {
-      templateContext().expand("Rewrite.javaDoc:internal", out);
-      out.println(ind + "private " + getReturnType() + " rewrite" + getParentName() + "_" + getChildName() + "() {");
-      if (config().rewriteLimit() > 0) {
-        out.println(ind2
-            + "debugRewrite(\"Rewriting \" + getClass().getName() + \" "
-            + "using rule in " + getFileNameEscaped() + " at line "
-            + getStartLine() + "\");");
-      }
       out.println(ind2 + "return " + Unparser.unparse(getResult()) + ";");
       out.println(ind + "}");
     }
@@ -152,6 +117,56 @@ aspect Rewrites {
   syn lazy boolean ASTDecl.hasRewrites() =
       getNumRewrite() > 0 || (superClass() != null && superClass().hasRewrites());
 
-  syn lazy boolean AttrDecl.isRewriteCircularNtaAttr() =
-      config().rewriteCircularNTA() && name().equals("rewritten"); 
+  /**
+   * @return {@code true} if this AST node has a rewrittenNode attribute declaration
+   * for circular NTA rewrites.
+   */
+  syn lazy boolean ASTDecl.hasRewriteAttribute() =
+      getNumRewrite() > 0 && (superClass() == null || !superClass().hasRewrites());
+
+  /**
+   * Generates the attribute code for circular rewrites.
+   */
+  public void ASTDecl.emitRewriteAttribute(PrintStream out) {
+    if (config().rewriteCircularNTA() && hasRewriteAttribute()) {
+      // Generate the rewrittenNode attribute only if this node has rewrites and
+      // a supertype does not have rewrites (if the supertype has rewrites then
+      // this node inherites the rewrittenNode attribute).
+      CircularRewriteDecl decl = getCircularRewriteDecl();
+      TemplateContext tt = decl.templateContext();
+      String newValue = "new_" + decl.signature() + "_value";
+      String oldValue = decl.signature() + "_value";
+      tt.bind("CircularComputeRhs", oldValue + ".rewriteTo()");
+      tt.bind("ChangeCondition", String.format("%s != %s || %s.canRewrite()",
+            newValue, oldValue, newValue));
+      tt.bind("BottomValue", "this");
+      tt.bind("TracePrintReturnNewValue",
+          decl.tracePrintReturnNewValue(decl.signature() + "_value"));
+      tt.bind("TracePrintReturnPreviousValue",
+          decl.tracePrintReturnPreviousValue(decl.signature() + "_value"));
+      tt.expand("AttrDecl.resetMethod", out);
+      tt.expand("AttrDecl.cycleDeclaration", out);
+      tt.expand("AttrDecl.cacheDeclarations", out);
+      tt.expand("AttrDecl.circularEquation:unparameterized", out);
+    } else if (isASTNodeDecl()) {
+      out.format("public %s rewrittenNode() { "
+          + "throw new Error(\"rewrittenNode is undefined for ASTNode\"); }%n",
+          config().astNodeType());
+    }
+  }
+
+  syn lazy CircularRewriteDecl ASTDecl.getCircularRewriteDecl() =
+      new CircularRewriteDecl(
+          new List<Parameter>(),
+          "rewrittenNode",
+          "ASTNode",
+          CacheMode.DEFAULT,
+          "",
+          0,
+          0,
+          false,
+          true,
+          "",
+          "",
+          new List<Annotation>());
 }
diff --git a/src/jastadd/core/TemplateUtil.jrag b/src/jastadd/core/TemplateUtil.jrag
index c08bf726a7320c316909456846ae2f286a80bc9d..2af97ce35c790c0a2269bee7e8a1f7b65be77aff 100644
--- a/src/jastadd/core/TemplateUtil.jrag
+++ b/src/jastadd/core/TemplateUtil.jrag
@@ -69,8 +69,6 @@ aspect TemplateUtil {
     loadTemplates(tt, "core/Synchronization");
     
     loadTemplates(tt, "flush/Flush");
-    loadTemplates(tt, "flush/FlushHooks");
-    loadTemplates(tt, "flush/FlushRewrite");
 
     if (config().incremental()) {
       loadTemplates(tt, "incremental/DDGNodeCopy");
diff --git a/src/jastadd/incremental/IncrementalDebug.jadd b/src/jastadd/incremental/IncrementalDebug.jadd
index 8cf11397a36fd9c09de17b718bc6f2a664180504..ad8a96f87c6eda3c3ed74a2af6d359853a83b702 100644
--- a/src/jastadd/incremental/IncrementalDebug.jadd
+++ b/src/jastadd/incremental/IncrementalDebug.jadd
@@ -53,8 +53,7 @@ aspect IncrementalDebug {
   public String ASTDecl.genDumpDepsInNTAsString() {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       if ((attr.isNTA() || attr.getNTA()) && !attr.isPrimitive() &&
          !(attr.type().equals("String") || attr.type().equals("java.lang.String"))) {
         tt.bind("IsParameterized", attr.getNumParameter() > 0);
@@ -72,8 +71,7 @@ aspect IncrementalDebug {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
     // Add dump string for each attribute
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       tt.bind("IsParameterized", attr.getNumParameter() > 0);
       tt.bind("IsNTA", (attr.isNTA() || attr.getNTA()) && !attr.isPrimitive() &&
             !(attr.type().equals("String") || attr.type().equals("java.lang.String")));
@@ -106,8 +104,7 @@ aspect IncrementalDebug {
   public String ASTDecl.genDumpAttributeValuesString() {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       tt.bind("IsParameterized", attr.getNumParameter() > 0);
       tt.bind("PrintAsObject", attr.isPrimitive() || attr.getType().equals("String"));
       tt.bind("AttrSign", attr.signature());
diff --git a/src/jastadd/incremental/IncrementalEval.jadd b/src/jastadd/incremental/IncrementalEval.jadd
index 38f4bae099153b6e4806df2bcc2713e905c976a3..422784b789378d6d8ae78e793f8ceb6ecf34a09b 100644
--- a/src/jastadd/incremental/IncrementalEval.jadd
+++ b/src/jastadd/incremental/IncrementalEval.jadd
@@ -54,8 +54,11 @@ aspect IncrementalEval {
   /**
    * Returns a list of all cached attributes (syn, inh).
    */
-  public ArrayList ASTDecl.listOfCachedAttributes() {
-    ArrayList list = new ArrayList();
+  public ArrayList<AttrDecl> ASTDecl.listOfCachedAttributes() {
+    ArrayList<AttrDecl> list = new ArrayList<AttrDecl>();
+    if (config().rewriteCircularNTA() && hasRewriteAttribute()) {
+      list.add(getCircularRewriteDecl());
+    }
     for (int k = 0; k < getNumSynEq(); k++) {
       AttrDecl attr = getSynEq(k).decl();
       if (attr != null && (attr.isLazy() || attr.isCircular())) {
diff --git a/src/jastadd/incremental/IncrementalNotification.jadd b/src/jastadd/incremental/IncrementalNotification.jadd
index 35bb5a20047320b9281e4bb8d8922fae3f9231b8..33829769dc6628bff6a099cb145dfaaa297a6f73 100644
--- a/src/jastadd/incremental/IncrementalNotification.jadd
+++ b/src/jastadd/incremental/IncrementalNotification.jadd
@@ -74,8 +74,7 @@
   public String ASTDecl.emitFlushNtaSubTreesString() {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       tt.bind("IsNTA", (attr.isNTA() || attr.getNTA()) && !attr.isPrimitive()
               && !(attr.type().equals("String") || attr.type().equals("java.lang.String")));
       tt.bind("IsParameterized", attr.isParameterized());
@@ -93,8 +92,7 @@
   public String ASTDecl.emitTransferSetsFromAttrTokenHandlersString() {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       tt.bind("IsParameterized", attr.isParameterized());
       tt.bind("AttrSign", attr.signature());
       res.append(tt.expand("ASTDecl.transferSetsFromAttributeHandler"));
@@ -115,8 +113,7 @@
   public String ASTDecl.emitFlushNTAsInRegionString() {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       tt.bind("IsNTA", (attr.isNTA() || attr.getNTA()) && !attr.isPrimitive()
             && !(attr.type().equals("String") || attr.type().equals("java.lang.String")));
       tt.bind("IsParameterized", attr.getNumParameter() > 0);
@@ -136,8 +133,7 @@
   public String ASTDecl.emitFlushNTAsString() {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       if ((attr.isNTA() || attr.getNTA()) && !attr.isPrimitive() &&
       		!(attr.type().equals("String") || attr.type().equals("java.lang.String")) &&
       		attr.getNumParameter() == 0) {
@@ -162,8 +158,7 @@
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
     boolean firstAttr = true;
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       res.append(firstAttr ? "" : "else ");
       tt.bind("AttrResetVisit", attr.resetVisit());
       tt.bind("AttrResetCache", attr.resetCache());
@@ -195,8 +190,7 @@
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
     boolean firstAttr = true;
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       res.append(firstAttr ? "" : "else ");
       tt.bind("IsParameterized", attr.getNumParameter() > 0);
       tt.bind("AttrSign", attr.signature());
@@ -218,8 +212,7 @@
   public String ASTDecl.emitFlushAttrsString() {
     StringBuffer res = new StringBuffer();
     TemplateContext tt = templateContext();
-    for (Iterator itr = listOfCachedAttributes().iterator(); itr.hasNext();) {
-      AttrDecl attr = (AttrDecl)itr.next();
+    for (AttrDecl attr : listOfCachedAttributes()) {
       tt.bind("IsParameterized", attr.getNumParameter() > 0);
       tt.bind("AttrSign", attr.signature());
       tt.bind("AttrResetVisit", attr.resetVisit());
diff --git a/src/java/org/jastadd/Configuration.java b/src/java/org/jastadd/Configuration.java
index e646bb2124c5ac8efe3b5c4b6ea4a36e28f2f2b3..03c037376fb36ae9a4cc5c7c4d64004f67824641 100644
--- a/src/java/org/jastadd/Configuration.java
+++ b/src/java/org/jastadd/Configuration.java
@@ -205,10 +205,8 @@ public class Configuration {
       "enable the legacy refine syntax")
       .defaultValue(true);
 
-  // TODO(jesper): add description for --stagedRewrites option.
   Option<Boolean> stagedRewritesOption = new FlagOption("stagedRewrites", "")
-      .templateVariable("StagedRewrites")
-      .nonStandard();
+      .deprecated("2.2.1", "this option currently does nothing");
 
   Option<Boolean> doxygenOption = new FlagOption("doxygen", "")
       .deprecated("2.1.5", "this option currently does nothing");
@@ -537,15 +535,13 @@ public class Configuration {
 
     // Rewrite options.
     tt.bind("RewriteEnabled", rewriteEnabled());
-    tt.bind("RewriteLimit", rewriteLimit());
-    tt.bind("HasRewriteLimit", rewriteLimit() > 0);
     tt.bind("RewriteCircularNTA", rewriteCircularNTA());
+    tt.bind("LegacyRewrite", legacyRewrite());
 
     // Flush options.
     tt.bind("FlushEnabled", flushEnabled());
     tt.bind("FlushAttr", flushAttr());
     tt.bind("FlushColl", flushColl());
-    tt.bind("FlushRewrite", flushRewrite());
 
     // Incremental options.
     tt.bind("IncrementalEnabled", incremental());
@@ -579,7 +575,6 @@ public class Configuration {
     tt.bind("VisitCheckEnabled", visitCheckEnabled());
     tt.bind("CacheCycle", cacheCycle());
     tt.bind("StaticState", staticState());
-    tt.bind("StagedRewrites", stagedRewrites());
     tt.bind("LazyMaps", lazyMaps());
 
     return root;
@@ -1105,17 +1100,18 @@ public class Configuration {
   }
 
   /**
-   * @return {@code true} if --rewrite=none
+   * @return {@code true} if rewrites are enabled and the old rewrite
+   * implementation should be used.
    */
-  public boolean rewriteEnabled() {
-    return !rewriteOption.hasValue("none");
+  public boolean legacyRewrite() {
+    return rewriteEnabled() && !rewriteCircularNTA();
   }
 
   /**
-   * @return {@code true} if --stagedRewrites=true
+   * @return {@code true} if --rewrite=none
    */
-  public boolean stagedRewrites() {
-    return stagedRewritesOption.value();
+  public boolean rewriteEnabled() {
+    return !rewriteOption.hasValue("none");
   }
 
   /**
@@ -1171,15 +1167,6 @@ public class Configuration {
         || flushOption.hasValue("full");
   }
 
-  /**
-   * @return {@code true} if --flush=rewrite || --flush=full
-   */
-  public boolean flushRewrite() {
-    return flushOption.hasValue("rewrite")
-        || incremental()
-        || flushOption.hasValue("full");
-  }
-
   /**
    * @return default map initialization
    */
@@ -1205,13 +1192,6 @@ public class Configuration {
     return !noInhEqCheckOption.value();
   }
 
-  /**
-   * @return rewrite limit (0 if disabled)
-   */
-  public int rewriteLimit() {
-    return debugMode() ? 100 : 0;
-  }
-
   /**
    * @return {@code true} if --beaver
    */
diff --git a/src/javacc/jrag/Jrag.jjt b/src/javacc/jrag/Jrag.jjt
index 3486e5258852d103c66518e9dd4a300e34b02a53..7b86d44b2482c06c94089e86fd7c112e7d3655d4 100644
--- a/src/javacc/jrag/Jrag.jjt
+++ b/src/javacc/jrag/Jrag.jjt
@@ -1,5 +1,5 @@
 /* Copyright (c) 2006, Sun Microsystems, Inc.
- *               2006-2013, The JastAdd Team
+ *               2006-2016, The JastAdd Team
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1138,24 +1138,17 @@ void AspectRewrite() :
   SimpleNode eq;
   Token first, last;
 
-  Token parent = null;
-  Token child = null;
   String type;
 }
 {
   "rewrite" {cond = null; first = token;} t = <IDENTIFIER> { className = t.image; }
-  [<IDENTIFIER> parent = <IDENTIFIER> "." child = <IDENTIFIER> <LPAREN> <RPAREN>]
   <LBRACE>
     ( ["when" { first = token; } <LPAREN> cond = Expression() <RPAREN>]
       "to" type = AspectType() ( (eq = Expression() ";" { last = token; }) | eq = Block() { last = token; } )
       {
-        if(parent != null && child != null) {
-          root.addRewriteList(className, cond, eq, type, fileName, first.beginLine, last.endLine, parent.image, child.image, enclosingAspect);
-        }
-        else {
-          root.addRewrite(className, cond, eq, type, fileName, first.beginLine, last.endLine, enclosingAspect);
-        }
-        cond = null;}
+        root.addRewrite(className, cond, eq, type, fileName, first.beginLine, last.endLine, enclosingAspect);
+        cond = null;
+      }
     )+
   <RBRACE>
 }
diff --git a/src/template/ast/ASTNode.tt b/src/template/ast/ASTNode.tt
index 8ae1c30f1f6aa1f175b50ddd2fe44910116fae49..ec28d309143f3faafd220f6302adf68b4def2f80 100644
--- a/src/template/ast/ASTNode.tt
+++ b/src/template/ast/ASTNode.tt
@@ -29,30 +29,36 @@
 # for the ASTNode AST node type
 
 ASTNode.declarations [[
-  /** @apilevel internal */
-  private int $ASTNode.childIndex;
+  /**
+   * Cached child index. Child indices are assumed to never change (AST should
+   * not change after construction).
+   * @apilevel internal
+   */
+  private int $ASTNode.childIndex = -1;
 
   /** @apilevel low-level */
   public int $ASTNode.getIndexOfChild($ASTNode node) {
     if (node == null) {
       return -1;
     }
-    if (node.childIndex < numChildren && node == children[node.childIndex]) {
+$if(RewriteCircularNTA)
+    if (node.childIndex >= 0) {
       return node.childIndex;
     }
-    for(int i = 0; children != null && i < children.length; i++) {
-      if (children[i] == node) {
+    for (int i = 0; children != null && i < children.length; i++) {
+      if (getChild(i) == node) {
         node.childIndex = i;
         return i;
       }
     }
-$if(RewriteCircularNTA)
-    if (rewritten_int_values != null) {
-      for (java.util.Iterator itr = rewritten_int_values.entrySet().iterator(); itr.hasNext();) {
-        java.util.Map.Entry e = (java.util.Map.Entry)itr.next();
-        if (e.getValue() == node) {
-          return ((Integer)e.getKey()).intValue();
-        }
+$else
+    if (node.childIndex >= 0) {
+      return node.childIndex;
+    }
+    for (int i = 0; children != null && i < children.length; i++) {
+      if (children[i] == node) {
+        node.childIndex = i;
+        return i;
       }
     }
 $endif
@@ -105,7 +111,7 @@ $else
   }
 $endif
 
-$if(RewriteEnabled)
+$if(LegacyRewrite)
   /** @apilevel internal */
   public boolean $ASTNode.in$$Circle = false;
 
@@ -118,64 +124,6 @@ $if(RewriteEnabled)
   public void $ASTNode.in$$Circle(boolean b) {
     in$$Circle = b;
   }
-
-$if(HasRewriteLimit)
-  /** @apilevel internal */
-  public void $ASTNode.debugRewrite(String info) {
-    if (!parent.is$$Final()) return;
-    java.util.ArrayList key = new java.util.ArrayList(2);
-    key.add(getParent());
-    key.add(Integer.valueOf(getParent().getIndexOfChild(this)));
-    java.util.ArrayList list;
-    if (state().debugRewrite.containsKey(key)) {
-      list = (java.util.ArrayList) state().debugRewrite.get(key);
-    } else {
-      list = new java.util.ArrayList();
-      state().debugRewrite.put(key, list);
-    }
-    list.add(info);
-    if (list.size() > $RewriteLimit) {
-      StringBuffer buf = new StringBuffer("Iteration count exceeded for rewrite:");
-      java.util.Iterator iter = list.iterator();
-      while (iter.hasNext()) {
-        buf.append("\n" + iter.next());
-      }
-      throw new RuntimeException(buf.toString());
-    }
-  }
-
-  /** @apilevel internal */
-  public void $ASTNode.debugRewriteRemove() {
-    java.util.ArrayList key = new java.util.ArrayList(2);
-    key.add(getParent());
-    key.add(Integer.valueOf(getParent().getIndexOfChild(this)));
-    state().debugRewrite.remove(key);
-  }
-$endif
-$if(StagedRewrites)
-  /** @apilevel internal */
-  public int $ASTNode.is$$Final = 0;
-
-  /** @apilevel internal */
-  public boolean $ASTNode.is$$Final() {
-    return is$$Final >= state().rewritePhase;
-  }
-
-  /** @apilevel internal */
-  public void $ASTNode.is$$Final(int phase) {
-    is$$Final = phase;
-  }
-
-  /** @apilevel internal */
-  public void $ASTNode.enterRewritePhase(int phase) {
-    state().rewritePhase = phase;
-  }
-
-  /** @apilevel internal */
-  public boolean $ASTNode.inRewritePhase(int phase) {
-    return state().rewritePhase >= phase;
-  }
-$else
   /** @apilevel internal */
   public boolean $ASTNode.is$$Final = false;
 
@@ -188,7 +136,6 @@ $else
   public void $ASTNode.is$$Final(boolean b) {
     is$$Final = b;
   }
-$endif
 $endif
 
   /**
@@ -231,6 +178,7 @@ $endif
   $include(ASTNode.nodeToStringMethod)
 ]]
 
+# Adds debug checks for tree construction.
 ASTNode.debugDecls [[
 $if(DebugMode)
   /** @apilevel internal */
@@ -244,8 +192,8 @@ $if(DebugMode)
       throw new RuntimeException("Trying to assign null to a tree child node");
     }
 
-    while(node != null && !node.debugNodeAttachmentIsRoot()) {
-$if(RewriteEnabled)
+    while (node != null && !node.debugNodeAttachmentIsRoot()) {
+$if(LegacyRewrite)
       if (node.in$$Circle())
         return;
 $endif
@@ -269,11 +217,6 @@ ASTNode.setParent [[
     $SynchBegin
     $include(ASTNode.incHookSetParent)
     parent = node;
-$if(RewriteCircularNTA)
-    if (state().inCircle()) {
-      flushTreeCache();
-    }
-$endif
     $SynchEnd
   }
 ]]
@@ -282,12 +225,10 @@ ASTNode.getParent [[
   /** @apilevel low-level */
   public $ASTNode $ASTNode.getParent() {
     $SynchBegin
-$if(RewriteEnabled)
-$if(!RewriteCircularNTA)
+$if(LegacyRewrite)
     if (parent != null && (($ASTNode) parent).is$$Final() != is$$Final()) {
       state().boundariesCrossed++;
     }
-$endif
 $endif
     $include(ASTNode.incHookGetParent)
     return ($ASTNode) parent;
@@ -436,14 +377,16 @@ ASTNode.removeChild [[
 ASTNode.getChild [[
   /** @apilevel low-level */
   public T $ASTNode.getChild(int i) {
-
 $if(RewriteEnabled)
  $if(RewriteCircularNTA)
     $ASTNode node = this.getChildNoTransform(i);
-    if (node.mayHaveRewrite()) {
-      node = rewritten(i);
+    if (node != null && node.mayHaveRewrite()) {
+      $ASTNode rewritten = node.rewrittenNode();
+      if (rewritten != node) {
+        rewritten.setParent(this);
+        node = rewritten;
+      }
     }
-    node.is$$Final(true);
     return (T) node;
  $else
     $SynchBegin
@@ -457,18 +400,13 @@ $if(RewriteEnabled)
       return (T) node;
     }
     if (!node.mayHaveRewrite()) {
-  $if(StagedRewrites)
-      node.is$$Final(this.is$$Final);
-  $else
       node.is$$Final(this.is$$Final());
-  $endif
       $include(ASTNode.incHookGetChild4)
       $include(ASTNode.incHookGetChild12)
       return (T) node;
     }
     if (!node.in$$Circle()) {
       $include(ASTNode.traceRewriteEnterCase1)
-      $include(ASTNode.flushHookRewriteEnterCircle)
       $include(ASTNode.incHookGetChild1)
       int rewriteState;
       int _boundaries = state().boundariesCrossed;
@@ -490,15 +428,8 @@ $if(RewriteEnabled)
         $include(ASTNode.incHookGetChild6)
       } while(rewriteState == $StateClass.REWRITE_CHANGE);
       if (rewriteState == $StateClass.REWRITE_NOCHANGE && this.is$$Final()) {
-  $if(StagedRewrites)
-        node.is$$Final(state().rewritePhase);
-  $else
         node.is$$Final(true);
-  $endif
         state().boundariesCrossed = _boundaries;
-  $if(HasRewriteLimit)
-        node.debugRewriteRemove();
-  $endif
         $include(ASTNode.traceRewriteCached)
       } else {
         $include(ASTNode.traceRewriteCacheAbort)
@@ -517,12 +448,10 @@ $if(RewriteEnabled)
     $SynchEnd
  $endif
 $else
-    // No rewrites
     $ASTNode child = getChildNoTransform(i);
     $include(ASTNode.incHookGetChildNT)
     return (T) child;
 $endif
-
   }
 ]]
 
diff --git a/src/template/ast/Attributes.tt b/src/template/ast/Attributes.tt
index ee25d56d662335bb4c209fcfbe8d9657c6ce885c..6957419facd5c9ab46467ec4c095e62c839c4b5e 100644
--- a/src/template/ast/Attributes.tt
+++ b/src/template/ast/Attributes.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2015, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-AttrDecl.returnStmt = [[
+AttrDecl.returnStmt [[
 $if(#isAttrNTA)
 #(getType) node = (#boxedType) this.getChild(#(signature)ChildPosition());
 $include(AttrDecl.incHookAttrCompEnd)
@@ -38,7 +38,7 @@ return #(signature)_value;
 $endif
 ]]
 
-AttrDecl.cacheDeclarations = [[
+AttrDecl.cacheDeclarations [[
 $if(!#isParameterized)
   /** @apilevel internal */
   protected boolean #(signature)_computed = false;
@@ -64,22 +64,21 @@ $endif
 $endif
 ]]
 
-# attribute declarations
-AttrDecl.synDecl = AttrDecl.inhDecl = [[
+AttrDecl.synDecl = AttrDecl.inhDecl [[
 #docComment
   #annotations
   $include(AttrDecl.generatedAnnotations)
   public #getType #name(#parametersDecl);
 ]]
 
-AttrDecl.abstractSynDecl = [[
+AttrDecl.abstractSynDecl [[
 #docComment
   #annotations
   $include(AttrDecl.generatedAnnotations)
   public abstract #getType #name(#parametersDecl);
 ]]
 
-AttrDecl.emitInlineComputeWithTry = [[
+AttrDecl.emitInlineComputeWithTry [[
 #docComment
   #annotations
   $include(AttrDecl.generatedAnnotations)
@@ -104,7 +103,7 @@ AttrDecl.emitInlineComputeWithTry = [[
   }
 ]]
 
-AttrDecl.emitInlineComputeWithoutTry = [[
+AttrDecl.emitInlineComputeWithoutTry [[
 #docComment
   #annotations
   $include(AttrDecl.generatedAnnotations)
@@ -122,7 +121,7 @@ AttrDecl.emitInlineComputeWithoutTry = [[
   }
 ]]
 
-SynEq.emitComputeMethod = [[
+SynEq.emitComputeMethod [[
   /** @apilevel internal */
 $if(#hasComputeBlock)
   private #getType #(name)_compute(#parametersDecl) #computeCode
@@ -142,7 +141,7 @@ $endif
 ]]
 
 AttrDecl.visitedDeclaration [[
-$if(RewriteEnabled)
+$if(LegacyRewrite)
   $if(#isParameterized)
 /** @apilevel internal */
 protected $DefaultMapType #(signature)_visited$if(!LazyMaps) = $CreateDefaultMap$endif;
@@ -163,7 +162,7 @@ $endif
 
 AttrDecl.checkVisited [[
 $if(VisitCheckEnabled)
-  $if(RewriteEnabled)
+  $if(LegacyRewrite)
     $if(#isParameterized)
 if (Integer.valueOf(state().boundariesCrossed).equals(#(signature)_visited.get(_parameters))) {
   $include(AttrDecl.visitedException)
@@ -189,7 +188,7 @@ $endif
 
 AttrDecl.setVisited [[
 $if(VisitCheckEnabled)
-$if(RewriteEnabled)
+$if(LegacyRewrite)
   $if(#isParameterized)
 #(signature)_visited.put(_parameters, Integer.valueOf(state().boundariesCrossed));
   $else
@@ -207,7 +206,7 @@ $endif
 
 AttrDecl.clearVisited [[
 $if(VisitCheckEnabled)
-$if(RewriteEnabled)
+$if(LegacyRewrite)
   $if(#isParameterized)
 #(signature)_visited.remove(_parameters);
   $else
@@ -223,7 +222,7 @@ $endif
 $endif
 ]]
 
-SynDecl.higherOrderAttributeCode:norewrite = [[
+SynDecl.higherOrderAttributeCode:norewrite [[
 $if(#isParameterized)
 if (#(signature)_list == null) {
   #(signature)_list = new $List();
@@ -236,40 +235,28 @@ $else
 $endif
 ]]
 
-SynDecl.higherOrderAttributeCode:nostagedrewrites = [[
+SynDecl.higherOrderAttributeCode:rewritesEnabled [[
 $if(#isParameterized)
 if (#(signature)_list == null) {
   #(signature)_list = new $List();
   $include(AttrDecl.incHookCreateNtaList)
+  $if(LegacyRewrite)
   #(signature)_list.is$$Final = true;
+  $endif
   #(signature)_list.setParent(this);
 }
 #(signature)_list.add(#(signature)_value);
 if (#(signature)_value != null) {
-  #(signature)_value = (#boxedType) #(signature)_list.getChild(#(signature)_list.numChildren-1);
+  #(signature)_value = (#boxedType) #(signature)_list.getChild(#(signature)_list.numChildren - 1);
+  $if(LegacyRewrite)
   #(signature)_value.is$$Final = true;
+  $endif
 }
 $else
 #(signature)_value.setParent(this);
+$if(LegacyRewrite)
 #(signature)_value.is$$Final = true;
 $endif
-]]
-
-SynDecl.higherOrderAttributeCode:stagedrewrites = [[
-$if(#isParameterized)
-if (#(signature)_list == null) {
-  #(signature)_list = new $List();
-  $include(AttrDecl.incHookCreateNtaList)
-  #(signature)_list.is$$Final = java.lang.Integer.MAX_VALUE;
-  #(signature)_list.setParent(this);
-}
-if (#(signature)_value != null) {
-  #(signature)_list.add(#(signature)_value);
-  #(signature)_value.is$$Final = java.lang.Integer.MAX_VALUE;
-}
-$else
-#(signature)_value.setParent(this);
-#(signature)_value.is$$Final = java.lang.Integer.MAX_VALUE;
 $endif
 ]]
 
@@ -300,7 +287,7 @@ AttrDecl.emitEquation [[
   }
 ]]
 
-AttrDecl.cacheCheck = [[
+AttrDecl.cacheCheck [[
 $if(#hasCache)
 $include(AttrDecl.incHookAttrRead)
   $if(!#isParameterized)
@@ -328,20 +315,19 @@ $endif
 # Update the cache value for this attribute if caching is enabled.
 AttrDecl.cacheUpdate [[
 $if(#isLazy)
-  $if(#isParameterized)
+  $if(LegacyRewrite)
 if (#cacheStoreCondition) {
+  $endif
+  $if(#isParameterized)
   $include(AttrDecl.incHookAttrCompBeforeStore)
   #(signature)_values.put(_parameters, #(signature)_value);
   $include(AttrDecl.traceCacheStore)
-} else {
-  $include(AttrDecl.traceCacheAbort)
-  $include(AttrDecl.incHookAttrCompAfterStore)
-}
   $else
-if (#cacheStoreCondition) {
   $include(AttrDecl.incHookAttrCompBeforeStore)
   #(signature)_computed = true;
   $include(AttrDecl.traceCacheStore)
+  $endif
+  $if(LegacyRewrite)
 } else {
   $include(AttrDecl.traceCacheAbort)
   $include(AttrDecl.incHookAttrCompAfterStore)
@@ -351,8 +337,10 @@ $endif
 ]]
 
 AttrDecl.cacheInit [[
-$if(#isLazy)
+$if(LegacyRewrite)
+  $if(#isLazy)
 $include(AttrDecl.cacheInitRewrite)
+  $endif
 $endif
 ]]
 
diff --git a/src/template/ast/Circular.tt b/src/template/ast/Circular.tt
index e51626b118a85a1cabb9048343b42d37f10eced7..1fb3873ac194cb86b54ab42d5e496644a298f427 100644
--- a/src/template/ast/Circular.tt
+++ b/src/template/ast/Circular.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2015, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -56,7 +56,7 @@ $endif
       #(signature)_value = $BottomValue;
 $if(#getNTA)
       if (#(signature)_value != null) {
-        #(signature)_value.setParent(this);
+        #(signature)_value.setParent(#ntaParent);
       }
 $endif
     }
@@ -64,7 +64,9 @@ $endif
       $include(AttrDecl.traceCircularEnterCase1)
       state.enterCircle();
       #tracePrintCycleBeginString
+$if(LegacyRewrite)
       $include(AttrDecl.cacheInitRewrite)
+$endif
       do {
         #(signature)_cycle = state.nextCycle();
         #tracePrintBeginComputingValue
@@ -80,12 +82,13 @@ $endif
         #(signature)_value = new_#(signature)_value;
 $if(#getNTA)
         if (#(signature)_value != null) {
-          #(signature)_value.setParent(this);
+          #(signature)_value.setParent(#ntaParent);
         }
 $endif
         #tracePrintStartingCycle
         #cycleLimitCheck
       } while (state.testAndClearChangeInCycle());
+$if(LegacyRewrite)
       if (#cacheStoreCondition) {
         #(signature)_computed = true;
         $include(AttrDecl.cacheCycleInit)
@@ -97,6 +100,11 @@ $endif
         #(signature)_initialized = false;
         $include(AttrDecl.traceCacheAbort)
       }
+$else
+      #(signature)_computed = true;
+      $include(AttrDecl.cacheCycleInit)
+      $include(AttrDecl.traceCacheStore)
+$endif
       state.leaveCircle();
       $TracePrintReturnNewValue
       #tracePrintCycleEndString
@@ -105,7 +113,9 @@ $endif
       $include(AttrDecl.traceCircularEnterCase2)
       #(signature)_cycle = state.cycle();
       $include(AttrDecl.cacheCycleCheck)
+$if(LegacyRewrite)
       $include(AttrDecl.resetCycleCheck)
+$endif
       #tracePrintBeginComputingValue
       $include(AttrDecl.incHookAttrCompStartCircular)
       $include(AttrDecl.traceComputeBegin)
@@ -119,7 +129,7 @@ $endif
       #(signature)_value = new_#(signature)_value;
 $if(#getNTA)
       if (#(signature)_value != null) {
-        #(signature)_value.setParent(this);
+        #(signature)_value.setParent(#ntaParent);
       }
 $endif
       $TracePrintReturnNewValue
@@ -154,70 +164,50 @@ AttrDecl.circularEquation:parameterized [[
       #(signature)_values.put(_parameters, _value);
       _value.value = $BottomValue;
 $if(#getNTA)
- $if(#isRewriteCircularNtaAttr)
-       if (_value.value != null) {
-         (($ASTNode) _value.value).setParent(this);
-         (($ASTNode) _value.value).childIndex = i;
-       }
- $else
        if (_value.value != null) {
          if (#(signature)_list == null) {
            #(signature)_list = new $List();
-           #(signature)_list.setParent(this);
+           #(signature)_list.setParent(#ntaParent);
          }
          (($ASTNode) _value.value).setParent(#(signature)_list);
       }
- $endif
 $endif
     }
     $StateClass state = state();
     if (!state.inCircle() || state.calledByLazyAttribute()) {
       $include(AttrDecl.traceCircularEnterCase1)
       state.enterCircle();
-$if(#isRewriteCircularNtaAttr)
-      int rewriteState;
-$endif
       #tracePrintCycleBeginString
+$if(LegacyRewrite)
       $include(AttrDecl.cacheInitRewrite)
+$endif
       #getType new_#(signature)_value;
       do {
         _value.cycle = state.nextCycle();
         #tracePrintBeginComputingValue
-$if(#isRewriteCircularNtaAttr)
-        state.push($StateClass.REWRITE_CHANGE);
-$endif
         $include(AttrDecl.incHookAttrCompStartCircular)
         $include(AttrDecl.traceComputeBegin)
         new_#(signature)_value = $CircularComputeRhs;
         $include(AttrDecl.traceComputeEnd)
         $include(AttrDecl.incHookAttrCompEndCircular)
-$if(#isRewriteCircularNtaAttr)
-        rewriteState = state.pop();
-$endif
         if ($ChangeCondition) {
           state.setChangeInCycle();
           $include(AttrDecl.traceCircularCase1Change)
           _value.value = new_#(signature)_value;
 $if(#getNTA)
- $if(#isRewriteCircularNtaAttr)
-          if (_value.value != null) {
-            (($ASTNode) _value.value).setParent(this);
-            (($ASTNode) _value.value).childIndex = i;
-          }
- $else
           if (_value.value != null) {
             if (#(signature)_list == null) {
               #(signature)_list = new $List();
-              #(signature)_list.setParent(this);
+              #(signature)_list.setParent(#ntaParent);
             }
             (($ASTNode) _value.value).setParent(#(signature)_list);
           }
- $endif
 $endif
         }
         #tracePrintStartingCycle
         #cycleLimitCheck
       } while (state.testAndClearChangeInCycle());
+$if(LegacyRewrite)
       if (#cacheStoreCondition) {
         #(signature)_values.put(_parameters, new_#(signature)_value);
         $include(AttrDecl.cacheCycleInit)
@@ -228,6 +218,11 @@ $endif
         #getType $$tmp = $CircularComputeRhs;
         $include(AttrDecl.traceCacheAbort)
       }
+$else
+      #(signature)_values.put(_parameters, new_#(signature)_value);
+      $include(AttrDecl.cacheCycleInit)
+      $include(AttrDecl.traceCacheStore)
+$endif
       state.leaveCircle();
       $TracePrintReturnNewValue
       #tracePrintCycleEndString
@@ -237,38 +232,29 @@ $endif
       _value.cycle = state.cycle();
       $include(AttrDecl.traceCircularEnterCase2)
       #tracePrintBeginComputingValue
-$if(#isRewriteCircularNtaAttr)
-      state.push($StateClass.REWRITE_CHANGE);
-$endif
       $include(AttrDecl.incHookAttrCompStartCircular)
       $include(AttrDecl.traceComputeBegin)
       #getType new_#(signature)_value = $CircularComputeRhs;
       $include(AttrDecl.traceComputeEnd)
       $include(AttrDecl.incHookAttrCompEndCircular)
-$if(#isRewriteCircularNtaAttr)
-      int rewriteState = state.pop();
-$endif
       $include(AttrDecl.cacheCycleCheck)
+$if(LegacyRewrite)
       $include(AttrDecl.resetCycleCheck)
       else if ($ChangeCondition) {
+$else
+      if ($ChangeCondition) {
+$endif
         state.setChangeInCycle();
         $include(AttrDecl.traceCircularCase2Change)
         _value.value = new_#(signature)_value;
 $if(#getNTA)
- $if(#isRewriteCircularNtaAttr)
-        if (_value.value != null) {
-          (($ASTNode) _value.value).setParent(this);
-          (($ASTNode) _value.value).childIndex = i;
-        }
- $else
         if (_value.value != null) {
           if (#(signature)_list == null) {
             #(signature)_list = new $List();
-            #(signature)_list.setParent(this);
+            #(signature)_list.setParent(#ntaParent);
           }
           (($ASTNode) _value.value).setParent(#(signature)_list);
         }
- $endif
 $endif
       }
       $TracePrintReturnNewValue
@@ -286,13 +272,7 @@ $endif
 AttrDecl.cacheCycleInit [[
 $if(CacheCycle)
 state.startLastCycle();
- $if(#isRewriteCircularNtaAttr)
-state.push($StateClass.REWRITE_CHANGE);
- $endif
 #getType $$tmp = $CircularComputeRhs;
- $if(#isRewriteCircularNtaAttr)
-state.pop();
- $endif
 $endif
 ]]
 
@@ -312,6 +292,7 @@ if (state.lastCycle()) {
 $endif
 ]]
 
+# Only used for legacy rewrites.
 AttrDecl.resetCycleCheck [[
 if (state.resetCycle()) {
 $if(#isParameterized)
diff --git a/src/template/ast/CopyNode.tt b/src/template/ast/CopyNode.tt
index fe43aa3424a15430604926ba9bd0231242ef327c..6adad7a0916b3fcb9d671aca516db5d3f80174b2 100644
--- a/src/template/ast/CopyNode.tt
+++ b/src/template/ast/CopyNode.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -25,8 +25,8 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-# generates ASTNode.copy()
-ASTDecl.emitCopyNode = [[
+# Generates the ASTNode.copy() method.
+ASTDecl.emitCopyNode [[
   /** @apilevel internal */
   #annotations
   public #copyReturnType #name.copy() {
@@ -55,8 +55,8 @@ $endif
   }
 ]]
 
-# generates ASTNode.fullCopy()
-ASTDecl.emitFullCopy = [[
+# Generates the ASTNode.fullCopy() method.
+ASTDecl.emitFullCopy [[
   /**
    * Create a deep copy of the AST subtree at this node.
    * The copy is dangling, i.e. has no parent.
@@ -75,7 +75,7 @@ $else
 $endif
 ]]
 
-ASTDecl.emitTreeCopyNoTransform = [[
+ASTDecl.emitTreeCopyNoTransform [[
   /**
    * Create a deep copy of the AST subtree at this node.
    * The copy is dangling, i.e. has no parent.
@@ -110,7 +110,7 @@ $endif
 $endif
 ]]
 
-ASTNode.emitDoFullTraversal = [[
+ASTNode.emitDoFullTraversal [[
   /**
    * Performs a full traversal of the tree using getChild to trigger rewrites
    * @apilevel low-level
@@ -125,7 +125,7 @@ ASTNode.emitDoFullTraversal = [[
   }
 ]]
 
-ASTDecl.emitTreeCopy = [[
+ASTDecl.emitTreeCopy [[
   /**
    * Create a deep copy of the AST subtree at this node.
    * The subtree of this node is traversed to trigger rewrites before copy.
@@ -139,41 +139,56 @@ $if(#hasAbstract)
 $else
   public #copyReturnType #name.treeCopy() {
     $SynchBegin
+  $if(LegacyRewrite)
     doFullTraversal();
     return treeCopyNoTransform();
+  $else
+    #name tree = (#name) copy();
+    if (children != null) {
+      for (int i = 0; i < children.length; ++i) {
+        $SkipNTAs
+        $ASTNode child = ($ASTNode) getChild(i);
+        if (child != null) {
+          child = child.treeCopyNoTransform();
+    $if(IncrementalEnabled)
+          tree.children[i] = child;
+          child.parent = tree;
+    $else
+          tree.setChild(child, i);
+    $endif
+        }
+      }
+    }
+    return tree;
+  $endif
     $SynchEnd
   }
 $endif
 ]]
 
+# Generates the ASTNode.clone() method.
 #
-# ASTNode.clone()
-#
-# NOTE: We should not invoke node.flushCache() since this methods can invoke
-#       flushRewriteCache(), which should not be called during cloning.
+# NOTE: We should not invoke node.flushCache() since this methods can
+#       flush CNTA rewrites, which should not be called during cloning.
 #       This is tested in the test case flush/flushRewriteAndTreeCopy01.
-ASTDecl.emitCloneNode = [[
+ASTDecl.emitCloneNode [[
   /** @apilevel internal */
   #annotations
   public #copyReturnType #name.clone() throws CloneNotSupportedException {
     $SynchBegin
     #name node = (#name) super.clone();
-    $if(#isASTNodeDecl)
-$if(RewriteEnabled)
+$if(#isASTNodeDecl)
+  $if(LegacyRewrite)
     if (node.is$$Final()) {
       node.flushAttrAndCollectionCache();
     }
     node.in$$Circle(false);
     // flush rewrites
-  $if(StagedRewrites)
-    node.is$$Final(0);
-  $else
     node.is$$Final(false);
-  $endif
-$else
+  $else
     node.flushAttrAndCollectionCache();
+  $endif
 $endif
-    $endif
     return node;
     $SynchEnd
   }
diff --git a/src/template/ast/InheritedAttributes.tt b/src/template/ast/InheritedAttributes.tt
index be51a61d6c5fb3e5d861e1f2317cbc3a0ff8d712..fe9ebb7ec736f09582ec8f9439b706e45533b092 100644
--- a/src/template/ast/InheritedAttributes.tt
+++ b/src/template/ast/InheritedAttributes.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -71,66 +71,33 @@ InhDecl.canDefineMethod [[
   }
 ]]
 
-# list child equation clause
+# List child equation clause.
 InhEq.emitListClause [[
-$if(RewriteCircularNTA)
-if (_callerNode == get#(childName)ListNoTransform() ||
-  (rewritten_int_values != null &&
-    rewritten_int_values.get(Integer.valueOf(get#(childName)ListChildPosition())) != null &&
-    ((_callerNode == rewritten_int_values.get(Integer.valueOf(get#(childName)ListChildPosition()))) ||
-      (rewritten_int_values.get(Integer.valueOf(get#(childName)ListChildPosition())) instanceof $StateClass.CircularValue &&
-      _callerNode == (($StateClass.CircularValue)rewritten_int_values.get(Integer.valueOf(get#(childName)ListChildPosition()))).value)))) {
-  // #declaredat
-  int $ChildIndexVar = _callerNode.getIndexOfChild(_childNode);
-  $EvalStmt
-}
-$else
 if (_callerNode == get#(childName)ListNoTransform()) {
   // #declaredat
   int $ChildIndexVar = _callerNode.getIndexOfChild(_childNode);
   $EvalStmt
 }
-$endif
 ]]
 
-# optional child equation clause
+# Optional child equation clause.
 InhEq.emitOptClause [[
-$if(RewriteCircularNTA)
-if (_callerNode == get#(childName)OptNoTransform()
-    || (rewritten_int_values != null
-      && rewritten_int_values.get(Integer.valueOf(get#(childName)OptChildPosition())) != null
-      && ((_callerNode == rewritten_int_values.get(Integer.valueOf(get#(childName)OptChildPosition())))
-        || (rewritten_int_values.get(Integer.valueOf(get#(childName)OptChildPosition())) instanceof $StateClass.CircularValue
-          && _callerNode == (($StateClass.CircularValue)rewritten_int_values.get(Integer.valueOf(get#(childName)OptChildPosition()))).value)))) {
-  // #declaredat
-  $EvalStmt
-}
-$else
 if (_callerNode == get#(childName)OptNoTransform()) {
   // #declaredat
   $EvalStmt
 }
-$endif
 ]]
 
-# regular child equation clause
+# Regular child equation clause.
 InhEq.emitChildClause [[
-$if(RewriteCircularNTA)
-if (_callerNode == get#(childName)NoTransform()
-    || (rewritten_int_values != null
-    && rewritten_int_values.get(Integer.valueOf(get#(childName)ChildPosition())) != null
-    && ((_callerNode == rewritten_int_values.get(Integer.valueOf(get#(childName)ChildPosition())))
-      || (rewritten_int_values.get(Integer.valueOf(get#(childName)ChildPosition())) instanceof $StateClass.CircularValue
-        && _callerNode == (($StateClass.CircularValue)rewritten_int_values.get(Integer.valueOf(get#(childName)ChildPosition()))).value)))) {
-  // #declaredat
-  $EvalStmt
-}
-$else
+$if(LegacyRewrite)
 if (_callerNode == get#(childName)NoTransform()) {
+$else
+if (_callerNode == get#(childName)()) {
+$endif
   // #declaredat
   $EvalStmt
 }
-$endif
 ]]
 
 # getChild equation clause
diff --git a/src/template/ast/List.tt b/src/template/ast/List.tt
index b253a75714e8ed3a4559e8b1fb5ee469f8efe97d..c4adae5ff531c11b65701ae9e440b4bd05312fba 100644
--- a/src/template/ast/List.tt
+++ b/src/template/ast/List.tt
@@ -30,10 +30,6 @@
 
 List.implicitAspectDecls [[
 
-$if(#needsListTouched)
-  private boolean $List.list$$touched = true;
-$endif
-
   public $List<T> $List.add(T node) {
     $SynchBegin
 $if(DebugMode)
@@ -70,18 +66,12 @@ $endif
 
   public void $List.insertChild($ASTNode node, int i) {
     $SynchBegin
-$if(#needsListTouched)
-    list$$touched = true;
-$endif
     super.insertChild(node, i);
     $SynchEnd
   }
 
   public void $List.addChild(T node) {
     $SynchBegin
-$if(#needsListTouched)
-    list$$touched = true;
-$endif
     super.addChild(node);
     $SynchEnd
   }
@@ -89,23 +79,12 @@ $endif
   /** @apilevel low-level */
   public void $List.removeChild(int i) {
     $SynchBegin
-$if(#needsListTouched)
-    list$$touched = true;
-$endif
     super.removeChild(i);
     $SynchEnd
   }
 
   public int $List.getNumChild() {
     $SynchBegin
-$if(#needsListTouched)
-    if (list$$touched) {
-      for (int i = 0; i < getNumChildNoTransform(); i++) {
-        getChild(i);
-      }
-      list$$touched = false;
-    }
-$endif
     return getNumChildNoTransform();
     $SynchEnd
   }
diff --git a/src/template/ast/Rewrites.tt b/src/template/ast/Rewrites.tt
index b0c8f092f677bfcab49a15785c7b7e5b6110eed0..1ec844a86d55b53db68101c7cc2fd6e4e76517f2 100644
--- a/src/template/ast/Rewrites.tt
+++ b/src/template/ast/Rewrites.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -25,46 +25,53 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-ASTDecl.emitRewrites.begin = [[
+ASTDecl.rewriteTo:begin [[
   /** @apilevel internal */
   public $ASTNode rewriteTo() {
 ]]
 
-ASTDecl.emitRewrites.touch_list = [[
-    if (list$$touched) {
-      for(int i = 0 ; i < getNumChildNoTransform(); i++) {
-        getChild(i);
-      }
-      list$$touched = false;
-$if(RewriteCircularNTA)
-      if (state().changeInCycle()) {
-        return this;
-      }
-$else
-      return this;
-$endif
-    }
-]]
-
-ASTDecl.emitRewrites.end:ASTNode = [[
+ASTDecl.rewriteTo:end:ASTNode [[
+$if(LegacyRewrite)
     if (state().peek() == $StateClass.REWRITE_CHANGE) {
       state().pop();
       state().push($StateClass.REWRITE_NOCHANGE);
     }
+$endif
     return this;
   }
 ]]
 
-ASTDecl.emitRewrites.end:!unconditional = [[
+ASTDecl.rewriteTo:end:conditional [[
     return super.rewriteTo();
   }
 ]]
 
-ASTDecl.emitRewrites.end = [[
+ASTDecl.rewriteTo:end:unconditional [[
   }
 ]]
 
-Rewrite.genRewrite.declaredat = [[
+ASTDecl.canRewrite:begin [[
+  /** @apilevel internal */
+  public boolean canRewrite() {
+]]
+
+ASTDecl.canRewrite:end [[
+    return false;
+  }
+]]
+
+ASTDecl.canRewrite:end:unconditional [[
+    return true;
+  }
+]]
+
+Rewrite.condition [[
+    if ($Condition) {
+      return true;
+    }
+]]
+
+Rewrite.declaredat [[
     // Declared at #sourceLocation
 ]]
 
@@ -78,31 +85,8 @@ Rewrite.genRewrite:unconditional [[
     return rewriteRule$RewriteIndex();
 ]]
 
-RewriteList.genRewrite [[
-    if (getParent().getParent() instanceof #getParentName &&
-        ((#getParentName)getParent().getParent()).#(getChildName)ListNoTransform() == getParent()$Condition) {
-      $List list = ($List) getParent();
-      int i = list.getIndexOfChild(this);
-      $List newList = rewrite#(getParentName)_#getChildName();
-      // The first child is set by the normal rewrite loop.
-      for(int j = 1; j < newList.getNumChildNoTransform(); j++) {
-        list.insertChild(newList.getChildNoTransform(j), ++i);
-      }
-      return newList.getChildNoTransform(0);
-    }
-]]
-
 Rewrite.javaDoc:internal [[
   /**
    * #declaredat
    * @apilevel internal
    */]]
-
-ASTNode.rewrittenAttr = [[
-$if(RewriteCircularNTA)
-syn nta $ASTNode $ASTNode.rewritten(int i)
-    circular [getChildNoTransform(i).treeCopyNoTransform()] =
-  rewritten(i).rewriteTo();
-
-$endif
-]]
diff --git a/src/template/ast/State.tt b/src/template/ast/State.tt
index d1528a9904113d386032455eefe449d30696170e..6cd3d553a0289caf8117225df4cf7e40082d7c3a 100644
--- a/src/template/ast/State.tt
+++ b/src/template/ast/State.tt
@@ -50,7 +50,9 @@ public class $StateClass {
   protected static class CircleState {
     final CircleState next;
     boolean inCircle = false;
+$if(LegacyRewrite)
     boolean resetCycle = false;
+$endif
     boolean change = false;
 
     /** Evaluation depth of lazy attributes. */
@@ -175,6 +177,7 @@ $if(CacheCycle)
   }
 $endif
 
+$if(LegacyRewrite)
   /** @apilevel internal */
   protected void startResetCycle() {
     circle.resetCycle = true;
@@ -185,21 +188,17 @@ $endif
     return circle.resetCycle;
   }
 
+$endif
   protected $StateClass() {
 $if(ComponentCheck)
     circle.completed = true;
 $endif
-$if(RewriteEnabled)
+$if(LegacyRewrite)
     stack = new int[64];
     pos = 0;
 $endif
   }
-$if(RewriteEnabled)
-  $if(HasRewriteLimit)
-  /** @apilevel internal */
-  public $DefaultMapType debugRewrite = $CreateDefaultMap;
-
-  $endif
+$if(LegacyRewrite)
   /** @apilevel internal */
   public static final int REWRITE_CHANGE = 1;
 
@@ -217,8 +216,9 @@ $if(RewriteEnabled)
   private int pos;
 
   private void ensureSize(int size) {
-    if (size < stack.length)
+    if (size < stack.length) {
       return;
+    }
     int[] newStack = new int[stack.length * 2];
     System.arraycopy(stack, 0, newStack, 0, stack.length);
     stack = newStack;
@@ -234,11 +234,8 @@ $if(RewriteEnabled)
   }
 
   public int peek() {
-    return stack[pos-1];
+    return stack[pos - 1];
   }
-  $if(StagedRewrites)
-  public int rewritePhase = 1;
-  $endif
 $endif
   $include(State.incHook)
 
@@ -255,20 +252,14 @@ $endif
 }
 ]]
 
-ASTNode$State.reset = [[
+ASTNode$State.reset [[
   /** @apilevel internal */
   public void $StateClass.reset() {
     $SynchBegin
     // Reset circular evaluation state.
     circle = CIRCLE_BOTTOM;
-$if(RewriteEnabled)
+$if(LegacyRewrite)
     boundariesCrossed = 0;
-  $if(HasRewriteLimit)
-    debugRewrite = $CreateDefaultMap;
-  $endif
-  $if(StagedRewrites)
-    rewritePhase = 1;
-  $endif
 $endif
     $SynchEnd
   }
diff --git a/src/template/ast/components/AggregateComponent.tt b/src/template/ast/components/AggregateComponent.tt
index 597161d4078d95aabf821eb27485ef9f0ffe0ae0..8c3d8eb9b5f9ef6a4d26d794019ec3d7d756acfa 100644
--- a/src/template/ast/components/AggregateComponent.tt
+++ b/src/template/ast/components/AggregateComponent.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-AggregateComponent = [[
+AggregateComponent [[
 $if(!#isNTA)
   /**
    * Replaces the $Name child.
@@ -74,16 +74,6 @@ $if(#isNTA)
     return $Index;
   }
 $else
-  $if(RewriteCircularNTA)
-  /**
-   * Retrieves the child position of the optional child $Name.
-   * @return The the child position of the optional child $Name.
-   * @apilevel low-level
-   */
-  protected int $Host.get$(Name)ChildPosition() {
-    return $Index;
-  }
-  $endif
   /**
    * Retrieves the $Name child.
    * @return The current node used as the $Name child.
diff --git a/src/template/ast/components/ListComponent.tt b/src/template/ast/components/ListComponent.tt
index d2d97930d94635ada32dc8f95f4adc9b2dc778bd..4c2d0a77e043376019cc7b2119fbc14302b2a9d2 100644
--- a/src/template/ast/components/ListComponent.tt
+++ b/src/template/ast/components/ListComponent.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
 
 # List component boilerplate code for accessing children etc.
 
-ListComponent = [[
+ListComponent [[
 $if(!#isNTA)
   /**
    * Replaces the $Name list.
@@ -159,17 +159,6 @@ $if(#isNTA)
   }
 $else
 
-$if(RewriteCircularNTA)
-  /**
-   * Retrieves the child position of the $Name list.
-   * @return The the child position of the $Name list.
-   * @apilevel low-level
-   */
-  protected int $Host.get$(Name)ListChildPosition() {
-    return $Index;
-  }
-$endif
-
   /**
    * Retrieves the $Name list.
    * @return The node representing the $Name list.
diff --git a/src/template/ast/components/OptionalComponent.tt b/src/template/ast/components/OptionalComponent.tt
index 1e03444f14abbdb63a1f76fa5ef71550ec32758b..af87a26876ed1030c087ba5beca67c5a6987fbcf 100644
--- a/src/template/ast/components/OptionalComponent.tt
+++ b/src/template/ast/components/OptionalComponent.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-OptionalComponent = [[
+OptionalComponent [[
 $if(!#isNTA)
   /**
    * Replaces the optional node for the $Name child. This is the <code>Opt</code>
@@ -114,17 +114,6 @@ $if(#isNTA)
   }
 $else
 
-$if(RewriteCircularNTA)
-  /**
-   * Retrieves the child position of the optional child $Name.
-   * @return The the child position of the optional child $Name.
-   * @apilevel low-level
-   */
-  protected int $Host.get$(Name)OptChildPosition() {
-    return $Index;
-  }
-$endif
-
   /**
    * Retrieves the optional node for the $Name child. This is the <code>Opt</code> node containing the child $Name, not the actual child!
    * @return The optional node for child the $Name child.
diff --git a/src/template/flush/Flush.tt b/src/template/flush/Flush.tt
index 539991e1dbfd5a43b906285d2fe83d190a19ed4e..c438ebc801a8e13634eb5eb3f66987c3ec337efa 100644
--- a/src/template/flush/Flush.tt
+++ b/src/template/flush/Flush.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -25,26 +25,23 @@
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-ASTNode.flushTreeCacheMethod = [[
+ASTNode.flushTreeCacheMethod [[
 $if(FlushEnabled)
 $if(#isASTNodeDecl)
   /** @apilevel low-level */
   public void $ASTNode.flushTreeCache() {
     $SynchBegin
     flushCache();
-    if (children == null) {
-      return;
-    }
-    for (int i = 0; i < children.length; i++) {
-      $if(RewriteEnabled)
-      if (children[i] != null && (($ASTNode)children[i]).is$$Final) {
-        (($ASTNode)children[i]).flushTreeCache();
-      }
-      $else
-      if (children[i] != null) {
-        (($ASTNode)children[i]).flushTreeCache();
+    if (children != null) {
+      for (int i = 0; i < children.length; i++) {
+  $if(LegacyRewrite)
+        if (children[i] != null && (($ASTNode) children[i]).is$$Final) {
+  $else
+        if (children[i] != null) {
+  $endif
+          (($ASTNode) children[i]).flushTreeCache();
+        }
       }
-      $endif
     }
     $SynchEnd
   }
@@ -52,15 +49,12 @@ $endif
 $endif
 ]]
 
-ASTDecl.flushCacheMethod = [[
+ASTDecl.flushCacheMethod [[
 $if(FlushEnabled)
 $if(#isASTNodeDecl)
   /** @apilevel low-level */
   public void #name.flushCache() {
     $SynchBegin
-    $if(FlushRewrite)
-    flushRewriteCache();
-    $endif
     flushAttrAndCollectionCache();
     $SynchEnd
   }
@@ -69,7 +63,7 @@ $endif
 ]]
 
 
-ASTDecl.flushAttrAndCollectionCacheMethod = [[
+ASTDecl.flushAttrAndCollectionCacheMethod [[
 $if(FlushEnabled)
 $if(#isASTNodeDecl)
   /** @apilevel internal */
@@ -87,7 +81,7 @@ $endif
 $endif
 ]]
 
-ASTDecl.flushAttrCacheMethod = [[
+ASTDecl.flushAttrCacheMethod [[
 $if(FlushAttr)
   /** @apilevel internal */
   public void #name.flushAttrCache() {
@@ -99,7 +93,7 @@ $if(FlushAttr)
 $endif
 ]]
 
-ASTDecl.flushCollectionCacheMethod = [[
+ASTDecl.flushCollectionCacheMethod [[
 $if(FlushColl)
   /** @apilevel internal */
   public void #name.flushCollectionCache() {
@@ -112,7 +106,7 @@ $endif
 ]]
 
 # TODO: Figure out if this can be removed
-TokenComponent.flushNTACache = [[
+TokenComponent.flushNTACache [[
 $if(FlushAttr)
 if (((Object)token$(TypeSign)_$Id) instanceof $ASTNode) {
   token$(TypeSign)_$Id = null;
@@ -120,7 +114,7 @@ if (((Object)token$(TypeSign)_$Id) instanceof $ASTNode) {
 $endif
 ]]
 
-AttrDecl.resetMethod = [[
+AttrDecl.resetMethod [[
 $if(FlushAttr)
   /** @apilevel internal */
   private void #(signature)_reset() {
@@ -131,7 +125,7 @@ $if(FlushAttr)
 $endif
 ]]
 
-AttrDecl.resetAttrCache = [[
+AttrDecl.resetAttrCache [[
 $if(#isLazy)
   $if(#isParameterized)
     $if(LazyMaps)
@@ -154,14 +148,14 @@ $if(#isLazy)
 $endif
 ]]
 
-AttrDecl.resetAttrVisit = [[
+AttrDecl.resetAttrVisit [[
 $if(#isCircular)
  $if(!#isParameterized)
 #(signature)_cycle = null;
  $endif
 $else
  $if(VisitCheckEnabled)
-  $if(RewriteEnabled)
+  $if(LegacyRewrite)
    $if(#isParameterized)
     $if(LazyMaps)
 #(signature)_visited = null;
diff --git a/src/template/flush/FlushHooks.tt b/src/template/flush/FlushHooks.tt
deleted file mode 100644
index a72ccdea3d86c663c294ca2a61e5f0954d0a83f5..0000000000000000000000000000000000000000
--- a/src/template/flush/FlushHooks.tt
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright (c) 2013, The JastAdd Team
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-#     * Redistributions of source code must retain the above copyright notice,
-#       this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in the
-#       documentation and/or other materials provided with the distribution.
-#     * Neither the name of the Lund University nor the names of its
-#       contributors may be used to endorse or promote products derived from
-#       this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-# TODO: Remove after incremental code has been refactored
-# Removing maintenance of initial rewrite values
-# These hooks are not included 
-ASTNode.flushHookSetChildCopyState = [[
-$if(FlushRewrite)
-if (init_children != null) {
-  $ASTNode d[] = new $ASTNode[i << 1];
-  System.arraycopy(init_children, 0, d, 0, init_children.length);
-  init_children = d;
-}
-if (children_computed != null) {
-  boolean[] b = new boolean[i << 1];
-  System.arraycopy(children_computed, 0, b, 0, children_computed.length);
-  children_computed = b;
-}
-$endif
-]]
-ASTNode.flushHookSetChildInitState = [[
-$if(FlushRewrite)
-if (children_computed != null) {
-  children_computed[i] = false;
-}
-$endif
-]]
-ASTNode.flushHookInsertChildUpdateState = [[
-$if(FlushRewrite)
-if (init_children != null) {
-  $ASTNode d[] = new $ASTNode[init_children.length + 1];
-  System.arraycopy(init_children, 0, d, 0, init_children.length);
-  if (i < init_children.length) {
-    System.arraycopy(init_children, i, d, i+1, init_children.length - i);
-  }
-  init_children = d;
-}
-if (children_computed != null) {
-  boolean b[] = new boolean[children_computed.length + 1];
-  System.arraycopy(children_computed, 0, b, 0, children_computed.length);
-  if (i < children_computed.length) {
-    System.arraycopy(children_computed, i, b, i+1, children_computed.length - i);
-  }
-  children_computed = b;
-}
-$endif
-]]
-ASTNode.flushHookRemoveChild = [[
-$if(FlushRewrite)
-if (init_children != null) {
-  System.arraycopy(init_children, i+1, init_children, i, init_children.length-i-1);
-}
-if (children_computed != null) {
-  System.arraycopy(children_computed, i+1, children_computed, i, children_computed.length-i-1);
-}
-$endif
-]]
-
-
-# Stores initial value for outermost rewrites on entry to evaluation case 1
-ASTNode.flushHookRewriteEnterCircle = [[
-$if(FlushRewrite)
-if (!node.getChild_hasEnclosingInitValue()) {
-  if(this.init_children == null) {
-    this.init_children = new $ASTNode[this.children.length];
-    this.children_computed = new boolean[this.children.length];
-  }
-  this.init_children[i] = node.treeCopyNoTransform();
-  this.children_computed[i] = true;
-  $include(ASTNode.traceFlushRewriteInit)
-}
-$endif
-]]
diff --git a/src/template/flush/FlushRewrite.tt b/src/template/flush/FlushRewrite.tt
deleted file mode 100644
index 49c21005229104fc0ca46796fec266ddd172336b..0000000000000000000000000000000000000000
--- a/src/template/flush/FlushRewrite.tt
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright (c) 2013, The JastAdd Team
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-#     * Redistributions of source code must retain the above copyright notice,
-#       this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in the
-#       documentation and/or other materials provided with the distribution.
-#     * Neither the name of the Lund University nor the names of its
-#       contributors may be used to endorse or promote products derived from
-#       this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-# Method flushing rewrites in a node
-ASTDecl.flushRewriteCacheMethod = [[
-$if(RewriteEnabled)
-  /** @apilevel internal */
-  public void #name.flushRewriteCache() {
-    $SynchBegin
-$if(#isASTNodeDecl)
- $if(FlushRewrite)
-    for (int i = 0; i < getNumChildNoTransform(); i++) {
-      if (children_computed != null && children_computed[i]) {
-        $include(ASTNode.traceFlushRewrite)
-        if (init_children[i] != null) {
-          setChild(init_children[i], i);
-          init_children[i] = null;
-        }
-        children_computed[i] = false;
-      }
-    }
- $else
-    in$$Circle(false);
-  $if(!#isRootNode)
-   $if(StagedRewrites)
-    is$$Final(0);
-   $else
-    is$$Final(false);
-   $endif
-  $endif
- $endif
-$else
-    super.flushRewriteCache();
-$endif
-    $SynchEnd
-  }
-$endif
-]]
-
-# State variables needed to handle flushing of rewrites
-# TODO: These should be protected, but are public now for debugging
-ASTNode.getChild_initValue = [[
-$if(RewriteEnabled)
-$if(FlushRewrite)
-$if(#isASTNodeDecl)
-  /** @apilevel internal */
-  public $ASTNode[] $ASTNode.init_children;
-
-  /** @apilevel internal */
-  public boolean[] $ASTNode.children_computed;
-$endif
-$endif
-$endif
-]]
-
-# Method needed for to handler flushing of rewrites.
-# Checks whether there is an enclosing rewritten node.
-ASTNode.getChild_hasEnclosingInitValueMethod = [[
-$if(RewriteEnabled)
-$if(FlushRewrite)
-$if(#isASTNodeDecl)
-  /** @apilevel internal */
-  protected boolean $ASTNode.getChild_hasEnclosingInitValue() {
-    $ASTNode child = this;
-    $ASTNode parent = this.parent;
-    while (parent != null) {
-      if (parent.mayHaveRewrite()) {
-        return true;
-      }
-      child = parent;
-      parent = parent.parent;
-    }
-    return false;
-  }
-$endif
-$endif
-$endif
-]]
diff --git a/src/template/incremental/ASTChange.tt b/src/template/incremental/ASTChange.tt
index 4af419c89758bc8c5721ae10ef0c8df7d5a89601..22f8d49d49d00ab5f267a9e08c05dae28d70f2a0 100644
--- a/src/template/incremental/ASTChange.tt
+++ b/src/template/incremental/ASTChange.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -160,10 +160,6 @@ $endif
 ASTNode.incHookSetChild3 = [[
 $if(IncrementalEnabled)
 
-$if(!FlushRewrite)
-$include(ASTNode.flushHookSetChildCopyState)
-$endif
-
 $if(IncrementalLevelParam)
 if (getChild_handler != null) {
   $DDGNodeName h[] = new $DDGNodeName[i << 1];
@@ -189,12 +185,6 @@ $endif
 ASTNode.incHookSetChild5 = [[
 $if(IncrementalEnabled)
 
-$if(!FlushRewrite)
-if (children_computed != null) {
-  children_computed[i] = false;
-}
-$endif
-
 $endif
 ]]
 
@@ -272,10 +262,6 @@ $endif
 ASTNode.incHookInsertChild3 = [[
 $if(IncrementalEnabled)
 
-$if(!FlushRewrite)
-$include(ASTNode.flushHookInsertChildUpdateState)
-$endif
-
 $if(IncrementalLevelParam)
 if (getChild_handler != null) {
   $DDGNodeName h[] = new $DDGNodeName[getChild_handler.length + 1];
@@ -365,20 +351,6 @@ $endif
 ASTNode.incHookRemoveChild3 = [[
 $if(IncrementalEnabled)
 
-$if (!FlushRewrite)
-if (init_children != null) {
-  if (i < init_children.length && init_children[i] != null) {
-    init_children[i].inc_throwAway();
-  }
-  System.arraycopy(init_children, i+1, init_children, i, init_children.length-i-1);
-  init_children[init_children.length-1] = null;
-}
-if (children_computed != null) {
-  System.arraycopy(children_computed, i+1, children_computed, i, children_computed.length-i-1);
-  children_computed[children_computed.length-1] = false;
-}
-$endif
-
 $if(IncrementalLevelParam)
 if (getChild_handler != null && this instanceof $List) {
   getChild_handler[numChildren] = null;
diff --git a/src/template/incremental/Tracking.tt b/src/template/incremental/Tracking.tt
index b64dc0f46548e48d0962f19ae50cd479108420f1..1e3a25ebf1a92344d40fba5d6f8f1892d7d0d107 100644
--- a/src/template/incremental/Tracking.tt
+++ b/src/template/incremental/Tracking.tt
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The JastAdd Team
+# Copyright (c) 2013-2016, The JastAdd Team
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,6 @@ $endif
 
 ASTNode.incHookAddChild = [[
 $if(IncrementalEnabled)
-
 $if(IncrementalLevelParam)
 int i = getNumChildNoTransform() - 1;
 if (getChild_handler[i] == null) {
@@ -65,33 +64,41 @@ $else
 $endif
 }
 state().addHandlerDepTo(getChild_handler[i]);
+  $if(LegacyRewrite)
 if (state().IN_ATTR_STORE_EVAL && !node.mayHaveRewrite()) {
   node.is$$Final(is$$Final());
 }
+  $endif
 $endif
 
 $if(IncrementalLevelAttr)
 state().addHandlerDepTo(getChild_handler);
+  $if(LegacyRewrite)
 if (state().IN_ATTR_STORE_EVAL && !node.mayHaveRewrite()) {
   node.is$$Final(is$$Final());
 }
+  $endif
 $endif
 
 $if(IncrementalLevelNode)
 if (node != null) {
   state().addHandlerDepTo(node.handler);
+  $if(LegacyRewrite)
   if (state().IN_ATTR_STORE_EVAL && !node.mayHaveRewrite()) {
     node.is$$Final(is$$Final());
   }
+  $endif
 }
 $endif
 
 $if(IncrementalLevelRegion)
 if (node != null && node.isRegionRoot()) {
   state().addHandlerDepTo(node.handler());
+  $if(LegacyRewrite)
   if (state().IN_ATTR_STORE_EVAL && !node.mayHaveRewrite()) {
     node.is$$Final(is$$Final());
   }
+  $endif
 }
 $endif
 
@@ -115,17 +122,6 @@ $endif
 ASTNode.incHookGetChild1 = [[
 $if(IncrementalEnabled)
 
-$if (!FlushRewrite)
-if(this.init_children == null) {
-  this.init_children = new $ASTNode[this.children.length];
-  this.children_computed = new boolean[this.children.length];
-}
-if(!node.getChild_hasEnclosingInitValue()) {
-  this.init_children[i] = node.fullCopy();
-  this.children_computed[i] = true;
-}
-$endif
-
 $if(IncrementalLevelParam)
 this.state().enterRewriteEval(this.getChild_handler[i]);
 $endif
@@ -154,12 +150,6 @@ $endif
 ASTNode.incHookGetChild3 = [[
 $if(IncrementalEnabled)
 
-$if(!FlushRewrite)
-if (rewriteState == $StateClass.REWRITE_CHANGE) {
-  this.children_computed[i] = true;
-}
-$endif
-
 $endif
 ]]
 
diff --git a/src/template/trace/TraceHooks.tt b/src/template/trace/TraceHooks.tt
index f72012c0cb823adf3cf798d901867ad726d16029..aafbcefc012853d12e8269495d78cd41c317afa0 100644
--- a/src/template/trace/TraceHooks.tt
+++ b/src/template/trace/TraceHooks.tt
@@ -85,7 +85,7 @@ $if (TraceCache)
   $if(#isLazy)
     $if(#isParameterized)
       $if(#isCircular)
-state().trace().cacheRead(this, "#hostClassName.#signatureJavaStyle", _parameters, _o);
+state().trace().cacheRead(this, "#hostClassName.#signatureJavaStyle", _parameters, _cache);
       $else
 state().trace().cacheRead(this, "#hostClassName.#signatureJavaStyle", _parameters, #(signature)_values.get(_parameters));
       $endif
@@ -322,16 +322,3 @@ state().trace().flushAttr(this, "#hostClassName.#signatureJavaStyle", "", #(sign
     $endif
 $endif
 ]]
-
-ASTNode.traceFlushRewrite [[
-$if (TraceRewrite)
-state().trace().flushRewrite(this, "ASTNode.getChild", i, nodeToString(children[i]));
-$endif
-]]
-
-ASTNode.traceFlushRewriteInit [[
-$if (TraceRewrite)
-state().trace().flushRewriteInit(this, "ASTNode.getChild", i, nodeToString(children[i]));
-$endif
-]]
-
diff --git a/src/template/trace/Tracer.tt b/src/template/trace/Tracer.tt
index 4f7512e7a1b24a8e2ef2f9805cf0300d5fef117a..85913441c6b94605aa684ebdafcde1d486563b86 100644
--- a/src/template/trace/Tracer.tt
+++ b/src/template/trace/Tracer.tt
@@ -427,22 +427,6 @@ public static class Trace {
     add($StateClass.Trace.Event.FLUSH_ATTR, node, attr, params, value);
   }
 
-  /**
-   * Trace that a rewrite was flushed.
-   * @param value The value of the attribute.
-   */
-  public void flushRewrite($ASTNode node, String attr, Object params, Object value) {
-    add($StateClass.Trace.Event.FLUSH_REWRITE, node, attr, params, value);
-  }
-
-  /**
-   * Trace that the initial value of an enclosing rewrite was stored for flushing.
-   * @param value The value of the attribute.
-   */
-  public void flushRewriteInit($ASTNode node, String attr, Object params, Object value) {
-    add($StateClass.Trace.Event.FLUSH_REWRITE_INIT, node, attr, params, value);
-  }
-
   /**
    * Process all trace entries given a trace processor
    */