http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/CustomAttribute.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/CustomAttribute.java 
b/src/main/java/org/apache/freemarker/core/ast/CustomAttribute.java
deleted file mode 100644
index 8eda14d..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/CustomAttribute.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.freemarker.core.ast;
-
-import org.apache.freemarker.core.Configuration;
-import org.apache.freemarker.core.Template;
-
-/**
- * A class that allows one to associate custom data with a {@link 
Configuration}, a {@link Template}, or
- * {@link Environment}.
- * 
- * <p>This API has similar approach to that of {@link ThreadLocal} (which 
allows one to associate
- * custom data with a thread). With an example:</p>
- * 
- * <pre>
- * // The object identity itself will serve as the attribute identifier; 
there's no attribute name String:
- * public static final CustomAttribute MY_ATTR = new 
CustomAttribute(CustomAttribute.SCOPE_CONFIGURATION);
- * ...
- *     // Set the attribute in this particular Configuration object:
- *     MY_ATTR.set(myAttrValue, cfg);
- *     ...
- *     // Read the attribute from this particular Configuration object:
- *     myAttrValue = MY_ATTR.get(cfg);
- * </pre>
- */
-// [2.4] Use generics; type parameter used for the type of the stored value 
-public class CustomAttribute {
-    
-    /**
-     * Constant used in the constructor specifying that this attribute is 
{@link Environment}-scoped.
-     */
-    public static final int SCOPE_ENVIRONMENT = 0;
-        
-    /**
-     * Constant used in the constructor specifying that this attribute is 
{@link Template}-scoped.
-     */
-    public static final int SCOPE_TEMPLATE = 1;
-        
-    /**
-     * Constant used in the constructor specifying that this attribute is 
{@link Configuration}-scoped.
-     */
-    public static final int SCOPE_CONFIGURATION = 2;
-
-    // We use an internal key instead of 'this' so that malicious subclasses 
-    // overriding equals() and hashCode() can't gain access to other attribute
-    // values. That's also the reason why get() and set() are marked final.
-    private final Object key = new Object();
-    private final int scope;
-    
-    /**
-     * Creates a new custom attribute with the specified scope
-     * @param scope one of <tt>SCOPE_</tt> constants. 
-     */
-    public CustomAttribute(int scope) {
-        if (scope != SCOPE_ENVIRONMENT && 
-           scope != SCOPE_TEMPLATE && 
-           scope != SCOPE_CONFIGURATION) {
-                throw new IllegalArgumentException();
-            }
-        this.scope = scope;
-    }
-    
-    /**
-     * This method is invoked when {@link #get()} is invoked without 
-     * {@link #set(Object)} being invoked before it to define the value in the 
-     * current scope. Override it to create the attribute value on-demand.  
-     * @return the initial value for the custom attribute. By default returns 
null.
-     */
-    protected Object create() {
-        return null;
-    }
-    
-    /**
-     * Gets the attribute from the appropriate scope that's accessible through 
the specified {@link Environment}. If
-     * the attribute has {@link #SCOPE_ENVIRONMENT} scope, it will be get from 
the given {@link Environment} directly.
-     * If the attribute has {@link #SCOPE_TEMPLATE} scope, it will be get from 
the parent of the given
-     * {@link Environment} (that is, in {@link Environment#getParent()}) 
directly). If the attribute has
-     * {@link #SCOPE_CONFIGURATION} scope, it will be get from {@link 
Environment#getConfiguration()}.
-     * 
-     * @throws NullPointerException
-     *             If {@code env} is null
-     * 
-     * @return The new value of the attribute (possibly {@code null}), or 
{@code null} if the attribute doesn't exist.
-     * 
-     * @since 2.3.22
-     */
-    public final Object get(Environment env) {
-        return getScopeConfigurable(env).getCustomAttribute(key, this);
-    }
-
-    /**
-     * Same as {@link #get(Environment)}, but uses {@link 
Environment#getCurrentEnvironment()} to fill the 2nd argument.
-     * 
-     * @throws IllegalStateException
-     *             If there is no current {@link Environment}, which is 
usually the case when the current thread isn't
-     *             processing a template.
-     */
-    public final Object get() {
-        return 
getScopeConfigurable(getRequiredCurrentEnvironment()).getCustomAttribute(key, 
this);
-    }
-    
-    /**
-     * Gets the value of a {@link Template}-scope attribute from the given 
{@link Template}.
-     * 
-     * @throws UnsupportedOperationException
-     *             If this custom attribute has different scope than {@link 
#SCOPE_TEMPLATE}.
-     * @throws NullPointerException
-     *             If {@code template} is null
-     */
-    public final Object get(Template template) {
-        if (scope != SCOPE_TEMPLATE) {
-            throw new UnsupportedOperationException("This is not a 
template-scope attribute");
-        }
-        return ((Configurable) template).getCustomAttribute(key, this);
-    }
-    
-    /**
-     * Same as {@link #get(Template)}, but applies to a {@link 
TemplateConfiguration}.  
-     * 
-     * @since 2.3.24
-     */
-    public Object get(TemplateConfiguration templateConfiguration) {
-        if (scope != SCOPE_TEMPLATE) {
-            throw new UnsupportedOperationException("This is not a 
template-scope attribute");
-        }
-        return templateConfiguration.getCustomAttribute(key, this);
-    }
-    
-    /**
-     * Gets the value of a {@link Configuration}-scope attribute from the 
given {@link Configuration}.
-     * 
-     * @throws UnsupportedOperationException
-     *             If this custom attribute has different scope than {@link 
#SCOPE_CONFIGURATION}.
-     * @throws NullPointerException
-     *             If {@code cfg} is null
-     * 
-     * @since 2.3.22
-     */
-    public final Object get(Configuration cfg) {
-        if (scope != SCOPE_CONFIGURATION) {
-            throw new UnsupportedOperationException("This is not a 
template-scope attribute");
-        }
-        return ((Configurable) cfg).getCustomAttribute(key, this);
-    }
-    
-    /**
-     * Sets the attribute inside the appropriate scope that's accessible 
through the specified {@link Environment}. If
-     * the attribute has {@link #SCOPE_ENVIRONMENT} scope, it will be set in 
the given {@link Environment} directly. If
-     * the attribute has {@link #SCOPE_TEMPLATE} scope, it will be set in the 
parent of the given {@link Environment}
-     * (that is, in {@link Environment#getParent()}) directly). If the 
attribute has {@link #SCOPE_CONFIGURATION} scope,
-     * it will be set in {@link Environment#getConfiguration()}.
-     * 
-     * @param value
-     *            The new value of the attribute. Can be {@code null}.
-     * 
-     * @throws NullPointerException
-     *             If {@code env} is null
-     * 
-     * @since 2.3.22
-     */
-    public final void set(Object value, Environment env) {
-        getScopeConfigurable(env).setCustomAttribute(key, value);
-    }
-
-    /**
-     * Same as {@link #set(Object, Environment)}, but uses {@link 
Environment#getCurrentEnvironment()} to fill the 2nd
-     * argument.
-     * 
-     * @throws IllegalStateException
-     *             If there is no current {@link Environment}, which is 
usually the case when the current thread isn't
-     *             processing a template.
-     */
-    public final void set(Object value) {
-        
getScopeConfigurable(getRequiredCurrentEnvironment()).setCustomAttribute(key, 
value);
-    }
-
-    /**
-     * Sets the value of a {@link Template}-scope attribute in the given 
{@link Template}.
-     * 
-     * @param value
-     *            The new value of the attribute. Can be {@code null}.
-     * 
-     * @throws UnsupportedOperationException
-     *             If this custom attribute has different scope than {@link 
#SCOPE_TEMPLATE}.
-     * @throws NullPointerException
-     *             If {@code template} is null
-     */
-    public final void set(Object value, Template template) {
-        if (scope != SCOPE_TEMPLATE) {
-            throw new UnsupportedOperationException("This is not a 
template-scope attribute");
-        }
-        ((Configurable) template).setCustomAttribute(key, value);
-    }
-
-    /**
-     * Same as {@link #set(Object, Template)}, but applicable to a {@link 
TemplateConfiguration}. 
-     * 
-     * @since 2.3.24
-     */
-    public final void set(Object value, TemplateConfiguration 
templateConfiguration) {
-        if (scope != SCOPE_TEMPLATE) {
-            throw new UnsupportedOperationException("This is not a 
template-scope attribute");
-        }
-        templateConfiguration.setCustomAttribute(key, value);
-    }
-    
-    /**
-     * Sets the value of a {@link Configuration}-scope attribute in the given 
{@link Configuration}.
-     * 
-     * @param value
-     *            The new value of the attribute. Can be {@code null}.
-     * 
-     * @throws UnsupportedOperationException
-     *             If this custom attribute has different scope than {@link 
#SCOPE_CONFIGURATION}.
-     * @throws NullPointerException
-     *             If {@code cfg} is null
-     * 
-     * @since 2.3.22
-     */
-    public final void set(Object value, Configuration cfg) {
-        if (scope != SCOPE_CONFIGURATION) {
-            throw new UnsupportedOperationException("This is not a 
configuration-scope attribute");
-        }
-        ((Configurable) cfg).setCustomAttribute(key, value);
-    }
-    
-    private Environment getRequiredCurrentEnvironment() {
-        Environment c = Environment.getCurrentEnvironment();
-        if (c == null) {
-            throw new IllegalStateException("No current environment");
-        }
-        return c;
-    }
-
-    private Configurable getScopeConfigurable(Environment env) throws Error {
-        switch (scope) {
-        case SCOPE_ENVIRONMENT:
-            return env;
-        case SCOPE_TEMPLATE:
-            return env.getParent();
-        case SCOPE_CONFIGURATION:
-            return env.getParent().getParent();
-        default:
-            throw new BugException();
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/DefaultToExpression.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/ast/DefaultToExpression.java 
b/src/main/java/org/apache/freemarker/core/ast/DefaultToExpression.java
deleted file mode 100755
index f6aef0e..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/DefaultToExpression.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.freemarker.core.ast;
-
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateHashModelEx;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleCollection;
-
-/** {@code exp!defExp}, {@code (exp)!defExp} and the same two with {@code 
(exp)!}. */
-class DefaultToExpression extends Expression {
-       
-    private static final TemplateCollectionModel EMPTY_COLLECTION = new 
SimpleCollection(new java.util.ArrayList(0));
-    
-       static private class EmptyStringAndSequence 
-         implements TemplateScalarModel, TemplateSequenceModel, 
TemplateHashModelEx {
-               @Override
-        public String getAsString() {
-                       return "";
-               }
-               @Override
-        public TemplateModel get(int i) {
-                       return null;
-               }
-               @Override
-        public TemplateModel get(String s) {
-                       return null;
-               }
-               @Override
-        public int size() {
-                       return 0;
-               }
-               @Override
-        public boolean isEmpty() {
-                       return true;
-               }
-               @Override
-        public TemplateCollectionModel keys() {
-                       return EMPTY_COLLECTION;
-               }
-               @Override
-        public TemplateCollectionModel values() {
-                       return EMPTY_COLLECTION;
-               }
-               
-       }
-       
-       static final TemplateModel EMPTY_STRING_AND_SEQUENCE = new 
EmptyStringAndSequence();
-       
-       private final Expression lho, rho;
-       
-       DefaultToExpression(Expression lho, Expression rho) {
-               this.lho = lho;
-               this.rho = rho;
-       }
-
-       @Override
-    TemplateModel _eval(Environment env) throws TemplateException {
-               TemplateModel left;
-               if (lho instanceof ParentheticalExpression) {
-            boolean lastFIRE = env.setFastInvalidReferenceExceptions(true);
-               try {
-                left = lho.eval(env);
-               } catch (InvalidReferenceException ire) {
-                   left = null;
-            } finally {
-                env.setFastInvalidReferenceExceptions(lastFIRE);
-               }
-               } else {
-            left = lho.eval(env);
-               }
-               
-               if (left != null) return left;
-               else if (rho == null) return EMPTY_STRING_AND_SEQUENCE;
-               else return rho.eval(env);
-       }
-
-       @Override
-    boolean isLiteral() {
-               return false;
-       }
-
-       @Override
-    protected Expression deepCloneWithIdentifierReplaced_inner(String 
replacedIdentifier, Expression replacement, ReplacemenetState replacementState) 
{
-        return new DefaultToExpression(
-                lho.deepCloneWithIdentifierReplaced(replacedIdentifier, 
replacement, replacementState),
-                rho != null
-                        ? 
rho.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, 
replacementState)
-                        : null);
-       }
-
-       @Override
-    public String getCanonicalForm() {
-               if (rho == null) {
-                       return lho.getCanonicalForm() + '!';
-               }
-               return lho.getCanonicalForm() + '!' + rho.getCanonicalForm();
-       }
-       
-       @Override
-    String getNodeTypeSymbol() {
-        return "...!...";
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 2;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        switch (idx) {
-        case 0: return lho;
-        case 1: return rho;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        return ParameterRole.forBinaryOperatorOperand(idx);
-    }
-        
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/DirectiveCallPlace.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/ast/DirectiveCallPlace.java 
b/src/main/java/org/apache/freemarker/core/ast/DirectiveCallPlace.java
deleted file mode 100644
index e69d797..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/DirectiveCallPlace.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.freemarker.core.ast;
-
-import java.util.IdentityHashMap;
-
-import org.apache.freemarker.core.Configuration;
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.model.TemplateDirectiveModel;
-import org.apache.freemarker.core.model.TemplateTransformModel;
-import org.apache.freemarker.core.util.ObjectFactory;
-
-/**
- * Gives information about the place where a directive is called from, also 
lets you attach a custom data object to that
- * place. Each directive call in a template has its own {@link 
DirectiveCallPlace} object (even when they call the same
- * directive with the same parameters). The life cycle of the {@link 
DirectiveCallPlace} object is bound to the
- * {@link Template} object that contains the directive call. Hence, the {@link 
DirectiveCallPlace} object and the custom
- * data you put into it is cached together with the {@link Template} (and 
templates are normally cached - see
- * {@link Configuration#getTemplate(String)}). The custom data is normally 
initialized on demand, that is, when the
- * directive call is first executed, via {@link #getOrCreateCustomData(Object, 
ObjectFactory)}.
- * 
- * <p>
- * Currently this method doesn't give you access to the {@link Template} 
object, because it's probable that future
- * versions of FreeMarker will be able to use the same parsed representation 
of a "file" for multiple {@link Template}
- * objects. Then the call place will be bound to the parsed representation, 
not to the {@link Template} objects that are
- * based on it.
- * 
- * <p>
- * <b>Don't implement this interface yourself</b>, as new methods can be added 
to it any time! It's only meant to be
- * implemented by the FreeMarker core.
- * 
- * <p>
- * This interface is currently only used for custom directive calls (that is, 
a {@code <@...>} that calls a
- * {@link TemplateDirectiveModel}, {@link TemplateTransformModel}, or a macro).
- * 
- * @see Environment#getCurrentDirectiveCallPlace()
- * 
- * @since 2.3.22
- */
-public interface DirectiveCallPlace {
-
-    /**
-     * The 1-based column number of the first character of the directive call 
in the template source code, or -1 if it's
-     * not known.
-     */
-    int getBeginColumn();
-
-    /**
-     * The 1-based line number of the first character of the directive call in 
the template source code, or -1 if it's
-     * not known.
-     */
-    int getBeginLine();
-
-    /**
-     * The 1-based column number of the last character of the directive call 
in the template source code, or -1 if it's
-     * not known. If the directive has an end-tag ({@code </@...>}), then it 
points to the last character of that.
-     */
-    int getEndColumn();
-
-    /**
-     * The 1-based line number of the last character of the directive call in 
the template source code, or -1 if it's
-     * not known. If the directive has an end-tag ({@code </@...>}), then it 
points to the last character of that.
-     */
-    int getEndLine();
-
-    /**
-     * Returns the custom data, or if that's {@code null}, then it creates and 
stores it in an atomic operation then
-     * returns it. This method is thread-safe, however, it doesn't ensure 
thread safe (like synchronized) access to the
-     * custom data itself. See the top-level documentation of {@link 
DirectiveCallPlace} to understand the scope and
-     * life-cycle of the custom data. Be sure that the custom data only 
depends on things that get their final value
-     * during template parsing, not on runtime settings.
-     * 
-     * <p>
-     * This method will block other calls while the {@code objectFactory} is 
executing, thus, the object will be
-     * <em>usually</em> created only once, even if multiple threads request 
the value when it's still {@code null}. It
-     * doesn't stand though when {@code providerIdentity} mismatches occur 
(see later). Furthermore, then it's also
-     * possible that multiple objects created by the same {@link 
ObjectFactory} will be in use on the same time, because
-     * of directive executions already running in parallel, and because of 
memory synchronization delays (hardware
-     * dependent) between the threads.
-     * 
-     * @param providerIdentity
-     *            This is usually the class of the {@link 
TemplateDirectiveModel} that creates (and uses) the custom
-     *            data, or if you are using your own class for the custom data 
object (as opposed to a class from some
-     *            more generic API), then that class. This is needed as the 
same call place might calls different
-     *            directives depending on runtime conditions, and so it must 
be ensured that these directives won't
-     *            accidentally read each other's custom data, ending up with 
class cast exceptions or worse. In the
-     *            current implementation, if there's a {@code 
providerIdentity} mismatch (means, the
-     *            {@code providerIdentity} object used when the custom data 
was last set isn't the exactly same object
-     *            as the one provided with the parameter now), the previous 
custom data will be just ignored as if it
-     *            was {@code null}. So if multiple directives that use the 
custom data feature use the same call place,
-     *            the caching of the custom data can be inefficient, as they 
will keep overwriting each other's custom
-     *            data. (In a more generic implementation the {@code 
providerIdentity} would be a key in a
-     *            {@link IdentityHashMap}, but then this feature would be 
slower, while {@code providerIdentity}
-     *            mismatches aren't occurring in most applications.)
-     * @param objectFactory
-     *            Called when the custom data wasn't yet set, to create its 
initial value. If this parameter is
-     *            {@code null} and the custom data wasn't set yet, then {@code 
null} will be returned. The returned
-     *            value of {@link ObjectFactory#createObject()} can be any 
kind of object, but can't be {@code null}.
-     * 
-     * @return The current custom data object, or possibly {@code null} if 
there was no {@link ObjectFactory} provided.
-     * 
-     * @throws CallPlaceCustomDataInitializationException
-     *             If the {@link ObjectFactory} had to be invoked but failed.
-     */
-    Object getOrCreateCustomData(Object providerIdentity, ObjectFactory 
objectFactory)
-            throws CallPlaceCustomDataInitializationException;
-
-    /**
-     * Tells if the nested content (the body) can be safely cached, as it only 
depends on the template content (not on
-     * variable values and such) and has no side-effects (other than writing 
to the output). Examples of cases that give
-     * {@code false}: {@code <@foo>Name: } <tt>${name}</tt>{@code</@foo>},
-     * {@code <@foo>Name: <#if showIt>Joe</#if></@foo>}. Examples of cases 
that give {@code true}:
-     * {@code <@foo>Name: Joe</@foo>}, {@code <@foo />}. Note that we get 
{@code true} for no nested content, because
-     * that's equivalent with 0-length nested content in FTL.
-     * 
-     * <p>
-     * This method returns a pessimistic result. For example, if it sees a 
custom directive call, it can't know what it
-     * does, so it will assume that it's not cacheable.
-     */
-    boolean isNestedOutputCacheable();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/DollarVariable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/DollarVariable.java 
b/src/main/java/org/apache/freemarker/core/ast/DollarVariable.java
deleted file mode 100644
index f892766..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/DollarVariable.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.freemarker.core.ast;
-
-import java.io.IOException;
-import java.io.Writer;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.util.FTLUtil;
-
-/**
- * An instruction that outputs the value of an <tt>Expression</tt>.
- */
-final class DollarVariable extends Interpolation {
-
-    private final Expression expression;
-    
-    /** For {@code #escape x as ...} (legacy auto-escaping) */
-    private final Expression escapedExpression;
-    
-    /** For OutputFormat-based auto-escaping */
-    private final OutputFormat outputFormat;
-    private final MarkupOutputFormat markupOutputFormat;
-    private final boolean autoEscape;
-
-    DollarVariable(
-            Expression expression, Expression escapedExpression,
-            OutputFormat outputFormat, boolean autoEscape) {
-        this.expression = expression;
-        this.escapedExpression = escapedExpression;
-        this.outputFormat = outputFormat;
-        markupOutputFormat
-                = (MarkupOutputFormat) (outputFormat instanceof 
MarkupOutputFormat ? outputFormat : null);
-        this.autoEscape = autoEscape;
-    }
-
-    /**
-     * Outputs the string value of the enclosed expression.
-     */
-    @Override
-    TemplateElement[] accept(Environment env) throws TemplateException, 
IOException {
-        final Object moOrStr = calculateInterpolatedStringOrMarkup(env);
-        final Writer out = env.getOut();
-        if (moOrStr instanceof String) {
-            final String s = (String) moOrStr;
-            if (autoEscape) {
-                markupOutputFormat.output(s, out);
-            } else {
-                out.write(s);
-            }
-        } else {
-            final TemplateMarkupOutputModel mo = (TemplateMarkupOutputModel) 
moOrStr;
-            final MarkupOutputFormat moOF = mo.getOutputFormat();
-            // ATTENTION: Keep this logic in sync. ?esc/?noEsc's logic!
-            if (moOF != outputFormat && 
!outputFormat.isOutputFormatMixingAllowed()) {
-                final String srcPlainText;
-                // ATTENTION: Keep this logic in sync. ?esc/?noEsc's logic!
-                srcPlainText = moOF.getSourcePlainText(mo);
-                if (srcPlainText == null) {
-                    throw new _TemplateModelException(escapedExpression,
-                            "The value to print is in ", new 
_DelayedToString(moOF),
-                            " format, which differs from the current output 
format, ",
-                            new _DelayedToString(outputFormat), ". Format 
conversion wasn't possible.");
-                }
-                if (outputFormat instanceof MarkupOutputFormat) {
-                    ((MarkupOutputFormat) outputFormat).output(srcPlainText, 
out);
-                } else {
-                    out.write(srcPlainText);
-                }
-            } else {
-                moOF.output(mo, out);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    protected Object calculateInterpolatedStringOrMarkup(Environment env) 
throws TemplateException {
-        return 
EvalUtil.coerceModelToStringOrMarkup(escapedExpression.eval(env), 
escapedExpression, null, env);
-    }
-
-    @Override
-    protected String dump(boolean canonical, boolean inStringLiteral) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("${");
-        final String exprCF = expression.getCanonicalForm();
-        sb.append(inStringLiteral ? FTLUtil.escapeStringLiteralPart(exprCF, 
'"') : exprCF);
-        sb.append("}");
-        if (!canonical && expression != escapedExpression) {
-            sb.append(" auto-escaped");            
-        }
-        return sb.toString();
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return "${...}";
-    }
-
-    @Override
-    boolean heedsOpeningWhitespace() {
-        return true;
-    }
-
-    @Override
-    boolean heedsTrailingWhitespace() {
-        return true;
-    }
-
-    @Override
-    int getParameterCount() {
-        return 1;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        if (idx != 0) throw new IndexOutOfBoundsException();
-        return expression;
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        if (idx != 0) throw new IndexOutOfBoundsException();
-        return ParameterRole.CONTENT;
-    }
-
-    @Override
-    boolean isNestedBlockRepeater() {
-        return false;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Dot.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/Dot.java 
b/src/main/java/org/apache/freemarker/core/ast/Dot.java
deleted file mode 100644
index c3b3931..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/Dot.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.freemarker.core.ast;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.util._StringUtil;
-
-/**
- * The dot operator. Used to reference items inside a
- * <code>TemplateHashModel</code>.
- */
-final class Dot extends Expression {
-    private final Expression target;
-    private final String key;
-
-    Dot(Expression target, String key) {
-        this.target = target;
-        this.key = key;
-    }
-
-    @Override
-    TemplateModel _eval(Environment env) throws TemplateException {
-        TemplateModel leftModel = target.eval(env);
-        if (leftModel instanceof TemplateHashModel) {
-            return ((TemplateHashModel) leftModel).get(key);
-        }
-        throw new NonHashException(target, leftModel, env);
-    }
-
-    @Override
-    public String getCanonicalForm() {
-        return target.getCanonicalForm() + getNodeTypeSymbol() + 
_StringUtil.toFTLIdentifierReferenceAfterDot(key);
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return ".";
-    }
-    
-    @Override
-    boolean isLiteral() {
-        return target.isLiteral();
-    }
-
-    @Override
-    protected Expression deepCloneWithIdentifierReplaced_inner(
-            String replacedIdentifier, Expression replacement, 
ReplacemenetState replacementState) {
-       return new Dot(
-               target.deepCloneWithIdentifierReplaced(replacedIdentifier, 
replacement, replacementState),
-               key);
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 2;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        return idx == 0 ? target : key;
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        return ParameterRole.forBinaryOperatorOperand(idx);
-    }
-    
-    String getRHO() {
-        return key;
-    }
-
-    boolean onlyHasIdentifiers() {
-        return (target instanceof Identifier) || ((target instanceof Dot) && 
((Dot) target).onlyHasIdentifiers());
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/DynamicKeyName.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/DynamicKeyName.java 
b/src/main/java/org/apache/freemarker/core/ast/DynamicKeyName.java
deleted file mode 100644
index 38f4ee3..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/DynamicKeyName.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.freemarker.core.ast;
-
-import java.util.ArrayList;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.Constants;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
-
-/**
- * {@code target[keyExpression]}, where, in FM 2.3, {@code keyExpression} can 
be string, a number or a range,
- * and {@code target} can be a hash or a sequence.
- */
-final class DynamicKeyName extends Expression {
-
-    private final Expression keyExpression;
-    private final Expression target;
-
-    DynamicKeyName(Expression target, Expression keyExpression) {
-        this.target = target; 
-        this.keyExpression = keyExpression;
-    }
-
-    @Override
-    TemplateModel _eval(Environment env) throws TemplateException {
-        TemplateModel targetModel = target.eval(env);
-        target.assertNonNull(targetModel, env);
-        
-        TemplateModel keyModel = keyExpression.eval(env);
-        keyExpression.assertNonNull(keyModel, env);
-        if (keyModel instanceof TemplateNumberModel) {
-            int index = keyExpression.modelToNumber(keyModel, env).intValue();
-            return dealWithNumericalKey(targetModel, index, env);
-        }
-        if (keyModel instanceof TemplateScalarModel) {
-            String key = EvalUtil.modelToString((TemplateScalarModel) 
keyModel, keyExpression, env);
-            return dealWithStringKey(targetModel, key, env);
-        }
-        if (keyModel instanceof RangeModel) {
-            return dealWithRangeKey(targetModel, (RangeModel) keyModel, env);
-        }
-        throw new UnexpectedTypeException(keyExpression, keyModel, "number, 
range, or string",
-                new Class[] { TemplateNumberModel.class, 
TemplateScalarModel.class, Range.class }, env);
-    }
-
-    static private Class[] NUMERICAL_KEY_LHO_EXPECTED_TYPES;
-    static {
-        NUMERICAL_KEY_LHO_EXPECTED_TYPES = new Class[1 + 
NonStringException.STRING_COERCABLE_TYPES.length];
-        NUMERICAL_KEY_LHO_EXPECTED_TYPES[0] = TemplateSequenceModel.class;
-        for (int i = 0; i < NonStringException.STRING_COERCABLE_TYPES.length; 
i++) {
-            NUMERICAL_KEY_LHO_EXPECTED_TYPES[i + 1] = 
NonStringException.STRING_COERCABLE_TYPES[i];
-        }
-    }
-    
-    private TemplateModel dealWithNumericalKey(TemplateModel targetModel, 
-                                               int index, 
-                                               Environment env)
-        throws TemplateException {
-        if (targetModel instanceof TemplateSequenceModel) {
-            TemplateSequenceModel tsm = (TemplateSequenceModel) targetModel;
-            int size;
-            try {
-                size = tsm.size();
-            } catch (Exception e) {
-                size = Integer.MAX_VALUE;
-            }
-            return index < size ? tsm.get(index) : null;
-        } 
-        
-        try {
-            String s = target.evalAndCoerceToPlainText(env);
-            try {
-                return new SimpleScalar(s.substring(index, index + 1));
-            } catch (IndexOutOfBoundsException e) {
-                if (index < 0) {
-                    throw new _MiscTemplateException("Negative index not 
allowed: ", Integer.valueOf(index));
-                }
-                if (index >= s.length()) {
-                    throw new _MiscTemplateException(
-                            "String index out of range: The index was ", 
Integer.valueOf(index),
-                            " (0-based), but the length of the string is only 
", Integer.valueOf(s.length()) , ".");
-                }
-                throw new RuntimeException("Can't explain exception", e);
-            }
-        } catch (NonStringException e) {
-            throw new UnexpectedTypeException(
-                    target, targetModel,
-                    "sequence or " + 
NonStringException.STRING_COERCABLE_TYPES_DESC,
-                    NUMERICAL_KEY_LHO_EXPECTED_TYPES,
-                    (targetModel instanceof TemplateHashModel
-                            ? "You had a numberical value inside the []. 
Currently that's only supported for "
-                                    + "sequences (lists) and strings. To get a 
Map item with a non-string key, "
-                                    + "use myMap?api.get(myKey)."
-                            : null),
-                    env);
-        }
-    }
-
-    private TemplateModel dealWithStringKey(TemplateModel targetModel, String 
key, Environment env)
-        throws TemplateException {
-        if (targetModel instanceof TemplateHashModel) {
-            return((TemplateHashModel) targetModel).get(key);
-        }
-        throw new NonHashException(target, targetModel, env);
-    }
-
-    private TemplateModel dealWithRangeKey(TemplateModel targetModel, 
RangeModel range, Environment env)
-    throws UnexpectedTypeException, InvalidReferenceException, 
TemplateException {
-        final TemplateSequenceModel targetSeq;
-        final String targetStr;
-        if (targetModel instanceof TemplateSequenceModel) {
-            targetSeq = (TemplateSequenceModel) targetModel;
-            targetStr = null;
-        } else {
-            targetSeq = null;
-            try {
-                targetStr = target.evalAndCoerceToPlainText(env);
-            } catch (NonStringException e) {
-                throw new UnexpectedTypeException(
-                        target, target.eval(env),
-                        "sequence or " + 
NonStringException.STRING_COERCABLE_TYPES_DESC,
-                        NUMERICAL_KEY_LHO_EXPECTED_TYPES, env);
-            }
-        }
-        
-        final int size = range.size();
-        final boolean rightUnbounded = range.isRightUnbounded();
-        final boolean rightAdaptive = range.isRightAdaptive();
-        
-        // Right bounded empty ranges are accepted even if the begin index is 
out of bounds. That's because a such range
-        // produces an empty sequence, which thus doesn't contain any illegal 
indexes.
-        if (!rightUnbounded && size == 0) {
-            return emptyResult(targetSeq != null);
-        }
-
-        final int firstIdx = range.getBegining();
-        if (firstIdx < 0) {
-            throw new _MiscTemplateException(keyExpression,
-                    "Negative range start index (", Integer.valueOf(firstIdx),
-                    ") isn't allowed for a range used for slicing.");
-        }
-        
-        final int targetSize = targetStr != null ? targetStr.length() : 
targetSeq.size();
-        final int step = range.getStep();
-        
-        // Right-adaptive increasing ranges can start 1 after the last element 
of the target, because they are like
-        // ranges with exclusive end index of at most targetSize. Thence a 
such range is just an empty list of indexes,
-        // and thus it isn't out-of-bounds.
-        // Right-adaptive decreasing ranges has exclusive end -1, so it can't 
help on a  to high firstIndex. 
-        // Right-bounded ranges at this point aren't empty, so the right index 
surely can't reach targetSize. 
-        if (rightAdaptive && step == 1 ? firstIdx > targetSize : firstIdx >= 
targetSize) {
-            throw new _MiscTemplateException(keyExpression,
-                    "Range start index ", Integer.valueOf(firstIdx), " is out 
of bounds, because the sliced ",
-                    (targetStr != null ? "string" : "sequence"),
-                    " has only ", Integer.valueOf(targetSize), " ", (targetStr 
!= null ? "character(s)" : "element(s)"),
-                    ". ", "(Note that indices are 0-based).");
-        }
-        
-        final int resultSize;
-        if (!rightUnbounded) {
-            final int lastIdx = firstIdx + (size - 1) * step;
-            if (lastIdx < 0) {
-                if (!rightAdaptive) {
-                    throw new _MiscTemplateException(keyExpression,
-                            "Negative range end index (", 
Integer.valueOf(lastIdx),
-                            ") isn't allowed for a range used for slicing.");
-                } else {
-                    resultSize = firstIdx + 1;
-                }
-            } else if (lastIdx >= targetSize) {
-                if (!rightAdaptive) {
-                    throw new _MiscTemplateException(keyExpression,
-                            "Range end index ", Integer.valueOf(lastIdx), " is 
out of bounds, because the sliced ",
-                            (targetStr != null ? "string" : "sequence"),
-                            " has only ", Integer.valueOf(targetSize), " ", 
(targetStr != null ? "character(s)" : "element(s)"),
-                            ". (Note that indices are 0-based).");
-                } else {
-                    resultSize = Math.abs(targetSize - firstIdx);
-                }
-            } else {
-                resultSize = size;
-            }
-        } else {
-            resultSize = targetSize - firstIdx;
-        }
-        
-        if (resultSize == 0) {
-            return emptyResult(targetSeq != null);
-        }
-        if (targetSeq != null) {
-            ArrayList/*<TemplateModel>*/ list = new ArrayList(resultSize);
-            int srcIdx = firstIdx;
-            for (int i = 0; i < resultSize; i++) {
-                list.add(targetSeq.get(srcIdx));
-                srcIdx += step;
-            }
-            // List items are already wrapped, so the wrapper will be null:
-            return new SimpleSequence(list, null);
-        } else {
-            final int exclEndIdx;
-            if (step < 0 && resultSize > 1) {
-                if (!(range.isAffactedByStringSlicingBug() && resultSize == 
2)) {
-                    throw new _MiscTemplateException(keyExpression,
-                            "Decreasing ranges aren't allowed for slicing 
strings (as it would give reversed text). "
-                            + "The index range was: first = ", 
Integer.valueOf(firstIdx),
-                            ", last = ", Integer.valueOf(firstIdx + 
(resultSize - 1) * step));
-                } else {
-                    // Emulate the legacy bug, where "foo"[n .. n-1] gives "" 
instead of an error (if n >= 1).  
-                    // Fix this in FTL [2.4]
-                    exclEndIdx = firstIdx;
-                }
-            } else {
-                exclEndIdx = firstIdx + resultSize;
-            }
-            
-            return new SimpleScalar(targetStr.substring(firstIdx, exclEndIdx));
-        }
-    }
-
-    private TemplateModel emptyResult(boolean seq) {
-        return seq ? Constants.EMPTY_SEQUENCE : 
TemplateScalarModel.EMPTY_STRING;
-    }
-
-    @Override
-    public String getCanonicalForm() {
-        return target.getCanonicalForm() 
-               + "[" 
-               + keyExpression.getCanonicalForm() 
-               + "]";
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return "...[...]";
-    }
-    
-    @Override
-    boolean isLiteral() {
-        return constantValue != null || (target.isLiteral() && 
keyExpression.isLiteral());
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 2;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        return idx == 0 ? target : keyExpression;
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        return idx == 0 ? ParameterRole.LEFT_HAND_OPERAND : 
ParameterRole.ENCLOSED_OPERAND;
-    }
-
-    @Override
-    protected Expression deepCloneWithIdentifierReplaced_inner(
-            String replacedIdentifier, Expression replacement, 
ReplacemenetState replacementState) {
-       return new DynamicKeyName(
-               target.deepCloneWithIdentifierReplaced(replacedIdentifier, 
replacement, replacementState),
-               
keyExpression.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, 
replacementState));
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ElseOfList.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/ElseOfList.java 
b/src/main/java/org/apache/freemarker/core/ast/ElseOfList.java
deleted file mode 100644
index 38e1389..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/ElseOfList.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.freemarker.core.ast;
-
-import java.io.IOException;
-
-import org.apache.freemarker.core.TemplateException;
-
-/**
- * #else element that belongs to a #list, not to an #if.
- */
-final class ElseOfList extends TemplateElement {
-    
-    ElseOfList(TemplateElements children) {
-        setChildren(children);
-    }
-
-    @Override
-    TemplateElement[] accept(Environment env) throws TemplateException, 
IOException {
-        return getChildBuffer();
-    }
-
-    @Override
-    protected String dump(boolean canonical) {
-        if (canonical) {
-            StringBuilder buf = new StringBuilder();
-            buf.append('<').append(getNodeTypeSymbol()).append('>');
-            buf.append(getChildrenCanonicalForm());            
-            return buf.toString();
-        } else {
-            return getNodeTypeSymbol();
-        }
-    }
-
-    @Override
-    String getNodeTypeSymbol() {
-        return "#else";
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 0;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        throw new IndexOutOfBoundsException();
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        throw new IndexOutOfBoundsException();
-    }
-
-    @Override
-    boolean isNestedBlockRepeater() {
-        return false;
-    }
-    
-}

Reply via email to