freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [3/3] freemarker git commit: Some ground work to support dialects later. Added classes like Dialect and StaticallyLinkedNamespaceEntry, but these are non-public for now, and just drafts, and aren't actually used by the templates. The final ones will need
Date Sat, 16 Jun 2018 11:42:32 GMT
Some ground work to support dialects later. Added classes like Dialect and StaticallyLinkedNamespaceEntry, but these are non-public for now, and just drafts, and aren't actually used by the templates. The final ones will need more features to be able to replace the trickier built-in directives. Note that some early version (not a public API) of dialects will be needed for FREEMARKER-99, which is why I started this.

Along the way, some internal renaming in the ASTNode related API-s. Most notably visit(...) to execute(...), as we don't use the visitor pattern.


Project: http://git-wip-us.apache.org/repos/asf/freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/freemarker/commit/e8e58ffa
Tree: http://git-wip-us.apache.org/repos/asf/freemarker/tree/e8e58ffa
Diff: http://git-wip-us.apache.org/repos/asf/freemarker/diff/e8e58ffa

Branch: refs/heads/3
Commit: e8e58ffa52937ae4e67d03edb81dd76c84ac9118
Parents: 056635c
Author: ddekany <ddekany@apache.org>
Authored: Wed Apr 18 19:19:08 2018 +0200
Committer: ddekany <ddekany@apache.org>
Committed: Sat Jun 16 13:42:15 2018 +0200

----------------------------------------------------------------------
 README.md                                       |   3 +
 .../org/apache/freemarker/core/ASTPrinter.java  |  10 +-
 .../core/GetOptionalTemplateTest.java           |   2 +-
 .../core/InterpolationSyntaxTest.java           |   2 +
 .../core/MistakenlyPublicImportAPIsTest.java    |   9 +-
 .../core/TemplateCallableModelTest.java         |   2 +-
 .../freemarker/core/TemplateLanguageTest.java   |   5 +-
 .../org/apache/freemarker/core/ASTComment.java  |   8 +-
 .../apache/freemarker/core/ASTDebugBreak.java   |  15 +-
 .../freemarker/core/ASTDirAdhocTest1.java       | 211 +++++++++++++++++++
 .../freemarker/core/ASTDirAdhocTest2.java       | 165 +++++++++++++++
 .../freemarker/core/ASTDirAssignment.java       |   8 +-
 .../core/ASTDirAssignmentsContainer.java        |  10 +-
 .../core/ASTDirAttemptRecoverContainer.java     |  12 +-
 .../apache/freemarker/core/ASTDirAutoEsc.java   |  10 +-
 .../org/apache/freemarker/core/ASTDirBreak.java |   8 +-
 .../core/ASTDirCapturingAssignment.java         |  19 +-
 .../org/apache/freemarker/core/ASTDirCase.java  |   8 +-
 .../apache/freemarker/core/ASTDirCompress.java  |  15 +-
 .../apache/freemarker/core/ASTDirContinue.java  |   8 +-
 .../freemarker/core/ASTDirElseOfList.java       |  10 +-
 .../apache/freemarker/core/ASTDirEscape.java    |  10 +-
 .../apache/freemarker/core/ASTDirFallback.java  |   8 +-
 .../org/apache/freemarker/core/ASTDirFlush.java |   8 +-
 .../core/ASTDirIfElseIfElseContainer.java       |  14 +-
 .../freemarker/core/ASTDirIfOrElseOrElseIf.java |   8 +-
 .../apache/freemarker/core/ASTDirImport.java    |   8 +-
 .../apache/freemarker/core/ASTDirInclude.java   |   8 +-
 .../org/apache/freemarker/core/ASTDirItems.java |  12 +-
 .../org/apache/freemarker/core/ASTDirList.java  |  18 +-
 .../core/ASTDirListElseContainer.java           |  12 +-
 .../freemarker/core/ASTDirMacroOrFunction.java  |  10 +-
 .../apache/freemarker/core/ASTDirNested.java    |   8 +-
 .../apache/freemarker/core/ASTDirNoAutoEsc.java |  10 +-
 .../apache/freemarker/core/ASTDirNoEscape.java  |  12 +-
 .../freemarker/core/ASTDirOutputFormat.java     |  12 +-
 .../apache/freemarker/core/ASTDirRecover.java   |  10 +-
 .../apache/freemarker/core/ASTDirRecurse.java   |   8 +-
 .../apache/freemarker/core/ASTDirReturn.java    |   8 +-
 .../org/apache/freemarker/core/ASTDirSep.java   |  12 +-
 .../apache/freemarker/core/ASTDirSetting.java   |   8 +-
 .../org/apache/freemarker/core/ASTDirStop.java  |   8 +-
 .../apache/freemarker/core/ASTDirSwitch.java    |  22 +-
 .../freemarker/core/ASTDirTOrRtOrLtOrNt.java    |   8 +-
 .../org/apache/freemarker/core/ASTDirVisit.java |   8 +-
 .../apache/freemarker/core/ASTDirective.java    |  63 ++++++
 .../freemarker/core/ASTDynamicTopLevelCall.java |  26 +--
 .../org/apache/freemarker/core/ASTElement.java  | 138 ++++++------
 .../freemarker/core/ASTExpAddOrConcat.java      |   4 +-
 .../org/apache/freemarker/core/ASTExpAnd.java   |   4 +-
 .../freemarker/core/ASTExpArithmetic.java       |   4 +-
 .../freemarker/core/ASTExpBooleanLiteral.java   |   9 +-
 .../apache/freemarker/core/ASTExpBuiltIn.java   |   4 +-
 .../freemarker/core/ASTExpBuiltInVariable.java  |   9 +-
 .../freemarker/core/ASTExpComparison.java       |   4 +-
 .../apache/freemarker/core/ASTExpDefault.java   |   4 +-
 .../org/apache/freemarker/core/ASTExpDot.java   |   6 +-
 .../freemarker/core/ASTExpDynamicKeyName.java   |   4 +-
 .../apache/freemarker/core/ASTExpExists.java    |   6 +-
 .../freemarker/core/ASTExpFunctionCall.java     |   6 +-
 .../freemarker/core/ASTExpHashLiteral.java      |   4 +-
 .../freemarker/core/ASTExpListLiteral.java      |   4 +-
 .../freemarker/core/ASTExpNegateOrPlus.java     |   4 +-
 .../org/apache/freemarker/core/ASTExpNot.java   |   4 +-
 .../freemarker/core/ASTExpNumberLiteral.java    |   4 +-
 .../org/apache/freemarker/core/ASTExpOr.java    |   4 +-
 .../freemarker/core/ASTExpParenthesis.java      |   4 +-
 .../org/apache/freemarker/core/ASTExpRange.java |   6 +-
 .../freemarker/core/ASTExpStringLiteral.java    |   4 +-
 .../apache/freemarker/core/ASTExpVariable.java  |   4 +-
 .../apache/freemarker/core/ASTExpression.java   |  15 +-
 .../freemarker/core/ASTImplicitParent.java      |  15 +-
 .../freemarker/core/ASTInterpolation.java       |  45 ++--
 .../org/apache/freemarker/core/ASTNode.java     |  95 ++++-----
 .../apache/freemarker/core/ASTStaticText.java   |  15 +-
 .../core/BuiltInWithParseTimeParameters.java    |   6 +-
 .../org/apache/freemarker/core/CallPlace.java   |   2 +
 .../apache/freemarker/core/Configuration.java   |  53 ++++-
 .../apache/freemarker/core/DefaultDialect.java  |  82 +++++++
 .../core/DefaultTemplateLanguage.java           |  25 ++-
 .../org/apache/freemarker/core/Dialect.java     | 127 +++++++++++
 .../org/apache/freemarker/core/Environment.java | 161 ++++++++++----
 .../apache/freemarker/core/MessageUtils.java    |  19 ++
 .../freemarker/core/ParsingConfiguration.java   |   5 +-
 .../core/StaticLinkingCheckException.java       |  74 +++++++
 .../core/StaticallyLinkedNamespaceEntry.java    | 117 ++++++++++
 .../org/apache/freemarker/core/Template.java    |   2 +-
 .../freemarker/core/TemplateConfiguration.java  |   9 +-
 .../core/TemplateElementArrayBuilder.java       |  13 --
 .../core/TemplateElementsToVisit.java           |   4 +-
 .../freemarker/core/TemplateLanguage.java       |  35 +--
 ...nterruptionSupportTemplatePostProcessor.java |  10 +-
 .../core/UnparsedTemplateLanguage.java          |   3 +-
 .../core/UnsupportedFM2TemplateLanguage.java    |   2 +-
 .../apache/freemarker/core/_CallableUtils.java  | 147 +++++++------
 .../java/org/apache/freemarker/core/_Debug.java |  25 ++-
 .../core/_ErrorDescriptionBuilder.java          |   6 +-
 .../org/apache/freemarker/core/_EvalUtils.java  |  30 +++
 .../freemarker/core/util/_ArrayAdapterList.java |   2 +-
 .../freemarker/core/util/_ArrayEnumeration.java |  51 -----
 .../freemarker/core/util/_ArrayIterator.java    |   8 +-
 .../core/util/_NullArgumentException.java       |   2 +
 freemarker-core/src/main/javacc/FTL.jj          |   8 +-
 103 files changed, 1691 insertions(+), 645 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 15a5f33..7d34e6d 100644
