http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/EscapeBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/EscapeBlock.java 
b/src/main/java/org/apache/freemarker/core/ast/EscapeBlock.java
deleted file mode 100644
index 07f02b5..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/EscapeBlock.java
+++ /dev/null
@@ -1,112 +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;
-import org.apache.freemarker.core.ast.Expression.ReplacemenetState;
-import org.apache.freemarker.core.util._StringUtil;
-
-/**
- * Representation of the compile-time #escape directive.
- */
-class EscapeBlock extends TemplateElement {
-
-    private final String variable;
-    private final Expression expr;
-    private Expression escapedExpr;
-
-
-    EscapeBlock(String variable, Expression expr, Expression escapedExpr) {
-        this.variable = variable;
-        this.expr = expr;
-        this.escapedExpr = escapedExpr;
-    }
-
-    void setContent(TemplateElements children) {
-        setChildren(children);
-        // We don't need it anymore at this point
-        escapedExpr = null;
-    }
-
-    @Override
-    TemplateElement[] accept(Environment env) throws TemplateException, 
IOException {
-        return getChildBuffer();
-    }
-
-    Expression doEscape(Expression expression) {
-        return escapedExpr.deepCloneWithIdentifierReplaced(variable, 
expression, new ReplacemenetState());
-    }
-
-    @Override
-    protected String dump(boolean canonical) {
-        StringBuilder sb = new StringBuilder();
-        if (canonical) sb.append('<');
-        sb.append(getNodeTypeSymbol())
-                .append(' 
').append(_StringUtil.toFTLTopLevelIdentifierReference(variable))
-                .append(" as ").append(expr.getCanonicalForm());
-        if (canonical) {
-            sb.append('>');
-            sb.append(getChildrenCanonicalForm());
-            sb.append("</").append(getNodeTypeSymbol()).append('>');
-        }
-        return sb.toString();
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return "#escape";
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 2;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        switch (idx) {
-        case 0: return variable;
-        case 1: return expr;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        switch (idx) {
-        case 0: return ParameterRole.PLACEHOLDER_VARIABLE;
-        case 1: return ParameterRole.EXPRESSION_TEMPLATE;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }    
-
-    @Override
-    boolean isOutputCacheable() {
-        return true;
-    }
-
-    @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/EvalUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/EvalUtil.java 
b/src/main/java/org/apache/freemarker/core/ast/EvalUtil.java
deleted file mode 100644
index a55769d..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/EvalUtil.java
+++ /dev/null
@@ -1,540 +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.Date;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateNumberModel;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-
-/**
- * Internally used static utilities for evaluation expressions.
- */
-class EvalUtil {
-    static final int CMP_OP_EQUALS = 1;
-    static final int CMP_OP_NOT_EQUALS = 2;
-    static final int CMP_OP_LESS_THAN = 3;
-    static final int CMP_OP_GREATER_THAN = 4;
-    static final int CMP_OP_LESS_THAN_EQUALS = 5;
-    static final int CMP_OP_GREATER_THAN_EQUALS = 6;
-    // If you add a new operator here, update the "compare" and 
"cmpOpToString" methods!
-    
-    // Prevents instantination.
-    private EvalUtil() { }
-    
-    /**
-     * @param expr {@code null} is allowed, but may results in less helpful 
error messages
-     * @param env {@code null} is allowed
-     */
-    static String modelToString(TemplateScalarModel model, Expression expr, 
Environment env)
-    throws TemplateModelException {
-        String value = model.getAsString();
-        if (value == null) {
-            throw newModelHasStoredNullException(String.class, model, expr);
-        }
-        return value;
-    }
-    
-    /**
-     * @param expr {@code null} is allowed, but may results in less helpful 
error messages
-     */
-    static Number modelToNumber(TemplateNumberModel model, Expression expr)
-        throws TemplateModelException {
-        Number value = model.getAsNumber();
-        if (value == null) throw newModelHasStoredNullException(Number.class, 
model, expr);
-        return value;
-    }
-
-    /**
-     * @param expr {@code null} is allowed, but may results in less helpful 
error messages
-     */
-    static Date modelToDate(TemplateDateModel model, Expression expr)
-        throws TemplateModelException {
-        Date value = model.getAsDate();
-        if (value == null) throw newModelHasStoredNullException(Date.class, 
model, expr);
-        return value;
-    }
-    
-    /** Signals the buggy case where we have a non-null model, but it wraps a 
null. */
-    static TemplateModelException newModelHasStoredNullException(
-            Class expected, TemplateModel model, Expression expr) {
-        return new _TemplateModelException(expr,
-                
_TemplateModelException.modelHasStoredNullDescription(expected, model));
-    }
-
-    /**
-     * Compares two expressions according the rules of the FTL comparator 
operators.
-     * 
-     * @param leftExp not {@code null}
-     * @param operator one of the {@code COMP_OP_...} constants, like {@link 
#CMP_OP_EQUALS}.
-     * @param operatorString can be null {@code null}; the actual operator 
used, used for more accurate error message.
-     * @param rightExp not {@code null}
-     * @param env {@code null} is tolerated, but should be avoided
-     */
-    static boolean compare(
-            Expression leftExp,
-            int operator, String  operatorString,
-            Expression rightExp,
-            Expression defaultBlamed,
-            Environment env) throws TemplateException {
-        TemplateModel ltm = leftExp.eval(env);
-        TemplateModel rtm = rightExp.eval(env);
-        return compare(
-                ltm, leftExp,
-                operator, operatorString,
-                rtm, rightExp,
-                defaultBlamed, false,
-                false, false, false,
-                env);
-    }
-    
-    /**
-     * Compares values according the rules of the FTL comparator operators; if 
the {@link Expression}-s are
-     * accessible, use {@link #compare(Expression, int, String, Expression, 
Expression, Environment)} instead, as
-     * that gives better error messages.
-     * 
-     * @param leftValue maybe {@code null}, which will usually cause the 
appropriate {@link TemplateException}. 
-     * @param operator one of the {@code COMP_OP_...} constants, like {@link 
#CMP_OP_EQUALS}.
-     * @param rightValue maybe {@code null}, which will usually cause the 
appropriate {@link TemplateException}.
-     * @param env {@code null} is tolerated, but should be avoided
-     */
-    static boolean compare(
-            TemplateModel leftValue, int operator, TemplateModel rightValue,
-            Environment env) throws TemplateException {
-        return compare(
-                leftValue, null,
-                operator, null,
-                rightValue, null,
-                null, false,
-                false, false, false,
-                env);
-    }
-
-    /**
-     * Same as {@link #compare(TemplateModel, int, TemplateModel, 
Environment)}, but if the two types are incompatible,
-     *     they are treated as non-equal instead of throwing an exception. 
Comparing dates of different types will
-     *     still throw an exception, however.
-     */
-    static boolean compareLenient(
-            TemplateModel leftValue, int operator, TemplateModel rightValue,
-            Environment env) throws TemplateException {
-        return compare(
-                leftValue, null,
-                operator, null,
-                rightValue, null,
-                null, false,
-                true, false, false,
-                env);
-    }
-    
-    private static final String VALUE_OF_THE_COMPARISON_IS_UNKNOWN_DATE_LIKE
-            = "value of the comparison is a date-like value where "
-              + "it's not known if it's a date (no time part), time, or 
date-time, "
-              + "and thus can't be used in a comparison.";
-    
-    /**
-     * @param leftExp {@code null} is allowed, but may results in less helpful 
error messages
-     * @param operator one of the {@code COMP_OP_...} constants, like {@link 
#CMP_OP_EQUALS}.
-     * @param operatorString can be null {@code null}; the actual operator 
used, used for more accurate error message.
-     * @param rightExp {@code null} is allowed, but may results in less 
helpful error messages
-     * @param defaultBlamed {@code null} allowed; the expression to which the 
error will point to if something goes
-     *        wrong that is not specific to the left or right side expression, 
or if that expression is {@code null}.
-     * @param typeMismatchMeansNotEqual If the two types are incompatible, 
they are treated as non-equal instead
-     *     of throwing an exception. Comparing dates of different types will 
still throw an exception, however. 
-     * @param leftNullReturnsFalse if {@code true}, a {@code null} left value 
will not cause exception, but make the
-     *     expression {@code false}.  
-     * @param rightNullReturnsFalse if {@code true}, a {@code null} right 
value will not cause exception, but make the
-     *     expression {@code false}.  
-     */
-    static boolean compare(
-            TemplateModel leftValue, Expression leftExp,
-            int operator, String operatorString,
-            TemplateModel rightValue, Expression rightExp,
-            Expression defaultBlamed, boolean quoteOperandsInErrors,
-            boolean typeMismatchMeansNotEqual,
-            boolean leftNullReturnsFalse, boolean rightNullReturnsFalse,
-            Environment env) throws TemplateException {
-        if (leftValue == null) {
-            if (leftNullReturnsFalse) { 
-                return false;
-            } else {
-                if (leftExp != null) {
-                    throw InvalidReferenceException.getInstance(leftExp, env);
-                } else {
-                    throw new _MiscTemplateException(defaultBlamed, env, 
-                                "The left operand of the comparison was 
undefined or null.");
-                }
-            }
-        }
-
-        if (rightValue == null) {
-            if (rightNullReturnsFalse) { 
-                return false;
-            } else {
-                if (rightExp != null) {
-                    throw InvalidReferenceException.getInstance(rightExp, env);
-                } else {
-                    throw new _MiscTemplateException(defaultBlamed, env,
-                                "The right operand of the comparison was 
undefined or null.");
-                }
-            }
-        }
-
-        final int cmpResult;
-        if (leftValue instanceof TemplateNumberModel && rightValue instanceof 
TemplateNumberModel) {
-            Number leftNum = EvalUtil.modelToNumber((TemplateNumberModel) 
leftValue, leftExp);
-            Number rightNum = EvalUtil.modelToNumber((TemplateNumberModel) 
rightValue, rightExp);
-            ArithmeticEngine ae =
-                    env != null
-                        ? env.getArithmeticEngine()
-                        : (leftExp != null
-                            ? leftExp.getTemplate().getArithmeticEngine()
-                            : ArithmeticEngine.BIGDECIMAL_ENGINE);
-            try {
-                cmpResult = ae.compareNumbers(leftNum, rightNum);
-            } catch (RuntimeException e) {
-                throw new _MiscTemplateException(defaultBlamed, e, env, new 
Object[]
-                        { "Unexpected error while comparing two numbers: ", e 
});
-            }
-        } else if (leftValue instanceof TemplateDateModel && rightValue 
instanceof TemplateDateModel) {
-            TemplateDateModel leftDateModel = (TemplateDateModel) leftValue;
-            TemplateDateModel rightDateModel = (TemplateDateModel) rightValue;
-            
-            int leftDateType = leftDateModel.getDateType();
-            int rightDateType = rightDateModel.getDateType();
-            
-            if (leftDateType == TemplateDateModel.UNKNOWN || rightDateType == 
TemplateDateModel.UNKNOWN) {
-                String sideName;
-                Expression sideExp;
-                if (leftDateType == TemplateDateModel.UNKNOWN) {
-                    sideName = "left";
-                    sideExp = leftExp;
-                } else {
-                    sideName = "right";
-                    sideExp = rightExp;
-                }
-                
-                throw new _MiscTemplateException(sideExp != null ? sideExp : 
defaultBlamed, env,
-                        "The ", sideName, " ", 
VALUE_OF_THE_COMPARISON_IS_UNKNOWN_DATE_LIKE);
-            }
-            
-            if (leftDateType != rightDateType) {
-                ;
-                throw new _MiscTemplateException(defaultBlamed, env,
-                        "Can't compare dates of different types. Left date 
type is ",
-                        TemplateDateModel.TYPE_NAMES.get(leftDateType), ", 
right date type is ",
-                        TemplateDateModel.TYPE_NAMES.get(rightDateType), ".");
-            }
-
-            Date leftDate = EvalUtil.modelToDate(leftDateModel, leftExp);
-            Date rightDate = EvalUtil.modelToDate(rightDateModel, rightExp);
-            cmpResult = leftDate.compareTo(rightDate);
-        } else if (leftValue instanceof TemplateScalarModel && rightValue 
instanceof TemplateScalarModel) {
-            if (operator != CMP_OP_EQUALS && operator != CMP_OP_NOT_EQUALS) {
-                throw new _MiscTemplateException(defaultBlamed, env,
-                        "Can't use operator \"", cmpOpToString(operator, 
operatorString), "\" on string values.");
-            }
-            String leftString = EvalUtil.modelToString((TemplateScalarModel) 
leftValue, leftExp, env);
-            String rightString = EvalUtil.modelToString((TemplateScalarModel) 
rightValue, rightExp, env);
-            // FIXME NBC: Don't use the Collator here. That's locale-specific, 
but ==/!= should not be.
-            cmpResult = env.getCollator().compare(leftString, rightString);
-        } else if (leftValue instanceof TemplateBooleanModel && rightValue 
instanceof TemplateBooleanModel) {
-            if (operator != CMP_OP_EQUALS && operator != CMP_OP_NOT_EQUALS) {
-                throw new _MiscTemplateException(defaultBlamed, env,
-                        "Can't use operator \"", cmpOpToString(operator, 
operatorString), "\" on boolean values.");
-            }
-            boolean leftBool = ((TemplateBooleanModel) 
leftValue).getAsBoolean();
-            boolean rightBool = ((TemplateBooleanModel) 
rightValue).getAsBoolean();
-            cmpResult = (leftBool ? 1 : 0) - (rightBool ? 1 : 0);
-        } else {
-            if (typeMismatchMeansNotEqual) {
-                if (operator == CMP_OP_EQUALS) {
-                    return false;
-                } else if (operator == CMP_OP_NOT_EQUALS) {
-                    return true;
-                }
-                // Falls through
-            }
-            throw new _MiscTemplateException(defaultBlamed, env,
-                    "Can't compare values of these types. ",
-                    "Allowed comparisons are between two numbers, two strings, 
two dates, or two booleans.\n",
-                    "Left hand operand ",
-                    (quoteOperandsInErrors && leftExp != null
-                            ? new Object[] { "(", new 
_DelayedGetCanonicalForm(leftExp), ") value " }
-                            : ""),
-                    "is ", new _DelayedAOrAn(new 
_DelayedFTLTypeDescription(leftValue)), ".\n",
-                    "Right hand operand ",
-                    (quoteOperandsInErrors && rightExp != null
-                            ? new Object[] { "(", new 
_DelayedGetCanonicalForm(rightExp), ") value " }
-                            : ""),
-                    "is ", new _DelayedAOrAn(new 
_DelayedFTLTypeDescription(rightValue)),
-                    ".");
-        }
-
-        switch (operator) {
-            case CMP_OP_EQUALS: return cmpResult == 0;
-            case CMP_OP_NOT_EQUALS: return cmpResult != 0;
-            case CMP_OP_LESS_THAN: return cmpResult < 0;
-            case CMP_OP_GREATER_THAN: return cmpResult > 0;
-            case CMP_OP_LESS_THAN_EQUALS: return cmpResult <= 0;
-            case CMP_OP_GREATER_THAN_EQUALS: return cmpResult >= 0;
-            default: throw new BugException("Unsupported comparator operator 
code: " + operator);
-        }
-    }
-
-    private static String cmpOpToString(int operator, String operatorString) {
-        if (operatorString != null) {
-            return operatorString;
-        } else {
-            switch (operator) {
-                case CMP_OP_EQUALS: return "equals";
-                case CMP_OP_NOT_EQUALS: return "not-equals";
-                case CMP_OP_LESS_THAN: return "less-than";
-                case CMP_OP_GREATER_THAN: return "greater-than";
-                case CMP_OP_LESS_THAN_EQUALS: return "less-than-equals";
-                case CMP_OP_GREATER_THAN_EQUALS: return "greater-than-equals";
-                default: return "???";
-            }
-        }
-    }
-
-    /**
-     * Converts a value to plain text {@link String}, or a {@link 
TemplateMarkupOutputModel} if that's what the
-     * {@link TemplateValueFormat} involved produces.
-     * 
-     * @param seqTip
-     *            Tip to display if the value type is not coercable, but it's 
sequence or collection.
-     * 
-     * @return Never {@code null}
-     * @throws TemplateException 
-     */
-    static Object coerceModelToStringOrMarkup(TemplateModel tm, Expression 
exp, String seqTip, Environment env)
-            throws TemplateException {
-        return coerceModelToStringOrMarkup(tm, exp, false, seqTip, env);
-    }
-    
-    /**
-     * @return {@code null} if the {@code returnNullOnNonCoercableType} 
parameter is {@code true}, and the coercion is
-     *         not possible, because of the type is not right for it.
-     * 
-     * @see #coerceModelToStringOrMarkup(TemplateModel, Expression, String, 
Environment)
-     */
-    static Object coerceModelToStringOrMarkup(
-            TemplateModel tm, Expression exp, boolean 
returnNullOnNonCoercableType, String seqTip, Environment env)
-            throws TemplateException {
-        if (tm instanceof TemplateNumberModel) {
-            TemplateNumberModel tnm = (TemplateNumberModel) tm; 
-            TemplateNumberFormat format = env.getTemplateNumberFormat(exp, 
false);
-            try {
-                return assertFormatResultNotNull(format.format(tnm));
-            } catch (TemplateValueFormatException e) {
-                throw MessageUtil.newCantFormatNumberException(format, exp, e, 
false);
-            }
-        } else if (tm instanceof TemplateDateModel) {
-            TemplateDateModel tdm = (TemplateDateModel) tm;
-            TemplateDateFormat format = env.getTemplateDateFormat(tdm, exp, 
false);
-            try {
-                return assertFormatResultNotNull(format.format(tdm));
-            } catch (TemplateValueFormatException e) {
-                throw MessageUtil.newCantFormatDateException(format, exp, e, 
false);
-            }
-        } else if (tm instanceof TemplateMarkupOutputModel) {
-            return tm;
-        } else { 
-            return coerceModelToTextualCommon(tm, exp, seqTip, true, 
returnNullOnNonCoercableType, env);
-        }
-    }
-
-    /**
-     * Like {@link #coerceModelToStringOrMarkup(TemplateModel, Expression, 
String, Environment)}, but gives error
-     * if the result is markup. This is what you normally use where markup 
results can't be used.
-     *
-     * @param seqTip
-     *            Tip to display if the value type is not coercable, but it's 
sequence or collection.
-     * 
-     * @return Never {@code null}
-     */
-    static String coerceModelToStringOrUnsupportedMarkup(
-            TemplateModel tm, Expression exp, String seqTip, Environment env)
-            throws TemplateException {
-        if (tm instanceof TemplateNumberModel) {
-            TemplateNumberModel tnm = (TemplateNumberModel) tm; 
-            TemplateNumberFormat format = env.getTemplateNumberFormat(exp, 
false);
-            try {
-                return ensureFormatResultString(format.format(tnm), exp, env);
-            } catch (TemplateValueFormatException e) {
-                throw MessageUtil.newCantFormatNumberException(format, exp, e, 
false);
-            }
-        } else if (tm instanceof TemplateDateModel) {
-            TemplateDateModel tdm = (TemplateDateModel) tm;
-            TemplateDateFormat format = env.getTemplateDateFormat(tdm, exp, 
false);
-            try {
-                return ensureFormatResultString(format.format(tdm), exp, env);
-            } catch (TemplateValueFormatException e) {
-                throw MessageUtil.newCantFormatDateException(format, exp, e, 
false);
-            }
-        } else { 
-            return coerceModelToTextualCommon(tm, exp, seqTip, false, false, 
env);
-        }
-    }
-
-    /**
-     * Converts a value to plain text {@link String}, even if the {@link 
TemplateValueFormat} involved normally produces
-     * markup. This should be used rarely, where the user clearly intend to 
use the plain text variant of the format.
-     * 
-     * @param seqTip
-     *            Tip to display if the value type is not coercable, but it's 
sequence or collection.
-     * 
-     * @return Never {@code null}
-     */
-    static String coerceModelToPlainText(TemplateModel tm, Expression exp, 
String seqTip,
-            Environment env) throws TemplateException {
-        if (tm instanceof TemplateNumberModel) {
-            return 
assertFormatResultNotNull(env.formatNumberToPlainText((TemplateNumberModel) tm, 
exp, false));
-        } else if (tm instanceof TemplateDateModel) {
-            return 
assertFormatResultNotNull(env.formatDateToPlainText((TemplateDateModel) tm, 
exp, false));
-        } else {
-            return coerceModelToTextualCommon(tm, exp, seqTip, false, false, 
env);
-        }
-    }
-
-    /**
-     * @param tm
-     *            If {@code null} that's an exception
-     * 
-     * @param supportsTOM
-     *            Whether the caller {@code coerceModelTo...} method could 
handle a {@link TemplateMarkupOutputModel}.
-     *            
-     * @return Never {@code null}
-     */
-    private static String coerceModelToTextualCommon(
-            TemplateModel tm, Expression exp, String seqHint, boolean 
supportsTOM, boolean returnNullOnNonCoercableType,
-            Environment env)
-            throws TemplateModelException, InvalidReferenceException, 
TemplateException,
-                    NonStringOrTemplateOutputException, NonStringException {
-        if (tm instanceof TemplateScalarModel) {
-            return modelToString((TemplateScalarModel) tm, exp, env);
-        } else if (tm == null) {
-            if (exp != null) {
-                throw InvalidReferenceException.getInstance(exp, env);
-            } else {
-                throw new InvalidReferenceException(
-                        "Null/missing value (no more informatoin avilable)",
-                        env);
-            }
-        } else if (tm instanceof TemplateBooleanModel) {
-            // [FM3] This should be before TemplateScalarModel, but automatic 
boolean-to-string is only non-error since
-            // 2.3.20, so to keep backward compatibility we couldn't insert 
this before TemplateScalarModel.
-            boolean booleanValue = ((TemplateBooleanModel) tm).getAsBoolean();
-            return env.formatBoolean(booleanValue, false);
-        } else {
-            if (returnNullOnNonCoercableType) {
-                return null;
-            }
-            if (seqHint != null && (tm instanceof TemplateSequenceModel || tm 
instanceof TemplateCollectionModel)) {
-                if (supportsTOM) {
-                    throw new NonStringOrTemplateOutputException(exp, tm, 
seqHint, env);
-                } else {
-                    throw new NonStringException(exp, tm, seqHint, env);
-                }
-            } else {
-                if (supportsTOM) {
-                    throw new NonStringOrTemplateOutputException(exp, tm, env);
-                } else {
-                    throw new NonStringException(exp, tm, env);
-                }
-            }
-        }
-    }
-
-    private static String ensureFormatResultString(Object formatResult, 
Expression exp, Environment env)
-            throws NonStringException {
-        if (formatResult instanceof String) { 
-            return (String) formatResult;
-        }
-        
-        assertFormatResultNotNull(formatResult);
-        
-        TemplateMarkupOutputModel mo = (TemplateMarkupOutputModel) 
formatResult;
-        _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder(
-                "Value was formatted to convert it to string, but the result 
was markup of ouput format ",
-                new _DelayedJQuote(mo.getOutputFormat()), ".")
-                .tip("Use value?string to force formatting to plain text.")
-                .blame(exp);
-        throw new NonStringException(null, desc);
-    }
-
-    static String assertFormatResultNotNull(String r) {
-        if (r != null) {
-            return r;
-        }
-        throw new NullPointerException("TemplateValueFormatter result can't be 
null");
-    }
-
-    static Object assertFormatResultNotNull(Object r) {
-        if (r != null) {
-            return r;
-        }
-        throw new NullPointerException("TemplateValueFormatter result can't be 
null");
-    }
-
-    static TemplateMarkupOutputModel concatMarkupOutputs(TemplateObject 
parent, TemplateMarkupOutputModel leftMO,
-            TemplateMarkupOutputModel rightMO) throws TemplateException {
-        MarkupOutputFormat leftOF = leftMO.getOutputFormat();
-        MarkupOutputFormat rightOF = rightMO.getOutputFormat();
-        if (rightOF != leftOF) {
-            String rightPT;
-            String leftPT;
-            if ((rightPT = rightOF.getSourcePlainText(rightMO)) != null) {
-                return leftOF.concat(leftMO, 
leftOF.fromPlainTextByEscaping(rightPT));
-            } else if ((leftPT = leftOF.getSourcePlainText(leftMO)) != null) {
-                return rightOF.concat(rightOF.fromPlainTextByEscaping(leftPT), 
rightMO);
-            } else {
-                Object[] message = { "Concatenation left hand operand is in ", 
new _DelayedToString(leftOF),
-                        " format, while the right hand operand is in ", new 
_DelayedToString(rightOF),
-                        ". Conversion to common format wasn't possible." };
-                if (parent instanceof Expression) {
-                    throw new _MiscTemplateException((Expression) parent, 
message);
-                } else {
-                    throw new _MiscTemplateException(message);
-                }
-            }
-        } else {
-            return leftOF.concat(leftMO, rightMO);
-        }
-    }
-
-    /**
-     * Returns an {@link ArithmeticEngine} even if {@code env} is {@code 
null}, because we are in parsing phase.
-     */
-    static ArithmeticEngine getArithmeticEngine(Environment env, 
TemplateObject tObj) {
-        return env != null
-                ? env.getArithmeticEngine()
-                : 
tObj.getTemplate().getParserConfiguration().getArithmeticEngine();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ExistenceBuiltins.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/ast/ExistenceBuiltins.java 
b/src/main/java/org/apache/freemarker/core/ast/ExistenceBuiltins.java
deleted file mode 100644
index 2fc343b..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/ExistenceBuiltins.java
+++ /dev/null
@@ -1,134 +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.List;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateMethodModelEx;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-
-/**
- * A holder for builtins that deal with null left-hand values.
- */
-class ExistenceBuiltins {
-
-    // Can't be instantiated
-    private ExistenceBuiltins() { }
-
-    private static abstract class ExistenceBuiltIn extends BuiltIn {
-    
-        protected TemplateModel evalMaybeNonexistentTarget(Environment env) 
throws TemplateException {
-            TemplateModel tm;
-            if (target instanceof ParentheticalExpression) {
-                boolean lastFIRE = env.setFastInvalidReferenceExceptions(true);
-                try {
-                    tm = target.eval(env);
-                } catch (InvalidReferenceException ire) {
-                    tm = null;
-                } finally {
-                    env.setFastInvalidReferenceExceptions(lastFIRE);
-                }
-            } else {
-                tm = target.eval(env);
-            }
-            return tm;
-        }
-        
-    }
-    
-    static class defaultBI extends ExistenceBuiltins.ExistenceBuiltIn {
-        
-        @Override
-        TemplateModel _eval(final Environment env) throws TemplateException {
-            TemplateModel model = evalMaybeNonexistentTarget(env);
-            return model == null ? FIRST_NON_NULL_METHOD : new 
ConstantMethod(model);
-        }
-
-        private static class ConstantMethod implements TemplateMethodModelEx {
-            private final TemplateModel constant;
-
-            ConstantMethod(TemplateModel constant) {
-                this.constant = constant;
-            }
-
-            @Override
-            public Object exec(List args) {
-                return constant;
-            }
-        }
-
-        /**
-         * A method that goes through the arguments one by one and returns
-         * the first one that is non-null. If all args are null, returns null.
-         */
-        private static final TemplateMethodModelEx FIRST_NON_NULL_METHOD =
-            new TemplateMethodModelEx() {
-                @Override
-                public Object exec(List args) throws TemplateModelException {
-                    int argCnt = args.size();
-                    if (argCnt == 0) throw 
MessageUtil.newArgCntError("?default", argCnt, 1, Integer.MAX_VALUE);
-                    for (int i = 0; i < argCnt; i++ ) {
-                        TemplateModel result = (TemplateModel) args.get(i);
-                        if (result != null) return result;
-                    }
-                    return null;
-                }
-            };
-    }
-    
-    static class existsBI extends ExistenceBuiltins.ExistenceBuiltIn {
-        @Override
-        TemplateModel _eval(Environment env) throws TemplateException {
-            return evalMaybeNonexistentTarget(env) == null ? 
TemplateBooleanModel.FALSE : TemplateBooleanModel.TRUE;
-        }
-    
-        @Override
-        boolean evalToBoolean(Environment env) throws TemplateException {
-            return _eval(env) == TemplateBooleanModel.TRUE;
-        }
-    }
-
-    static class has_contentBI extends ExistenceBuiltins.ExistenceBuiltIn {
-        @Override
-        TemplateModel _eval(Environment env) throws TemplateException {
-            return Expression.isEmpty(evalMaybeNonexistentTarget(env))
-                    ? TemplateBooleanModel.FALSE
-                    : TemplateBooleanModel.TRUE;
-        }
-    
-        @Override
-        boolean evalToBoolean(Environment env) throws TemplateException {
-            return _eval(env) == TemplateBooleanModel.TRUE;
-        }
-    }
-
-    static class if_existsBI extends ExistenceBuiltins.ExistenceBuiltIn {
-        @Override
-        TemplateModel _eval(Environment env)
-                throws TemplateException {
-            TemplateModel model = evalMaybeNonexistentTarget(env);
-            return model == null ? TemplateModel.NOTHING : model;
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ExistsExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/ExistsExpression.java 
b/src/main/java/org/apache/freemarker/core/ast/ExistsExpression.java
deleted file mode 100755
index 166fc62..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/ExistsExpression.java
+++ /dev/null
@@ -1,90 +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.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateModel;
-
-/** {@code exp??} and {@code (exp)??} */
-class ExistsExpression extends Expression {
-       
-       protected final Expression exp;
-       
-       ExistsExpression(Expression exp) {
-               this.exp = exp;
-       }
-
-       @Override
-    TemplateModel _eval(Environment env) throws TemplateException {
-        TemplateModel tm;
-           if (exp instanceof ParentheticalExpression) {
-            boolean lastFIRE = env.setFastInvalidReferenceExceptions(true);
-            try {
-                tm = exp.eval(env);
-            } catch (InvalidReferenceException ire) {
-                tm = null;
-            } finally {
-                env.setFastInvalidReferenceExceptions(lastFIRE);
-            }
-           } else {
-            tm = exp.eval(env);
-           }
-               return tm == null ? TemplateBooleanModel.FALSE : 
TemplateBooleanModel.TRUE;
-       }
-
-       @Override
-    boolean isLiteral() {
-               return false;
-       }
-
-       @Override
-    protected Expression deepCloneWithIdentifierReplaced_inner(String 
replacedIdentifier, Expression replacement, ReplacemenetState replacementState) 
{
-               return new ExistsExpression(
-                       exp.deepCloneWithIdentifierReplaced(replacedIdentifier, 
replacement, replacementState));
-       }
-
-       @Override
-    public String getCanonicalForm() {
-               return exp.getCanonicalForm() + getNodeTypeSymbol();
-       }
-       
-       @Override
-    String getNodeTypeSymbol() {
-        return "??";
-    }
-
-    @Override
-    int getParameterCount() {
-        return 1;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        return exp;
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        return ParameterRole.LEFT_HAND_OPERAND;
-    }
-       
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Expression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/Expression.java 
b/src/main/java/org/apache/freemarker/core/ast/Expression.java
deleted file mode 100644
index 7f3c9bb..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/Expression.java
+++ /dev/null
@@ -1,214 +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;
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-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.beans.BeanModel;
-
-/**
- * <b>Internal API - subject to change:</b> Represent expression nodes in the 
parsed template.
- * 
- * @deprecated This is an internal FreeMarker API with no backward 
compatibility guarantees, so you shouldn't depend on
- *             it.
- */
-@Deprecated
-abstract public class Expression extends TemplateObject {
-
-    /**
-     * @param env might be {@code null}, if this kind of expression can be 
evaluated during parsing (as opposed to
-     *     during template execution).
-     */
-    abstract TemplateModel _eval(Environment env) throws TemplateException;
-    
-    abstract boolean isLiteral();
-
-    // Used to store a constant return value for this expression. Only if it
-    // is possible, of course.
-    
-    TemplateModel constantValue;
-
-    // Hook in here to set the constant value if possible.
-    
-    @Override
-    void setLocation(Template template, int beginColumn, int beginLine, int 
endColumn, int endLine) {
-        super.setLocation(template, beginColumn, beginLine, endColumn, 
endLine);
-        if (isLiteral()) {
-            try {
-                constantValue = _eval(null);
-            } catch (Exception e) {
-            // deliberately ignore.
-            }
-        }
-    }
-
-    final TemplateModel getAsTemplateModel(Environment env) throws 
TemplateException {
-        return eval(env);
-    }
-    
-    final TemplateModel eval(Environment env) throws TemplateException {
-        return constantValue != null ? constantValue : _eval(env);
-    }
-    
-    String evalAndCoerceToPlainText(Environment env) throws TemplateException {
-        return EvalUtil.coerceModelToPlainText(eval(env), this, null, env);
-    }
-
-    /**
-     * @param seqTip Tip to display if the value type is not coercable, but 
it's sequence or collection.
-     */
-    String evalAndCoerceToPlainText(Environment env, String seqTip) throws 
TemplateException {
-        return EvalUtil.coerceModelToPlainText(eval(env), this, seqTip, env);
-    }
-
-    Object evalAndCoerceToStringOrMarkup(Environment env) throws 
TemplateException {
-        return EvalUtil.coerceModelToStringOrMarkup(eval(env), this, null, 
env);
-    }
-
-    /**
-     * @param seqTip Tip to display if the value type is not coercable, but 
it's sequence or collection.
-     */
-    Object evalAndCoerceToStringOrMarkup(Environment env, String seqTip) 
throws TemplateException {
-        return EvalUtil.coerceModelToStringOrMarkup(eval(env), this, seqTip, 
env);
-    }
-    
-    String evalAndCoerceToStringOrUnsupportedMarkup(Environment env) throws 
TemplateException {
-        return EvalUtil.coerceModelToStringOrUnsupportedMarkup(eval(env), 
this, null, env);
-    }
-
-    /**
-     * @param seqTip Tip to display if the value type is not coercable, but 
it's sequence or collection.
-     */
-    String evalAndCoerceToStringOrUnsupportedMarkup(Environment env, String 
seqTip) throws TemplateException {
-        return EvalUtil.coerceModelToStringOrUnsupportedMarkup(eval(env), 
this, seqTip, env);
-    }
-    
-    Number evalToNumber(Environment env) throws TemplateException {
-        TemplateModel model = eval(env);
-        return modelToNumber(model, env);
-    }
-
-    Number modelToNumber(TemplateModel model, Environment env) throws 
TemplateException {
-        if (model instanceof TemplateNumberModel) {
-            return EvalUtil.modelToNumber((TemplateNumberModel) model, this);
-        } else {
-            throw new NonNumericalException(this, model, env);
-        }
-    }
-    
-    boolean evalToBoolean(Environment env) throws TemplateException {
-        return evalToBoolean(env, null);
-    }
-
-    boolean evalToBoolean(Configuration cfg) throws TemplateException {
-        return evalToBoolean(null, cfg);
-    }
-
-    TemplateModel evalToNonMissing(Environment env) throws TemplateException {
-        TemplateModel result = eval(env);
-        assertNonNull(result, env);
-        return result;
-    }
-    
-    private boolean evalToBoolean(Environment env, Configuration cfg) throws 
TemplateException {
-        TemplateModel model = eval(env);
-        return modelToBoolean(model, env, cfg);
-    }
-    
-    boolean modelToBoolean(TemplateModel model, Environment env) throws 
TemplateException {
-        return modelToBoolean(model, env, null);
-    }
-
-    boolean modelToBoolean(TemplateModel model, Configuration cfg) throws 
TemplateException {
-        return modelToBoolean(model, null, cfg);
-    }
-    
-    private boolean modelToBoolean(TemplateModel model, Environment env, 
Configuration cfg) throws TemplateException {
-        if (model instanceof TemplateBooleanModel) {
-            return ((TemplateBooleanModel) model).getAsBoolean();
-        } else {
-            throw new NonBooleanException(this, model, env);
-        }
-    }
-    
-    final Expression deepCloneWithIdentifierReplaced(
-            String replacedIdentifier, Expression replacement, 
ReplacemenetState replacementState) {
-        Expression clone = 
deepCloneWithIdentifierReplaced_inner(replacedIdentifier, replacement, 
replacementState);
-        if (clone.beginLine == 0) {
-            clone.copyLocationFrom(this);
-        }
-        return clone;
-    }
-    
-    static class ReplacemenetState {
-        /**
-         * If the replacement expression is not in use yet, we don't have to 
clone it.
-         */
-        boolean replacementAlreadyInUse; 
-    }
-
-    /**
-     * This should return an equivalent new expression object (or an 
identifier replacement expression).
-     * The position need not be filled, unless it will be different from the 
position of what we were cloning. 
-     */
-    protected abstract Expression deepCloneWithIdentifierReplaced_inner(
-            String replacedIdentifier, Expression replacement, 
ReplacemenetState replacementState);
-
-    static boolean isEmpty(TemplateModel model) throws TemplateModelException {
-        if (model instanceof BeanModel) {
-            return ((BeanModel) model).isEmpty();
-        } else if (model instanceof TemplateSequenceModel) {
-            return ((TemplateSequenceModel) model).size() == 0;
-        } else if (model instanceof TemplateScalarModel) {
-            String s = ((TemplateScalarModel) model).getAsString();
-            return (s == null || s.length() == 0);
-        } else if (model == null) {
-            return true;
-        } else if (model instanceof TemplateMarkupOutputModel) { // Note: 
happens just after FTL string check
-            TemplateMarkupOutputModel mo = (TemplateMarkupOutputModel) model;
-            return mo.getOutputFormat().isEmpty(mo);
-        } else if (model instanceof TemplateCollectionModel) {
-            return !((TemplateCollectionModel) model).iterator().hasNext();
-        } else if (model instanceof TemplateHashModel) {
-            return ((TemplateHashModel) model).isEmpty();
-        } else if (model instanceof TemplateNumberModel
-                || model instanceof TemplateDateModel
-                || model instanceof TemplateBooleanModel) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-    
-    void assertNonNull(TemplateModel model, Environment env) throws 
InvalidReferenceException {
-        if (model == null) throw InvalidReferenceException.getInstance(this, 
env);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ExtendedDecimalFormatParser.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/ast/ExtendedDecimalFormatParser.java 
b/src/main/java/org/apache/freemarker/core/ast/ExtendedDecimalFormatParser.java
deleted file mode 100644
index 4f09696..0000000
--- 
a/src/main/java/org/apache/freemarker/core/ast/ExtendedDecimalFormatParser.java
+++ /dev/null
@@ -1,525 +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.math.RoundingMode;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.ParseException;
-import java.util.Arrays;
-import java.util.Currency;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Set;
-
-import org.apache.freemarker.core.util._StringUtil;
-
-class ExtendedDecimalFormatParser {
-    
-    private static final String PARAM_ROUNDING_MODE = "roundingMode";
-    private static final String PARAM_MULTIPIER = "multipier";
-    private static final String PARAM_DECIMAL_SEPARATOR = "decimalSeparator";
-    private static final String PARAM_MONETARY_DECIMAL_SEPARATOR = 
"monetaryDecimalSeparator";
-    private static final String PARAM_GROUP_SEPARATOR = "groupingSeparator";
-    private static final String PARAM_EXPONENT_SEPARATOR = "exponentSeparator";
-    private static final String PARAM_MINUS_SIGN = "minusSign";
-    private static final String PARAM_INFINITY = "infinity";
-    private static final String PARAM_NAN = "nan";
-    private static final String PARAM_PERCENT = "percent";
-    private static final String PARAM_PER_MILL = "perMill";
-    private static final String PARAM_ZERO_DIGIT = "zeroDigit";
-    private static final String PARAM_CURRENCY_CODE = "currencyCode";
-    private static final String PARAM_CURRENCY_SYMBOL = "currencySymbol";
-
-    private static final String PARAM_VALUE_RND_UP = "up";
-    private static final String PARAM_VALUE_RND_DOWN = "down";
-    private static final String PARAM_VALUE_RND_CEILING = "ceiling";
-    private static final String PARAM_VALUE_RND_FLOOR = "floor";
-    private static final String PARAM_VALUE_RND_HALF_DOWN = "halfDown";
-    private static final String PARAM_VALUE_RND_HALF_EVEN = "halfEven";
-    private static final String PARAM_VALUE_RND_HALF_UP = "halfUp";
-    private static final String PARAM_VALUE_RND_UNNECESSARY = "unnecessary";
-    
-    private static final HashMap<String, ? extends ParameterHandler> 
PARAM_HANDLERS;
-    static {
-        HashMap<String, ParameterHandler> m = new HashMap<>();
-        m.put(PARAM_ROUNDING_MODE, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                RoundingMode parsedValue;
-                if (value.equals(PARAM_VALUE_RND_UP)) {
-                    parsedValue = RoundingMode.UP;
-                } else if (value.equals(PARAM_VALUE_RND_DOWN)) {
-                    parsedValue = RoundingMode.DOWN;
-                } else if (value.equals(PARAM_VALUE_RND_CEILING)) {
-                    parsedValue = RoundingMode.CEILING;
-                } else if (value.equals(PARAM_VALUE_RND_FLOOR)) {
-                    parsedValue = RoundingMode.FLOOR;
-                } else if (value.equals(PARAM_VALUE_RND_HALF_DOWN)) {
-                    parsedValue = RoundingMode.HALF_DOWN;
-                } else if (value.equals(PARAM_VALUE_RND_HALF_EVEN)) {
-                    parsedValue = RoundingMode.HALF_EVEN;
-                } else if (value.equals(PARAM_VALUE_RND_HALF_UP)) {
-                    parsedValue = RoundingMode.HALF_UP;
-                } else if (value.equals(PARAM_VALUE_RND_UNNECESSARY)) {
-                    parsedValue = RoundingMode.UNNECESSARY;
-                } else {
-                    throw new InvalidParameterValueException("Should be one 
of: u, d, c, f, hd, he, hu, un");
-                }
-
-                parser.roundingMode = parsedValue;
-            }
-        });
-        m.put(PARAM_MULTIPIER, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                try {
-                    parser.multipier = Integer.valueOf(value);
-                } catch (NumberFormatException e) {
-                    throw new InvalidParameterValueException("Malformed 
integer.");
-                }
-            }
-        });
-        m.put(PARAM_DECIMAL_SEPARATOR, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                if (value.length() != 1) {
-                    throw new InvalidParameterValueException("Must contain 
exactly 1 character.");
-                }
-                parser.symbols.setDecimalSeparator(value.charAt(0));
-            }
-        });
-        m.put(PARAM_MONETARY_DECIMAL_SEPARATOR, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                if (value.length() != 1) {
-                    throw new InvalidParameterValueException("Must contain 
exactly 1 character.");
-                }
-                parser.symbols.setMonetaryDecimalSeparator(value.charAt(0));
-            }
-        });
-        m.put(PARAM_GROUP_SEPARATOR, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                if (value.length() != 1) {
-                    throw new InvalidParameterValueException("Must contain 
exactly 1 character.");
-                }
-                parser.symbols.setGroupingSeparator(value.charAt(0));
-            }
-        });
-        m.put(PARAM_EXPONENT_SEPARATOR, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                parser.symbols.setExponentSeparator(value);
-            }
-        });
-        m.put(PARAM_MINUS_SIGN, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                if (value.length() != 1) {
-                    throw new InvalidParameterValueException("Must contain 
exactly 1 character.");
-                }
-                parser.symbols.setMinusSign(value.charAt(0));
-            }
-        });
-        m.put(PARAM_INFINITY, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                parser.symbols.setInfinity(value);
-            }
-        });
-        m.put(PARAM_NAN, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                parser.symbols.setNaN(value);
-            }
-        });
-        m.put(PARAM_PERCENT, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                if (value.length() != 1) {
-                    throw new InvalidParameterValueException("Must contain 
exactly 1 character.");
-                }
-                parser.symbols.setPercent(value.charAt(0));
-            }
-        });
-        m.put(PARAM_PER_MILL, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                if (value.length() != 1) {
-                    throw new InvalidParameterValueException("Must contain 
exactly 1 character.");
-                }
-                parser.symbols.setPerMill(value.charAt(0));
-            }
-        });
-        m.put(PARAM_ZERO_DIGIT, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                if (value.length() != 1) {
-                    throw new InvalidParameterValueException("Must contain 
exactly 1 character.");
-                }
-                parser.symbols.setZeroDigit(value.charAt(0));
-            }
-        });
-        m.put(PARAM_CURRENCY_CODE, new ParameterHandler() {
-            @Override
-            public void handle(ExtendedDecimalFormatParser parser, String 
value)
-                    throws InvalidParameterValueException {
-                Currency currency;
-                try {
-                    currency = Currency.getInstance(value);
-                } catch (IllegalArgumentException e) {
-                    throw new InvalidParameterValueException("Not a known ISO 
4217 code.");
-                }
-                parser.symbols.setCurrency(currency);
-            }
-        });
-        PARAM_HANDLERS = m;
-    }
-
-    private static final String SNIP_MARK = "[...]";
-    private static final int MAX_QUOTATION_LENGTH = 10; // Must be more than 
SNIP_MARK.length!
-
-    private final String src;
-    private int pos = 0;
-
-    private final DecimalFormatSymbols symbols;
-    private RoundingMode roundingMode;
-    private Integer multipier;
-
-    static DecimalFormat parse(String formatString, Locale locale) throws 
ParseException {
-        return new ExtendedDecimalFormatParser(formatString, locale).parse();
-    }
-
-    private DecimalFormat parse() throws ParseException {
-        String stdPattern = fetchStandardPattern();
-        skipWS();
-        parseFormatStringExtension();
-
-        DecimalFormat decimalFormat;
-        try {
-            decimalFormat = new DecimalFormat(stdPattern, symbols);
-        } catch (IllegalArgumentException e) {
-            ParseException pe = new ParseException(e.getMessage(), 0);
-            if (e.getCause() != null) {
-                try {
-                    e.initCause(e.getCause());
-                } catch (Exception e2) {
-                    // Supress
-                }
-            }
-            throw pe;
-        }
-
-        if (roundingMode != null) {
-            decimalFormat.setRoundingMode(roundingMode);
-        }
-
-        if (multipier != null) {
-            decimalFormat.setMultiplier(multipier.intValue());
-        }
-
-        return decimalFormat;
-    }
-
-    private void parseFormatStringExtension() throws ParseException {
-        int ln = src.length();
-
-        if (pos == ln) {
-            return;
-        }
-
-        String currencySymbol = null;  // Exceptional, as must be applied 
after "currency code"
-        fetchParamters: do {
-            int namePos = pos;
-            String name = fetchName();
-            if (name == null) {
-                throw newExpectedSgParseException("name");
-            }
-
-            skipWS();
-
-            if (!fetchChar('=')) {
-                throw newExpectedSgParseException("\"=\"");
-            }
-
-            skipWS();
-
-            int valuePos = pos;
-            String value = fetchValue();
-            if (value == null) {
-                throw newExpectedSgParseException("value");
-            }
-            int paramEndPos = pos;
-
-            ParameterHandler handler = PARAM_HANDLERS.get(name);
-            if (handler == null) {
-                if (name.equals(PARAM_CURRENCY_SYMBOL)) {
-                    currencySymbol = value;
-                } else {
-                    throw newUnknownParameterException(name, namePos);
-                }
-            } else {
-                try {
-                    handler.handle(this, value);
-                } catch (InvalidParameterValueException e) {
-                    throw newInvalidParameterValueException(name, value, 
valuePos, e);
-                }
-            }
-
-            skipWS();
-
-            // Optional comma
-            if (fetchChar(',')) {
-                skipWS();
-            } else {
-                if (pos == ln) {
-                    break fetchParamters;
-                }
-                if (pos == paramEndPos) {
-                    throw newExpectedSgParseException("parameter separator 
whitespace or comma");
-                }
-            }
-        } while (true);
-        
-        // This is brought out to here to ensure that it's applied after 
"currency code":
-        if (currencySymbol != null) {
-            symbols.setCurrencySymbol(currencySymbol);
-        }
-    }
-
-    private ParseException newInvalidParameterValueException(String name, 
String value, int valuePos,
-            InvalidParameterValueException e) {
-        return new java.text.ParseException(
-                _StringUtil.jQuote(value) + " is an invalid value for the \"" 
+ name + "\" parameter: "
-                + e.message,
-                valuePos);
-    }
-
-    private ParseException newUnknownParameterException(String name, int 
namePos) throws ParseException {
-        StringBuilder sb = new StringBuilder(128);
-        sb.append("Unsupported parameter name, 
").append(_StringUtil.jQuote(name));
-        sb.append(". The supported names are: ");
-        Set<String> legalNames = PARAM_HANDLERS.keySet();
-        String[] legalNameArr = legalNames.toArray(new 
String[legalNames.size()]);
-        Arrays.sort(legalNameArr);
-        for (int i = 0; i < legalNameArr.length; i++) {
-            if (i != 0) {
-                sb.append(", ");
-            }
-            sb.append(legalNameArr[i]);
-        }
-        return new java.text.ParseException(sb.toString(), namePos);
-    }
-
-    private void skipWS() {
-        int ln = src.length();
-        while (pos < ln && isWS(src.charAt(pos))) {
-            pos++;
-        }
-    }
-
-    private boolean fetchChar(char fetchedChar) {
-        if (pos < src.length() && src.charAt(pos) == fetchedChar) {
-            pos++;
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private boolean isWS(char c) {
-        return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 
'\u00A0';
-    }
-
-    private String fetchName() throws ParseException {
-        int ln = src.length();
-        int startPos = pos;
-        boolean firstChar = true;
-        scanUntilEnd: while (pos < ln) {
-            char c = src.charAt(pos);
-            if (firstChar) {
-                if (!Character.isJavaIdentifierStart(c)) {
-                    break scanUntilEnd;
-                }
-                firstChar = false;
-            } else if (!Character.isJavaIdentifierPart(c)) {
-                break scanUntilEnd;
-            }
-            pos++;
-        }
-        return !firstChar ? src.substring(startPos, pos) : null;
-    }
-
-    private String fetchValue() throws ParseException {
-        int ln = src.length();
-        int startPos = pos;
-        char openedQuot = 0;
-        boolean needsUnescaping = false;
-        scanUntilEnd: while (pos < ln) {
-            char c = src.charAt(pos);
-            if (c == '\'' || c == '"') {
-                if (openedQuot == 0) {
-                    if (startPos != pos) {
-                        throw new java.text.ParseException(
-                                "The " + c + " character can only be used for 
quoting values, "
-                                        + "but it was in the middle of an 
non-quoted value.",
-                                pos);
-                    }
-                    openedQuot = c;
-                } else if (c == openedQuot) {
-                    if (pos + 1 < ln && src.charAt(pos + 1) == openedQuot) {
-                        pos++; // skip doubled quote (escaping)
-                        needsUnescaping = true;
-                    } else {
-                        String str = src.substring(startPos + 1, pos);
-                        pos++;
-                        return needsUnescaping ? unescape(str, openedQuot) : 
str;
-                    }
-                }
-            } else {
-                if (openedQuot == 0 && !Character.isJavaIdentifierPart(c)) {
-                    break scanUntilEnd;
-                }
-            }
-            pos++;
-        } // while
-        if (openedQuot != 0) {
-            throw new java.text.ParseException(
-                    "The " + openedQuot 
-                    + " quotation wasn't closed when the end of the source was 
reached.",
-                    pos);
-        }
-        return startPos == pos ? null : src.substring(startPos, pos);
-    }
-
-    private String unescape(String s, char openedQuot) {
-        return openedQuot == '\'' ? _StringUtil.replace(s, "\'\'", "\'") : 
_StringUtil.replace(s, "\"\"", "\"");
-    }
-
-    private String fetchStandardPattern() {
-        int pos = this.pos;
-        int ln = src.length();
-        int semicolonCnt = 0;
-        boolean quotedMode = false;
-        findStdPartEnd: while (pos < ln) {
-            char c = src.charAt(pos);
-            if (c == ';' && !quotedMode) {
-                semicolonCnt++;
-                if (semicolonCnt == 2) {
-                    break findStdPartEnd;
-                }
-            } else if (c == '\'') {
-                if (quotedMode) {
-                    if (pos + 1 < ln && src.charAt(pos + 1) == '\'') {
-                        // Skips "''" used for escaping "'"
-                        pos++;
-                    } else {
-                        quotedMode = false;
-                    }
-                } else {
-                    quotedMode = true;
-                }
-            }
-            pos++;
-        }
-
-        String stdFormatStr;
-        if (semicolonCnt < 2) { // We have a standard DecimalFormat string
-            // Note that "0.0;" and "0.0" gives the same result with 
DecimalFormat, so we leave a ';' there
-            stdFormatStr = src;
-        } else { // `pos` points to the 2nd ';'
-            int stdEndPos = pos;
-            if (src.charAt(pos - 1) == ';') { // we have a ";;"
-                // Note that ";;" is illegal in DecimalFormat, so this is 
backward compatible.
-                stdEndPos--;
-            }
-            stdFormatStr = src.substring(0, stdEndPos);
-        }
-
-        if (pos < ln) {
-            pos++; // Skips closing ';'
-        }
-        this.pos = pos;
-
-        return stdFormatStr;
-    }
-
-    private ExtendedDecimalFormatParser(String formatString, Locale locale) {
-        src = formatString;
-        symbols = new DecimalFormatSymbols(locale);
-    }
-
-    private ParseException newExpectedSgParseException(String expectedThing) {
-        String quotation;
-
-        // Ignore trailing WS when calculating the length:
-        int i = src.length() - 1;
-        while (i >= 0 && Character.isWhitespace(src.charAt(i))) {
-            i--;
-        }
-        int ln = i + 1;
-
-        if (pos < ln) {
-            int qEndPos = pos + MAX_QUOTATION_LENGTH;
-            if (qEndPos >= ln) {
-                quotation = src.substring(pos, ln);
-            } else {
-                quotation = src.substring(pos, qEndPos - SNIP_MARK.length()) + 
SNIP_MARK;
-            }
-        } else {
-            quotation = null;
-        }
-
-        return new ParseException(
-                "Expected a(n) " + expectedThing + " at position " + pos + " 
(0-based), but "
-                        + (quotation == null ? "reached the end of the input." 
: "found: " + quotation),
-                pos);
-    }
-
-    private interface ParameterHandler {
-
-        void handle(ExtendedDecimalFormatParser parser, String value)
-                throws InvalidParameterValueException;
-
-    }
-
-    private static class InvalidParameterValueException extends Exception {
-
-        private final String message;
-
-        public InvalidParameterValueException(String message) {
-            this.message = message;
-        }
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/FallbackInstruction.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/ast/FallbackInstruction.java 
b/src/main/java/org/apache/freemarker/core/ast/FallbackInstruction.java
deleted file mode 100644
index d5fe03c..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/FallbackInstruction.java
+++ /dev/null
@@ -1,69 +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;
-
-final class FallbackInstruction extends TemplateElement {
-
-    @Override
-    TemplateElement[] accept(Environment env) throws IOException, 
TemplateException {
-        env.fallback();
-        return null;
-    }
-
-    @Override
-    protected String dump(boolean canonical) {
-        return canonical ? "<" + getNodeTypeSymbol() + "/>" : 
getNodeTypeSymbol();
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return "#fallback";
-    }
-    
-    @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;
-    }
-    
-    @Override
-    boolean isShownInStackTrace() {
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/FlushInstruction.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/FlushInstruction.java 
b/src/main/java/org/apache/freemarker/core/ast/FlushInstruction.java
deleted file mode 100644
index fd9518a..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/FlushInstruction.java
+++ /dev/null
@@ -1,65 +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;
-
-/**
- * An instruction that flushes the output stream.
- */
-final class FlushInstruction extends TemplateElement {
-
-    @Override
-    TemplateElement[] accept(Environment env) throws IOException {
-        env.getOut().flush();
-        return null;
-    }
-
-    @Override
-    protected String dump(boolean canonical) {
-        return canonical ? "<" + getNodeTypeSymbol() + "/>" : 
getNodeTypeSymbol();
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return "#flush";
-    }
- 
-    @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;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/HTMLOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/HTMLOutputFormat.java 
b/src/main/java/org/apache/freemarker/core/ast/HTMLOutputFormat.java
deleted file mode 100644
index ca0ae6d..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/HTMLOutputFormat.java
+++ /dev/null
@@ -1,75 +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.model.TemplateModelException;
-import org.apache.freemarker.core.util._StringUtil;
-
-/**
- * Represents the HTML output format (MIME type "text/html", name "HTML"). 
This format escapes by default (via
- * {@link _StringUtil#XHTMLEnc(String)}). The {@code ?html}, {@code ?xhtml} 
and {@code ?xml} built-ins silently bypass
- * template output values of the type produced by this output format ({@link 
TemplateHTMLOutputModel}).
- * 
- * @since 2.3.24
- */
-public final class HTMLOutputFormat extends 
CommonMarkupOutputFormat<TemplateHTMLOutputModel> {
-
-    /**
-     * The only instance (singleton) of this {@link OutputFormat}.
-     */
-    public static final HTMLOutputFormat INSTANCE = new HTMLOutputFormat();
-    
-    private HTMLOutputFormat() {
-        // Only to decrease visibility
-    }
-    
-    @Override
-    public String getName() {
-        return "HTML";
-    }
-
-    @Override
-    public String getMimeType() {
-        return "text/html";
-    }
-
-    @Override
-    public void output(String textToEsc, Writer out) throws IOException, 
TemplateModelException {
-        _StringUtil.XHTMLEnc(textToEsc, out);
-    }
-
-    @Override
-    public String escapePlainText(String plainTextContent) {
-        return _StringUtil.XHTMLEnc(plainTextContent);
-    }
-
-    @Override
-    public boolean isLegacyBuiltInBypassed(String builtInName) {
-        return builtInName.equals("html") || builtInName.equals("xml") || 
builtInName.equals("xhtml");
-    }
-
-    @Override
-    protected TemplateHTMLOutputModel newTemplateMarkupOutputModel(String 
plainTextContent, String markupContent) {
-        return new TemplateHTMLOutputModel(plainTextContent, markupContent);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/HashLiteral.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/HashLiteral.java 
b/src/main/java/org/apache/freemarker/core/ast/HashLiteral.java
deleted file mode 100644
index 1b8bf3a..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/HashLiteral.java
+++ /dev/null
@@ -1,218 +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 java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.ListIterator;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateHashModelEx2;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateModelIterator;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
-
-final class HashLiteral extends Expression {
-
-    private final ArrayList keys, values;
-    private final int size;
-
-    HashLiteral(ArrayList/*<Expression>*/ keys, ArrayList/*<Expression>*/ 
values) {
-        this.keys = keys;
-        this.values = values;
-        size = keys.size();
-        keys.trimToSize();
-        values.trimToSize();
-    }
-
-    @Override
-    TemplateModel _eval(Environment env) throws TemplateException {
-        return new SequenceHash(env);
-    }
-
-    @Override
-    public String getCanonicalForm() {
-        StringBuilder buf = new StringBuilder("{");
-        for (int i = 0; i < size; i++) {
-            Expression key = (Expression) keys.get(i);
-            Expression value = (Expression) values.get(i);
-            buf.append(key.getCanonicalForm());
-            buf.append(": ");
-            buf.append(value.getCanonicalForm());
-            if (i != size - 1) {
-                buf.append(", ");
-            }
-        }
-        buf.append("}");
-        return buf.toString();
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return "{...}";
-    }
-
-    @Override
-    boolean isLiteral() {
-        if (constantValue != null) {
-            return true;
-        }
-        for (int i = 0; i < size; i++) {
-            Expression key = (Expression) keys.get(i);
-            Expression value = (Expression) values.get(i);
-            if (!key.isLiteral() || !value.isLiteral()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-
-    @Override
-    protected Expression deepCloneWithIdentifierReplaced_inner(
-            String replacedIdentifier, Expression replacement, 
ReplacemenetState replacementState) {
-               ArrayList clonedKeys = (ArrayList) keys.clone();
-               for (ListIterator iter = clonedKeys.listIterator(); 
iter.hasNext(); ) {
-            iter.set(((Expression) 
iter.next()).deepCloneWithIdentifierReplaced(
-                    replacedIdentifier, replacement, replacementState));
-        }
-               ArrayList clonedValues = (ArrayList) values.clone();
-               for (ListIterator iter = clonedValues.listIterator(); 
iter.hasNext(); ) {
-            iter.set(((Expression) 
iter.next()).deepCloneWithIdentifierReplaced(
-                    replacedIdentifier, replacement, replacementState));
-        }
-       return new HashLiteral(clonedKeys, clonedValues);
-    }
-
-    private class SequenceHash implements TemplateHashModelEx2 {
-
-        private HashMap map; // maps keys to integer offset
-        private TemplateCollectionModel keyCollection, valueCollection; // 
ordered lists of keys and values
-
-        SequenceHash(Environment env) throws TemplateException {
-            map = new LinkedHashMap();
-            for (int i = 0; i < size; i++) {
-                Expression keyExp = (Expression) keys.get(i);
-                Expression valExp = (Expression) values.get(i);
-                String key = keyExp.evalAndCoerceToPlainText(env);
-                TemplateModel value = valExp.eval(env);
-                valExp.assertNonNull(value, env);
-                map.put(key, value);
-            }
-        }
-
-        @Override
-        public int size() {
-            return size;
-        }
-
-        @Override
-        public TemplateCollectionModel keys() {
-            if (keyCollection == null) {
-                keyCollection = new CollectionAndSequence(new 
SimpleSequence(map.keySet()));
-            }
-            return keyCollection;
-        }
-
-        @Override
-        public TemplateCollectionModel values() {
-            if (valueCollection == null) {
-                valueCollection = new CollectionAndSequence(new 
SimpleSequence(map.values()));
-            }
-            return valueCollection;
-        }
-
-        @Override
-        public TemplateModel get(String key) {
-            return (TemplateModel) map.get(key);
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return size == 0;
-        }
-        
-        @Override
-        public String toString() {
-            return getCanonicalForm();
-        }
-
-        @Override
-        public KeyValuePairIterator keyValuePairIterator() throws 
TemplateModelException {
-            return new KeyValuePairIterator() {
-                private final TemplateModelIterator keyIterator = 
keys().iterator();
-                private final TemplateModelIterator valueIterator = 
values().iterator();
-
-                @Override
-                public boolean hasNext() throws TemplateModelException {
-                    return keyIterator.hasNext();
-                }
-
-                @Override
-                public KeyValuePair next() throws TemplateModelException {
-                    return new KeyValuePair() {
-                        private final TemplateModel key = keyIterator.next();
-                        private final TemplateModel value = 
valueIterator.next();
-
-                        @Override
-                        public TemplateModel getKey() throws 
TemplateModelException {
-                            return key;
-                        }
-
-                        @Override
-                        public TemplateModel getValue() throws 
TemplateModelException {
-                            return value;
-                        }
-                        
-                    };
-                }
-                
-            };
-        }
-        
-    }
-
-    @Override
-    int getParameterCount() {
-        return size * 2;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        checkIndex(idx);
-        return idx % 2 == 0 ? keys.get(idx / 2) : values.get(idx / 2);
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        checkIndex(idx);
-        return idx % 2 == 0 ? ParameterRole.ITEM_KEY : 
ParameterRole.ITEM_VALUE;
-    }
-
-    private void checkIndex(int idx) {
-        if (idx >= size * 2) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-    
-}

Reply via email to