--- a/README.md
+++ b/README.md
@@ -201,6 +201,9 @@ Last tested Eclipse Oxygen (4.7.0)
   - Fro each project: Project -> Properties -> FindBugs -> [x] Run Automatically
   - There should 0 errors. But sometimes the plugin fails to take the
     @SuppressFBWarnings annotations into account; then use Project -> Clean. 
+- Setting type filters (not required, but convenient): "Window" -> "Preferences" ->
+  "Java" -> "Appearance" -> "Type filter", "Add..." these:
+  `javax.swing.*`, `freemarker.*`, `com.sun.*`
 
 ### IntelliJ IDEA
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core-test/src/test/java/org/apache/freemarker/core/ASTPrinter.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ASTPrinter.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ASTPrinter.java
index 8157c19..297e975 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ASTPrinter.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ASTPrinter.java
@@ -35,7 +35,6 @@ import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.StandardCharsets;
-import java.util.Enumeration;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
@@ -261,7 +260,7 @@ public class ASTPrinter {
     private static void validateAST(ASTElement te) {
         int childCount = te.getChildCount();
         for (int i = 0; i < childCount; i++) {
-            ASTElement child = te.getChild(i);
+            ASTElement child = te.fastGetChild(i);
             ASTElement parentElement = child.getParent();
             // As ASTImplicitParent.accept does nothing but returns its children, it's optimized out in the final
             // AST tree. While it will be present as a child, the parent element also will have children
@@ -321,7 +320,7 @@ public class ASTPrinter {
             ASTNode tObj = (ASTNode) node;
 
             printNodeLineStart(paramRole, ind, out);
-            out.write(tObj.getASTNodeDescriptor());
+            out.write(tObj.getLabelWithoutParameters());
             printNodeLineEnd(node, out, opts);
             
             if (opts.getShowConstantValue() && node instanceof ASTExpression) {
@@ -345,9 +344,8 @@ public class ASTPrinter {
                 printNode(value, ind + INDENTATION, role, opts, out);
             }
             if (tObj instanceof ASTElement) {
-                Enumeration enu = ((ASTElement) tObj).children();
-                while (enu.hasMoreElements()) {
-                    printNode(enu.nextElement(), INDENTATION + ind, null, opts, out);
+                for (ASTElement child : ((ASTElement) tObj).getChildren()) {
+                    printNode(child, INDENTATION + ind, null, opts, out);
                 }
             }
         } else {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java
index 22d6aff..f6c973e 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/GetOptionalTemplateTest.java
@@ -107,7 +107,7 @@ public class GetOptionalTemplateTest extends TemplateTest {
     @Test
     public void testWrongArguments() throws Exception {
         assertErrorContains("<#assign t = .getOptionalTemplate()>", "argument");
-        assertErrorContains("<#assign t = .getOptionalTemplate('1', '2', '3')>", "arguments", "3");
+        assertErrorContains("<#assign t = .getOptionalTemplate('1', '2', '3')>", "1", "arguments", "more");
         assertErrorContains("<#assign t = .getOptionalTemplate(1)>", "1st argument", "string", "number");
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
index 2bf4200..9865c18 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
@@ -33,11 +33,13 @@ public class InterpolationSyntaxTest extends TemplateTest {
 
     /** Non-standard template language */
     private final TemplateLanguage F3ASU = new DefaultTemplateLanguage("dummy",
+            DefaultDialect.INSTANCE,
             UndefinedOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT,
             TagSyntax.ANGLE_BRACKET, InterpolationSyntax.SQUARE_BRACKET); 
 
     /** Non-standard template language */
     private final TemplateLanguage F3SDU = new DefaultTemplateLanguage("dummy",
+            DefaultDialect.INSTANCE,
             UndefinedOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT,
             TagSyntax.SQUARE_BRACKET, InterpolationSyntax.DOLLAR); 
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicImportAPIsTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicImportAPIsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicImportAPIsTest.java
index 5fcee97..be85eeb 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicImportAPIsTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicImportAPIsTest.java
@@ -35,9 +35,12 @@ import org.junit.Test;
 
 /**
  * These are things that users shouldn't do, but we shouldn't break backward compatibility without knowing about it.
+ * 
+ * TODO [FM3] Now we should make this illegal, but I'm not sure how to catch when the user does this.
  */
 public class MistakenlyPublicImportAPIsTest {
 
+    
     @Test
     public void testImportCopying() throws IOException, TemplateException {
         StringTemplateLoader tl = new StringTemplateLoader();
@@ -60,7 +63,7 @@ public class MistakenlyPublicImportAPIsTest {
                 t2.process(null, _NullWriter.INSTANCE);
                 fail();
             } catch (InvalidReferenceException e) {
-                // Apparenly, it has never worked like this...
+                // Apparently, it has never worked like this...
                 assertEquals("i1", e.getBlamedExpressionString());
             }
         }
@@ -72,6 +75,7 @@ public class MistakenlyPublicImportAPIsTest {
         assertThat(i1, instanceOf(Namespace.class));
         TemplateModel i2 = env.getVariable("i2");
         assertThat(i2, instanceOf(Namespace.class));
+        Environment originalEnv = env;
 
         {
             Template t2 = new Template(null, "<@i1.m/>", cfg);
@@ -80,6 +84,7 @@ public class MistakenlyPublicImportAPIsTest {
             env = t2.createProcessingEnvironment(null, sw);
             env.setVariable("i1", i1);
             
+            originalEnv.setOut(sw); // The imported macros are still bound to and will use this.
             env.process();
             assertEquals("1", sw.toString());
         }
@@ -88,10 +93,12 @@ public class MistakenlyPublicImportAPIsTest {
             Template t2 = new Template(null, "<@i2.m/>", cfg);
             
             StringWriter sw = new StringWriter();
+            env.setOut(sw); // In the old Environment instance, to which the imported macros are bound.
             env = t2.createProcessingEnvironment(null, sw);
             env.setVariable("i2", i2);
             
             try {
+                originalEnv.setOut(sw); // The imported macros are still bound to and will use this.
                 env.process();
                 assertEquals("2", sw.toString());
             } catch (NullPointerException e) {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java
index a1e684d..8675d13 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java
@@ -219,7 +219,7 @@ public class TemplateCallableModelTest extends TemplateTest {
     @Test
     @SuppressWarnings("ThrowableNotThrown")
     public void testRuntimeErrors() throws IOException, TemplateException {
-        assertErrorContains("<@p 9, 9, 9 />", "can only have 2", "3", "by position");
+        assertErrorContains("<@p 9, 9, 9 />", "can only have 2", "more", "by position");
         assertErrorContains("<@n 9 />", "can't have arguments passed by position");
         assertErrorContains("<@n n3=9 />", "has no", "\"n3\"", "supported", "\"n1\", \"n2\"");
         assertErrorContains("<@p n1=9 />", "directive", "can't have arguments that are passed by name", "\"n1\"",

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
index 069394b..3bcc382 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
@@ -67,12 +67,13 @@ public class TemplateLanguageTest {
 
         public DummyTemplateLanguage(String fileExtension, OutputFormat outputFormat,
                 AutoEscapingPolicy autoEscapingPolicy) {
-            super(fileExtension, outputFormat, autoEscapingPolicy);
+            super(fileExtension, DefaultDialect.INSTANCE, outputFormat, autoEscapingPolicy);
         }
 
         DummyTemplateLanguage(String fileExtension, boolean allowExtensionStartingWithF, OutputFormat outputFormat,
                 AutoEscapingPolicy autoEscapingPolicy) {
-            super(fileExtension, allowExtensionStartingWithF, outputFormat, autoEscapingPolicy);
+            super(fileExtension, allowExtensionStartingWithF, DefaultDialect.INSTANCE,
+                    outputFormat, autoEscapingPolicy);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java
index 8a16965..2224fa1 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java
@@ -24,6 +24,7 @@ import org.apache.freemarker.core.util._StringUtils;
 /**
  * AST comment node
  */
+//TODO [FM3] will be public
 final class ASTComment extends ASTElement {
 
     private final String text;
@@ -33,13 +34,13 @@ final class ASTComment extends ASTElement {
     }
 
     @Override
-    ASTElement[] accept(Environment env) {
+    ASTElement[] execute(Environment env) {
         // do nothing, skip the body
         return null;
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
             return "<#--" + text + "-->";
         } else {
@@ -48,10 +49,9 @@ final class ASTComment extends ASTElement {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#--...--";
     }
-    
 
     @Override
     int getParameterCount() {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java
index 562a2cb..0634ffc 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java
@@ -27,23 +27,24 @@ import org.apache.freemarker.core.debug._DebuggerService;
  * AST node: A debug breakpoint
  */
 class ASTDebugBreak extends ASTElement {
-    public ASTDebugBreak(ASTElement nestedBlock) {
+    
+    ASTDebugBreak(ASTElement nestedBlock) {
         addChild(nestedBlock);
         copyLocationFrom(nestedBlock);
     }
     
     @Override
-    protected ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    protected ASTElement[] execute(Environment env) throws TemplateException, IOException {
         if (!_DebuggerService.suspendEnvironment(
-                env, getTemplate().getSourceName(), getChild(0).getBeginLine())) {
-            return getChild(0).accept(env);
+                env, getTemplate().getSourceName(), fastGetChild(0).getBeginLine())) {
+            return fastGetChild(0).execute(env);
         } else {
             throw new StopException(env, "Stopped by debugger");
         }
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
             StringBuilder sb = new StringBuilder();
             sb.append("<#-- ");
@@ -52,7 +53,7 @@ class ASTDebugBreak extends ASTElement {
                 sb.append(" /-->");
             } else {
                 sb.append(" -->");
-                sb.append(getChild(0).getCanonicalForm());                
+                sb.append(fastGetChild(0).getCanonicalForm());                
                 sb.append("<#--/ debug break -->");
             }
             return sb.toString();
@@ -62,7 +63,7 @@ class ASTDebugBreak extends ASTElement {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#debugBreak";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest1.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest1.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest1.java
new file mode 100644
index 0000000..69d40ef
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest1.java
@@ -0,0 +1,211 @@
+package org.apache.freemarker.core;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.freemarker.core.model.ArgumentArrayLayout;
+import org.apache.freemarker.core.model.TemplateDirectiveModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.impl.SimpleNumber;
+import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
+import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util.CommonSupplier;
+import org.apache.freemarker.core.util.StringToIndexMap;
+
+/**
+ * Example of an AST directive that's bound to some Configuration setting (the htmlOutputFormat in this case).
+ */
+//TODO [FM3][FREEMARKER-99] Delete this class when we are finished.
+class ASTDirAdhocTest1 extends ASTDirective {
+    private final MarkupOutputFormat<?> htmlOutputFormat;
+    private ASTExpression p1;
+    private ASTExpression p2;
+    private ASTExpression n1;
+    private ASTExpression n2;
+    private StringToIndexMap nestedContentParamNames;
+
+    private ASTDirAdhocTest1(MarkupOutputFormat<?> htmlOutputFormat) {
+        this.htmlOutputFormat = htmlOutputFormat;
+    }
+
+    static class Factory implements CommonSupplier<ASTDirective> {
+        private final MarkupOutputFormat<?> htmlOutputFormat;
+
+        Factory(MarkupOutputFormat<?> htmlOutputFormat) {
+            this.htmlOutputFormat = htmlOutputFormat;
+        }
+
+        @Override
+        public ASTDirective get() {
+            return new ASTDirAdhocTest1(htmlOutputFormat);
+        }
+    }
+    
+    static TemplateDirectiveModel VALUE = new TemplateDirectiveModel() {
+
+        @Override
+        public void execute(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env)
+                throws TemplateException, IOException {
+            throw new UnsupportedOperationException("execute not implemented");
+        }
+
+        @Override
+        public boolean isNestedContentSupported() {
+            return true;
+        }
+
+        @Override
+        public ArgumentArrayLayout getDirectiveArgumentArrayLayout() {
+            return ARGS_LAYOUT;
+        }
+
+    };
+
+    private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create(2, false,
+            StringToIndexMap.of("n1", 2, "n2", 3), false);
+    
+    @Override
+    public void setPositionalArgument(int position, ASTExpression valueExp) throws StaticLinkingCheckException {
+        if (position == 0) {
+            p1 = valueExp;
+        } else if (position == 1) {
+            p2 = valueExp;
+        } else {
+            // TODO: Standardize error message; see CallableUtils 
+            throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
+                  "Too many positional arguments; can only have ",
+                  ARGS_LAYOUT.getPredefinedPositionalArgumentCount(), "."));
+        }
+    }
+
+    @Override
+    public void setNamedArgument(String name, ASTExpression valueExp) throws StaticLinkingCheckException {
+        if (name.equals("n1")) {
+            n1 = valueExp;
+        } else if (name.equals("n2")) {
+            n2 = valueExp;
+        } else {
+            // TODO: Standardize error message; see CallableUtils 
+            throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
+                    "Unsupported parameter name ", new _DelayedJQuote(name), ". The supported parameters are: ",
+                    new _DelayedJQuotedListing(ARGS_LAYOUT.getPredefinedNamedArgumentsMap().getKeys())));
+        }
+    }
+
+    @Override
+    public void checkArgumentsAndSetNestedContentParameters(StringToIndexMap nestedContentParamNames)
+            throws StaticLinkingCheckException {
+        // TODO: Standardize error message; see CallableUtils 
+        if (p1 == null) {
+            throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
+                    "Missing mandatory ", new _DelayedOrdinal(1), " positional argument"));
+        }
+        // TODO: Standardize error message; see CallableUtils 
+        if (n1 == null) {
+            throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
+                    "Missing mandatory named argument, ", new _DelayedJQuote("n1")));
+        }
+        
+        // TODO: Make this check easier? 
+        if (nestedContentParamNames == null || nestedContentParamNames.size() != 1) {
+            throw new StaticLinkingCheckException(
+                    MessageUtils.newBadNumberOfNestedContentParameterPassedMessage(nestedContentParamNames, 1));
+        }
+        this.nestedContentParamNames = nestedContentParamNames;
+    }
+
+    @Override
+    public StringToIndexMap getNestedContentParamNames() {
+        return nestedContentParamNames;
+    }
+    
+    @Override
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
+        env.pushElement(this);
+        try {
+            Writer out = env.getOut();
+            out.write("#foo(");
+            // TODO Bind to cfg.getOutputFormat("HTML")
+            
+            int p1Int = CallableUtils.castArgumentValueToInt(p1.eval(env), 0, false, 0, VALUE, false);
+            
+            env.interpolate(p1, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
+            if (p2 != null) {
+                out.write(", ");
+                env.interpolate(p2, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
+            }
+            out.write(", n1=");
+            env.interpolate(n1, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
+            if (n2 != null) {
+                out.write(", n2=");
+                env.interpolate(n2, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
+            }
+            out.write(") {\n");
+            
+            for (int i = 0; i < p1Int; i++) {
+                env.executeNestedContent(this, nestedContentParamNames, new TemplateModel[] { new SimpleNumber(i) });
+            }
+            
+            out.write("}-foo\n");
+            return null;
+        } finally {
+            env.popElement();
+        }
+    }
+
+    @Override
+    boolean isNestedBlockRepeater() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    String dump(boolean canonical) {
+        return "<#adhocTest1 ...>";
+    }
+
+    @Override
+    public String getLabelWithoutParameters() {
+        return "#adhocTest1";
+    }
+
+    @Override
+    int getParameterCount() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    Object getParameterValue(int idx) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    ParameterRole getParameterRole(int idx) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+    
+    
+
+}

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest2.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest2.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest2.java
new file mode 100644
index 0000000..1b03af8
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAdhocTest2.java
@@ -0,0 +1,165 @@
+package org.apache.freemarker.core;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.freemarker.core.model.ArgumentArrayLayout;
+import org.apache.freemarker.core.model.TemplateDirectiveModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util.CommonSupplier;
+import org.apache.freemarker.core.util.StringToIndexMap;
+
+/**
+ * Example of an AST directive that's not bound to some Configuration setting.
+ */
+//TODO [FM3][FREEMARKER-99] Delete this class when we are finished.
+class ASTDirAdhocTest2 extends ASTDirective {
+    private ASTExpression countExp;
+
+    private ASTDirAdhocTest2() {
+        //
+    }
+
+    final static CommonSupplier<ASTDirective> FACTORY = new CommonSupplier<ASTDirective>() {
+        @Override
+        public ASTDirective get() throws Exception {
+            return new ASTDirAdhocTest2();
+        }
+    };
+    
+    static TemplateDirectiveModel VALUE = new TemplateDirectiveModel() {
+
+        @Override
+        public void execute(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env)
+                throws TemplateException, IOException {
+            throw new UnsupportedOperationException("execute not implemented");
+        }
+
+        @Override
+        public boolean isNestedContentSupported() {
+            return true;
+        }
+
+        @Override
+        public ArgumentArrayLayout getDirectiveArgumentArrayLayout() {
+            return ARGS_LAYOUT;
+        }
+
+    };
+
+    private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.SINGLE_POSITIONAL_PARAMETER;
+    
+    @Override
+    public void setPositionalArgument(int position, ASTExpression valueExp) throws StaticLinkingCheckException {
+        if (position == 0) {
+            countExp = valueExp;
+        } else {
+            // TODO: Standardize error message; see CallableUtils 
+            throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
+                  "Too many positional arguments; can only have ",
+                  ARGS_LAYOUT.getPredefinedPositionalArgumentCount(), "."));
+        }
+    }
+
+    @Override
+    public void setNamedArgument(String name, ASTExpression valueExp) throws StaticLinkingCheckException {
+        // TODO: Standardize error message; see CallableUtils 
+        throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
+                "Unsupported parameter name ", new _DelayedJQuote(name), ". This directive has no named parameters."));
+    }
+
+    @Override
+    public void checkArgumentsAndSetNestedContentParameters(StringToIndexMap nestedContentParamNames)
+            throws StaticLinkingCheckException {
+        // TODO: Standardize error message; see CallableUtils 
+        if (countExp == null) {
+            throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
+                    "Missing mandatory ", new _DelayedOrdinal(1), " positional argument"));
+        }
+
+        // TODO: Standardize error message; see CallableUtils
+        if (nestedContentParamNames != null) {
+            throw new StaticLinkingCheckException("This directive doesn't support nested content parameters.");
+        }
+    }
+
+    @Override
+    public StringToIndexMap getNestedContentParamNames() {
+        return null;
+    }
+    
+    @Override
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
+        env.pushElement(this);
+        try {
+            Writer out = env.getOut();
+            int count = CallableUtils.castArgumentValueToInt(countExp.eval(env), 0, false, 0, VALUE, false);
+            for (int i = 0; i < count; i++) {
+                out.write(".");
+            }
+            return null;
+        } finally {
+            env.popElement();
+        }
+    }
+
+    @Override
+    boolean isNestedBlockRepeater() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    String dump(boolean canonical) {
+        return "<#adhocTest2 ...>";
+    }
+
+    @Override
+    public String getLabelWithoutParameters() {
+        return "#adhocTest2";
+    }
+
+    @Override
+    int getParameterCount() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    Object getParameterValue(int idx) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    ParameterRole getParameterRole(int idx) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isNestedContentSupported() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java
index 26a6d69..aba716d 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java
@@ -102,7 +102,7 @@ final class ASTDirAssignment extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException {
+    ASTElement[] execute(Environment env) throws TemplateException {
         final Environment.Namespace namespace;
         if (namespaceExp == null) {
             switch (scope) {
@@ -187,9 +187,9 @@ final class ASTDirAssignment extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder buf = new StringBuilder();
-        String dn = getParent() instanceof ASTDirAssignmentsContainer ? null : getASTNodeDescriptor();
+        String dn = getParent() instanceof ASTDirAssignmentsContainer ? null : getLabelWithoutParameters();
         if (dn != null) {
             if (canonical) buf.append("<");
             buf.append(dn);
@@ -217,7 +217,7 @@ final class ASTDirAssignment extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return getDirectiveName(scope);
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java
index 3cd1e91..b572795 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java
@@ -44,17 +44,17 @@ final class ASTDirAssignmentsContainer extends ASTDirective {
         this.namespaceExp = namespaceExp;
         int ln = getChildCount();
         for (int i = 0; i < ln; i++) {
-            ((ASTDirAssignment) getChild(i)).setNamespaceExp(namespaceExp);
+            ((ASTDirAssignment) fastGetChild(i)).setNamespaceExp(namespaceExp);
         }
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder buf = new StringBuilder();
         if (canonical) buf.append('<');
         buf.append(ASTDirAssignment.getDirectiveName(scope));
@@ -65,7 +65,7 @@ final class ASTDirAssignmentsContainer extends ASTDirective {
                 if (i != 0) {
                     buf.append(", ");
                 }
-                ASTDirAssignment assignment = (ASTDirAssignment) getChild(i);
+                ASTDirAssignment assignment = (ASTDirAssignment) fastGetChild(i);
                 buf.append(assignment.getCanonicalForm());
             }
         } else {
@@ -103,7 +103,7 @@ final class ASTDirAssignmentsContainer extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return ASTDirAssignment.getDirectiveName(scope);
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java
index 19aff47..d996420 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java
@@ -40,20 +40,20 @@ final class ASTDirAttemptRecoverContainer extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         env.visitAttemptRecover(this, attemptedSection, recoverySection);
         return null;
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (!canonical) {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         } else {
             StringBuilder buf = new StringBuilder();
-            buf.append("<").append(getASTNodeDescriptor()).append(">");
+            buf.append("<").append(getLabelWithoutParameters()).append(">");
             buf.append(getChildrenCanonicalForm());            
-            buf.append("</").append(getASTNodeDescriptor()).append(">");
+            buf.append("</").append(getLabelWithoutParameters()).append(">");
             return buf.toString();
         }
     }
@@ -76,7 +76,7 @@ final class ASTDirAttemptRecoverContainer extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#attempt";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java
index b982e56..9e52f30 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java
@@ -31,21 +31,21 @@ final class ASTDirAutoEsc extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
-            return "<" + getASTNodeDescriptor() + "\">" + getChildrenCanonicalForm() + "</" + getASTNodeDescriptor() + ">";
+            return "<" + getLabelWithoutParameters() + "\">" + getChildrenCanonicalForm() + "</" + getLabelWithoutParameters() + ">";
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#autoEsc";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java
index 128e684..428f4be 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java
@@ -25,17 +25,17 @@ package org.apache.freemarker.core;
 final class ASTDirBreak extends ASTDirective {
 
     @Override
-    ASTElement[] accept(Environment env) {
+    ASTElement[] execute(Environment env) {
         throw BreakOrContinueException.BREAK_INSTANCE;
     }
 
     @Override
-    protected String dump(boolean canonical) {
-        return canonical ? "<" + getASTNodeDescriptor() + "/>" : getASTNodeDescriptor();
+    String dump(boolean canonical) {
+        return canonical ? "<" + getLabelWithoutParameters() + "/>" : getLabelWithoutParameters();
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#break";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
index 6fc4c5f..f151ba5 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
@@ -21,6 +21,7 @@ package org.apache.freemarker.core;
 
 import java.io.IOException;
 import java.io.StringWriter;
+import java.io.Writer;
 
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.impl.SimpleString;
@@ -46,13 +47,19 @@ final class ASTDirCapturingAssignment extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         ASTElement[] children = getChildBuffer();
 
         TemplateModel capturedValue;
         if (children != null) {
             StringWriter out = new StringWriter();
-            env.visit(children, out);
+            Writer prevOut = env.getOut();
+            try {
+                env.setOut(out);
+                env.executeElements(children);
+            } finally {
+                env.setOut(prevOut);
+            }
             capturedValue = capturedStringToModel(out.toString());
         } else {
             capturedValue = capturedStringToModel("");
@@ -79,10 +86,10 @@ final class ASTDirCapturingAssignment extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append("<");
-        sb.append(getASTNodeDescriptor());
+        sb.append(getLabelWithoutParameters());
         sb.append(' ');
         sb.append(varName);
         if (namespaceExp != null) {
@@ -93,7 +100,7 @@ final class ASTDirCapturingAssignment extends ASTDirective {
             sb.append('>');
             sb.append(getChildrenCanonicalForm());
             sb.append("</");
-            sb.append(getASTNodeDescriptor());
+            sb.append(getLabelWithoutParameters());
             sb.append('>');
         } else {
             sb.append(" = .nestedOutput");
@@ -102,7 +109,7 @@ final class ASTDirCapturingAssignment extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return ASTDirAssignment.getDirectiveName(scope);
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java
index eca7ae4..6a4cfab 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java
@@ -35,15 +35,15 @@ final class ASTDirCase extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) {
+    ASTElement[] execute(Environment env) {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append('<');
-        sb.append(getASTNodeDescriptor());
+        sb.append(getLabelWithoutParameters());
         if (condition != null) {
             sb.append(' ');
             sb.append(condition.getCanonicalForm());
@@ -56,7 +56,7 @@ final class ASTDirCase extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return condition != null ? "#case" : "#default";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java
index 6bdda37..b03c16d 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java
@@ -34,30 +34,33 @@ final class ASTDirCompress extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         ASTElement[] childBuffer = getChildBuffer();
         if (childBuffer != null) {
             CompressWriter out = new CompressWriter(env.getOut(), 2048, false);
+            Writer prevOut = env.getOut();
             try {
-                env.visit(childBuffer, out);
+                env.setOut(out);
+                env.executeElements(childBuffer);
             } finally {
                 out.close();
+                env.setOut(prevOut);
             }
         }
         return null;
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
-            return "<" + getASTNodeDescriptor() + ">" + getChildrenCanonicalForm() + "</" + getASTNodeDescriptor() + ">";
+            return "<" + getLabelWithoutParameters() + ">" + getChildrenCanonicalForm() + "</" + getLabelWithoutParameters() + ">";
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#compress";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirContinue.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirContinue.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirContinue.java
index 4d18785..8ca7afa 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirContinue.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirContinue.java
@@ -25,17 +25,17 @@ package org.apache.freemarker.core;
 final class ASTDirContinue extends ASTDirective {
 
     @Override
-    ASTElement[] accept(Environment env) {
+    ASTElement[] execute(Environment env) {
         throw BreakOrContinueException.CONTINUE_INSTANCE;
     }
 
     @Override
-    protected String dump(boolean canonical) {
-        return canonical ? "<" + getASTNodeDescriptor() + "/>" : getASTNodeDescriptor();
+    String dump(boolean canonical) {
+        return canonical ? "<" + getLabelWithoutParameters() + "/>" : getLabelWithoutParameters();
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#continue";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java
index 31ebea7..6126904 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java
@@ -31,24 +31,24 @@ final class ASTDirElseOfList extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
             StringBuilder buf = new StringBuilder();
-            buf.append('<').append(getASTNodeDescriptor()).append('>');
+            buf.append('<').append(getLabelWithoutParameters()).append('>');
             buf.append(getChildrenCanonicalForm());            
             return buf.toString();
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#else";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirEscape.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirEscape.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirEscape.java
index 7a324cd..57678d3 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirEscape.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirEscape.java
@@ -47,7 +47,7 @@ class ASTDirEscape extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
@@ -56,22 +56,22 @@ class ASTDirEscape extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append('<');
-        sb.append(getASTNodeDescriptor())
+        sb.append(getLabelWithoutParameters())
                 .append(' ').append(_StringUtils.toFTLTopLevelIdentifierReference(variable))
                 .append(" as ").append(expr.getCanonicalForm());
         if (canonical) {
             sb.append('>');
             sb.append(getChildrenCanonicalForm());
-            sb.append("</").append(getASTNodeDescriptor()).append('>');
+            sb.append("</").append(getLabelWithoutParameters()).append('>');
         }
         return sb.toString();
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#escape";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFallback.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFallback.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFallback.java
index 255de11..0ddb5d6 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFallback.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFallback.java
@@ -27,18 +27,18 @@ import java.io.IOException;
 final class ASTDirFallback extends ASTDirective {
 
     @Override
-    ASTElement[] accept(Environment env) throws IOException, TemplateException {
+    ASTElement[] execute(Environment env) throws IOException, TemplateException {
         env.fallback();
         return null;
     }
 
     @Override
-    protected String dump(boolean canonical) {
-        return canonical ? "<" + getASTNodeDescriptor() + "/>" : getASTNodeDescriptor();
+    String dump(boolean canonical) {
+        return canonical ? "<" + getLabelWithoutParameters() + "/>" : getLabelWithoutParameters();
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#fallback";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFlush.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFlush.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFlush.java
index 469eff8..0b2faed 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFlush.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirFlush.java
@@ -27,18 +27,18 @@ import java.io.IOException;
 final class ASTDirFlush extends ASTDirective {
 
     @Override
-    ASTElement[] accept(Environment env) throws IOException {
+    ASTElement[] execute(Environment env) throws IOException {
         env.getOut().flush();
         return null;
     }
 
     @Override
-    protected String dump(boolean canonical) {
-        return canonical ? "<" + getASTNodeDescriptor() + "/>" : getASTNodeDescriptor();
+    String dump(boolean canonical) {
+        return canonical ? "<" + getLabelWithoutParameters() + "/>" : getLabelWithoutParameters();
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#flush";
     }
  

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfElseIfElseContainer.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfElseIfElseContainer.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfElseIfElseContainer.java
index 8a250bf..1c8fad7 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfElseIfElseContainer.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfElseIfElseContainer.java
@@ -38,10 +38,10 @@ final class ASTDirIfElseIfElseContainer extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         int ln  = getChildCount();
         for (int i = 0; i < ln; i++) {
-            ASTDirIfOrElseOrElseIf cblock = (ASTDirIfOrElseOrElseIf) getChild(i);
+            ASTDirIfOrElseOrElseIf cblock = (ASTDirIfOrElseOrElseIf) fastGetChild(i);
             ASTExpression condition = cblock.condition;
             env.replaceElementStackTop(cblock);
             if (condition == null || condition.evalToBoolean(env)) {
@@ -55,7 +55,7 @@ final class ASTDirIfElseIfElseContainer extends ASTDirective {
     ASTElement postParseCleanup(boolean stripWhitespace)
         throws ParseException {
         if (getChildCount() == 1) {
-            ASTDirIfOrElseOrElseIf cblock = (ASTDirIfOrElseOrElseIf) getChild(0);
+            ASTDirIfOrElseOrElseIf cblock = (ASTDirIfOrElseOrElseIf) fastGetChild(0);
             cblock.setLocation(getTemplate(), cblock, this);
             return cblock.postParseCleanup(stripWhitespace);
         } else {
@@ -64,23 +64,23 @@ final class ASTDirIfElseIfElseContainer extends ASTDirective {
     }
     
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
             StringBuilder buf = new StringBuilder();
             int ln = getChildCount();
             for (int i = 0; i < ln; i++) {
-                ASTDirIfOrElseOrElseIf cblock = (ASTDirIfOrElseOrElseIf) getChild(i);
+                ASTDirIfOrElseOrElseIf cblock = (ASTDirIfOrElseOrElseIf) fastGetChild(i);
                 buf.append(cblock.dump(canonical));
             }
             buf.append("</#if>");
             return buf.toString();
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#if-#elseIf-#else-container";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfOrElseOrElseIf.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfOrElseOrElseIf.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfOrElseOrElseIf.java
index 28178d9..cb6a8cf 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfOrElseOrElseIf.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirIfOrElseOrElseIf.java
@@ -44,7 +44,7 @@ final class ASTDirIfOrElseOrElseIf extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         if (condition == null || condition.evalToBoolean(env)) {
             return getChildBuffer();
         }
@@ -52,10 +52,10 @@ final class ASTDirIfOrElseOrElseIf extends ASTDirective {
     }
     
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder buf = new StringBuilder();
         if (canonical) buf.append('<');
-        buf.append(getASTNodeDescriptor());
+        buf.append(getLabelWithoutParameters());
         if (condition != null) {
             buf.append(' ');
             buf.append(condition.getCanonicalForm());
@@ -71,7 +71,7 @@ final class ASTDirIfOrElseOrElseIf extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         if (type == TYPE_ELSE) {
             return "#else";
         } else if (type == TYPE_IF) {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirImport.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirImport.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirImport.java
index 88cfeb5..9d7b522 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirImport.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirImport.java
@@ -45,7 +45,7 @@ final class ASTDirImport extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         final String importedTemplateName = importedTemplateNameExp.evalAndCoerceToPlainText(env);
         final String fullImportedTemplateName;
         try {
@@ -68,10 +68,10 @@ final class ASTDirImport extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder buf = new StringBuilder();
         if (canonical) buf.append('<');
-        buf.append(getASTNodeDescriptor());
+        buf.append(getLabelWithoutParameters());
         buf.append(' ');
         buf.append(importedTemplateNameExp.getCanonicalForm());
         buf.append(" as ");
@@ -81,7 +81,7 @@ final class ASTDirImport extends ASTDirective {
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#import";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirInclude.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
index 76ce1f6..5afc30a 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
@@ -56,7 +56,7 @@ final class ASTDirInclude extends ASTDirective {
     }
     
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         final String includedTemplateName = includedTemplateNameExp.evalAndCoerceToPlainText(env);
         final String fullIncludedTemplateName;
         try {
@@ -93,10 +93,10 @@ final class ASTDirInclude extends ASTDirective {
     }
     
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder buf = new StringBuilder();
         if (canonical) buf.append('<');
-        buf.append(getASTNodeDescriptor());
+        buf.append(getLabelWithoutParameters());
         buf.append(' ');
         buf.append(includedTemplateNameExp.getCanonicalForm());
         if (ignoreMissingExp != null) {
@@ -107,7 +107,7 @@ final class ASTDirInclude extends ASTDirective {
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#include";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirItems.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirItems.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirItems.java
index cf85b77..04aaf94 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirItems.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirItems.java
@@ -43,12 +43,12 @@ class ASTDirItems extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         final IterationContext iterCtx = ASTDirList.findEnclosingIterationContext(env, null);
         if (iterCtx == null) {
             // The parser should prevent this situation
             throw new TemplateException(env,
-                    getASTNodeDescriptor(), " without iteration in context");
+                    getLabelWithoutParameters(), " without iteration in context");
         }
         
         iterCtx.loopForItemsElement(env, getChildBuffer(), nestedContentParamName, nestedContentParam2Name);
@@ -61,10 +61,10 @@ class ASTDirItems extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append('<');
-        sb.append(getASTNodeDescriptor());
+        sb.append(getLabelWithoutParameters());
         sb.append(" as ");
         sb.append(_StringUtils.toFTLTopLevelIdentifierReference(nestedContentParamName));
         if (nestedContentParam2Name != null) {
@@ -75,14 +75,14 @@ class ASTDirItems extends ASTDirective {
             sb.append('>');
             sb.append(getChildrenCanonicalForm());
             sb.append("</");
-            sb.append(getASTNodeDescriptor());
+            sb.append(getLabelWithoutParameters());
             sb.append('>');
         }
         return sb.toString();
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#items";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirList.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirList.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirList.java
index 8034018..201c96c 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirList.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirList.java
@@ -78,7 +78,7 @@ final class ASTDirList extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         acceptWithResult(env);
         return null;
     }
@@ -117,10 +117,10 @@ final class ASTDirList extends ASTDirective {
     }
     
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder buf = new StringBuilder();
         if (canonical) buf.append('<');
-        buf.append(getASTNodeDescriptor());
+        buf.append(getLabelWithoutParameters());
         buf.append(' ');
         buf.append(listedExp.getCanonicalForm());
         if (nestedContentParamName != null) {
@@ -136,7 +136,7 @@ final class ASTDirList extends ASTDirective {
             buf.append(getChildrenCanonicalForm());
             if (!(getParent() instanceof ASTDirListElseContainer)) {
                 buf.append("</");
-                buf.append(getASTNodeDescriptor());
+                buf.append(getLabelWithoutParameters());
                 buf.append('>');
             }
         }
@@ -179,7 +179,7 @@ final class ASTDirList extends ASTDirective {
     }    
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#list";
     }
 
@@ -266,7 +266,7 @@ final class ASTDirList extends ASTDirective {
                                 nestedContentParam = iterModel.next();
                                 hasNext = iterModel.hasNext();
                                 try {
-                                    env.visit(childBuffer);
+                                    env.executeElements(childBuffer);
                                 } catch (BreakOrContinueException br) {
                                     if (br == BreakOrContinueException.BREAK_INSTANCE) {
                                         break listLoop;
@@ -279,7 +279,7 @@ final class ASTDirList extends ASTDirective {
                         // We must reuse this later, because TemplateIterableModel-s that wrap an Iterator only
                         // allow one iterator() call.
                         openedIterator = iterModel;
-                        env.visit(childBuffer);
+                        env.executeElements(childBuffer);
                     }
                 }
             } else if (listedValue instanceof TemplateHashModelEx) {
@@ -316,7 +316,7 @@ final class ASTDirList extends ASTDirective {
                                 nestedContentParam2 = kvp.getValue();
                                 hasNext = kvpIter.hasNext();
                                 try {
-                                    env.visit(childBuffer);
+                                    env.executeElements(childBuffer);
                                 } catch (BreakOrContinueException br) {
                                     if (br == BreakOrContinueException.BREAK_INSTANCE) {
                                         break listLoop;
@@ -328,7 +328,7 @@ final class ASTDirList extends ASTDirective {
                     } else {
                         // We will reuse this at the #iterms
                         openedIterator = kvpIter;
-                        env.visit(childBuffer);
+                        env.executeElements(childBuffer);
                     }
                 }
             } else if (listedValue instanceof TemplateIterableModel) {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirListElseContainer.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirListElseContainer.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirListElseContainer.java
index 686b03c..47cc9f7 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirListElseContainer.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirListElseContainer.java
@@ -37,9 +37,9 @@ class ASTDirListElseContainer extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         if (!listPart.acceptWithResult(env)) {
-            return elsePart.accept(env);
+            return elsePart.execute(env);
         }
         return null;
     }
@@ -50,23 +50,23 @@ class ASTDirListElseContainer extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
             StringBuilder buf = new StringBuilder();
             int ln = getChildCount();
             for (int i = 0; i < ln; i++) {
-                ASTElement element = getChild(i);
+                ASTElement element = fastGetChild(i);
                 buf.append(element.dump(canonical));
             }
             buf.append("</#list>");
             return buf.toString();
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#list-#else-container";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirMacroOrFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirMacroOrFunction.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirMacroOrFunction.java
index 786bfcf..3c64eaa 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirMacroOrFunction.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirMacroOrFunction.java
@@ -112,13 +112,13 @@ final class ASTDirMacroOrFunction extends ASTDirective implements TemplateModel
     }
 
     @Override
-    ASTElement[] accept(Environment env) {
+    ASTElement[] execute(Environment env) {
         env.visitMacroOrFunctionDefinition(this);
         return null;
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return function ? "#function" : "#macro";
     }
 
@@ -138,10 +138,10 @@ final class ASTDirMacroOrFunction extends ASTDirective implements TemplateModel
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append('<');
-        sb.append(getASTNodeDescriptor());
+        sb.append(getLabelWithoutParameters());
         sb.append(' ');
         sb.append(_StringUtils.toFTLTopLevelTragetIdentifier(name));
 
@@ -236,7 +236,7 @@ final class ASTDirMacroOrFunction extends ASTDirective implements TemplateModel
         if (canonical) {
             sb.append('>');
             sb.append(getChildrenCanonicalForm());
-            sb.append("</").append(getASTNodeDescriptor()).append('>');
+            sb.append("</").append(getLabelWithoutParameters()).append('>');
         }
         return sb.toString();
     }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNested.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNested.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNested.java
index 25344e6..df0074e 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNested.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNested.java
@@ -42,7 +42,7 @@ final class ASTDirNested extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws IOException, TemplateException {
+    ASTElement[] execute(Environment env) throws IOException, TemplateException {
         CallPlace macroCallPlace = env.getCurrentMacroContext().callPlace;
 
         // When nestedContParamCnt < nestedContentParameters.getCollectionSize(), then we just skip calculating the
@@ -68,10 +68,10 @@ final class ASTDirNested extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append('<');
-        sb.append(getASTNodeDescriptor());
+        sb.append(getLabelWithoutParameters());
         if (nestedContentParameters != null) {
             for (int i = 0; i < nestedContentParameters.size(); i++) {
                 sb.append(' ');
@@ -83,7 +83,7 @@ final class ASTDirNested extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#nested";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoAutoEsc.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoAutoEsc.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoAutoEsc.java
index a3ef03d..5bbc6c7 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoAutoEsc.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoAutoEsc.java
@@ -31,21 +31,21 @@ final class ASTDirNoAutoEsc extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
-            return "<" + getASTNodeDescriptor() + "\">" + getChildrenCanonicalForm() + "</" + getASTNodeDescriptor() + ">";
+            return "<" + getLabelWithoutParameters() + "\">" + getChildrenCanonicalForm() + "</" + getLabelWithoutParameters() + ">";
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#noAutoEsc";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoEscape.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoEscape.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoEscape.java
index 61a32b8..b3af156 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoEscape.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirNoEscape.java
@@ -31,17 +31,17 @@ class ASTDirNoEscape extends ASTDirective {
     }
     
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
-            return "<" + getASTNodeDescriptor() + '>' + getChildrenCanonicalForm()
-                    + "</" + getASTNodeDescriptor() + '>';
+            return "<" + getLabelWithoutParameters() + '>' + getChildrenCanonicalForm()
+                    + "</" + getLabelWithoutParameters() + '>';
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
 
@@ -61,7 +61,7 @@ class ASTDirNoEscape extends ASTDirective {
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#noEscape";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirOutputFormat.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirOutputFormat.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirOutputFormat.java
index c2aa7b8..33912ab 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirOutputFormat.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirOutputFormat.java
@@ -34,22 +34,22 @@ final class ASTDirOutputFormat extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
-            return "<" + getASTNodeDescriptor() + " \"" + paramExp.getCanonicalForm() + "\">"
-                    + getChildrenCanonicalForm() + "</" + getASTNodeDescriptor() + ">";
+            return "<" + getLabelWithoutParameters() + " \"" + paramExp.getCanonicalForm() + "\">"
+                    + getChildrenCanonicalForm() + "</" + getLabelWithoutParameters() + ">";
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
     
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#outputFormat";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecover.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecover.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecover.java
index 7879f18..b441eeb 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecover.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecover.java
@@ -31,24 +31,24 @@ final class ASTDirRecover extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException, IOException {
+    ASTElement[] execute(Environment env) throws TemplateException, IOException {
         return getChildBuffer();
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         if (canonical) {
             StringBuilder buf = new StringBuilder();
-            buf.append('<').append(getASTNodeDescriptor()).append('>');
+            buf.append('<').append(getLabelWithoutParameters()).append('>');
             buf.append(getChildrenCanonicalForm());            
             return buf.toString();
         } else {
-            return getASTNodeDescriptor();
+            return getLabelWithoutParameters();
         }
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#recover";
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
index 1904edc..1a491f5 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
@@ -41,7 +41,7 @@ final class ASTDirRecurse extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws IOException, TemplateException {
+    ASTElement[] execute(Environment env) throws IOException, TemplateException {
         TemplateModel node = targetNode == null ? null : targetNode.eval(env);
         if (node != null && !(node instanceof TemplateNodeModel)) {
             throw MessageUtils.newUnexpectedOperandTypeException(
@@ -75,10 +75,10 @@ final class ASTDirRecurse extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append('<');
-        sb.append(getASTNodeDescriptor());
+        sb.append(getLabelWithoutParameters());
         if (targetNode != null) {
             sb.append(' ');
             sb.append(targetNode.getCanonicalForm());
@@ -92,7 +92,7 @@ final class ASTDirRecurse extends ASTDirective {
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#recurse";
     }
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e8e58ffa/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirReturn.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirReturn.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirReturn.java
index c5d23b3..5a24eef 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirReturn.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirReturn.java
@@ -31,7 +31,7 @@ final class ASTDirReturn extends ASTDirective {
     }
 
     @Override
-    ASTElement[] accept(Environment env) throws TemplateException {
+    ASTElement[] execute(Environment env) throws TemplateException {
         if (exp != null) {
             env.setLastReturnValue(exp.eval(env));
         }
@@ -43,10 +43,10 @@ final class ASTDirReturn extends ASTDirective {
     }
 
     @Override
-    protected String dump(boolean canonical) {
+    String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();
         if (canonical) sb.append('<');
-        sb.append(getASTNodeDescriptor());
+        sb.append(getLabelWithoutParameters());
         if (exp != null) {
             sb.append(' ');
             sb.append(exp.getCanonicalForm());
@@ -56,7 +56,7 @@ final class ASTDirReturn extends ASTDirective {
     }
 
     @Override
-    String getASTNodeDescriptor() {
+    public String getLabelWithoutParameters() {
         return "#return";
     }
     


Mime
View raw message