/*
 *
 *  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.flex.compiler.internal.as.codegen;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Vector;
import java.util.Stack;

import static org.apache.flex.abc.ABCConstants.*;

import org.apache.flex.abc.ABCConstants;
import org.apache.flex.abc.instructionlist.InstructionList;
import org.apache.flex.abc.semantics.ECMASupport;
import org.apache.flex.abc.semantics.Instruction;
import org.apache.flex.abc.semantics.InstructionFactory;
import org.apache.flex.abc.semantics.Label;
import org.apache.flex.abc.semantics.MethodInfo;
import org.apache.flex.abc.semantics.Name;
import org.apache.flex.abc.semantics.Namespace;
import org.apache.flex.abc.semantics.NoOperandsInstruction;
import org.apache.flex.abc.semantics.Nsset;
import org.apache.flex.abc.semantics.PooledValue;
import org.apache.flex.compiler.constants.IASLanguageConstants;
import org.apache.flex.compiler.constants.IASLanguageConstants.BuiltinType;
import org.apache.flex.compiler.definitions.IAccessorDefinition;
import org.apache.flex.compiler.definitions.IConstantDefinition;
import org.apache.flex.compiler.definitions.IDefinition;
import org.apache.flex.compiler.definitions.ITypeDefinition;
import org.apache.flex.compiler.definitions.IVariableDefinition;
import org.apache.flex.compiler.exceptions.CodegenInterruptedException;
import org.apache.flex.compiler.exceptions.DuplicateLabelException;
import org.apache.flex.compiler.exceptions.UnknownControlFlowTargetException;
import org.apache.flex.compiler.internal.semantics.SemanticUtils;
import org.apache.flex.compiler.internal.tree.as.BaseVariableNode;
import org.apache.flex.compiler.internal.tree.as.VariableExpressionNode;
import org.apache.flex.compiler.problems.AmbiguousGotoTargetProblem;
import org.apache.flex.compiler.problems.AnyNamespaceCannotBeQualifierProblem;
import org.apache.flex.compiler.problems.CodegenInternalProblem;
import org.apache.flex.compiler.problems.DuplicateLabelProblem;
import org.apache.flex.compiler.problems.DuplicateNamespaceDefinitionProblem;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.InvalidLvalueProblem;
import org.apache.flex.compiler.problems.InvalidNamespaceInitializerProblem;
import org.apache.flex.compiler.problems.MultipleSwitchDefaultsProblem;
import org.apache.flex.compiler.problems.NonConstantParamInitializerProblem;
import org.apache.flex.compiler.problems.PackageCannotBeUsedAsValueProblem;
import org.apache.flex.compiler.problems.UnexpectedReturnProblem;
import org.apache.flex.compiler.problems.UnknownGotoTargetProblem;
import org.apache.flex.compiler.problems.UnknownNamespaceProblem;
import org.apache.flex.compiler.problems.UnknownBreakTargetProblem;
import org.apache.flex.compiler.problems.UnknownContinueTargetProblem;
import org.apache.flex.compiler.problems.VoidTypeProblem;
import org.apache.flex.compiler.projects.ICompilerProject;
import org.apache.flex.compiler.tree.as.IASNode;
import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
import org.apache.flex.compiler.tree.as.ICatchNode;
import org.apache.flex.compiler.tree.as.IContainerNode;
import org.apache.flex.compiler.tree.as.IExpressionNode;
import org.apache.flex.compiler.tree.as.IForLoopNode;
import org.apache.flex.compiler.tree.as.IFunctionCallNode;
import org.apache.flex.compiler.tree.as.IFunctionNode;
import org.apache.flex.compiler.tree.as.IIdentifierNode;
import org.apache.flex.compiler.tree.as.IImportNode;
import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
import org.apache.flex.compiler.tree.as.IParameterNode;
import org.apache.flex.compiler.tree.as.IScopedNode;
import org.apache.flex.compiler.tree.as.ITryNode;
import org.apache.flex.compiler.tree.as.ITypedExpressionNode;
import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
import org.apache.flex.compiler.tree.as.IWhileLoopNode;
import org.apache.flex.compiler.tree.as.IWithNode;
import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
import org.apache.flex.compiler.tree.as.IOperatorNode.OperatorType;
import org.apache.flex.compiler.tree.mxml.IMXMLEventSpecifierNode;
import org.apache.flex.compiler.internal.as.codegen.LexicalScope.NestingState;
import org.apache.flex.compiler.internal.definitions.AccessorDefinition;
import org.apache.flex.compiler.internal.definitions.ClassDefinition;
import org.apache.flex.compiler.internal.definitions.DefinitionBase;
import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
import org.apache.flex.compiler.internal.definitions.GetterDefinition;
import org.apache.flex.compiler.internal.definitions.NamespaceDefinition;
import org.apache.flex.compiler.internal.definitions.SetterDefinition;
import org.apache.flex.compiler.internal.definitions.TypeDefinitionBase;
import org.apache.flex.compiler.internal.tree.as.BaseDefinitionNode;
import org.apache.flex.compiler.internal.tree.as.BinaryOperatorInNode;
import org.apache.flex.compiler.internal.tree.as.DynamicAccessNode;
import org.apache.flex.compiler.internal.tree.as.EmbedNode;
import org.apache.flex.compiler.internal.tree.as.ExpressionNodeBase;
import org.apache.flex.compiler.internal.tree.as.ForLoopNode;
import org.apache.flex.compiler.internal.tree.as.FunctionNode;
import org.apache.flex.compiler.internal.tree.as.FunctionObjectNode;
import org.apache.flex.compiler.internal.tree.as.IdentifierNode;
import org.apache.flex.compiler.internal.tree.as.LabeledStatementNode;
import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.flex.compiler.internal.tree.as.NamespaceNode;
import org.apache.flex.compiler.internal.tree.as.RegExpLiteralNode;
import org.apache.flex.compiler.internal.tree.as.SwitchNode;
import org.apache.flex.compiler.internal.tree.as.TernaryOperatorNode;
import org.apache.flex.compiler.internal.tree.as.VariableNode;

/*
 * Notes on changing the reducer:
 * 
 * - Do not add OP_finddefinition, OP_finddefstrict or OP_getlex instructions directly.  Instead use
 *   LexicalScope.findProperty() and LexicalScope.getPropertyValue(), as these methods will
 *   ensure the correct instructions are added when inlining a function body where the scope
 *   chain can not be depended on.
 */
public class ABCGeneratingReducer
{
    /**
     *  A struct for the decoded pieces of a catch block.
     */
    public static class CatchPrototype
    {
        Name catchType;
        Name catchVarName;
        InstructionList catchBody;
    }

    /**
     *  ConditionalFragment holds the disparate elements of a conditional statement fragment.
     */
    public class ConditionalFragment
    {
        IASNode site;
        /**
         * condition is non-null when the conditional expression is not a constant.
         * condition is null if an unconditional fragement, or if the fragement is
         * a constant, in which case constantCondition is non-null.
         */
        InstructionList condition;
        /**
         * constantCondition is non-null when the conditional expression is a constant.
         * constantCondition is null if an unconditional fragement, or if the fragement is
         * a non-constant, in which case condition is non-null.
         */
        Object constantCondition;
        InstructionList statement;

        private Label statementLabel = null;

        /**
         *  Construct a ConditionalFragment with a single statement.
         */
        ConditionalFragment( IASNode site, InstructionList condition, InstructionList statement)
        {
            this.site = site;
            this.condition = condition;
            this.constantCondition = null;
            this.statement = statement;
        }

        /**
         *  Construct a ConditionalFragment with a list of statements,
         *  coalescing them into a composite statement.
         */
        ConditionalFragment( IASNode site, InstructionList condition, Vector<InstructionList> statements)
        {
            this(site, condition, null, statements);
        }

        /**
         * Construct a constant conditional ConditionalFragment with a list of
         * statements, coalescing them into a composite statement.
         */
        ConditionalFragment(IASNode site, Object constantConditional, Vector<InstructionList> statements)
        {
            this(site, null, constantConditional, statements);
        }

        /**
         * Private constructor called by public constructors
         * @param site
         * @param condition
         * @param constantCondition
         * @param statements
         */
        private ConditionalFragment(IASNode site, InstructionList condition, Object constantCondition, Vector<InstructionList> statements)
        {
            assert (condition == null || constantCondition == null) : "condition and constantCondition can't both be non-null";
            this.site = site;
            this.condition = condition;
            this.constantCondition = constantCondition;
            this.statement = createInstructionList(site);

            for (InstructionList stmt : statements)
            {
                this.statement.addAll(stmt);
            }
        }

        /**
         *  @return the label of the fragment's condition, or
         *    its statement label if it's the default alternative.
         */
        Label getLabel()
        {
            if ( !this.isUnconditionalAlternative() )
            {
                if ( this.condition != null )
                    return this.condition.getLabel();
                else
                    return getStatementLabel();
            }
            else
            {
                return getStatementLabel();
            }
        }

        /**
         *  Cache and return the label of this conditional fragment's
         *  statement so it can be retrieved after the statement's been
         *  added to the overall conditional statement and this.statement
         *  is invalidated.
         */
        Label getStatementLabel()
        {
            if ( null == this.statementLabel )
                this.statementLabel = this.statement.getLabel();

            return this.statementLabel;
        }

        /**
         *  @return true if this is an unconditional alternative,
         *    i.e. a default case or the last else in an if/else if/else.
         */
        boolean isUnconditionalAlternative()
        {
            return (null == this.condition) && (null == this.constantCondition);
        }

        void convertConstantConditionToInstruction()
        {
            if ((constantCondition == null && condition != null)  || condition == null)
                return;

            condition = transform_constant_value(site, constantCondition);
            constantCondition = null;
        }

        /**
         * @return true if this is a constant conditonal fragement i.e. case 7:
         */
        boolean isConstantConditional()
        {
            return this.constantCondition != null;
        }
    }

    /**
     *  The RuntimeMultiname class holds the components of 
     *  the various types of runtime multiname, and puts them
     *  together in the right order to generate the names and
     *  instruction sequences to jamble up the AVM.
     *
     *  Only some permutations of the compile-time/runtime
     *  qualifier::name possibilities are valid:
     *  Name::expression generates MultinameL
     *  expression::expression generates RTQnameL
     *  expression::name generates RTQname
     *  (name::name is a plain Multiname)
     */
    class RuntimeMultiname
    {
        /**
         *  The compile-time qualifier of a MultinameL.
         *  compileTimeName isn't valid (this would
         *  be a compile-time constant Multiname).
         */
        Name compileTimeQualifier;

        /**
         *  The runtime qualifier of a RTQname or RTQNameL.
         *  Compile-time and runtime names are valid.
         */
        InstructionList runtimeQualifier;

        /**
         *  The compile-time constant name of a RTQName.
         *  compileTimeQualifier isn't valid (this would
         *  be a compile-time constant Multiname).
         */
        Name compileTimeName;

        /**
         *  The runtime name of a MultinameL or RTQnameL.
         */
        InstructionList runtimeName;

        /**
         *  Construct a RTQnameL-type runtime name.
         *  @param qualifier - the runtime qualifier.
         *  @param name - the runtime name.
         */
        RuntimeMultiname(InstructionList qualifier, InstructionList runtime_name)
        {
            this.runtimeQualifier = qualifier;
            this.runtimeName  = runtime_name;
        }

        /**
         *  Construct a RTQname-type runtime name.
         *  @param qualifier - the runtime qualifier.
         *  @param name - the compile-time name.
         */
        RuntimeMultiname(InstructionList qualifier, Name name)
        {
            this.runtimeQualifier = qualifier;
            this.compileTimeName  = name;
        }

        /**
         *  Construct a MultinameL-type runtime name.
         *  @param qualifier - the Multiname.  Note this
         *    is the only kind of runtime name that receives
         *    a qualifying name.
         *  @param nameL - the runtime expression that 
         *    yields the base name.
         */
        RuntimeMultiname(Name qualifier, InstructionList nameL)
        {
            assert(qualifier.getKind() == CONSTANT_MultinameL || qualifier.getKind() == CONSTANT_MultinameLA): "Bad qualifier kind " + qualifier.getKind() + " on name " + qualifier.toString();
            this.compileTimeQualifier = qualifier;
            this.runtimeName = nameL;
        }

        /**
         *  Assemble the ingredients into an expression.
         *  @param opcode - one of OP_getproperty or OP_setproperty.
         *  @param rhs - the value of a setproperty call.  Passed to
         *    this routine because there may be name-specific 
         *    instructions before and after the value.
         */
        InstructionList generateGetOrSet(IASNode iNode, int opcode, InstructionList rhs)
        {
            InstructionList result = createInstructionList(iNode);

            //  Note: numerous microoptimization opportunities here
            //  to avoid storing values in temps by creative use of
            //  OP_dup and OP_swap, especially in getproperty gen.

            if ( this.compileTimeQualifier != null && this.runtimeName != null )
            {
                //  Generate MultinameL type code.
                Binding name_temp = currentScope.allocateTemp();

                result.addAll(this.runtimeName);
                result.addInstruction(OP_dup);
                result.addInstruction(name_temp.setlocal());
                //  findprop(MultinameL) consumes a name from the value stack.
                result.addInstruction(OP_findpropstrict, this.compileTimeQualifier);
                result.addInstruction(name_temp.getlocal());
                if ( rhs != null )
                    result.addAll(rhs);

                //  get/setprop(MultinameL) consumes a name from the value stack.
                result.addInstruction(opcode, this.compileTimeQualifier);
            }
            else if ( this.runtimeQualifier != null && this.runtimeName != null )
            {
                //  Generate RTQnameL type code.
                Binding name_temp = currentScope.allocateTemp();
                Binding qual_temp = currentScope.allocateTemp();

                Name rtqnl = new Name(CONSTANT_RTQnameL, null, null);

                result.addAll(getRuntimeName(iNode));
                result.addInstruction(name_temp.setlocal());

                result.addAll(getRuntimeQualifier(iNode));
                result.addInstruction(OP_dup);
                result.addInstruction(qual_temp.setlocal());

                result.addInstruction(name_temp.getlocal());
                //  findprop(RTQNameL) consumes namespace and name from the value stack.
                result.addInstruction(OP_findpropstrict, rtqnl);
                result.addInstruction(qual_temp.getlocal());
                result.addInstruction(name_temp.getlocal());
                if ( rhs != null )
                    result.addAll(rhs);

                //  get/setprop(RTQNameL) consumes namespace and name from the value stack.
                result.addInstruction(opcode, rtqnl);

                currentScope.releaseTemp(name_temp);
                currentScope.releaseTemp(qual_temp);
            }
            else
            {
                //  Last valid combination generates a RTQname.
                assert(this.runtimeQualifier != null && this.compileTimeName != null) : "Unknown runtime name configuration: " + this.toString();

                Name rtqn = new Name(CONSTANT_RTQname, null, this.compileTimeName.getBaseName());

                result.addAll(getRuntimeQualifier(iNode));
                result.addInstruction(OP_dup);
                //  findprop(RTQName) consumes a namespace from the value stack.
                result.addInstruction(OP_findpropstrict, rtqn);
                result.addInstruction(OP_swap);
                if ( rhs != null )
                    result.addAll(rhs);

                //  get/setprop(RTQName) consumes a namespace from the value stack.
                result.addInstruction(opcode, rtqn);
            }

            return result;
        }

        /**
         *  Generate the InstructionList that expresses this RuntimeName's qualifier.
         *  @param iNode - an IASNode to contribute debug info to the result InstructionList.
         *  @return the runtime qualifier setup instructions.
         */
        public InstructionList getRuntimeQualifier(IASNode iNode)
        {
            assert(hasRuntimeQualifier());
            InstructionList result = createInstructionList(iNode);

            result.addAll(replicate(this.runtimeQualifier));

            //  Ensure the last instruction is an OP_coerce to Namespace.
            Instruction last = result.lastElement();

            if  (
                    last.getOpcode() != OP_coerce ||
                    last.getOperandCount() == 0 ||
                    ! namespaceType.equals(last.getOperand(0))
                )
            {
                result.addInstruction(OP_coerce, namespaceType);
            }

            return result;
        }

        /**
         *  @return true if this RuntimeName has a runtime qualifier.
         */
        public boolean hasRuntimeQualifier()
        {
            return this.runtimeQualifier != null;
        }

        /**
         *  @return true if this RuntimeName has a runtime name.
         */
        public boolean hasRuntimeName()
        {
            return this.runtimeName != null;
        }

        /**
         *  Generate the InstructionList that expresses this RuntimeName's name.
         *  @param iNode - an IASNode to contribute debug info to the result InstructionList.
         *  @return the runtime name setup instructions.
         */
        public InstructionList getRuntimeName(IASNode iNode)
        {
            assert(hasRuntimeName());

            InstructionList result = createInstructionList(iNode);

            result.addAll(replicate(this.runtimeName));
            if ( result.lastElement().getOpcode() != OP_coerce_s)
                result.addInstruction(OP_coerce_s);
            return result;
        }

        /**
         *  Generate the runtime name appropriate to this qualifier/name combination.
         *  @return the runtime name appropriate to this qualifier/name combination.
         */
        public Name generateName()
        {
            Name result;

            if ( this.compileTimeQualifier != null )
            {
                result = this.compileTimeQualifier;
            }
            else if ( this.runtimeQualifier != null && this.runtimeName != null )
            {
                result = new Name(CONSTANT_RTQnameL, null, null);
            }
            else
            {
                //  Last valid combination generates a RTQname.
                assert(this.runtimeQualifier != null && this.compileTimeName != null) : "Unknown runtime name configuration: " + this.toString();

                result = new Name(CONSTANT_RTQname, null, this.compileTimeName.getBaseName());
            }

            return result;
        }

        /**
         *  Convenience method generates an assignment
         *  @param value - the value to set.
         *  @return the instruction sequence to set a
         *    the given multiname's value.
         */
        InstructionList generateAssignment(IASNode iNode, InstructionList value)
        {
            return generateGetOrSet(iNode, getAssignmentOpcode(iNode), value);
        }

        /**
         *  Deduce the correct assignment opcode for a property.
         *  @param iNode - the root of the reference to the property.
         *  @return OP_initproperty if the property is const, OP_setproperty if not.
         */
        int getAssignmentOpcode(IASNode iNode)
        {
            if ( SemanticUtils.isConst(iNode, currentScope.getProject()) && ABCGeneratingReducer.this.inInitializingContext(iNode) )
                return OP_initproperty;
            else
                return OP_setproperty;
        }

        /**
         *  Convenience method generates an r-value.
         *  @return the instruction sequence to look up
         *    the given multiname.
         */
        InstructionList generateRvalue(IASNode iNode)
        {
            return generateGetOrSet(iNode, OP_getproperty, null);
        }

        /**
         *  Diagnostic toString() method, 
         *  used primarily to debug the assertion in generate().
         */
        @Override
            public String toString()
            {
                return  "\n\t" + compileTimeQualifier + ",\n\t" + runtimeQualifier + ",\n\t" + compileTimeName + ",\n\t" + runtimeName;
            }
    }

    /**
     *  ForKeyValueLoopState holds the state of a for/in or for each/in loop:
     *  the Hasnext2Wrapper that tracks the state of the locals required to
     *  support the hasnext2 instruction, and the Labels that mark the top
     *  of the loop and the test.
     */
    private class ForKeyValueLoopState
    {
        /**
         *  Label for the loop-test logic.
         */
        Label test = new Label();
 
        /**
         *  Label for the top of the loop body.
         */
        Label loop = new Label();

        /**
         *  Hasnext2 management structure.
         */
        LexicalScope.Hasnext2Wrapper hasnext = currentScope.hasnext2();

        /**
         *  Generate the loop prologue code.
         *  @return loop prologue code.
         */
        InstructionList generatePrologue(IASNode iNode, InstructionList base)
        {
            InstructionList result = createInstructionList(iNode);

            //  Set up the object and index registers.
            result.addInstruction(OP_pushbyte, 0);
            result.addInstruction(hasnext.index_temp.setlocal());

            result.addAll(base);
            result.addInstruction(hasnext.stem_temp.setlocal());

            //  Go to the loop test.
            result.addInstruction(OP_jump, test);

            //  Top of loop processing.
            result.addInstruction(OP_label);
            result.labelCurrent(loop);
            return result;
        }

        /**
         *  Generate the instruction sequence that
         *  fetches the next key or value.
         *  @return the instruction sequence that
         *    fetches the next key or value.
         */
        InstructionList generateKeyOrValue(int opcode)
        {
            InstructionList result = new InstructionList();
            result.addInstruction(hasnext.stem_temp.getlocal());
            result.addInstruction(hasnext.index_temp.getlocal());
            result.addInstruction(opcode);
            return result;
        }

        /**
         *  Generate the loop epilogue code.
         *  @return loop epilogue code.
         */
        InstructionList generateEpilogue()
        {
            InstructionList result = new InstructionList();
            result.addInstruction(hasnext.instruction);
            result.labelCurrent(test);
            currentScope.getFlowManager().resolveContinueLabel(result);
            result.addInstruction(OP_iftrue, loop);
            hasnext.release();
            return result;
        }
    }

    /**
     *  The current LexicalScope.  Set by the caller,
     *  changes during reduction when a scoped construct
     *  such as an embedded function or a with statement
     *  is encountered.
     */
    private LexicalScope currentScope;

    /**
     *  Instructions sent by the caller to be added to
     *  a function definition.  Usually these are field
     *  initialization expressions in a constructor.
     */
    private InstructionList instanceInitializers;

    /**
     *  "Mini scope" regions, i.e., blocks of the method body.
     */
    Stack<InstructionList> miniScopes = new Stack<InstructionList>();

    /**
     *  A shared name for the Namespace type.
     */
    public static final Name namespaceType = new Name("Namespace");

    /**
     *  A shared name for the XML type.
     */
    public static final Name xmlType = new Name("XML");

    /**
     *  A shared name for the XMLList type.
     */
    public static final Name xmlListType = new Name("XMLList");

    /**
     *  A shared name for the RegExp type.
     */
    public static final Name regexType = new Name("RegExp");

    /**
     *  A shared name for the void type.
     */
    public static final Name voidType = new Name("void");

    /**
     *  Generate code to push a numeric constant.
     */
    public static void pushNumericConstant(long value, InstructionList result_list)
    {
        result_list.pushNumericConstant(value);
    }

    /**
     * Generate code to push a numeric value onto the stack.  This will take into account the type
     * of the expression that generated the number - e.g. a numeric value produced from a const of type 'int'
     * will produce at worst a pushint instruction
     *
     * Used by the constant folding routines so we don't lose type info when all we have is a Number.
     *
     * @param result_list   IL to add the instruction.
     * @param value         the numeric value to push
     * @param type          the type of the expression that produced the value.
     */
    public void pushNumericConstant(InstructionList result_list, Number value, IDefinition type)
    {
        ICompilerProject project = currentScope.getProject();
        if( type == project.getBuiltinType(BuiltinType.INT) )
        {
            int val = ECMASupport.toInt32(value);
            if( (byte)val == val )
            {
                result_list.addInstruction(OP_pushbyte, val);
            }
            else if( (short)val == val )
            {
                result_list.addInstruction(OP_pushshort, val);
            }
            else
            {
                result_list.addInstruction(OP_pushint, Integer.valueOf(val));
            }
        }
        else if( type == project.getBuiltinType(BuiltinType.UINT) )
        {
            long uval = ECMASupport.toUInt32(value.doubleValue());
            if ((uval & 0x7F) == uval) { // Pushbyte sign extends
                result_list.addInstruction(OP_pushbyte, (int)uval);
            }
            else if ((uval & 0x7FFF) == uval) { // Pushshort sign extends
                result_list.addInstruction(OP_pushshort, (int)uval);
            }
            else {
                result_list.addInstruction(OP_pushuint, Long.valueOf(uval));
            }
        }
        else
        {
            double dval = value.doubleValue();
            if( ECMASupport.isNan(dval) )
            {
                result_list.addInstruction(OP_pushnan);
            }
            else if (!Double.isInfinite(dval) && (dval == ECMASupport.toInt32(value)) )
            {
                // distinguish pos/neg 0
                // java treats -0 and 0 as equal, but divide by -0 results in NEG INFINITY, whereas pos
                // 0 results in POS INFINITY
                // positive 0 can be encoded with a pushbyte, but neg zero requires a pushdouble
                if( dval == 0 && 1/dval == Double.NEGATIVE_INFINITY )
                    result_list.addInstruction(OP_pushdouble, dval);
                else
                    // Integer
                    pushNumericConstant(result_list, ECMASupport.toInt32(value), project.getBuiltinType(BuiltinType.INT));
            }
            else if( Double.isNaN(dval) )
            {
                result_list.addInstruction(OP_pushnan);
            }
            else
            {
                result_list.addInstruction(OP_pushdouble, value.doubleValue());
            }
        }
    }

    /**
     *  @return the currently active collection of problems.
     */
    public Collection<ICompilerProblem> getProblems()
    {
        return currentScope.getProblems();
    }

    /**
     *  Generate a binary operator.
     *  @param l - the left-hand operand.
     *  @param r - the right-hand operand.
     *  @param opcode - the operator's opcode.
     *  @return the combined instruction sequence with the operator appended.
     */
    InstructionList binaryOp(IASNode iNode, InstructionList l, InstructionList r, int opcode)
    {
        checkBinaryOp(iNode, opcode);
        return binaryOperatorBody(iNode, l, r, InstructionFactory.getInstruction(opcode));
    }

    /**
     *  Generate a conditional jump operator.
     *  @param l - the left-hand operand.
     *  @param r - the right-hand operand.
     *  @param opcode - the operator's opcode.
     *  @return the combined instruction sequence with the operator appended.
     *    The target is filled in by a downstream reduction.
     */
    InstructionList conditionalJump(IASNode iNode, InstructionList l, InstructionList r, int opcode)
    {
        checkBinaryOp(iNode, opcode);
        return binaryOperatorBody(iNode, l, r, InstructionFactory.getTargetableInstruction(opcode));
    }

    /**
     *  Generate a binary operator.
     *  @param l - the left-hand operand.
     *  @param r - the right-hand operand.
     *  @param operator - the operator, as an Instruction.
     *  @return the combined instruction sequence with the operator appended.
     */
    InstructionList binaryOperatorBody(IASNode iNode, InstructionList l, InstructionList r, Instruction operator)
    {
        InstructionList result = createInstructionList(iNode, l.size() + r.size() + 1);
        result.addAll(l);
        result.addAll(r);
        result.addInstruction(operator);
        return result;
    }

    /**
     *  Perform semantic checks on a binary operator.
     */
    public void checkBinaryOp (IASNode iNode, int opcode)
    {
        currentScope.getMethodBodySemanticChecker().checkBinaryOperator(iNode, opcode);
    }

    /**
     *  Resolve a dotted name, e.g., foo.bar.baz
     */
    Binding dottedName(IASNode iNode, String qualifiers, String base_name)
    {
        if ( iNode instanceof IdentifierNode )
        {
            return currentScope.resolveName((IdentifierNode)iNode);
        }
        else if ( iNode instanceof ExpressionNodeBase )
        {
            ExpressionNodeBase expr = (ExpressionNodeBase) iNode;
            Name n = expr.getMName(currentScope.getProject());

            if ( n == null )
            {
                currentScope.addProblem(new CodegenInternalProblem(iNode, "Unable to resove member name: " + iNode.toString()));
                n = new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, qualifiers)), base_name);
            }

            return currentScope.getBinding(iNode, n, expr.resolve(currentScope.getProject()));
        }

        //else
            currentScope.addProblem(new CodegenInternalProblem(iNode, "Unable to resove to a dotted name: " + iNode.toString()));
            return new Binding(iNode, new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, qualifiers)), base_name), null);
    }

    /**
     *  Resolve a dotted name, e.g., foo.bar.baz, where the whole dotted name is a package
     *  this is an error, and a diagnostic will be emitted
     */
    Binding errorPackageName(IASNode iNode, String qualifiers, String base_name)
    {
        currentScope.addProblem(new PackageCannotBeUsedAsValueProblem(iNode, "'" + qualifiers + "." + base_name + "'"));
        return new Binding(iNode, new Name(qualifiers + "." + base_name), null);
    }

    private void generateAssignmentOp(IASNode site, Binding target, InstructionList result)
    {
        boolean inlined = generateInlineSetterAccess(target, result, true);

        if (!inlined)
            result.addInstruction(getAssignmentOpcode(site, target), target.getName());
    }

    /**
     * Deduce the correct assignment opcode for a Binding.
     * 
     * @param b - the Binding of interest.
     * @return the appropriate opcode to assign to the entity represented by the
     * Binding.
     */
    int getAssignmentOpcode(IASNode site, Binding b)
    {
        if (b.getDefinition() instanceof IConstantDefinition && this.inInitializingContext(site))
            return OP_initproperty;
        else if (b.isSuperQualified())
            return OP_setsuper;
        else
            return OP_setproperty;
    }

    /**
     *  Is the generator in an initializing context?
     *  @param iNode - the i-node of interest.
     *  @return true if the generator is in a context where it should
     *    generate initializer calls, i.e., OP_initproperty to set properties.
     */
    boolean inInitializingContext(IASNode iNode)
    {
        return SemanticUtils.isInVariableDeclaration(iNode) || SemanticUtils.isInConstructor(iNode);
    }


    /**
     *  Common routine used by reductions that
     *  need an empty list.
     *  @param iNode - the current AST node.
     */
    public InstructionList createInstructionList(IASNode iNode)
    {
        return createInstructionList(iNode, 0);
    }

    /**
     *  Common routine used by reductions that
     *  need an empty list.
     *  @param iNode - the current AST node.
     *  @param capacity - requested capacity of the new list.
     *    May be adjusted to accomodate debug instructions.
     */
    public InstructionList createInstructionList(IASNode iNode, int capacity)
    {
        DebugInfoInstructionList result;

        String file_name = SemanticUtils.getFileName(iNode);

        //  Note: getLine() uses zero-based counting.
        int line_num = iNode.getLine() + 1;

        //  Adjust the capacity requirement if debug
        //  instructions are to be emitted.
        if ( currentScope.emitFile(file_name) )
            capacity++;
        if ( currentScope.emitLine(line_num) )
            capacity++;

        //  If the required capacity is less than three
        //  instructions, the InstructionList can hold 
        //  them organically.  Specifying a capacity to
        //  the InstructionList ctor causes it to allocate
        //  a separate ArrayList.
        if ( capacity > 3 )
            result = new DebugInfoInstructionList(capacity);
        else
            result = new DebugInfoInstructionList();

        if ( currentScope.emitFile(file_name) )
        {
            currentScope.setDebugFile(file_name);
            result.addInstruction(OP_debugfile, currentScope.getDebugFile());
        }

        if ( currentScope.emitLine(line_num) )
        {
            // Set the line number in the instruction list - it will
            // emit or not emit the debugline depending on how it's used
            result.setDebugLine(line_num);
            currentScope.setDebugLine(line_num);
        }

        return result;
    }

    /**
     * Instruction list to help with emitting OP_debuglines.
     *
     * When given a line number, it will emit an OP_debugline when addInstruction is called with an
     * executable instruction.
     *
     * If addAll is called, then the debugline will not be emitted as the IL passed in should already have
     * any necessary debuglines if it contains executable instrucitons.
     *
     */
    private static class DebugInfoInstructionList extends InstructionList
    {
        /**
         * Constant for we don't have a line number
         */
        public static final int NO_LINE = -1;
        /**
         * The line number to use for an op_debugline when an executable instruction is added
         */
        private int line_num = NO_LINE;

        DebugInfoInstructionList (int capacity)
        {
            super(capacity);
        }
        DebugInfoInstructionList ()
        {
            super();
        }

        /**
         * Set the line number for this IL
         * @param line_num  the line number
         */
        void setDebugLine(int line_num)
        {
            this.line_num = line_num;
        }

        /**
         * Add the instruction to the IL.  If the instruction is
         * an exectuable instruction, and we have not emitted the line number yet,
         * then this will insert an OP_debugline with the line number before the instruction is
         * added.
         * @param insn  the instruction to be added.
         * @return      the added instruction
         */
        public Instruction addInstruction(Instruction insn)
        {

            if( line_num != NO_LINE && insn.isExecutable() )
            {
                // add the debugline instruction first

                // reset the line number
                // do this before adding the instruction so
                // we don't infinitely recurse
                int line = line_num;
                line_num = NO_LINE;

                addInstruction(OP_debugline, line);
            }
            return super.addInstruction(insn);
        }
    }

    /**
     *  Error trap.
     */
    public Binding error_namespaceAccess(IASNode iNode, IASNode raw_qualifier, Binding qualified_name)
    {
        String qualifier = ((IdentifierNode)raw_qualifier).getName();

        //  TODO: In some circumstances, the namespace qualifier
        //  may be an invalid attribute on a declaration.
        currentScope.addProblem(new UnknownNamespaceProblem(raw_qualifier, qualifier));

        return qualified_name;
    }

    /**
     *  Error trap.
     */
    public InstructionList error_reduce_Op_AssignId(IASNode iNode, InstructionList non_lvalue, InstructionList rvalue)
    {
        currentScope.addProblem(new InvalidLvalueProblem(iNode));
        InstructionList result = createInstructionList(iNode, 1);
        // Since we are reducing to an expression, make sure the instruction
        // list we return, produces a value on the operand stack.
        result.addInstruction(ABCConstants.OP_pushundefined);
        return result;
    }

    /**
     *  Generate access to a named entity.
     *  @param name - the entity's name.
     *  @return an instruction sequence to access the entity.
     */
    InstructionList generateAccess(Binding name)
    {
        return generateAccess(name, AccessType.Strict);
    }

    /**
     *  Enumerate possible access types to a named entity;
     *  Lenient is used in typeof expressions to access
     *  variables referred to by simple name and for the
     *  member references of member access expressions.
     *  All other expressions use strict access.
     */
    private enum AccessType { Strict, Lenient }

    /**
     *  Generate access to a named entity.
     *  @param name - the entity's name.
     *  @param accessType - one of Lenient or Strict.
     *  @return an instruction sequence to access the entity.
     */
    InstructionList generateAccess(Binding name, AccessType accessType)
    {
        InstructionList result = new InstructionList(2);
        generateAccess(name, accessType, result);
        return result;
    }

    /**
     *  Generate access to a named entity.
     *  @param name - the entity's name.
     *  @param result - the instruction sequence to generate into.
     */
    void generateAccess(Binding binding, InstructionList result)
    {
        generateAccess(binding, AccessType.Strict, result);
    }

    /**
     *  Generate access to a named entity.
     *  @param name - the entity's name.
     *  @param accessType - one of Lenient or Strict.
     *  @param result - the instruction sequence to generate into.
     */
    void generateAccess(Binding binding, AccessType accessType, InstructionList result)
    {
        if (binding.isLocal())
        {
            result.addInstruction(binding.getlocal());
        }
        else
        {
            assert (binding.getName() != null) : "non-local Binding " + binding + " must have a name";
            currentScope.getMethodBodySemanticChecker().checkGetProperty(binding);

            boolean inlined = generateInlineGetterAccess(binding, result, false);

            if (!inlined)
                generateAccess(binding, binding.isSuperQualified(), accessType, result);
        }
    }

    /**
     *  Generate access to a named entity.
     *  @param binding - the entity's binding.
     *  @param is_super - set if the name was explicitly qualified with "super."
     *  @param accessType - one of Lenient or Strict.
     *  @param result - the instruction sequence to generate into.
     */
    void generateAccess(Binding binding, final boolean is_super, AccessType accessType, InstructionList result)
    {
        final Name name = binding.getName();
        assert (name != null) : "binding must have a name when calling generateAccess()";

        final IASNode node = binding.getNode();
        if ( name.isTypeName() )
        {
            // a type names node should always be a ITypedExpressionNode
            ITypedExpressionNode typeNode = (ITypedExpressionNode)node;
            IExpressionNode collectionNode = typeNode.getCollectionNode();
            IDefinition collectionDefinition = SemanticUtils.getDefinition(collectionNode, currentScope.getProject());
            Binding collectionBinding = currentScope.getBinding(collectionNode, name.getTypeNameBase(), collectionDefinition);
            generateAccess(collectionBinding, is_super, AccessType.Strict, result);

            IExpressionNode typeTypeNode = typeNode.getTypeNode();
            IDefinition typeDefinition = SemanticUtils.getDefinition(typeTypeNode, currentScope.getProject());
            Binding typeBinding = currentScope.getBinding(typeTypeNode, name.getTypeNameParameter(), typeDefinition);
            generateTypeNameParameter(typeBinding, result);

            result.addInstruction(OP_applytype, 1);
        }
        else
        {
            // Test whether we're refering to the class being initialized, for example: 
            // public class C {
            //     private static var v:Vector.<C> = new Vector.<C>();
            // }
            // as in this case we need to do a getlocal0 as the class
            // hasn't been initialized yet
            boolean useLocal0 = false;
            if (node instanceof IdentifierNode)
            {
                IdentifierNode id = (IdentifierNode)node;
                IDefinition def = id.resolve(currentScope.getProject());
                if (SemanticUtils.isRefToClassBeingInited(id, def) && !currentScope.insideInlineFunction())
                    useLocal0 = true;
            }

            // TODO: use getslot when we can.
            // TODO: we can at least do this when we're accessing something in an activation object            
            if (useLocal0)
            {
                result.addInstruction(OP_getlocal0);
            }
            else if (is_super)
            {
                result.addAll(currentScope.findProperty(binding, true));
                result.addInstruction(OP_getsuper, name);
            }
            else if (accessType == AccessType.Lenient)
            {
                result.addAll(currentScope.findProperty(binding, false));
                result.addInstruction(OP_getproperty, name);
            }
            else
            {
                result.addAll(currentScope.getPropertyValue(binding));
            }
        }
    }

    private boolean generateInlineGetterAccess(Binding binding, InstructionList result, boolean isQualified)
    {
        IDefinition def = binding.getDefinition();
        if (!(def instanceof AccessorDefinition && currentScope.getMethodBodySemanticChecker().canGetterBeInlined((AccessorDefinition)def)))
            return false;

        AccessorDefinition accessorDefinition = (AccessorDefinition)def;
        if (accessorDefinition instanceof SetterDefinition)
            accessorDefinition = accessorDefinition.resolveCorrespondingAccessor(currentScope.getProject());

        assert (accessorDefinition != null) : "generateInlineGetterAccess() called with no getter definition";

        FunctionNode functionNode = (FunctionNode)accessorDefinition.getFunctionNode();
        return inlineFunction(accessorDefinition, functionNode, result, isQualified);
    }

    private boolean generateInlineSetterAccess(Binding binding, InstructionList result, boolean isQualified)
    {
        IDefinition def = binding.getDefinition();
        if (!(def instanceof AccessorDefinition && currentScope.getMethodBodySemanticChecker().canSetterBeInlined((AccessorDefinition)def)))
            return false;

        AccessorDefinition accessorDefinition = (AccessorDefinition)def;
        if (accessorDefinition instanceof GetterDefinition)
            accessorDefinition = accessorDefinition.resolveCorrespondingAccessor(currentScope.getProject());

        assert (accessorDefinition != null) : "generateInlineSetterAccess() called with no setter definition";

        FunctionNode functionNode = (FunctionNode)accessorDefinition.getFunctionNode();
        return inlineFunction(accessorDefinition, functionNode, result, isQualified);
    }

    private boolean generateInlineFunctionCall(Binding binding, InstructionList result, boolean isQualified, Vector<InstructionList> args)
    {
        IDefinition def = binding.getDefinition();
        if (!(def instanceof FunctionDefinition && (!(def instanceof IAccessorDefinition)) && currentScope.getMethodBodySemanticChecker().canFunctionBeInlined((FunctionDefinition)def)))
            return false;

        FunctionDefinition functionDef = (FunctionDefinition)binding.getDefinition();
        FunctionNode functionNode = (FunctionNode)functionDef.getFunctionNode();

        InstructionList insn = createInstructionList(functionNode);
        for (InstructionList arg: args)
            insn.addAll(arg);

        if (inlineFunction(functionDef, functionNode, insn, isQualified))
        {
            result.addAll(insn);
            return true;
        }
        else
        {
            return false;
        }
    }

    private boolean inlineFunction(FunctionDefinition functionDef, FunctionNode functionNode, InstructionList result, boolean isQualified)
    {
        try
        {
            InlineFunctionLexicalScope inlineFunctionScope = currentScope.pushInlineFunctionFrame(functionDef.getContainingScope(), isQualified, functionNode);
            currentScope = inlineFunctionScope;

            // generate the instructions for the body of the function
            IScopedNode body = functionNode.getScopedNode();
            InstructionList insns = inlineFunctionScope.getGenerator().generateInstructions(body, CmcEmitter.__statement_NT, inlineFunctionScope);

            currentScope = currentScope.popFrame();

            final ICompilerProject project = currentScope.getProject();
            if (currentScope.getMethodBodySemanticChecker().functionBodyHasNonInlineableInstructions(insns, functionDef.isInline(), functionDef.getBaseName()))
            {
                return false;
            }
            else
            {
                inlineFunctionScope.assignActualsToFormals(functionDef, result);

                if (isQualified)
                    result.addInstruction(inlineFunctionScope.setContainingClass());

                result.addAll(insns);

                // test for a fallthrough when the return type is non-void, as we
                // need coerce undefined to the return type to mimic returnvoid behavior
                if (!(functionDef instanceof SetterDefinition) && result.canFallThrough() || result.hasPendingLabels())
                {
                    TypeDefinitionBase returnType = (TypeDefinitionBase)functionDef.resolveReturnType(project);
                    if (returnType != currentScope.getProject().getBuiltinType(BuiltinType.VOID) &&
                        returnType != currentScope.getProject().getBuiltinType(BuiltinType.ANY_TYPE))
                    {
                        result.addInstruction(OP_pushundefined);
                        result.addInstruction(OP_coerce, returnType.getMName(project));
                    }
                }

                result.labelNext(inlineFunctionScope.getInlinedFunctionCallSiteLabel());
                inlineFunctionScope.mergeIntoContainingScope(result);
            }
        }
        finally
        {
            functionNode.discardFunctionBody();
        }

        return true;
    }

    /**
     *  Generate code to assign to a named entity.
     *  @param target - the entity to be assigned to.
     *  @param rvalue - the value to assign.
     *  @return an instruction sequence that stores
     *    the given rvalue in the target.
     *  
     */
    InstructionList generateAssignment(IASNode iNode, Binding target, InstructionList rvalue)
    {
        return generateAssignment(iNode, target, rvalue, false);
    }

    /**
     *  Generate code to assign to a named entity.
     *  @param target - the entity to be assigned to.
     *  @param rvalue - the value to assign.
     *  @param need_value - when true, 
     *    leave a DUP of the rvalue on the stack.
     *  @return an instruction sequence that stores
     *    the given rvalue in the target, and leaves
     *    a DUP of the rvalue on the stack if need_value is set.
     *  
     */
    InstructionList generateAssignment(IASNode iNode, Binding target, InstructionList rvalue, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode, rvalue.size() + 4);

        //  We may need to know if the RHS is in a local
        //  for some micro-optimizations; the rvalue instruction
        //  list is about to be invalidated, so speculatively
        //  determine that information here.
        int rhsOpcode = rvalue.lastElement().getOpcode();
        final boolean rhsIsLocal = 
            rhsOpcode == OP_getlocal || 
            rhsOpcode == OP_getlocal0 || 
            rhsOpcode == OP_getlocal1 || 
            rhsOpcode == OP_getlocal2 || 
            rhsOpcode == OP_getlocal3;

        result.addAll(rvalue);
        if ( need_value )
            result.addInstruction(OP_dup);

        // when assigning to a local or slot, we need to generate the type coerce and
        // runtime illegal write to const checks, so combine in this if block.
        if ( target.isLocal() || target.slotIdIsSet() )
        {
            if ( target.getDefinition() != null )
            {
                ITypeDefinition tgtType = target.getDefinition().resolveType(currentScope.getProject());
                ITypeDefinition srcType = null;

                srcType = SemanticUtils.resolveRHSTypeOfAssignment(currentScope.getProject(), iNode);

                if (
                    tgtType != null &&
                    tgtType != ClassDefinition.getAnyTypeClassDefinition() &&
                    !(srcType == tgtType && rhsIsLocal)
                )
                {
                    coerce(result, tgtType);
                }
            }

            //  If the target is a const and this assignment occurs outside the const's declaration,
            //  emulate the AVM's behavior by compiling in a throw statement.
            //  Note that this behavior differs from ASC's until ASC-4376 is fixed.
            //  We need to keep this runtime check, as in strict mode this is a semantic error, but
            //  in non-strict mode it needs to be caught at run time.
            if  (
                    SemanticUtils.isConstDefinition(target.getDefinition())  && 
                    !SemanticUtils.isInVariableDeclaration(iNode) && 
                    target.getName() != null
                )
            {
                result.addInstruction(OP_pushstring, "Illegal write to local const " + target.getName().getBaseName());
                result.addInstruction(OP_throw);
            }
            else if (target.slotIdIsSet())
            {
                if (currentScope.needsActivation())
                {
                    // Restore the activation object.
                    result.addInstruction(currentScope.getActivationStorage().getlocal());
                    result.addInstruction(OP_swap);
                }

                result.addInstruction(OP_setslot, target.getSlotId());
            }
            else
            {
                result.addInstruction(target.setlocal());
            }
        }
        else
        {
            boolean inlined = generateInlineSetterAccess(target, result, false);

            if (!inlined)
            {
                IDefinition def = target.getDefinition();
                if (def instanceof GetterDefinition)
                {
                    boolean isSuper = target.isSuperQualified();
                    SetterDefinition setter = (SetterDefinition)((GetterDefinition)def).
                                resolveCorrespondingAccessor(currentScope.getProject());
                    target = currentScope.getBinding(setter);   
                    if (isSuper)
                        target.setSuperQualified(true);
                }
                result.addAll(currentScope.findProperty(target, false));
                result.addInstruction(OP_swap);
                result.addInstruction(getAssignmentOpcode(iNode, target), target.getName());
            }
        }
        return result;
    }

    /**
     *  Generate a catch block.
     *  @param catch_proto - the catch block's prototype.
     */
    InstructionList generateCatchBlock( Label try_start, Label try_end, CatchPrototype catch_proto)
    {
        InstructionList scope_reinit = currentScope.getFlowManager().getScopeStackReinit();
        InstructionList current_catch = new InstructionList(catch_proto.catchBody.size() + scope_reinit.size() + 15);

        //  Common prologue code.
        if ( currentScope.needsThis() )
        {
            current_catch.addInstruction(OP_getlocal0);
            current_catch.addInstruction(OP_pushscope);
        }

        if( currentScope.needsActivation() )
        {
            //  Restore the activation object.
            current_catch.addInstruction(currentScope.getActivationStorage().getlocal());
            current_catch.addInstruction(OP_pushscope);
        }

        //  Re-establish enclosing exception scopes.
        current_catch.addAll(scope_reinit);

        int handler_number = currentScope.getMethodBodyVisitor().visitException(try_start, try_end, current_catch.getLabel(), catch_proto.catchType, catch_proto.catchVarName);
        Binding exception_storage = currentScope.getFlowManager().getFinallyContext().getExceptionStorage();

        current_catch.addInstruction(OP_newcatch, handler_number);
        current_catch.addInstruction(OP_dup);
        if ( exception_storage != null )
        {
            current_catch.addInstruction(exception_storage.setlocal());
            current_catch.addInstruction(OP_dup);
        }
        current_catch.addInstruction(OP_pushscope);
        current_catch.addInstruction(OP_swap);
        current_catch.addInstruction(OP_setslot, 1);

        current_catch.addAll(catch_proto.catchBody);

        if ( current_catch.canFallThrough() || current_catch.hasPendingLabels() )
        {
            current_catch.addInstruction(OP_popscope);
        }

        return current_catch;
    }

    /**
     *  Generate a compound assignment statement.
     */
    InstructionList generateCompoundAssignment(IASNode iNode, Binding lvalue, InstructionList expr, int opcode, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode, expr.size() + (lvalue.isLocal()? 4 : 8));

        currentScope.getMethodBodySemanticChecker().checkCompoundAssignment(iNode, lvalue, opcode);

        if ( lvalue.isLocal() )
        {
            result.addInstruction(lvalue.getlocal());
            result.addAll(expr);
            result.addInstruction(opcode);
            if ( need_value )
                result.addInstruction(OP_dup);

            // Coerce to the right type if the local has a type anno
            if ( lvalue.getDefinition() != null )
            {
                ITypeDefinition type = lvalue.getDefinition().resolveType(currentScope.getProject());

                if ( type != ClassDefinition.getAnyTypeClassDefinition() )
                {
                    coerce(result, type);
                }
            }

            result.addInstruction(lvalue.setlocal());
        }
        else
        {
            result.addAll(currentScope.findProperty(lvalue, true));
            result.addInstruction(OP_dup);
            result.addInstruction(OP_getproperty, lvalue.getName());
            result.addAll(expr);
            result.addInstruction(opcode);

            Binding value_temp = null;
            if ( need_value )
            {
                value_temp = currentScope.allocateTemp();
                result.addInstruction(OP_dup);
                result.addInstruction(value_temp.setlocal());
            }
            result.addInstruction(getAssignmentOpcode(iNode, lvalue), lvalue.getName());
            if ( need_value )
            {
                result.addInstruction(value_temp.getlocal());
                currentScope.releaseTemp(value_temp);
            }
        }

        return result;
    }

    InstructionList generateCompoundBracketAssignment(IASNode iNode, InstructionList stem, InstructionList index, InstructionList expr, int opcode, boolean need_value)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IBinaryOperatorNode)iNode).getLeftOperandNode();
        InstructionList result = createInstructionList(iNode, stem.size() * 2 + index.size() + expr.size() + 11 );

        //  Although ASC evaluates the stem twice, it only evaluates the index once.
        //  TODO: Inspect the index expression for side effects so the temp can be
        //  elided in most cases.
        Binding index_temp = currentScope.allocateTemp();
        result.addAll(index);
        result.addInstruction(index_temp.setlocal());

        result.addAll(replicate(stem));
        result.addInstruction(index_temp.getlocal());
        result.addInstruction(arrayAccess(arrayIndexNode, OP_getproperty));
        result.addAll(expr);
        result.addInstruction(opcode);

        Binding value_temp = currentScope.allocateTemp();
        result.addInstruction(value_temp.setlocal());

        result.addAll(stem);
        result.addInstruction(index_temp.getlocal());
        result.addInstruction(value_temp.getlocal());
        result.addInstruction(arrayAccess(arrayIndexNode, OP_setproperty));

        if ( need_value )
            result.addInstruction(value_temp.getlocal());

        currentScope.releaseTemp(value_temp);
        currentScope.releaseTemp(index_temp);

        return result;
    }

    InstructionList generateCompoundAssignmentToRuntimeName(IASNode iNode, RuntimeMultiname name, InstructionList expr, int opcode, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(name.generateRvalue(iNode));
        result.addAll(expr);
        result.addInstruction(opcode);

        if ( need_value )
        {
            //  TODO: In many cases this temp can be avoided by more sophisticated analysis.
            //  TODO: See also comments in RuntimeMultiname.generateGetOrSet().
            Binding temp = currentScope.allocateTemp();
            result.addInstruction(temp.setlocal());
            InstructionList temp_rhs = new InstructionList();
            temp_rhs.addInstruction(temp.getlocal());
            result.addAll(name.generateAssignment(iNode, temp_rhs));
            result.addInstruction(temp.getlocal());
            currentScope.releaseTemp(temp);
        }
        else
        {
            result = name.generateAssignment(iNode, result);
        }

        return result;
    }

    InstructionList generateCompoundMemberAssignment(IASNode iNode, InstructionList stem, Binding member, InstructionList expr, int fetch_opcode, int assign_opcode, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode, stem.size() * 2 + expr.size() + 5 );
        currentScope.getMethodBodySemanticChecker().checkCompoundAssignment(iNode, member, assign_opcode);

        //  TODO: Depending on the resolution of ASC-4159 and 
        //  the corresponding Falcon backwards compatibility
        //  issue, cache the stem expression in a local to avoid
        //  multiple evaluations.
        result.addAll(replicate(stem));
        result.addInstruction(fetch_opcode, member.getName());

        result.addAll(expr);
        result.addInstruction(assign_opcode);

        if ( need_value )
        {
            result.addInstruction(OP_dup);
        }

        result.addAll(stem);
        result.addInstruction(OP_swap);
        result.addInstruction(getAssignmentOpcode(iNode, member), member.getName());

        return result;
    }

    /**
     *  Generate a compound logical assignment expression to a named lvalue.
     *  @param iNode - the assignment operator (root of the subtree).
     *  @param lvalue - the lvalue's name.
     *  @param expr - the expression to assign.
     *  @param is_and - true if the expression is &amp;&amp;=, false if it's ||=.
     *  @param need_value - true if the expression's not used in a void context.
     */
    InstructionList generateCompoundLogicalAssignment(IASNode iNode, Binding lvalue, InstructionList expr, boolean is_and, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);
        int failure_test = is_and? OP_iffalse : OP_iftrue;

        currentScope.getMethodBodySemanticChecker().checkCompoundAssignment(iNode, lvalue, failure_test);

        Label tail = new Label();

        if ( lvalue.isLocal() )
        {
            //  Fetch and test the current value.
            result.addInstruction(lvalue.getlocal());
            //  The current value may not be the result value,
            //  but for now assume it is.
            if ( need_value )
                result.addInstruction( OP_dup);

            result.addInstruction( failure_test, tail );

            //  Test succeeded: reset the value, but first
            //  pop the value speculatively dup'd above.
            if ( need_value )
                result.addInstruction(OP_pop);

            result.addAll(expr);

            if ( need_value )
                result.addInstruction(OP_dup);

            result.addInstruction(lvalue.setlocal());
        }
        else
        {
            //  Fetch, speculatively dup, and test the current value.
            result.addAll(currentScope.getPropertyValue(lvalue));

            if ( need_value )
                result.addInstruction(OP_dup);

            result.addInstruction(failure_test, tail);

            if ( need_value )
                result.addInstruction(OP_pop);

            result.addAll(expr);

            if ( need_value )
            {
                result.addInstruction(OP_dup);
            }

            result.addAll(currentScope.findProperty(lvalue, true));
            result.addInstruction(OP_swap);
            result.addInstruction(getAssignmentOpcode(iNode, lvalue), lvalue.getName());

        }

        result.labelNext(tail);
        return result;
    }

    /**
     *  Generate compound logical assignment to a runtime name, e.g., n::x ||= foo;
     *  @param iNode - the root of the assignment subtree.
     *  @param name - the runtime name.
     *  @param expr - the second operand of the implied binary expression.
     *  @param is_and - true if the result is set to the second operand iff the first operand is true.
     *  @param need_value - true if the value of the assignment is required.
     */
    InstructionList generateCompoundLogicalRuntimeNameAssignment(IASNode iNode, RuntimeMultiname name, InstructionList expr, boolean is_and, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);

        Label tail = new Label();
        int failure_test = is_and? OP_iffalse : OP_iftrue;

        Binding rhs_temp = null;
        InstructionList rhs_fetch = null;

        //  Fetch, speculatively dup, and test the current value.
        result.addAll(name.generateRvalue(iNode));

        if ( need_value )
            result.addInstruction(OP_dup);

        result.addInstruction(failure_test, tail);

        if ( need_value )
        {
            //  Clear the speculative dup.
            result.addInstruction(OP_pop);
        }

        result.addAll(expr);

        if ( need_value )
        {
            //  The runtime multiname instruction sequence
            //  doesn't allow the rhs expression to travel
            //  on the stack.
            rhs_temp = currentScope.allocateTemp();
            rhs_fetch = createInstructionList(iNode);

            result.addInstruction(OP_dup);
            result.addInstruction(rhs_temp.setlocal());
            rhs_fetch.addInstruction(rhs_temp.getlocal());

            result.addAll(name.generateAssignment(iNode, rhs_fetch));
            currentScope.releaseTemp(rhs_temp);
        }
        else
        {
            result = (name.generateAssignment(iNode, result));
        }

        result.labelNext(tail);
        return result;
    }

    /**
     *  Generate a compound logical assignment expression to a a[i] type lvalue.
     *  @param iNode - the assignment operator (root of the subtree).
     *  @param stem - the expression that generates the lvalue's stem, e.g., a in a[i]
     *  @param index - the index expression.
     *  @param expr - the expression to assign.
     *  @param is_and - true if the expression is &amp;&amp;=, false if it's ||=.
     *  @param need_value - true if the expression's not used in a void context.
     */
    InstructionList generateCompoundLogicalBracketAssignment(IASNode iNode, InstructionList stem, InstructionList index, InstructionList expr, boolean is_and, boolean need_value)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IBinaryOperatorNode)iNode).getLeftOperandNode();
        
        InstructionList result = createInstructionList(iNode, stem.size() * 2 + index.size() + expr.size() + 11 );

        Label tail = new Label();
        int failure_test = is_and? OP_iffalse : OP_iftrue;

        //  Although ASC evaluates the stem twice, it only evaluates the index once.
        //  TODO: Inspect the index expression for side effects so the temp can be
        //  elided in most cases.
        Binding index_temp = currentScope.allocateTemp();
        result.addAll(index);
        result.addInstruction(index_temp.setlocal());

        result.addAll(replicate(stem));
        result.addInstruction(index_temp.getlocal());
        result.addAll(stem);
        result.addInstruction(index_temp.getlocal());
        result.addInstruction(arrayAccess(arrayIndexNode, OP_getproperty));
        //  Assume this is the result.
        result.addInstruction(OP_dup);
        result.addInstruction(failure_test, tail);

        //  Pop the speculative result and assign the correct one.
        result.addInstruction(OP_pop);
        result.addAll(expr);

        result.labelNext(tail);
        Binding value_temp = null;
        if ( need_value )
        {
            value_temp = currentScope.allocateTemp();
            result.addInstruction(OP_dup);
            result.addInstruction(value_temp.setlocal());
        }
        result.addInstruction(arrayAccess(arrayIndexNode, OP_setproperty));
        if ( need_value )
        {
            result.addInstruction(value_temp.getlocal());
            currentScope.releaseTemp(value_temp);
        }

        currentScope.releaseTemp(index_temp);

        return result;
    }

    /**
     *  Generate a compound logical assignment expression to a foo.bar type lvalue
     *  @param iNode - the assignment operator (root of the subtree).
     *  @param stem - the expression that generates the lvalue's stem, e.g., a in a[i]
     *  @param index - the index expression.
     *  @param expr - the expression to assign.
     *  @param is_and - true if the expression is &amp;&amp;=, false if it's ||=.
     *  @param need_value - true if the expression's not used in a void context.
     */
    InstructionList generateCompoundLogicalMemberAssignment(IASNode iNode, InstructionList stem, Binding member, InstructionList expr, int fetch_opcode, boolean is_and, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);
        int failure_test = is_and? OP_iffalse : OP_iftrue;
        currentScope.getMethodBodySemanticChecker().checkCompoundAssignment(iNode, member, failure_test);

        Label tail = new Label();

        result.addAll(replicate(stem));
        result.addAll(stem);
        result.addInstruction(OP_getproperty, member.getName());
        //  Assume this is the result.
        result.addInstruction(OP_dup);
        result.addInstruction(failure_test, tail);

        result.addInstruction(OP_pop);
        result.addAll(expr);

        result.labelNext(tail);
        Binding value_temp = null;

        if ( need_value )
        {
            value_temp = currentScope.allocateTemp();
            result.addInstruction(OP_dup);
            result.addInstruction(value_temp.setlocal());
        }

        result.addInstruction(getAssignmentOpcode(iNode, member), member.getName());

        if ( need_value )
        {
            result.addInstruction(value_temp.getlocal());
            currentScope.releaseTemp(value_temp);
        }

        return result;

    }

    /**
     *  generateFunctionBody() wrapper suitable for calling from the BURM.
     *  See JBurg ENHRQ <N> : the grammar that accepts the BURM's parameters
     *  to a JBurg.Reduction routine doesn't grok function calls, so the BURM
     *  cannot call generateFunctionBody(body, name.getName());
     */
    InstructionList generateFunctionBody(IASNode iNode, InstructionList function_body, Binding return_type)
    {
        return generateFunctionBody(iNode, function_body, return_type != null? return_type.getName(): null);
    }

    /**
     *  Generate boilerplate function prolog/epilog code.
     *  @param block - the actual CFG.
     *  @param return_type - the function's return type.
     *  @return the function body.
     */
    InstructionList generateFunctionBody(IASNode iNode, InstructionList function_body, Name return_type)
    {
        currentScope.getMethodBodySemanticChecker().checkFunctionBody(iNode);

        currentScope.getMethodInfo().setReturnType(return_type);
        InstructionList result = currentScope.finishMethodDeclaration( !function_body.isEmpty() || haveInstanceInitializers(), SemanticUtils.getFileName(iNode));

        //  Constructor-specific processing: add the instance initializers,
        //  add a constructsuper call if none exists.
        if ( haveInstanceInitializers() && currentScope.getNestingState() == NestingState.NotNested)
        {
            result.addAll(this.instanceInitializers);

            //  If this is a constructor and there's no explicit
            //  super() call, synthesize one.
            //  Note that this may be a semantic error if the 
            //  superclass' constructor needs arguments.
            if ( !function_body.hasSuchInstruction(OP_constructsuper) )
            {
                currentScope.getMethodBodySemanticChecker().checkDefaultSuperCall(iNode);
                //  Call the superclass' constructor after the instance
                //  init instructions; this doesn't seem like an abstractly
                //  correct sequence, but it's what ASC does.
                result.addInstruction(OP_getlocal0);
                result.addInstruction(OP_constructsuper, 0);
            }
        }

        result.addAll(function_body);

        //  Epilog code.
        if ( result.canFallThrough() || result.hasPendingLabels() )
        {
            //  Synthesize a returnvoid instruction, using the
            //  single-purpose returnvoid so the caller can
            //  search for it.

            //  If, at some point, the MBSC walks all functions' CFGs,
            //  then all returnvoid processing can be centralized and
            //  this specialized Instruction will be unnecessary.
            result.addInstruction(synthesizedReturnVoid);
        }

        return result;
    }

    /**
     *  This returnvoid instruction is used when the reducer injects a returnvoid at
     *  the end of a method body; the caller (with access to the MethodBodyInfo) can
     *  create a control flow graph and search it to emit a diagnostic as appropriate.
     */
    public static final Instruction synthesizedReturnVoid = new NoOperandsInstruction(OP_returnvoid);

    /**
     *  Generate a named nested function.
     *
     *  This will generate init instructions either in controlFlow?Sensitive?Destination, or in the current scopes hoisted init instructions.
     *  Most of the time the instuctions will go in the hoisted init instructions, but if the nested function is declared
     *  in a 'with' or 'catch' block then the init instructions need to go into the normal controlFlow?Sensitive?Destination.
     *
     *  @param iNode - the function node for the nested function.
     *  @param controlFlowSensitiveDestination - the instruction list to add instructions to
     *  @param func_name - the function's name.
     *  @param return_type - the function's return type.
     *  @param function_body - the body of the function.
     *  @pre the function's lexical scope must be at the
     *    top of the lexical scope stack, with the declaring
     *    function's lexical scope under it.
     *  @post the nested function's MethodInfo is filled in,
     *    the function body is attached to its MethodBodyInfo,
     *    and the declaring function's initialization sequence
     *    gets code to declare the function.
     */
    private void generateNestedFunction(IASNode iNode, InstructionList controlFlowSensitiveDestination, Binding func_name, Name return_type, InstructionList function_body)
    {
        currentScope.setFunctionName(func_name.getName().getBaseName());
        currentScope.generateNestedFunction(generateFunctionBody(iNode, function_body, return_type));
        //  Pull the nested function's MethodInfo out of its scope before we pop it.
        MethodInfo nested_method_info = currentScope.getMethodInfo();

        currentScope = currentScope.popFrame();

        //  Initialize the nested function; add a variable 
        //  to the containing function scope and add 
        //  newfunction/setproperty logic to the containing
        //  function's hoisted initialization instructions.
        currentScope.makeVariable(func_name);

        InstructionList init_insns = SemanticUtils.canNestedFunctionBeHoisted(iNode) ? currentScope.getHoistedInitInstructions() : controlFlowSensitiveDestination;

        //  The containing function must be marked needsActivation() so the
        //  binding cannot be local.
        assert(!func_name.isLocal());
        init_insns.addInstruction(OP_findproperty, func_name.getName());
        init_insns.addInstruction(OP_newfunction, nested_method_info);
        init_insns.addInstruction(OP_setproperty, func_name.getName());
    }

    /**
     *  Generate a try/catch/finally (or try/finally) compound statement.
     *  @param try_stmt - the body of the try block.
     *  @param catch_blocks - associated catch blocks.
     *    May be null if no catch blocks are present.
     *  @param finally_stmt - the body of the finally block.
     */
    InstructionList generateTryCatchFinally ( InstructionList try_stmt, Vector<CatchPrototype> catch_blocks, InstructionList finally_stmt)
    {
        InstructionList normal_flow_fixup = new InstructionList();
        InstructionList catch_insns = new InstructionList();
        InstructionList final_catch = new InstructionList();
        InstructionList finally_insns = new InstructionList();
        InstructionList final_throw = new InstructionList();

        ExceptionHandlingContext finally_context = currentScope.getFlowManager().getFinallyContext();

        Label final_catch_target = final_catch.getLabel();

        //  We need a local to store the caught exception.
        Binding exception_storage = finally_context.getExceptionStorage();

        Collection<Label> pending_normal_control_flow = try_stmt.stripPendingLabels();

        if ( try_stmt.canFallThrough() || pending_normal_control_flow != null )
        {
            normal_flow_fixup.addInstruction(OP_jump, finally_context.finallyBlock);
        }
        else
        {
            //  Extend the region past a terminating
            //  throw statement to give the AVM a
            //  little buffer to figure out its
            //  exception-handling regions.
            normal_flow_fixup.addInstruction(OP_nop);
        }

        Label try_start = try_stmt.getLabel();
        Label try_end   = normal_flow_fixup.getLastLabel();

        Label finally_region_end = null;

        if ( null == catch_blocks )
        {
            finally_region_end = try_end;
        }
        else
        {
            for ( CatchPrototype catch_proto: catch_blocks )
            {

                InstructionList catch_body = generateCatchBlock(try_start, try_end, catch_proto);

                boolean is_last_catch = catch_proto.equals(catch_blocks.lastElement());

                if ( catch_body.canFallThrough() )
                {
                    //  Signal the finally block that this execution succeeded.
                    catch_body.addInstruction(OP_pushbyte, 0);
                    catch_body.addInstruction(finally_context.finallyReturnStorage.setlocal());
                    catch_body.addInstruction(OP_jump, finally_context.finallyBlock);
                }
                else if ( is_last_catch )
                {
                    //  Extend the region past a terminating throw
                    //  insn to give the AVM a little buffer.
                    catch_body.addInstruction(OP_nop);
                }

                if ( is_last_catch )
                    finally_region_end = catch_body.getLastLabel();

                catch_insns.addAll(catch_body);
            }
        }

        //  Set up the exception handler for the finally block.
        currentScope.getMethodBodyVisitor().visitException(try_start, finally_region_end, final_catch_target, null, null);

        //  The final catch block only needs to save the
        //  caught exception for a rethrow.
        if ( currentScope.needsThis() )
        {
            final_catch.addInstruction(OP_getlocal0);
            final_catch.addInstruction(OP_pushscope);
        }

        if( currentScope.needsActivation() )
        {
            //  Restore the activation object
            final_catch.addInstruction(currentScope.getActivationStorage().getlocal());
            final_catch.addInstruction(OP_pushscope);
        }

        final_catch.addAll(currentScope.getFlowManager().getScopeStackReinit());
        final_catch.addInstruction(exception_storage.setlocal());
        //  Signal the finally epilog that this execution failed
        //  and should rethrow.
        final_catch.addInstruction(OP_pushbyte, currentScope.getFlowManager().getFinallyAlternativesSize() + 1);
        final_catch.addInstruction(finally_context.finallyReturnStorage.setlocal());

        //  falls through
        // final_catch.addInstruction(OP_jump,  finally_head);

        finally_insns.addInstruction(finally_context.finallyReturnStorage.getlocal());
        finally_insns.addInstruction(OP_convert_i);
        finally_insns.addAll(currentScope.getFlowManager().getFinallySwitch());

        //  Label the start of the final set of instructions.
        if (!finally_stmt.isEmpty())
        {
            finally_stmt.labelFirst(finally_context.finallyBlock);
        }
        else
            //  This is just an expedient for this degenerate finally.
            finally_insns.labelFirst(finally_context.finallyBlock);

        final_throw.addInstruction(exception_storage.getlocal());
        final_throw.labelCurrent(finally_context.finallyDoRethrow);
        final_throw.addInstruction(OP_throw);

        //  Assemble the statement.
        InstructionList result = new InstructionList();

        result.addInstruction(OP_pushbyte, 0);
        result.addInstruction(finally_context.finallyReturnStorage.setlocal());

        result.addAll(try_stmt);

        //  Send all "next statement" type control flow into the finally block.
        result.addAllPendingLabels(pending_normal_control_flow);

        result.addAll(normal_flow_fixup);

        result.addAll(catch_insns);
        result.addAll(final_catch);

        result.addAll(finally_stmt);
        result.addAll(finally_insns);
        result.addAll(final_throw);

        for ( ExceptionHandlingContext.FinallyReturn retblock: finally_context.finallyReturns )
            result.addAll(retblock.getInstructions());

        //  TODO: Need more analysis of how this temp travels through
        //  the system before it can be safely released.  For now
        //  just leak it.
        //  currentScope.releaseTemp(exception_storage);

        //  TODO: Removing a hanging kill exposed a latent bug 
        //  in hasPendingLabels() and end-of-routine processing.
        //  Give the CG a harmless instruction that will generate
        //  a returnvoid if this is the last statement in the routine.
        result.addInstruction(OP_nop);

        //  Fallthrough out of the finally block.
        result.labelNext(finally_context.finallyDoFallthrough);

        return result;
    }

    /**
     * Reduce a name to an instruction list that can be used in a parameterized type expression.
     * This is different from the normal name -> expression because '*' maps to pushnull.
     * @param iNode         the node
     * @param param_name    the name to reduce
     * @return              IL with instructions to push the appropriate value on the stack
     */
    public InstructionList reduce_typeNameParameter(IASNode iNode, Binding param_name)
    {
        InstructionList result = createInstructionList(iNode);

        generateTypeNameParameter(param_name, result);

        return result;
    }

    /**
     *  Generate the instruction sequence that designates
     *  the parameter of a parameterized type, e.g.,
     *  String in Vector.&lt;String&gt; or * in Vector.&lt;*&gt;.
     *  @param param_node - the type parameter's node.
     *  @param param_name - the type parameter's name.
     *    May be null in the * case.
     *  @param result - the instruction sequence to generate into.
     */
    private void generateTypeNameParameter(Binding param, InstructionList result)
    {
        if ( param == null || param.getName() == null || param.getName().couldBeAnyType() )
            result.addInstruction(OP_pushnull);
        else
            generateAccess(param, false, AccessType.Strict, result);
    }

    /**
     * @return A
     * {@link ControlFlowContextManager.ControlFlowContextSearchCriteria} that
     * will find the control context that a break statement without a label in
     * the current control flow context refers to. This should always be a
     * control flow context for any of:
     * <ul>
     * <li>a labeled statement</li>
     * <li>a loop</li>
     * <li>a switch statement</li>
     * </ul>
     */
    private ControlFlowContextManager.ControlFlowContextSearchCriteria getBreakCriteria()
    {
        return ControlFlowContextManager.breakWithOutLabelCriteria;
    }
    
    /**
     * @return A
     * {@link ControlFlowContextManager.ControlFlowContextSearchCriteria} that
     * will find the control context that a continue statement without a label
     * in the current control flow context refers to. This should always be a
     * control flow context for a loop.
     */
    private ControlFlowContextManager.ControlFlowContextSearchCriteria getContinueCriteria()
    {
        return ControlFlowContextManager.continueWithOutLabelCriteria;
    }
    
    /**
     * @param Label name in a break statement with a label.
     * @return A
     * {@link ControlFlowContextManager.ControlFlowContextSearchCriteria} that
     * will find the control context that a break statement with a label in the
     * current control flow context refers to. This should always be a control
     * flow context for labeled statement.
     */
    private ControlFlowContextManager.ControlFlowContextSearchCriteria getBreakCriteria(String label)
    {
        return currentScope.getFlowManager().breakWithLabelCriteria(label);
    }
    
    /**
     * @param Label name in a continue statement with a label.
     * @return A
     * {@link ControlFlowContextManager.ControlFlowContextSearchCriteria} that
     * will find the control context that a continue statement with a label
     * in the current control flow context refers to. This should always be a
     * control flow context for a loop.
     */
    private ControlFlowContextManager.ControlFlowContextSearchCriteria getContinueCriteria(String label)
    {
        return currentScope.getFlowManager().continueWithLabelCriteria(label);
    }
    
    /**
     * @param Label name in a goto statement.
     * @return A
     * {@link ControlFlowContextManager.ControlFlowContextSearchCriteria} that
     * will find the control context that a goto statement in the
     * current control flow context refers to. This should always be a control
     * flow context for labeled statement.
     */
    private ControlFlowContextManager.ControlFlowContextSearchCriteria getGotoCriteria(String label)
    {
        return currentScope.getFlowManager().gotoLabelCriteria(label, false);
    }
    
    /**
     * Constructs a sequence of code that will jump to the proper location in the
     * control flow context matched by the criteria object.  The returned code will
     * run finally blocks and adjust the scope stack if needed.
     * @param criteria Criteria object that matches the control flow context and specifies the location
     * in that context to which the generated code will jump to.
     * @return An {@link InstructionList} that will jump to the proper location in the
     * control flow context matched by the criteria object
     * @throws UnknownControlFlowTargetException
     */
    private InstructionList getBranchTarget(ControlFlowContextManager.ControlFlowContextSearchCriteria criteria)
        throws UnknownControlFlowTargetException
    {
        return currentScope.getFlowManager().getBranchTarget(criteria);
    }

    /**
     *  @return the double content of a numeric literal.
     *  @param iNode - the literal node.
     */
    Double getDoubleContent(IASNode iNode)
    {
        return SemanticUtils.getDoubleContent(iNode);
    }

    /**
     *  @return the name of an identifier.
     *  @param iNode - the IIdentifier node.
     */
    String getIdentifierContent(IASNode iNode)
    {
        return SemanticUtils.getIdentifierContent(iNode);
    }

    /**
     *  @return the int content of a numeric literal.
     *  @param iNode - the literal node.
     */
    Integer getIntegerContent(IASNode iNode)
    {
        return SemanticUtils.getIntegerContent(iNode);
    }
    
    /**
     *  @return always zero.
     *  @param iNode - the literal node.
     */
    Integer getIntegerZeroContent(IASNode iNode)
    {
        return 0;
    }    
    
    /**
     *  @return always zero.
     *  @param iNode - the literal node.
     */
    Long getIntegerZeroContentAsLong(IASNode iNode)
    {
        return 0L;
    }

    /**
     *  @return a node cast to MXMLEventSpecifierNode type.
     *  @param iNode - the MXMLEventSpecifierNode node.
     */
    IMXMLEventSpecifierNode getMXMLEventSpecifierContent(IASNode iNode)
    {
        return SemanticUtils.getMXMLEventSpecifierContent(iNode);
    }

    /**
     *  Find all active exception handling blocks or scopes,
     *  and set up finally return sequences and/or popscopes.
     *  @param original - the original control-flow sequence.
     *  @param criterion - the search criterion that identifies
     *    the boundary of the region to be exited.
     *  @return a control-flow sequence that is either the
     *    original sequence or the start of a trampoline of
     *    finally blocks, popscopes, and whatever else is 
     *    necessary to exit the control-flow region.
     *  @throws UnknownControlFlowTargetException if the criterion is not on the control-flow stack.
     */
    private InstructionList getNonLocalControlFlow(InstructionList original, ControlFlowContextManager.ControlFlowContextSearchCriteria criterion)
        throws UnknownControlFlowTargetException
    {
        return currentScope.getFlowManager().getNonLocalControlFlow(original, criterion);
    }
    
    /**
     *  Find all active exception handling blocks or scopes,
     *  and set up finally return sequences and/or popscopes.
     *  @param criterion - the search criterion that identifies
     *    the boundary of the region to be exited and the target
     *    in the found region to jump to.
     *  @return a control-flow sequence that is either the
     *    original sequence or the start of a trampoline of
     *    finally blocks, popscopes, and whatever else is 
     *    necessary to exit the control-flow region.
     *  @throws UnknownControlFlowTargetException if the criterion is not on the control-flow stack.
     */
    private InstructionList getNonLocalControlFlow(ControlFlowContextManager.ControlFlowContextSearchCriteria criterion)
        throws UnknownControlFlowTargetException
    {
        return currentScope.getFlowManager().getNonLocalControlFlow(getBranchTarget(criterion), criterion);
    }

    /**
     *  @return a parameter's definition.
     *  @param iNode - the parameter node.
     */
    IDefinition getParameterContent(IASNode iNode)
    {
        return SemanticUtils.getParameterContent(iNode);
    }
    
    /**
     *  @return the string content of a literal.
     *  @param iNode - the literal node.
     */
    String getStringLiteralContent(IASNode iNode)
    {
        return SemanticUtils.getStringLiteralContent(iNode);
    }

    /**
     *  @return the uint content of a numeric literal.
     *  @param iNode - the literal node.
     */
    Long getUintContent(IASNode iNode)
    {
        return SemanticUtils.getUintContent(iNode);
    }
    
    /**
     *  @return the Boolean content of a BOOLEAN literal.
     *  @param iNode - the literal node.
     */
    boolean getBooleanContent(IASNode iNode)
    {
        return SemanticUtils.getBooleanContent(iNode);
    }

    /**
     *  @return true if instance initialization instructions are present.
     */
    private boolean haveInstanceInitializers()
    {
        return instanceInitializers != null;
    }

    /* 
     * 
     *  *******************************
     *  **  Cost/Decision Functions  **
     *  *******************************
     *
     */

    /**
     *  Explore a MemberAccessNode and 
     *  decide if its stem is a reference
     *  to a package.
     *
     *  This method will always return a result greater than what isPackageName will return,
     *  as package name must "win" over dotted name.
     */
    int isDottedName(IASNode n)
    {
        int result = Integer.MAX_VALUE;

        if ( n instanceof MemberAccessExpressionNode )
        {
            MemberAccessExpressionNode ma = (MemberAccessExpressionNode)n;

            if(ma.stemIsPackage())
                // This needs to be greater than the value returned from isPackageName,
                // so that isPackageName wins
                result = 2;
        }

        return result;
    }

    /**
     *  Explore a MemberAccessNode and
     *  decide if it is a reference
     *  to a package.
     *
     *  This method will always return a result less than what isDottedName will return,
     *  as package name must "win" over dotted name.
     */
    int isPackageName(IASNode n)
    {
        int result = Integer.MAX_VALUE;

        if ( n instanceof MemberAccessExpressionNode )
        {
            MemberAccessExpressionNode ma = (MemberAccessExpressionNode)n;

            if(ma.isPackageReference())
                // This needs to be less than the value returned from isDottedName,
                // so that isPackageName wins
                result = 1;
        }

        return result;
    }

    /**
     *  Get the definition associated with a node's qualifier
     *  and decide if the qualifier is a compile-time constant.
     *  @param iNode - the node to check.
     *  @pre - the node has an IdentifierNode 0th child.
     *  @return an attractive cost if the child has a known namespace, i.e.,
     *    it's a compile-time constant qualifier.
     */
    int qualifierIsCompileTimeConstant(IASNode iNode)
    {
        IdentifierNode qualifier = (IdentifierNode)SemanticUtils.getNthChild(iNode, 0);
        IDefinition def = qualifier.resolve(currentScope.getProject());

        int result = def instanceof NamespaceDefinition ? 1 : Integer.MAX_VALUE;
        return result;
    }

    /**
     *  @return a feasible cost if a node has a compile-time constant defintion.
     */
    int isCompileTimeConstant(IASNode iNode)
    {
        if ( SemanticUtils.transformNameToConstantValue(iNode, currentScope.getProject()) != null )
            return 1;
        else
            return Integer.MAX_VALUE;
    }

    /**
     *  Check a Binding to decide if its referent 
     *  is statically known to be a Namespace. 
     *  @param b - the Binding to check.
     *  @return true if the given Binding refers to a namespace.
     */
    private boolean isNamespace(Binding b)
    {
        return b.getDefinition() instanceof NamespaceDefinition;
    }

    /**
     *  Check a Binding to see if it's defined as the ANY namespace.
     *  @param b - the Binding to check.
     *  @return true if the Binding's definition is the ANY namespace definition.
     */
    private boolean isAnyNamespace(Binding b)
    {
        return b.getDefinition().equals(NamespaceDefinition.getAnyNamespaceReference());
    }
    
    /**
     *  @return a feasible cost (1) if the node is for 'new Array()'
     */
    int isEmptyArrayConstructor(IASNode iNode)
    {
        ICompilerProject project = currentScope.getProject();
        IIdentifierNode identifierNode = (IIdentifierNode)SemanticUtils.getNthChild(iNode, 1);
        if (identifierNode.resolve(project) == project.getBuiltinType(BuiltinType.ARRAY))
            return 1;

        return Integer.MAX_VALUE;
    }

    /**
     *  @return a feasible cost (1) if the node is for 'new Object()'
     */
    int isEmptyObjectConstructor(IASNode iNode)
    {
        ICompilerProject project = currentScope.getProject();
        IIdentifierNode identifierNode = (IIdentifierNode)SemanticUtils.getNthChild(iNode, 1);
        if (identifierNode.resolve(project) == project.getBuiltinType(BuiltinType.OBJECT))
            return 1;

        return Integer.MAX_VALUE;
    }

    /*
     *  ************************
     *  **  Reduction prologues
     *  ************************
     */

    public void prologue_anonymousFunction(IASNode iNode)
    {
        //  TODO: The current scope may not 
        //  need an activation if the anonymous
        //  function doesn't access any of the
        //  current scope's locals.
        currentScope = currentScope.pushFrame();
        currentScope.declareAnonymousFunction();
        currentScope.setInitialControlFlowRegionNode(((FunctionObjectNode)iNode).getFunctionNode().getScopedNode());
    }
    
    public void prologue_functionObject(IASNode iNode)
    {
        final FunctionNode innerFunctionNode = ((FunctionObjectNode)iNode).getFunctionNode();
        currentScope = currentScope.pushFrame();
        currentScope.declareFunctionObject(innerFunctionNode.getName());
        currentScope.setInitialControlFlowRegionNode(innerFunctionNode.getScopedNode());
        prologue_function(iNode);
    }

    public void prologue_blockStmt(IASNode iNode)
    {
        //  Note: don't create an InstructionList with
        //  line number information here; this IL is
        //  a pure placeholder.
        this.miniScopes.push(new InstructionList());
    }

    public void prologue_blockStmt_to_finally_clause(IASNode iNode)
    {
        currentScope.getFlowManager().startFinallyContext(iNode);
    }

    public void prologue_catchBlock(IASNode iNode)
    {
        currentScope.getFlowManager().startCatchContext((ICatchNode)iNode);
    }

    private void loop_prologue_common(IASNode loopNode, IASNode loopContents)
    {
        currentScope.getFlowManager().startLoopControlFlowContext(loopContents);
    }
    
    public void prologue_countedForStmt(IASNode iNode)
    {
        loop_prologue_common(iNode, ((IForLoopNode)iNode).getStatementContentsNode());
    }

    public void prologue_doStmt(IASNode iNode)
    {
        loop_prologue_common(iNode, ((IWhileLoopNode)iNode).getStatementContentsNode());
    }

    public void prologue_forEachStmt(IASNode iNode)
    {
        loop_prologue_common(iNode, ((IForLoopNode)iNode).getStatementContentsNode());
    }

    public void prologue_forInStmt(IASNode iNode)
    {
        loop_prologue_common(iNode, ((IForLoopNode)iNode).getStatementContentsNode());
    }

    void prologue_function(IASNode n)
    {
        FunctionDefinition func = null;

        IFunctionNode funcNode = null;
        
        if ( n instanceof IFunctionNode )
            funcNode = (IFunctionNode)n;
        else if( n instanceof FunctionObjectNode )
            funcNode = ((FunctionObjectNode)n).getFunctionNode();

        // Add any parse problems which might have been encountered while lazily parsing the function
        if( funcNode instanceof FunctionNode )
        {
            Collection<ICompilerProblem> parseProblems = ((FunctionNode) funcNode).getParsingProblems();
            for( ICompilerProblem problem : parseProblems )
                currentScope.addProblem(problem);
        }

        assert funcNode != null : n + " has no FunctionNode child";
        func = (FunctionDefinition)funcNode.getDefinition();
        assert(func != null): n + " has no definition.";

        currentScope.setLocalASScope(func.getContainedScope());
        currentScope.resetDebugInfo();

        // Set the current file name - the function body will always start with an OP_debugfile
        // so we never need emit another one unless the method body spans multiple files
        currentScope.setDebugFile(SemanticUtils.getFileName(n));

        currentScope.getMethodBodySemanticChecker().checkFunctionDefinition(funcNode, func);
        for ( int i = 0; i < funcNode.getChildCount(); i++ )
            scanFunctionBodyForActivations(funcNode.getChild(i));
    }

    public void prologue_labeledStmt(IASNode iNode)
    {
        // Since the Prologue code runs before the subtrees have been reduced, 
        // we can't get the label string via the non_resolving_identifier reduction.
        try
        {
            currentScope.getFlowManager().startLabeledStatementControlFlowContext((LabeledStatementNode) iNode);
        }
        catch ( DuplicateLabelException dup_label )
        {
            currentScope.addProblem(new DuplicateLabelProblem(iNode));
        }
    }

    public void prologue_mxmlEventSpecifier(IASNode iNode)
    {
        // The method that implements an event specifier has a single parameter.
        // Its name is "event" (which is discovered from the ParameterDefinition
        // that the event node creates).
        // Its type, such as flash.events.MouseEvent, has already been determined
        // when we created the MethodInfo, so we access it there
        // rather than creatinga another equivalent Name.
        currentScope.makeParameter(
            getMXMLEventSpecifierContent(iNode).getEventParameterDefinition(),
            currentScope.getMethodInfo().getParamTypes().get(0));

    }

    public void prologue_switchStmt(IASNode iNode)
    {
        // Establish a switch context so that breaks inside the switch statement will work.
        currentScope.getFlowManager().startSwitchContext((SwitchNode)iNode);
    }

    public void prologue_tryCatchFinallyStmt(IASNode iNode)
    {
        currentScope.getFlowManager().startExceptionContext((ITryNode) iNode);
        currentScope.getFlowManager().getFinallyContext().setHasFinallyBlock(true);
    }

    public void prologue_tryCatchStmt(IASNode iNode)
    {
        currentScope.getFlowManager().startExceptionContext((ITryNode) iNode);
    }

    public void prologue_tryFinallyStmt(IASNode iNode)
    {
        currentScope.getFlowManager().startExceptionContext((ITryNode) iNode);
        currentScope.getFlowManager().getFinallyContext().setHasFinallyBlock(true);
    }

    public void prologue_typedFunction_to_statement(IASNode iNode)
    {
        //  Note: A named nested function does 
        //  always need an activation record.
        currentScope = currentScope.pushFrame();
        currentScope.declareNestedFunction();
        currentScope.setInitialControlFlowRegionNode(((IFunctionNode)iNode).getScopedNode());
        prologue_function(iNode);
    }

    public void prologue_typelessFunction_to_statement(IASNode iNode)
    {
        //  Note: A named nested function does 
        //  always need an activation record.
        currentScope = currentScope.pushFrame();
        currentScope.declareNestedFunction();
        currentScope.setInitialControlFlowRegionNode(((IFunctionNode)iNode).getScopedNode());
        prologue_function(iNode);
    }

    /**
     *  Count the number of typeof levels active.
     */
    private int typeofCount = 0;

    /**
     *  Before reducing the operands of a typeof,
     *  we need to increment the typeof counter.
     *  It will be decremented by the reduction's
     *  epilogue.
     */
    public void prologue_typeof(IASNode iNode)
    {
        this.typeofCount++;
    }

    public void prologue_whileStmt(IASNode iNode)
    {
        currentScope.getFlowManager().startLoopControlFlowContext(((IWhileLoopNode)iNode).getStatementContentsNode());
    }

    public void prologue_withStmt(IASNode iNode)
    {
        currentScope.getFlowManager().startWithContext(((IWithNode)iNode).getStatementContentsNode());
    }

    /*
     *  *************************
     *  **  Reduction actions  **
     *  *************************
     */
    

    public InstructionList reduce_anonymousFunction(IASNode iNode, InstructionList function_body)
    {
        InstructionList result = createInstructionList(iNode, 1);

        currentScope.generateNestedFunction(function_body);
        result.addInstruction(OP_newfunction, currentScope.getMethodInfo());

        currentScope = currentScope.popFrame();
        return result;
    }
    
    public InstructionList reduce_functionObject(IASNode iNode, IASNode function_name, InstructionList plist, Binding return_binding, InstructionList function_body)
    {
        InstructionList result = createInstructionList(iNode);

        Binding nestedFunctionName = currentScope.resolveName((IdentifierNode)function_name);
        Name return_type;

        if ( return_binding != null ) 
            return_type = return_binding.getName();
        else
            return_type = null;

        currentScope.generateNestedFunction(generateFunctionBody(iNode, function_body, return_type));
        //  Pull the nested function's MethodInfo out of its scope before we pop it.
        MethodInfo nested_method_info = currentScope.getMethodInfo();
        currentScope = currentScope.popFrame();

        //  Create a wrapper routine that returns the named
        //  routine wrapped in a closure; it's an anonymous
        //  function with an activation record.
        currentScope = currentScope.pushFrame();
        currentScope.declareAnonymousFunction();
        currentScope.setInitialControlFlowRegionNode(((FunctionObjectNode)iNode).getFunctionNode().getScopedNode());
        currentScope.setNeedsActivation();

        currentScope.makeVariable(
                nestedFunctionName, 
                SemanticUtils.getAETName(currentScope.getProject().getBuiltinType(BuiltinType.FUNCTION), currentScope.getProject()),
                null, // no meta tags
                null, // no initializer
                LexicalScope.VariableMutability.Constant
            );

        InstructionList wrapper_insns = createInstructionList(iNode);

        wrapper_insns.addInstruction(OP_newfunction, nested_method_info);
        wrapper_insns.addInstruction(OP_dup);
        wrapper_insns.addInstruction(OP_findproperty, nestedFunctionName.getName());
        wrapper_insns.addInstruction(OP_swap);
        wrapper_insns.addInstruction(OP_setslot, 1);
        wrapper_insns.addInstruction(OP_returnvalue);
        currentScope.generateNestedFunction(generateFunctionBody(iNode, wrapper_insns, LexicalScope.anyType));

        MethodInfo wrapper_method_info = currentScope.getMethodInfo();
        currentScope = currentScope.popFrame();

        result.addInstruction(OP_newfunction, wrapper_method_info);
        //  Doesn't matter much what we use as "this" --
        //  the store acts on the activation.
        result.addInstruction(OP_getlocal0);
        result.addInstruction(OP_call, 0);

        return result;
    
    }

    public InstructionList reduce_arrayIndexExpr(IASNode iNode, InstructionList stem, boolean is_super, InstructionList index)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)iNode;

        if ( is_super )
            currentScope.getMethodBodySemanticChecker().checkSuperAccess(arrayIndexNode);

        InstructionList result;

        if ( !is_super )
        {
            result = createInstructionList(arrayIndexNode, stem.size() + index.size() + 1);
            result.addAll(stem);
        }
        else
        {
            result = createInstructionList(arrayIndexNode, index.size() + 2);
            //  Use "this" as the stem.
            result.addInstruction(OP_getlocal0);
        }
        result.addAll(index);

        result.addInstruction(arrayAccess(arrayIndexNode, is_super? OP_getsuper: OP_getproperty));

        return result;
    }

    public InstructionList reduce_arrayLiteral(IASNode iNode, Vector<InstructionList> elements)
    {
        //  No semantic restrictions on array literals.

        //  TODO: Investigate optimizing.
        InstructionList result = createInstructionList(iNode);

        for ( InstructionList element: elements )
            result.addAll(element);

        result.addInstruction(OP_newarray, elements.size());
        return result;
    }

    public InstructionList reduce_assignToBracketExpr_to_expression(IASNode iNode, InstructionList stem, InstructionList index, InstructionList r, boolean is_super)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IBinaryOperatorNode)iNode).getLeftOperandNode();
        
        currentScope.getMethodBodySemanticChecker().checkAssignToBracketExpr(iNode);

        Binding local = currentScope.allocateTemp();

        InstructionList result = createInstructionList(iNode, (is_super ? 1:stem.size()) + index.size() + r.size() + 5);
        if( is_super )
            result.addInstruction(OP_getlocal0);
        else
            result.addAll(stem);
        
        result.addAll(index);
        result.addAll(r);
        result.addInstruction(OP_dup);
        result.addInstruction(local.setlocal() );
        result.addInstruction(arrayAccess(arrayIndexNode, is_super ? OP_setsuper : OP_setproperty));
        result.addInstruction(local.getlocal() );

        currentScope.releaseTemp(local);

        return result;
    }

    public InstructionList reduce_assignToBracketExpr_to_void_expression(IASNode iNode, InstructionList stem, InstructionList index, InstructionList r, boolean is_super)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IBinaryOperatorNode)iNode).getLeftOperandNode();
        
        /*
        ITypeDefinition destinationType = arrayIndexNode.resolveType(currentScope.getProject());
        IExpressionNode valueNode = ((IBinaryOperatorNode)iNode).getRightOperandNode();
        
        IDefinition type_def = valueNode.resolveType(currentScope.getProject()); //SemanticUtils.getDefinitionOfUnderlyingType(, 
                           // true, currentScope.getProject());
        boolean need_coerce = !type_def.equals(destinationType) || (valueNode instanceof TernaryOperatorNode);
        */

        currentScope.getMethodBodySemanticChecker().checkAssignToBracketExpr(iNode);
        
        int num_ins = /*need_coerce ? 2 :*/ 1;

        InstructionList result = createInstructionList(iNode, (is_super ? num_ins : stem.size()) + index.size() + r.size() + num_ins);
        if( is_super )
            result.addInstruction(OP_getlocal0);
        else
            result.addAll(stem);
        result.addAll(index);
        result.addAll(r);
        /*
        if (need_coerce)
            coerce(result, destinationType);
        */
        result.addInstruction(arrayAccess(arrayIndexNode, is_super ? OP_setsuper : OP_setproperty));

        return result;
    }

    public InstructionList reduce_assignToMemberExpr_to_expression(IASNode iNode, InstructionList stem, Binding member, InstructionList r)
    {
        currentScope.getMethodBodySemanticChecker().checkAssignment(iNode, member);

        Binding local = currentScope.allocateTemp();

        InstructionList result = createInstructionList(iNode, stem.size() + r.size() + 5);
        result.addAll(stem);
        result.addAll(r);
        result.addInstruction(OP_dup);
        result.addInstruction(local.setlocal() );
        generateAssignmentOp(iNode, member, result);
        result.addInstruction(local.getlocal() );

        currentScope.releaseTemp(local);

        return result;
    }

    public InstructionList reduce_assignToMemberExpr_to_void_expression(IASNode iNode, InstructionList stem, Binding member, InstructionList r)
    {
        currentScope.getMethodBodySemanticChecker().checkAssignment(iNode, member);

        InstructionList result = createInstructionList(iNode, stem.size() + r.size() + 1);
        result.addAll(stem);
        result.addAll(r);

        generateAssignmentOp(iNode, member, result);

        return result;
    }

    public InstructionList reduce_assignToDescendantsExpr(IASNode iNode, InstructionList stem, Binding member, InstructionList r, boolean need_value)
    {
        //  Note: This code doesn't assign to descendants!
        //  While one might think it should, it does in fact
        //  mirror the bytecode ASC emitted.
        currentScope.getMethodBodySemanticChecker().checkAssignment(iNode, member);

        Binding local = null;

        InstructionList result = createInstructionList(iNode, stem.size() + r.size() + 5);
        result.addAll(stem);
        result.addAll(r);
        if ( need_value )
        {
            local = currentScope.allocateTemp();
            result.addInstruction(OP_dup);
            result.addInstruction(local.setlocal() );
        }

        generateAssignmentOp(iNode, member, result);

        if ( need_value )
        {
            result.addInstruction(local.getlocal());
            currentScope.releaseTemp(local);
        }

        return result;
    }

    public InstructionList reduce_assignToNameExpr_to_void_expression(IASNode iNode, Binding lvalue, InstructionList r)
    {
        currentScope.getMethodBodySemanticChecker().checkAssignment(iNode, lvalue);
        return generateAssignment(iNode, lvalue, r);
    }

    public InstructionList reduce_assignToNameExpr_to_expression(IASNode iNode, Binding lvalue, InstructionList r)
    {
        currentScope.getMethodBodySemanticChecker().checkAssignment(iNode, lvalue);
        return generateAssignment(iNode, lvalue, r, true);
    }

    public InstructionList reduce_assignToQualifiedMemberExpr(IASNode iNode, InstructionList stem, Binding qualifier, Binding member, InstructionList rhs, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);

        if ( !isNamespace(qualifier) )
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
        }
        //  else the qualifier's namespace is already present in the name.
        result.addAll(rhs);

        Binding value_temp = null;
        if ( need_value )
        {
            value_temp = currentScope.allocateTemp();
            result.addInstruction(OP_dup);
            result.addInstruction(value_temp.setlocal());
        }

        generateAssignmentOp(iNode, member, result);

        if ( need_value )
        {
            result.addInstruction(value_temp.getlocal());
            currentScope.releaseTemp(value_temp);
        }

        return result;
    }

    public InstructionList reduce_assignToQualifiedRuntimeMemberExpr(IASNode iNode, InstructionList stem, Binding qualifier, InstructionList runtime_member_selector, InstructionList rhs, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        if ( isNamespace(qualifier) )
        {
            result.addAll(runtime_member_selector);
            //  Extract the URI from the namespace and use it to construct a qualified name.
            NamespaceDefinition ns_def = (NamespaceDefinition)qualifier.getDefinition();
            Name qualified_name = new Name(CONSTANT_MultinameL, new Nsset(ns_def.resolveAETNamespace(currentScope.getProject())), null);
            result.addAll(rhs);
            result.addInstruction(OP_setproperty, qualified_name);
        }
        else
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
            result.addAll(runtime_member_selector);
            result.addAll(rhs);

            Binding value_temp = null;
            if ( need_value )
            {
                value_temp = currentScope.allocateTemp();
                result.addInstruction(OP_dup);
                result.addInstruction(value_temp.setlocal());
            }
            result.addInstruction(OP_setproperty, new Name(CONSTANT_RTQnameL, null, null));

            if ( need_value )
            {
                result.addInstruction(value_temp.getlocal());
                currentScope.releaseTemp(value_temp);
            }
        }
        return result;
    }

    public InstructionList reduce_assignToQualifiedAttributeExpr(IASNode iNode, InstructionList stem, Binding qualifier, Binding member, InstructionList rhs, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);

        if ( !isNamespace(qualifier) )
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
        }
        //  else the qualifier's namespace is already present in the name.

        result.addAll(rhs);

        Binding value_temp = null;
        if ( need_value )
        {
            value_temp = currentScope.allocateTemp();
            result.addInstruction(OP_dup);
            result.addInstruction(value_temp.setlocal());
        }

        generateAssignmentOp(iNode, member, result);

        if ( need_value )
        {
            result.addInstruction(value_temp.getlocal());
            currentScope.releaseTemp(value_temp);
        }

        return result;
    }

    public InstructionList reduce_assignToQualifiedRuntimeAttributeExpr(IASNode iNode, InstructionList stem, Binding qualifier, InstructionList runtime_member_selector, InstructionList rhs, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);

        if ( isAnyNamespace(qualifier) )
        {
            IASNode site = qualifier.getNode() != null? qualifier.getNode(): iNode;

            currentScope.addProblem(new AnyNamespaceCannotBeQualifierProblem(site));
        }
        else if ( ! isNamespace(qualifier) )
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
            result.addAll(runtime_member_selector);
            result.addInstruction(OP_coerce_s);
            result.addAll(rhs);
            Binding value_temp = null;

            if ( need_value )
            {
                value_temp = currentScope.allocateTemp();
                result.addInstruction(OP_dup);
                result.addInstruction(value_temp.setlocal());
            }

            result.addInstruction(OP_setproperty, new Name(CONSTANT_RTQnameLA, null, null));

                if ( need_value )
                {
                    result.addInstruction(value_temp.getlocal());
                    currentScope.releaseTemp(value_temp);
                }

        }
        else
        {
            result.addAll(runtime_member_selector);
            //  Extract the URI from the namespace and use it to construct a qualified name.
            NamespaceDefinition ns_def = (NamespaceDefinition)qualifier.getDefinition();
            Name qualified_name = new Name(CONSTANT_MultinameLA, new Nsset(ns_def.resolveAETNamespace(currentScope.getProject())), null);
            result.addAll(rhs);

            Binding value_temp = null;
            if ( need_value )
            {
                value_temp = currentScope.allocateTemp();
                result.addInstruction(OP_dup);
                result.addInstruction(value_temp.setlocal());
            }

            result.addInstruction(OP_setproperty, qualified_name);

            if ( need_value )
            {
                result.addInstruction(value_temp.getlocal());
                currentScope.releaseTemp(value_temp);
            }
        }
        return result;
    }


    public InstructionList reduce_assignToRuntimeNameExpr(IASNode iNode, RuntimeMultiname lval, InstructionList r, final boolean need_value)
    {
        InstructionList result;

        if ( need_value )
        {
            //  TODO: In many cases this temp can be avoided by more sophisticated analysis.
            //  TODO: See also comments in RuntimeMultiname.generateGetOrSet().
            Binding temp = currentScope.allocateTemp();
            result = createInstructionList(iNode);
            result.addAll(r);
            result.addInstruction(temp.setlocal());
            InstructionList temp_rhs = new InstructionList();
            temp_rhs.addInstruction(temp.getlocal());
            result.addAll(lval.generateAssignment(iNode, temp_rhs));
            result.addInstruction(temp.getlocal());
            currentScope.releaseTemp(temp);
        }
        else
        {
            result = lval.generateAssignment(iNode, r);
        }

        return result;
    }

    public InstructionList reduce_assignToUnqualifiedRuntimeAttributeExpr(IASNode iNode, InstructionList stem, InstructionList rt_attr, InstructionList rhs, boolean need_value)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);
        result.addAll(rt_attr);
        result.addAll(rhs);

        Binding value_temp = null;
        if ( need_value )
        {
            value_temp = currentScope.allocateTemp();
            result.addInstruction(OP_dup);
            result.addInstruction(value_temp.setlocal());
        }

        result.addInstruction(OP_setproperty, new Name(CONSTANT_MultinameLA, new Nsset(new Namespace(CONSTANT_PackageNs)), null));

        if ( need_value )
        {
            result.addInstruction(value_temp.getlocal());
            currentScope.releaseTemp(value_temp);
        }

        return result;
    }

    public Binding reduce_attributeName(IASNode iNode, Binding attr_name)
    {
        // do nothing - just return the contained name
        // which will already be set up correctly for an attribute name
        return attr_name;
    }

    public InstructionList reduce_blockStmt_to_finally_clause(IASNode iNode, Vector<InstructionList> stmts)
    {
        InstructionList result = createInstructionList(iNode);

        for ( InstructionList stmt: stmts )
            result.addAll(stmt);

        currentScope.getFlowManager().endFinallyContext();
        return result;

    }

    public InstructionList reduce_blockStmt_to_statement(IASNode iNode, Vector<InstructionList> stmts)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(this.miniScopes.pop());

        for ( InstructionList stmt: stmts )
        {
            //  Some statement-level reductions return null.
            if ( stmt != null )
            {
                result.addAll(stmt);
            }
        }

        return result;
    }

    public Boolean reduce_booleanLiteral(IASNode iNode)
    {
        return SemanticUtils.getBooleanContent(iNode);
    }

    public InstructionList reduce_breakStmt(IASNode iNode)
    {
        try
        {
            ControlFlowContextManager.ControlFlowContextSearchCriteria criterion = getBreakCriteria();
            return getNonLocalControlFlow(criterion);
        }
        catch ( UnknownControlFlowTargetException no_target )
        {
            currentScope.addProblem(new UnknownBreakTargetProblem(iNode));
            return createInstructionList(iNode);
        }

    }

    public String reduce_by_concatenation(IASNode iNode, String first, String second)
    {
        return first + "." + second;
    }

    public CatchPrototype reduce_catchBlockTyped(IASNode iNode, Binding var_name, Binding exception, InstructionList action)
    {
        CatchPrototype result = new CatchPrototype();
        result.catchVarName = var_name.getName();
        result.catchType = exception.getName();
        result.catchBody = action;

        currentScope.getFlowManager().endCatchContext();
        return result;
    }

    public CatchPrototype reduce_catchBlockUntyped(IASNode iNode, Binding var_name, InstructionList action)
    {
        CatchPrototype result = new CatchPrototype();
        result.catchVarName = var_name.getName();
        result.catchType = null;
        result.catchBody = action;

        currentScope.getFlowManager().endCatchContext();
        return result;
    }

    public InstructionList reduce_commaExpr(IASNode iNode, InstructionList payload_expr, Vector<InstructionList> exprs)
    {
        //  TODO: Investigate optimizing this.
        InstructionList result = createInstructionList(iNode);

        for ( InstructionList other_expr: exprs )
            result.addAll(other_expr);

        //  The payload expression is the last expression in the
        //  comma list.  It was inverted by IASNodeAdapter into
        //  the 0th position to work around limitations of the
        //  BURG's n-ary operand processor.
        result.addAll(payload_expr);

        return result;
    }

    public ConditionalFragment reduce_conditionalFragment(IASNode iNode, InstructionList condition, Vector<InstructionList> consequents)
    {
        return new ConditionalFragment(iNode, condition, consequents);
    }

    public ConditionalFragment reduce_constantConditionalFragment(IASNode iNode, Object constantCondition, Vector<InstructionList> consequents)
    {
        return new ConditionalFragment(iNode, constantCondition, consequents);
    }

    /**
     * reduce a concatenation of two strings to a string constant
     * @param iNode  the node
     * @param l      the left string
     * @param r      the right string
     * @return       the concatenated string
     */
    public String reduce_constantStringConcatenation(IASNode iNode, String l, String r)
    {
        return l + r;
    }

    /**
     * reduce a concatenation of a string and a constant value to a string constant.  The constant
     * value will be converted to a string according to the ECMA spec, and then will be concatenated with the
     * string.
     * @param iNode  the node
     * @param l      the left string
     * @param r      the right value
     * @return       the concatenated string
     */
    public String reduce_constantStringConcatenation(IASNode iNode, String l, Object r)
    {
        return reduce_constantStringConcatenation(iNode, l, ECMASupport.toString(r));
    }

    /**
     * reduce a concatenation of a constant value and a string to a string constant.  The constant
     * value will be converted to a string according to the ECMA spec, and then will be concatenated with the
     * string.
     * @param iNode  the node
     * @param l      the left value
     * @param r      the right string
     * @return       the concatenated string
     */
    public String reduce_constantStringConcatenation(IASNode iNode, Object l, String r)
    {
        return reduce_constantStringConcatenation(iNode, ECMASupport.toString(l), r);
    }

    /**
     * reduce addition of two constant values.  If either of the constants is a String, then string
     * concatenation will be performed.  OTherwise the constants will be converted to Numbers, according to the
     * ECMA spec, and added
     * @param iNode     the node
     * @param l         the left value
     * @param r         the right value
     * @return          the result of adding the two values
     */
    public Object reduce_constantAddition(IASNode iNode, Object l, Object r)
    {
        checkBinaryOp(iNode, OP_add);
        if( l instanceof String )
            return reduce_constantStringConcatenation(iNode, (String)l, r);
        else if( r instanceof String )
            return reduce_constantStringConcatenation(iNode, l, (String)r);
        else
            return ECMASupport.toNumeric(l).doubleValue() + ECMASupport.toNumeric(r).doubleValue();
    }

    public InstructionList reduce_continueStmt(IASNode iNode)
    {
        try
        {
            ControlFlowContextManager.ControlFlowContextSearchCriteria criterion = getContinueCriteria();
            return getNonLocalControlFlow(criterion);
        }
        catch ( UnknownControlFlowTargetException no_target )
        {
            currentScope.addProblem(new UnknownContinueTargetProblem(iNode));
            return createInstructionList(iNode);
        }
    }

    public InstructionList reduce_countedForStmt(IASNode iNode, InstructionList init, InstructionList test_insns, InstructionList incr, InstructionList body)
    {
        InstructionList test_insns_with_debug_ops = ensureInstructionListHasDebugInfo(test_insns, init);
        InstructionList result = createInstructionList(iNode, init.size() + test_insns_with_debug_ops.size() + incr.size() + body.size() + 5);

        //  Initialize counters, jump to test
        result.addAll(init);

        result.addInstruction(OP_jump, test_insns_with_debug_ops.getLabel());

        //  Loop body
        InstructionList loop_body = new InstructionList();
        Label loop_head = new Label();
        loop_body.addInstruction(OP_label);
        loop_body.labelCurrent(loop_head);
        loop_body.addAll(body);

        //  Set the continue target on the correct instruction.
        if ( !incr.isEmpty() )
            currentScope.getFlowManager().resolveContinueLabel(incr);
        else
            currentScope.getFlowManager().resolveContinueLabel(loop_body);

        result.addAll(loop_body);

        //  Now add the loop counter increments.
        //  The continue context needs to be set
        //  first for InstructionList hygiene.
        result.addAll(incr);

        //  Add the test; a successful test branches
        //  back to the loop head.  The test generation
        //  rules guarantee this last instruction is a
        //  branch instruction that needs a target.
        test_insns_with_debug_ops.lastElement().setTarget(loop_head);
        result.addAll(test_insns_with_debug_ops);

        currentScope.getFlowManager().finishLoopControlFlowContext(result);

        return result;
    }

    /**
     * Check that the dest InstructionList contains debug information.  If not, a new InstructionList
     * will be returned with the debug information extracted from the src InstructionLevel.
     * 
     * @param dest the InstructionList to ensure has debug information
     * @param src the InstructionList from which to obtain debug information if needed
     * @return the resulting InstructionList with debug information
     */
    private static InstructionList ensureInstructionListHasDebugInfo(final InstructionList dest, final InstructionList src)
    {
        // the condition has some debug info, so nothing to do here.
        if (dest.hasSuchInstruction(OP_debugline))
            return dest;

        // If we don't have any debug info on the condition IL, get it from the init IL.
        String debugFile = null;
        int debugLine = LexicalScope.DEBUG_LINE_UNKNOWN;
        final ArrayList<Instruction> srcInstructions = src.getInstructions();
        for (int i = 0; i < srcInstructions.size(); i++)
        {
            final Instruction insn = srcInstructions.get(i);
            if (insn.getOpcode() == OP_debugfile)
            {
                debugFile = (String)insn.getOperand(0);
            }
            else if (insn.getOpcode() == OP_debugline)
            {
                debugLine = insn.getImmediate();
                break;
            }
        }

        InstructionList result = new DebugInfoInstructionList(dest.size() + 2);
        if (debugFile != null)
            result.addInstruction(OP_debugfile, debugFile);

        if (debugLine != LexicalScope.DEBUG_LINE_UNKNOWN)
            result.addInstruction(OP_debugline, debugLine);

        result.addAll(dest);

        return result;
    }

    public InstructionList reduce_defaultXMLNamespace(IASNode iNode, InstructionList ns_expr)
    {
        InstructionList result = createInstructionList(iNode);
        //  TODO: This could be optimized for the string constant case,
        //  but ASC doesn't do so, which means it's future and probably
        //  also not well tested in the AVM.
        result.addAll(ns_expr);
        result.addInstruction(OP_dxnslate);
        currentScope.setSetsDxns();
        return result;
    }

    /**
     * Reduce expression like:<br>
     * {@code delete o[p]}
     * 
     * @param iNode Tree node for the {@code delete} statement.
     * @param stem Instructions for creating a {@code DynamicAccessNode}.
     * @param index Instructions for initializing the index expression.
     * @return Instructions for executing a {@code delete} statement.
     */
    public InstructionList reduce_deleteBracketExpr(IASNode iNode, InstructionList stem, InstructionList index)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IUnaryOperatorNode)iNode).getOperandNode();
        
        // ASC doesn't check bracket expressions, and it's difficult
        // to see what could usefully be done in any case.
        // currentScope.getMethodBodySemanticChecker().checkDeleteExpr(iNode);
        InstructionList result = createInstructionList(iNode, stem.size() + index.size() + 1);
        result.addAll(stem);
        result.addAll(index);
        result.addInstruction(arrayAccess(arrayIndexNode, OP_deleteproperty));
        return result;
    }

    /**
     * Reduce E4X expression like:<br>
     * {@code delete x.@[foo]}
     * 
     * @param iNode Tree node for the {@code delete} statement.
     * @param stem Instructions for creating a
     * {@code MemberAccessExpressionNode}.
     * @param index Instructions for initializing the array index expression.
     * @return Instructions for executing a {@code delete} statement.
     */
    public InstructionList reduce_deleteAtBracketExpr(IASNode iNode, InstructionList stem, InstructionList index)
    {
        final InstructionList result = createInstructionList(iNode, stem.size() + index.size() + 1);
        result.addAll(stem);
        result.addAll(index);
        // The namespace is ignored by AVM. We choose to use the default 
        // namespace at the current scope.
        final Namespace ns = NamespaceDefinition
                .getDefaultNamespaceDefinition(currentScope.getLocalASScope())
                .resolveAETNamespace(currentScope.getProject());
        final Name multinameLA = new Name(
                CONSTANT_MultinameLA,
                new Nsset(ns),
                null);
        result.addInstruction(OP_deleteproperty, multinameLA);
        return result;
    }

    public InstructionList reduce_deleteDescendantsExpr(IASNode iNode, InstructionList stem, Binding field)
    {
        // TODO: Investigate semantics of this.
        // This special case should get a warning or some indication it's a tautology.

        InstructionList result = createInstructionList(iNode, stem.size() + 1);
        result.addAll(stem);
        result.addInstruction(OP_pop);
        result.addInstruction(OP_pushtrue);
        return result;
    }

    public InstructionList reduce_deleteExprExprExpr(IASNode iNode, InstructionList expr)
    {
        //  The expression must be run to allow for side effects.
        InstructionList result = createInstructionList(iNode, expr.size() + 2);
        result.addInstruction(OP_getlocal0);
        result.addAll(expr);
        result.addInstruction(arrayAccess(iNode, OP_deleteproperty));
        return result;
    }

    public InstructionList reduce_deleteMemberExpr(IASNode iNode, InstructionList stem, Binding field)
    {
        currentScope.getMethodBodySemanticChecker().checkDeleteExpr(iNode, field);

        InstructionList result = createInstructionList(iNode, stem.size() + 1);
        result.addAll(stem);
        result.addInstruction(OP_deleteproperty, field.getName());
        return result;
    }

    public InstructionList reduce_deleteRuntimeNameExpr(IASNode iNode, InstructionList stem, RuntimeMultiname rt_name)
    {
        //  TODO: Any relevant semantic checks?

        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);
        if ( rt_name.hasRuntimeQualifier() )
            result.addAll(rt_name.getRuntimeQualifier(iNode));
        if ( rt_name.hasRuntimeName() )
            result.addAll(rt_name.getRuntimeName(iNode));
        result.addInstruction(OP_deleteproperty, rt_name.generateName());
        return result;
    }

    public InstructionList reduce_deleteNameExpr(IASNode iNode, Binding n)
    {
        currentScope.getMethodBodySemanticChecker().checkDeleteExpr(iNode, n);

        InstructionList result = createInstructionList(iNode, 2);
        result.addAll(currentScope.findProperty(n, false));
        result.addInstruction(OP_deleteproperty, n.getName());
        return result;
    }

    public InstructionList reduce_doStmt(IASNode iNode, InstructionList body, InstructionList cond)
    {
        InstructionList result = createInstructionList(iNode, cond.size() + body.size() + 1);
        currentScope.getFlowManager().resolveContinueLabel(cond);

        if ( body.isEmpty() || body.firstElement().getOpcode() != OP_label ) 
            result.addInstruction(OP_label);

        result.addAll(body);
        result.addAll(cond);
        result.addInstruction(OP_iftrue, result.getLabel());

        currentScope.getFlowManager().finishLoopControlFlowContext(result);

        return result;
    }

    public InstructionList reduce_e4xFilter(IASNode iNode, InstructionList stem, InstructionList filter)
    {
        InstructionList result = createInstructionList(iNode);

        LexicalScope.Hasnext2Wrapper hasnext = currentScope.hasnext2();

        //  Cache each value of e.employee.
        Binding value_temp = currentScope.allocateTemp();
        //  Cache the result XMLList.
        Binding result_temp = currentScope.allocateTemp();

        //  Emit the stem expression and cache 
        //  the stem object in a local register.
        result.addAll(stem);
        result.addInstruction(OP_checkfilter);
        result.addInstruction(hasnext.stem_temp.setlocal() );

        //  Initialize the index register.
        result.addInstruction(OP_pushbyte, 0);
        result.addInstruction(hasnext.index_temp.setlocal());

        //  Create the result XMLList.
        result.addAll(currentScope.getPropertyValue(xmlListType, currentScope.getProject().getBuiltinType(BuiltinType.XMLLIST)));
        result.addInstruction(OP_pushstring, "");
        result.addInstruction(OP_construct, 1);
        result.addInstruction(result_temp.setlocal());

        //  Jump to the loop test.
        Label test = new Label();
        result.addInstruction(OP_jump, test);

        //  Top of the loop: put an AET Label on
        //  the ABC OP_Label.
        Label loop = new Label();
        result.labelNext(loop);
        result.addInstruction(OP_label);
        //  Get the next value and cache it.
        result.addInstruction(hasnext.stem_temp.getlocal());
        result.addInstruction(hasnext.index_temp.getlocal());
        result.addInstruction(OP_nextvalue);
        result.addInstruction(OP_dup);
        result.addInstruction(value_temp.setlocal() );
        //  See ECMA-357 11.2.4
        result.addInstruction(OP_pushwith);

        result.addAll(filter);

        Label no_match = new Label();
        result.addInstruction(OP_iffalse, no_match);

        result.addInstruction(result_temp.getlocal() );
        result.addInstruction(hasnext.index_temp.getlocal() );
        result.addInstruction(value_temp.getlocal() );

        result.addInstruction(arrayAccess(iNode, OP_setproperty));

        result.labelNext(no_match);
        //  See ECMA-357 11.2.4
        result.addInstruction(OP_popscope);
        result.labelNext(test);
        result.addInstruction(hasnext.instruction);
        result.addInstruction(OP_iftrue, loop);

        result.addInstruction(result_temp.getlocal());

        hasnext.release();
        currentScope.releaseTemp(value_temp);
        currentScope.releaseTemp(result_temp);

        return result;
    }

    public InstructionList reduce_embed(IASNode iNode)
    {
        String name = "";
        try
        {
            name = ((EmbedNode)iNode).getName(currentScope.getProject(), getProblems());
        }
        catch (InterruptedException e)
        {
            throw new CodegenInterruptedException(e);
        }

        // the parent of an embed node is always a variable
        final VariableNode variableNode = (VariableNode)iNode.getParent();
        final IVariableDefinition variableDef = (IVariableDefinition)variableNode.getDefinition();
        final ITypeDefinition variableType = variableDef.resolveType(currentScope.getProject());
        final String typeName = variableType.getQualifiedName();
        
        InstructionList result;
        if ("Class".equals(typeName))
        {
            result = createInstructionList(iNode);
            Name embedName = new Name(name);
            result.addInstruction(OP_getlex, embedName);
        }
        else if ("String".equals(typeName))
        {
            result = createInstructionList(iNode);
            result.addInstruction(OP_pushstring, name);
        }
        else
        {
            assert false : "this problem should have been caught already at EmbedNode construction time";
            result = null;
        }

        return result;
    }

    public InstructionList reduce_forKeyValueStmt(IASNode iNode, Binding it, InstructionList base, InstructionList body, int opcode)
    {
        currentScope.getMethodBodySemanticChecker().checkLValue(iNode, it);

        InstructionList result = createInstructionList(iNode, body.size() + base.size() + 15);

        ForKeyValueLoopState fkv = new ForKeyValueLoopState();

        result.addAll(fkv.generatePrologue(iNode, base));

        result.addAll(
            generateAssignment(
                iNode,
                it,
                fkv.generateKeyOrValue(opcode)
            )
        );

        result.addAll(body);

        result.addAll(fkv.generateEpilogue());

        currentScope.getFlowManager().finishLoopControlFlowContext(result);

        return result;
    }

    /**
     * Reduce {@code for(it in base)} or {@code for each(it in base)} loop with
     * variable initializer.
     * 
     * @param iNode {@code ForLoopNode}
     * @param single_decl Instructions to initialize a loop variable.
     * @param base Instructions to create a loop base.
     * @param body For loop body instructions.
     * @param opcode Use {@code OP_nextname} for "for" loops; use
     * {@code OP_nextvalue} for "for each" loops.
     * @return Instructions generated for the "for" loop node.
     */
    public InstructionList reduce_forVarDeclInStmt(IASNode iNode, InstructionList single_decl, InstructionList base, InstructionList body, int opcode)
    {
        final InstructionList result = createInstructionList(iNode);
        result.addAll(single_decl);

        final VariableNode var_node = findIteratorVariable((ForLoopNode)iNode);
        final Binding it = currentScope.resolveName((IdentifierNode)var_node.getNameExpressionNode());

        currentScope.getMethodBodySemanticChecker().checkLValue(iNode, it);

        final ForKeyValueLoopState fkv = new ForKeyValueLoopState();
        result.addAll(fkv.generatePrologue(iNode, base));
        result.addAll(generateAssignment(iNode, it, fkv.generateKeyOrValue(opcode)));
        result.addAll(body);
        result.addAll(fkv.generateEpilogue());
        currentScope.getFlowManager().finishLoopControlFlowContext(result);
        return result;
    }

    /**
     * Find the iterator {@code VariableNode} in a {@code ForLoopNode}.
     * 
     * <pre>
     * for (var it : String = "hello" in array) {...}
     * for each (var it : String = "hello" in array) {...}
     * </pre>
     * 
     * @param for_loop_node "for" loop node.
     * @return {@code VariableNode} of the iterator variable.
     */
    private static VariableNode findIteratorVariable(final ForLoopNode for_loop_node)
    {
        assert for_loop_node != null : "'for' loop node can't be null";

        final IASNode conditionalStatement = for_loop_node.getConditionalsContainerNode().getChild(0);
        final BinaryOperatorInNode in_node = (BinaryOperatorInNode)conditionalStatement;
        final VariableExpressionNode var_expr_node = (VariableExpressionNode)in_node.getLeftOperandNode();
        final VariableNode var_node = (VariableNode)var_expr_node.getChild(0);
        return var_node;
    }

    /**
     * Reduce statement like:<br>
     * {@code for (a[it] in base) body;}
     * 
     * @param iNode Tree node for the for-in loop.
     * @param stem Instructions for creating a {@code DynamicAccessNode}.
     * @param index Instructions for initializing the index expression.
     * @param base Instructions for initializing the base object of the <code>in</code> expression.
     * @param body Instructions for initializing the body of the for-loop.
     * @param opcode Opcode for <code>nextname</code> or ,code>nextvalue</code> instruction.
     * @param is_super Flag indicating whether the stem of the array index expression is <code>super</code>.
     * @return Instructions for executing the {@code for-in} statement.
     */
    public InstructionList reduce_forKeyValueArrayStmt(IASNode iNode, InstructionList stem, InstructionList index, InstructionList base, InstructionList body, int opcode, boolean is_super)
    {
        IContainerNode conditionalStatementsNode = ((IForLoopNode)iNode).getConditionalsContainerNode();
        IBinaryOperatorNode inNode = (IBinaryOperatorNode)SemanticUtils.getNthChild(conditionalStatementsNode, 0);
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)inNode.getLeftOperandNode();
        
        ForKeyValueLoopState fkv = new ForKeyValueLoopState();

        InstructionList result = createInstructionList(iNode, body.size() + base.size() + 15);

        result.addAll(fkv.generatePrologue(iNode, base));

        if( is_super )
            result.addInstruction(OP_getlocal0);
        else
            result.addAll(stem);

        result.addAll(index);
        result.addAll(fkv.generateKeyOrValue(opcode));

        result.addInstruction(arrayAccess(arrayIndexNode, is_super ? OP_setsuper : OP_setproperty));

        result.addAll(body);

        result.addAll(fkv.generateEpilogue());

        currentScope.getFlowManager().finishLoopControlFlowContext(result);
        return result;
    }

    public InstructionList reduce_forKeyValueMemberStmt(IASNode iNode, InstructionList stem, Binding member, InstructionList base, InstructionList body, int opcode, boolean is_super)
    {
        currentScope.getMethodBodySemanticChecker().checkLValue(iNode, member);

        ForKeyValueLoopState fkv = new ForKeyValueLoopState();

        InstructionList result = createInstructionList(iNode, body.size() + base.size() + 15);

        result.addAll(fkv.generatePrologue(iNode, base));

        if( is_super )
            result.addInstruction(OP_getlocal0);
        else
            result.addAll(stem);

        result.addAll(fkv.generateKeyOrValue(opcode));

        generateAssignmentOp(iNode, member, result);

        result.addAll(body);

        result.addAll(fkv.generateEpilogue());

        currentScope.getFlowManager().finishLoopControlFlowContext(result);
        return result;
    }

    /**
     * Reduce expression like:<br>
     * {@code a[i]()}
     * 
     * @param iNode Tree node for the function call.
     * @param stem Instructions for creating a {@code DynamicAccessNode}.
     * @param index Instructions for initializing the index expression.
     * @return Instructions for executing a {@code function call} statement.
     */
    public InstructionList reduce_functionAsBracketExpr(IASNode iNode, InstructionList stem, InstructionList index, Vector<InstructionList> args)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IFunctionCallNode)iNode).getNameNode();
        
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        result.addInstruction(OP_dup);
        result.addAll(index);
        result.addInstruction(arrayAccess(arrayIndexNode, OP_getproperty));
        result.addInstruction(OP_swap);

        for ( InstructionList arg: args)
            result.addAll(arg);
        result.addInstruction(OP_call, args.size() );  //  note: args.size() is an immediate operand to OP_call
        return result;
    }

    public InstructionList reduce_functionAsMemberExpr(IASNode iNode, InstructionList stem, Binding method_name, Vector<InstructionList> args)
    {
        //  Perform general function call checks and specific member checks
        currentScope.getMethodBodySemanticChecker().checkFunctionCall(iNode, method_name, args);

        //  TODO: Investigate optimizing this.
        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);

        boolean inlined = generateInlineFunctionCall(method_name, result, true, args);

        if (!inlined)
        {
            for (InstructionList arg: args)
                result.addAll(arg);

            result.addInstruction(OP_callproperty, new Object[] {method_name.getName(), args.size() } );
        }

        return result;
    }

    public InstructionList reduce_functionAsRandomExpr(IASNode iNode, InstructionList random_expr, Vector<InstructionList> args)
    {
        //  TODO: Investigate optimizing this.
        InstructionList result = createInstructionList(iNode);

        result.addAll(random_expr);

        // TODO: currentScope.getThis() or sth similar
        result.addInstruction(OP_getlocal0);

        for( InstructionList arg: args )
            result.addAll(arg);

        result.addInstruction(OP_call, args.size());

        return result;
    }

    public InstructionList reduce_functionCallExpr_to_expression(IASNode iNode, Binding method_name, Vector<InstructionList> args)
    {
        return reduce_functionCall_common(iNode, method_name, args, true);
    }

    public InstructionList reduce_functionCallExpr_to_void_expression(IASNode iNode, Binding method_name, Vector<InstructionList> args)
    {
        return reduce_functionCall_common(iNode, method_name, args, false);
    }

    private InstructionList reduce_functionCall_common(IASNode iNode, Binding method_name, Vector<InstructionList> args, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkFunctionCall(iNode, method_name, args);

        InstructionList result = createInstructionList(iNode);

        if (method_name.isLocal())
        {
            result.addInstruction(method_name.getlocal());
            result.addInstruction(OP_getlocal0);
            for (InstructionList arg : args)
                result.addAll(arg);

            result.addInstruction(OP_call, args.size());
            if (!need_result)
            {
                result.addInstruction(OP_pop);
            }
        }
        else if ( SemanticUtils.isMethodBinding(method_name.getDefinition()) )
        {
            //  A call to a class' method.
            boolean inlined = generateInlineFunctionCall(method_name, result, false, args);

            if (!inlined)
            {
                result.addAll(currentScope.findProperty(method_name, true));
                for (InstructionList arg : args)
                    result.addAll(arg);

                int opcode = need_result ? OP_callproperty : OP_callpropvoid;
                result.addInstruction(opcode, new Object[] {method_name.getName(), args.size()});
            }
        }
        else if ( method_name.getDefinition() != null )
        {
            //  We're in some context where the method can be found lexically.
            assert ( ! method_name.getName().isRuntimeName() );

            boolean inlined = generateInlineGetterAccess(method_name, result, false);
            
            if (!inlined)
                result.addAll(currentScope.getPropertyValue(method_name));
            
            result.addInstruction(OP_getglobalscope);
            for (InstructionList arg : args)
                result.addAll(arg);

            result.addInstruction(OP_call, args.size());
            

            if ( ! need_result )
                result.addInstruction(OP_pop);
        }
        else
        {
            //  Probably in a with or filter block.
            result.addInstruction(OP_findpropstrict, method_name.getName());
            for (InstructionList arg : args)
                result.addAll(arg);

            int opcode = need_result ? OP_callproperty : OP_callpropvoid;
            result.addInstruction(opcode, new Object[] {method_name.getName(), args.size()});

        }

        return result;
    }

    public InstructionList reduce_functionCallOfSuperclassMethod_to_expression(IASNode iNode, InstructionList stem, Binding method_name, Vector<InstructionList> args)
    {
        currentScope.getMethodBodySemanticChecker().checkSuperAccess(iNode);

        InstructionList result = createInstructionList(iNode);

        if ( stem != null )
            result.addAll(stem);
        else
            //  Implicit stem is "this".
            result.addInstruction(OP_getlocal0);

        for ( InstructionList arg: args)
            result.addAll(arg);
        result.addInstruction(OP_callsuper, new Object[] {method_name.getName(), args.size() } );
        return result;
    }

    public InstructionList reduce_functionCallOfSuperclassMethod_to_void_expression(IASNode iNode, InstructionList stem, Binding method_name, Vector<InstructionList> args)
    {
        currentScope.getMethodBodySemanticChecker().checkSuperAccess(iNode);

        InstructionList result = createInstructionList(iNode);

        if ( stem != null )
            result.addAll(stem);
        else
            //  Implicit stem is "this"
            result.addInstruction(OP_getlocal0);

        for ( InstructionList arg: args)
            result.addAll(arg);
        result.addInstruction(OP_callsupervoid, new Object[] {method_name.getName(), args.size() } );
        return result;
    }

    public InstructionList reduce_groupedVoidExpression(IASNode iNode, Vector<InstructionList> contents)
    {
        InstructionList result = createInstructionList(iNode);

        for ( InstructionList expr: contents )
            result.addAll(expr);

        return result;
    }

    public InstructionList reduce_ifElseIf(IASNode iNode, InstructionList test, InstructionList then, Vector<ConditionalFragment> if_elseif)
    {
        // need to convert any constant values back
        // to a conditional expression when not generating
        // a lookup switch.
        // TODO: CMP-1762 make use of any constant values to optimize away
        // constant if/else ifs.
        convertConstantValueConditionsToInstructions(if_elseif);
        
        //  TODO: Experiment with optimizing this.
        //  Iterating twice over the arms of the if
        //  might cost more than it helps.
        InstructionList result = createInstructionList(iNode);

        boolean has_else = !if_elseif.isEmpty();

        //  Label to the "next statement."
        Label tail = null;

        //  TODO: Use conditionalJump style tests.
        result.addAll(test);

        if ( has_else )
            result.addInstruction(OP_iffalse, if_elseif.firstElement().getLabel());
        else
            tail = addBranch(result, tail, OP_iffalse);

        result.addAll(then);

        if ( has_else )
        {
            tail = addInterstitialControlFlow(result, tail);

            for ( int i = 0; i < if_elseif.size() - 1; i++ )
            {
                ConditionalFragment alternative = if_elseif.elementAt(i);

                if ( !alternative.isUnconditionalAlternative() )
                {
                    //  Add the test and conditional jump to the next alternative.
                    result.addAll(alternative.condition);
                    ConditionalFragment next_alternative = if_elseif.elementAt(i+1);
                    result.addInstruction(OP_iffalse, next_alternative.getLabel());
                }

                result.addAll(alternative.statement);
                tail = addInterstitialControlFlow(result, tail);
            }

            ConditionalFragment last_clause = if_elseif.lastElement();

            if ( !last_clause.isUnconditionalAlternative() )
            {
                result.addAll(last_clause.condition);
                tail = addBranch(result, tail, OP_iffalse);
                result.addAll(last_clause.statement);
            }
            else
            {
                result.addAll(last_clause.statement);
            }
        }

        if ( tail != null )
            result.labelNext(tail);
        return result;
    }

    /**
     *  Add a branch instruction to an InstructionList.
     *  @param insns - the InstructionList.
     *  @param previousLabel - any existing label that targets the jump destination.
     *  @param opcode - the opcode of the branch (e.g., OP_jump, OP_iffalse, etc.)
     *  @return a label that targets the jump destination; if previousLabel was
     *    not null, then previousLabel, otherwise a new Label.  The caller is
     *    responsible for saving this label and applying it appropriately at
     *    the destination point.
     */
    private Label addBranch(InstructionList insns, Label previousLabel, int opcode)
    {
        Label result = previousLabel != null? previousLabel: new Label();
        insns.addInstruction(opcode, result);
        return result;
    }

    /**
     *  Add jumps from one bit of a control-flow statement to the next,
     *  if they're necessary.
     *  @param insns - the InstructionList that's building up the statement.
     *  @param previousLabel - any existing Label that targets the next part of
     *    the statement.  May be null if this is the first interstitial jump.
     *  @return previousLabel if previousLabel was not null;
     *    null if previousLabel was null and no jump is necessary; 
     *    otherwise a new Label that the caller must use to label the next
     *    part of the statement.
     */
    private Label addInterstitialControlFlow(InstructionList insns, Label previousLabel)
    {
        Label result;

        if ( insns.canFallThrough() )
        {
            result = addBranch(insns, previousLabel, OP_jump);
        }
        else if ( insns.hasPendingLabels() )
        {
            //  TODO: InstructionList needs a way to "alias"
            //  labels; with such a facility, this jump could be elided.
            result = addBranch(insns, previousLabel, OP_jump);
        }
        else
        {
            result = previousLabel;
        }

        return result;
    }

    public InstructionList reduce_importDirective(IASNode iNode)
    {
        currentScope.getMethodBodySemanticChecker().checkImportDirective(((IImportNode)iNode));
        return createInstructionList(iNode);
    }

    public InstructionList reduce_labeledBreakStmt(IASNode iNode)
    {
        String target = ((IdentifierNode)SemanticUtils.getNthChild(iNode, 0)).getName();
        try
        {
            ControlFlowContextManager.ControlFlowContextSearchCriteria criterion = getBreakCriteria(target);
            return getNonLocalControlFlow(criterion);
        }
        catch ( UnknownControlFlowTargetException no_target )
        {
            currentScope.addProblem(new UnknownBreakTargetProblem(SemanticUtils.getNthChild(iNode, 0)));
            return createInstructionList(iNode);
        }
    }

    public InstructionList reduce_labeledContinueStmt(IASNode iNode)
    {
        String target = ((IdentifierNode)SemanticUtils.getNthChild(iNode, 0)).getName();
        try
        {
            ControlFlowContextManager.ControlFlowContextSearchCriteria criterion = getContinueCriteria(target);
            return getNonLocalControlFlow(criterion);
        }
        catch ( UnknownControlFlowTargetException no_target )
        {
            currentScope.addProblem(new UnknownContinueTargetProblem(SemanticUtils.getNthChild(iNode, 0)));
            return createInstructionList(iNode);
        }
    }
    
    public InstructionList reduce_gotoStmt(IASNode iNode)
    {
        IdentifierNode labelIdentifierNode = (IdentifierNode)SemanticUtils.getNthChild(iNode, 0);
        String target = labelIdentifierNode.getName();
        try
        {
            ControlFlowContextManager.ControlFlowContextSearchCriteria criterion = getGotoCriteria(target);
            return getNonLocalControlFlow(criterion);
        }
        catch ( UnknownControlFlowTargetException no_target )
        {
            Collection<LabeledStatementNode> gotoLabels = currentScope.getFlowManager().getGotoLabels(target);
            if (gotoLabels.isEmpty())
                currentScope.addProblem(new UnknownGotoTargetProblem(labelIdentifierNode));
            else
                currentScope.addProblem(new AmbiguousGotoTargetProblem(labelIdentifierNode, gotoLabels));
            return createInstructionList(iNode);
        }
    }

    public InstructionList reduce_labeledStmt(IASNode iNode, String label, InstructionList substatement)
    {
        InstructionList result = createInstructionList(iNode, 1);
        Label gotoLabel = currentScope.getFlowManager().getGotoLabel(label);
        // Since duplicate labels are invisible to goto statements,
        // we can fail to find a goto context for a label.
        if (gotoLabel != null)
        {
            result.labelNext(gotoLabel);
            result.addInstruction(OP_label);
        }
        
        result.addAll(substatement);

        currentScope.getFlowManager().finishLabeledStatementControlFlowContext(result);
        return result;
    }

    public ConditionalFragment reduce_lastElse(IASNode iNode, InstructionList else_clause)
    {
        return new ConditionalFragment(iNode, null, else_clause);
    }

    public InstructionList reduce_logicalAndExpr(IASNode iNode, InstructionList l, InstructionList r)
    {
        InstructionList result = createInstructionList(iNode, l.size() + r.size() + 3);
        Label tail = new Label();

        result.addAll(l);
        result.addInstruction(OP_dup);
        result.addInstruction(OP_iffalse, tail);
        result.addInstruction(OP_pop);
        result.addAll(r);
        result.labelNext(tail);
        return result;
    }

    public InstructionList reduce_logicalNotExpr(IASNode iNode, InstructionList expr)
    {
        InstructionList result = createInstructionList(iNode, expr.size() + 1);
        result.addAll(expr);
        result.addInstruction(OP_not);
        return result;
    }

    public InstructionList reduce_logicalOrExpr(IASNode iNode, InstructionList l, InstructionList r)
    {
        InstructionList result = createInstructionList(iNode, l.size() + r.size() + 3);
        Label tail = new Label();

        result.addAll(l);
        result.addInstruction(OP_dup);
        result.addInstruction(OP_iftrue, tail);
        result.addInstruction(OP_pop);
        result.addAll(r);
        result.labelNext(tail);
        return result;
    }

    public InstructionList reduce_memberAccessExpr(IASNode iNode, InstructionList stem, Binding member, int opcode)
    {
        currentScope.getMethodBodySemanticChecker().checkMemberAccess(iNode, member, opcode);
        InstructionList result = createInstructionList(iNode, stem.size() + 1);

        result.addAll(stem);

        boolean inlined = generateInlineGetterAccess(member, result, true);

        if (!inlined)
            result.addInstruction(opcode, member.getName());

        return result;
    }

    public InstructionList reduce_qualifiedMemberAccessExpr(IASNode iNode, InstructionList stem, Binding qualifier, Binding member, int opcode)
    {
        currentScope.getMethodBodySemanticChecker().checkMemberAccess(iNode, member, opcode);
        InstructionList result = createInstructionList(iNode);
        Name member_name = member.getName();

        result.addAll(stem);
        if ( isNamespace(qualifier) )
        {
            result.addInstruction(opcode, member_name);
        }
        else
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
            result.addInstruction(opcode, member_name);
        }
        return result;
    }

    public InstructionList reduce_qualifiedAttributeRuntimeMemberExpr(IASNode iNode, InstructionList stem, Binding qualifier, InstructionList runtime_member_selector, int opcode)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        if ( isNamespace(qualifier) )
        {
            result.addAll(runtime_member_selector);
            //  Extract the URI from the namespace and use it to construct a qualified name.
            NamespaceDefinition ns_def = (NamespaceDefinition)qualifier.getDefinition();
            Name qualified_name = new Name(CONSTANT_MultinameLA, new Nsset(ns_def.resolveAETNamespace(currentScope.getProject())), null);
            result.addInstruction(opcode, qualified_name);
        }
        else
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
            result.addAll(runtime_member_selector);
            result.addInstruction(OP_coerce_s);
            result.addInstruction(opcode, new Name(CONSTANT_RTQnameLA, null, null));
        }
        return result;
    }

    public InstructionList reduce_qualifiedMemberRuntimeNameExpr(IASNode iNode, InstructionList stem, Binding qualifier, InstructionList runtime_member_selector)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        if ( isNamespace(qualifier) )
        {
            result.addAll(runtime_member_selector);
            //  Extract the URI from the namespace and use it to construct a qualified name.
            NamespaceDefinition ns_def = (NamespaceDefinition)qualifier.getDefinition();
            Name qualified_name = new Name(CONSTANT_MultinameL, new Nsset(ns_def.resolveAETNamespace(currentScope.getProject())), null);
            result.addInstruction(OP_getproperty, qualified_name);
        }
        else
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
            result.addAll(runtime_member_selector);
            result.addInstruction(OP_coerce_s);
            result.addInstruction(OP_getproperty, new Name(CONSTANT_RTQnameL, null, null));
        }
        return result;
    }

    public InstructionList reduce_qualifiedAttributeExpr(IASNode iNode, InstructionList stem, Binding qualifier, Binding member, int opcode)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        if ( !isNamespace(qualifier) )
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
            result.addInstruction(opcode, member.getName());
        }
        else
        {
            // the qualifier's namespace is already present in the name.
            result.addInstruction(opcode, member.getName());
        }

        return result;
    }

    public InstructionList reduce_unqualifiedAttributeExpr(IASNode iNode, InstructionList stem, InstructionList rt_attr, int opcode)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);
        result.addAll(rt_attr);
        result.addInstruction(opcode, new Name(CONSTANT_MultinameLA, new Nsset(new Namespace(CONSTANT_PackageNs)), null));

        return result;
    }
    
    /**
     * Reduce runtime attribute expression, such as {@code @[exp]}.
     * 
     * @param iNode Node for {@code @[...]}. It is a
     * {@code ArrayIndexExpressionID(Op_AtID, ...)}.
     * @param rt_attr Instructions generated for the runtime name expression.
     * @return Instructions to get the value of an attribute described with a
     * runtime name.
     */
    public InstructionList reduce_runtimeAttributeExp(IASNode iNode, InstructionList rt_attr)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(rt_attr);
        final Nsset qualifiers = SemanticUtils.getOpenNamespaces(iNode, currentScope.getProject());
        result.addInstruction(OP_getproperty, new Name(CONSTANT_MultinameLA, qualifiers, null));
        return result;
    }

    public InstructionList reduce_mxmlEventSpecifier(IASNode iNode, Vector<InstructionList> stmts)
    {
        //  TODO: Investigate optimizing.
        InstructionList body = createInstructionList(iNode);

        // An MXMLEventSpecifierNode can have N child nodes which are statements.
        // We need to codegen all of them as an effective method body.
        for ( InstructionList stmt: stmts )
            body.addAll(stmt);

        return generateFunctionBody(iNode, body, LexicalScope.anyType);
    }

    public Binding reduce_namespaceAccess(IASNode iNode, IASNode qualifier, Binding qualified_name)
    {
        currentScope.getMethodBodySemanticChecker().checkQualifier(qualifier);
        //  All the qualifying syntax nodes are just concrete.
        return qualified_name;
    }

    public RuntimeMultiname reduce_namespaceAccess_to_runtime_name(IASNode iNode, Binding qualified_name)
    {
        InstructionList qualifier = createInstructionList(iNode);
        generateAccess(reduce_simpleName(iNode.getChild(0)), qualifier);
        qualifier.addInstruction(OP_coerce, namespaceType);
        return new RuntimeMultiname(qualifier, qualified_name.getName());
    }

    public InstructionList reduce_namespaceAsName_to_expression(IASNode iNode)
    {
        InstructionList result = createInstructionList(iNode);
        Binding b = reduce_simpleName(iNode);
        generateAccess(b, result);
        result.addInstruction(OP_coerce, namespaceType);
        return result;
    }

    public Name reduce_namespaceAsName_to_multinameL(IASNode iNode)
    {
        return reduce_namespaceAsName_to_multinameL(iNode, false);
    }

    public Name reduce_namespaceAsName_to_multinameL(IASNode iNode, final boolean is_attribute)
    {
        IdentifierNode qualifier = (IdentifierNode)iNode;
        NamespaceDefinition ns = (NamespaceDefinition) qualifier.resolve(currentScope.getProject());

        int name_kind = is_attribute? CONSTANT_MultinameLA: CONSTANT_MultinameL;
        return new Name(name_kind, new Nsset( ns.resolveAETNamespace(currentScope.getProject())), null);
    }


    public Binding reduce_namespaceAsName_to_name(IASNode iNode)
    {
        //  Note: unresolved namespaces are trapped by a bespoke rule.
        return currentScope.resolveName((org.apache.flex.compiler.internal.tree.as.IdentifierNode)iNode);
    }

    public InstructionList reduce_namespaceDeclaration(IASNode iNode, Binding ns_name)
    {
        //  Get the AET Namespace from the namespace's definition.
        NamespaceDefinition def = ((NamespaceNode)iNode).getDefinition();
        return reduce_namespaceDeclarationConstantInitializer(iNode, ns_name, def.resolveAETNamespace(currentScope.getProject()));
    }

    public InstructionList reduce_namespaceDeclarationConstantInitializer(IASNode iNode, Binding ns_name, String uri)
    {
        // Make a new CONSTANT_Namespace with the given URI - all user defined namespaces initialized with a
        // String literal become CONSTANT_Namespaces
        return reduce_namespaceDeclarationConstantInitializer(iNode, ns_name, new Namespace(CONSTANT_Namespace, uri));
    }

    /**
     * Does the work for the various reduce_namespaceDecl methods.  Creates a new property, with an initial value
     * of the Namespace passed in.
     */
    public InstructionList reduce_namespaceDeclarationConstantInitializer(IASNode iNode, Binding ns_name, Namespace initializer)
    {
        currentScope.getMethodBodySemanticChecker().checkNamespaceDeclaration(iNode, ns_name);

        NamespaceDefinition def = ((NamespaceNode)iNode).getDefinition();

        switch (SemanticUtils.getMultiDefinitionType(def, currentScope.getProject()))
        {
            case AMBIGUOUS:
                currentScope.addProblem(new DuplicateNamespaceDefinitionProblem(iNode));
                break;
            case NONE:
                break;
            default:
                assert false;       // I don't think namespaces can have other type of multiple definitions
        }
        
        if( initializer == null )
        {
            // Can't declare a namespace if we don't know what its initial value is
            getProblems().add( new InvalidNamespaceInitializerProblem(iNode) );
            return null;
        }

        currentScope.makeNamespace(ns_name, initializer);
        if ( ns_name.isLocal() )
        {
            //  Locals have no initializer, so the variable
            //  needs explicit initialization code.
            currentScope.getHoistedInitInstructions().addInstruction(OP_pushnamespace, initializer);
            currentScope.getHoistedInitInstructions().addInstruction(ns_name.setlocal());

        }
        return null;
    }

    public InstructionList reduce_namespaceDeclarationInitializer(IASNode iNode, Binding ns_name, Binding second_ns)
    {
        Namespace ns_init = null;

        if ( second_ns.getDefinition() instanceof NamespaceDefinition )
        {
            NamespaceDefinition ns_def = (NamespaceDefinition)second_ns.getDefinition();
            // Grab the AET namespace from the initializer
            ns_init = ns_def.resolveAETNamespace(currentScope.getProject());
        }

        return reduce_namespaceDeclarationConstantInitializer(iNode, ns_name, ns_init);
    }

    public RuntimeMultiname reduce_namespaceMultinameL(IASNode iNode, IASNode qualifier_node, InstructionList expr)
    {
        currentScope.getMethodBodySemanticChecker().checkQualifier(qualifier_node);
        Name qualifier = reduce_namespaceAsName_to_multinameL(qualifier_node);
        return new RuntimeMultiname(qualifier, expr);
    }

    public RuntimeMultiname reduce_namespaceRTQName(IASNode iNode, InstructionList qualifier, Binding qualified_name)
    {
        return new RuntimeMultiname(qualifier, qualified_name.getName());
    }

    public RuntimeMultiname reduce_namespaceRTQNameL(IASNode iNode, InstructionList qualifier, InstructionList expr)
    {
        return new RuntimeMultiname(qualifier, expr);
    }

    public InstructionList reduce_neqExpr(IASNode iNode, InstructionList l, InstructionList r)
    {
        InstructionList result = binaryOp(iNode, l, r, OP_equals);
        result.addInstruction(OP_not);
        return result;
    }

    public Binding reduce_nameToTypeName(Binding name, boolean check_name)
    {
        if ( check_name )
            currentScope.getMethodBodySemanticChecker().checkTypeName(name);
        return name;
    }

    public InstructionList reduce_newMemberProperty(IASNode iNode, InstructionList stem, Binding member, Vector<InstructionList> args)
    {
        currentScope.getMethodBodySemanticChecker().checkNewExpr(iNode);

        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);

        for ( InstructionList arg: args)
            result.addAll(arg);

        result.addInstruction(OP_constructprop, new Object[] { member.getName(), args.size() } );

        return result;
    }

    public InstructionList reduce_newAsRandomExpr(IASNode iNode, InstructionList random_expr, Vector<InstructionList> args)
    {
        currentScope.getMethodBodySemanticChecker().checkNewExpr(iNode);

        InstructionList result = createInstructionList(iNode);

        result.addAll(random_expr);

        for ( InstructionList arg: args)
            result.addAll(arg);

        result.addInstruction(OP_construct, args.size() );

        return result;
    }

    public InstructionList reduce_newEmptyArray(IASNode iNode)
    {
        // Codegen 'new Array()' efficiently like an array literal
        // rather than like a constructor call. That is,
        //   newarray [0]
        // rather than
        //   findpropstrict :Array
        //   constructprop :Array, (0)
        InstructionList result = createInstructionList(iNode);
        result.addInstruction(OP_newarray, 0);
        return result;
    }

    public InstructionList reduce_newEmptyObject(IASNode iNode)
    {
        // Codegen 'new Object()' efficiently like an object literal
        // rather than like a constructor call. That is,
        //   newobject {0}
        // rather than
        //   findpropstrict :Object
        //   constructprop :Object, (0)
        InstructionList result = createInstructionList(iNode);
        result.addInstruction(OP_newobject, 0);
        return result;
    }

    public InstructionList reduce_newExpr(IASNode iNode, Binding class_binding, Vector<InstructionList> args)
    {
        currentScope.getMethodBodySemanticChecker().checkNewExpr(iNode, class_binding, args);

        //  TODO: Investigate optimizing this.
        InstructionList result = createInstructionList(iNode);

        Name class_name = class_binding.getName();

        if ( class_binding.isLocal() || class_name.isTypeName() )
        {
            generateAccess(class_binding, result);

            for ( InstructionList arg: args)
                result.addAll(arg);

            result.addInstruction(OP_construct, args.size());
        }
        else
        {
            result.addAll(currentScope.findProperty(class_binding, true));

            for ( InstructionList arg: args)
                result.addAll(arg);

            result.addInstruction(OP_constructprop, new Object[] { class_name, args.size() } );
        }

        return result;
    }

    public InstructionList reduce_newVectorLiteral(IASNode iNode, InstructionList literal)
    {
        return literal;
    }

    public InstructionList reduce_nilExpr_to_conditionalJump(IASNode iNode)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addInstruction(InstructionFactory.getTargetableInstruction(OP_jump));
        return result;
    }

    public InstructionList reduce_nilExpr_to_expression(IASNode iNode)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addInstruction(OP_pushundefined);
        return result;
    }

    public Object reduce_nullLiteral_to_constant_value(IASNode iNode)
    {
        return ABCConstants.NULL_VALUE;
    }

    public InstructionList reduce_nullLiteral_to_object_literal(IASNode iNode)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addInstruction(OP_pushnull);
        return result;
    }

    public InstructionList reduce_objectLiteral(IASNode iNode, Vector<InstructionList> elements)
    {
        //  TODO: Investigate optimizing.
        InstructionList result = createInstructionList(iNode);

        for ( InstructionList element: elements )
        {
            result.addAll(element);
        }

        result.addInstruction(OP_newobject, elements.size());

        return result;
    }

    public InstructionList reduce_objectLiteralElement(IASNode iNode, InstructionList id, InstructionList value)
    {
        InstructionList result = createInstructionList(iNode, value.size() + 1);
        result.addAll(id);
        //  TODO: Push type analysis up through the CG,
        //  so that string constants don't go through
        //  convert_s.  See http://bugs.adobe.com/jira/browse/CMP-118
        result.addInstruction(OP_convert_s);
        result.addAll(value);
        return result;
    }

    public InstructionList reduce_optionalParameter(IASNode iNode, Name param_name, Binding param_type, Object raw_default_value)
    {
        IParameterNode parameter_node = (IParameterNode)iNode;
        PooledValue transformed_default_value;
        // raw_default_value will be null if the parameter's default value was not a constant expression.
        if( raw_default_value == null )
        {
            currentScope.addProblem(new NonConstantParamInitializerProblem(parameter_node.getAssignedValueNode()));
            // re-write non-constant expression to undefined, so resulting ABC will pass the verifier.
            transformed_default_value = new PooledValue(ABCConstants.UNDEFINED_VALUE);
        }
        else
        {
            PooledValue default_value = new PooledValue(raw_default_value);
            transformed_default_value =
                currentScope.getMethodBodySemanticChecker().checkInitialValue(parameter_node, param_type, default_value);
        }
        currentScope.makeParameter(getParameterContent(iNode), param_type.getName());
        currentScope.addDefaultValue(transformed_default_value);
        return null;
    }

    public Binding reduce_parameterizedName(IASNode iNode, Binding base, Binding param)
    {
        Name param_name = param.getName();

        return new Binding(iNode, new Name(base.getName(), param_name), null);
    }

    public InstructionList reduce_parameterizedTypeExpression(IASNode iNode, InstructionList base, InstructionList param)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(base);
        result.addAll(param);
        result.addInstruction(OP_applytype, 1);

        return result;
    }

    public InstructionList reduce_plist(IASNode iNode, Vector<InstructionList> pdecl)
    {
        //  Parameter processing is done by side effect
        //  in the parameter reduction.
        return null;
    }

    public InstructionList reduce_postDecBracketExpr(IASNode iNode, InstructionList stem, InstructionList index, boolean need_result)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IUnaryOperatorNode)iNode).getOperandNode();

        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, false);
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        Binding stem_tmp = currentScope.allocateTemp();
        result.addInstruction(OP_dup);
        result.addInstruction(stem_tmp.setlocal() );

        result.addAll(index);
        result.addInstruction(OP_dup);

        //  Get the initial value, and dup a copy
        //  onto the stack as the value of this expression.
        Binding index_tmp = currentScope.allocateTemp();
        result.addInstruction(index_tmp.setlocal() );
        result.addInstruction(arrayAccess(arrayIndexNode, OP_getproperty));
        result.addInstruction(op_unplus());
        
        if( need_result )
            result.addInstruction(OP_dup);

        result.addInstruction(OP_decrement);
        Binding result_tmp = currentScope.allocateTemp();
        result.addInstruction(result_tmp.setlocal() );

        result.addInstruction(stem_tmp.getlocal() );
        result.addInstruction(index_tmp.getlocal() );
        result.addInstruction(result_tmp.getlocal() );
        result.addInstruction(arrayAccess(arrayIndexNode, OP_setproperty));

        currentScope.releaseTemp(stem_tmp);
        currentScope.releaseTemp(index_tmp);
        currentScope.releaseTemp(result_tmp);

        return result;
    }


    public InstructionList reduce_postDecMemberExpr(IASNode iNode, InstructionList stem, Binding field, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, false, field);
        
        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);
        result.addInstruction(OP_dup);
        result.addInstruction(OP_getproperty, field.getName());
        result.addInstruction(op_unplus());

        //  Save a copy of the original value to use as the value of this expression.
        Binding orig_tmp = null;
        if( need_result )
        {
            result.addInstruction(OP_dup);
            orig_tmp = currentScope.allocateTemp();
            result.addInstruction(orig_tmp.setlocal() );
        }

        result.addInstruction(OP_decrement);

        generateAssignmentOp(iNode, field, result);

        if( need_result )
        {
            result.addInstruction(orig_tmp.getlocal() );
            currentScope.releaseTemp(orig_tmp);
        }

        return result;
    }

    public InstructionList reduce_postDecNameExpr(IASNode iNode, Binding unary, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, false, unary);

        InstructionList result = createInstructionList(iNode);

        if ( unary.isLocal() ) {
            ICompilerProject project = currentScope.getProject();

            IDefinition inType = SemanticUtils.resolveUnaryExprType(iNode, project);

            IDefinition intType = project.getBuiltinType(BuiltinType.INT);
            IDefinition numberType = project.getBuiltinType(BuiltinType.NUMBER);
            if( inType == intType)
            {
                // Decrementing a local, typed as int
                // we can use declocal_i since we know the result will be stored in an int
                if( need_result )
                    result.addInstruction(unary.getlocal());
                result.addInstruction(unary.declocal_i());
            }
            else if( inType == numberType)
            {
                // Decrementing a local, typed as Number
                // we can use declocal since we know the result will be stored in a Number
                if( need_result )
                    result.addInstruction(unary.getlocal());
                result.addInstruction(unary.declocal());
            }
            else
            {
                result.addInstruction(unary.getlocal());
                result.addInstruction(op_unplus());
                if( need_result )
                    result.addInstruction(OP_dup);
                result.addInstruction(OP_decrement);
                coerce(result, inType);
                result.addInstruction(unary.setlocal());
            }
        }
        else
        {
            Name n = unary.getName();
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_getproperty,n);
            result.addInstruction(op_unplus());
            if( need_result )
                result.addInstruction(OP_dup);
            result.addInstruction(OP_decrement);
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_swap);
            result.addInstruction(OP_setproperty,n);
        }

        return result;
    }

    public InstructionList reduce_postIncBracketExpr(IASNode iNode, InstructionList stem, InstructionList index, boolean need_result)
    {        
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IUnaryOperatorNode)iNode).getOperandNode();

        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, true);
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        result.addInstruction(OP_dup);
        Binding stem_tmp = currentScope.allocateTemp();
        result.addInstruction(stem_tmp.setlocal() );

        result.addAll(index);
        result.addInstruction(OP_dup);

        //  Get the initial value, and dup a copy
        //  onto the stack as the value of this expression.
        Binding index_tmp = currentScope.allocateTemp();
        result.addInstruction(index_tmp.setlocal() );
        result.addInstruction(arrayAccess(arrayIndexNode, OP_getproperty));
        result.addInstruction(op_unplus());
        
        if( need_result )
            result.addInstruction(OP_dup);

        result.addInstruction(OP_increment);
        Binding result_tmp = currentScope.allocateTemp();
        result.addInstruction(result_tmp.setlocal());

        result.addInstruction(stem_tmp.getlocal() );
        result.addInstruction(index_tmp.getlocal() );
        result.addInstruction(result_tmp.getlocal() );
        result.addInstruction(arrayAccess(arrayIndexNode, OP_setproperty));

        currentScope.releaseTemp(stem_tmp);
        currentScope.releaseTemp(index_tmp);
        currentScope.releaseTemp(result_tmp);

        return result;
    }

    public InstructionList reduce_postIncMemberExpr(IASNode iNode, InstructionList stem, Binding field, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, true, field);

        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);
        result.addInstruction(OP_dup);
        result.addInstruction(OP_getproperty, field.getName());
        result.addInstruction(op_unplus());

        //  Save a copy of the original value to use as the value of this expression.
        Binding orig_tmp = null;
        if( need_result )
        {
            result.addInstruction(OP_dup);
            orig_tmp = currentScope.allocateTemp();
            result.addInstruction(orig_tmp.setlocal() );
        }
        
        result.addInstruction(OP_increment);
        result.addInstruction(OP_setproperty, field.getName());

        if( need_result )
        {
            result.addInstruction(orig_tmp.getlocal() );
            currentScope.releaseTemp(orig_tmp);
        }

        return result;
    }

    public InstructionList reduce_postIncNameExpr(IASNode iNode, Binding unary, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, true, unary);

        InstructionList result = createInstructionList(iNode);

        if ( unary.isLocal() ) {
            ICompilerProject project = currentScope.getProject();

            IDefinition inType = SemanticUtils.resolveUnaryExprType(iNode, project);

            IDefinition intType = project.getBuiltinType(BuiltinType.INT);
            IDefinition numberType = project.getBuiltinType(BuiltinType.NUMBER);
            if( inType == intType)
            {
                // Incrementing a local, typed as int
                // we can use inclocal_i since we know the result will be stored in an int
                if( need_result )
                    result.addInstruction(unary.getlocal());
                result.addInstruction(unary.inclocal_i());
            }
            else if( inType == numberType)
            {
                // Incrementing a local, typed as Number
                // we can use inclocal since we know the result will be stored in a Number
                if( need_result )
                    result.addInstruction(unary.getlocal());
                result.addInstruction(unary.inclocal());
            }
            else
            {
                result.addInstruction(unary.getlocal());
                result.addInstruction(op_unplus());
                if( need_result )
                    result.addInstruction(OP_dup);
                result.addInstruction(OP_increment);
                coerce(result, inType);
                result.addInstruction(unary.setlocal());
            }
        }
        else
        {
            Name n = unary.getName();
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_getproperty,n);
            result.addInstruction(op_unplus());
            if( need_result )
                result.addInstruction(OP_dup);
            result.addInstruction(OP_increment);
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_swap);
            result.addInstruction(OP_setproperty,n);
        }

        return result;
    }

    public InstructionList reduce_preDecBracketExpr(IASNode iNode, InstructionList stem, InstructionList index, boolean need_result)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IUnaryOperatorNode)iNode).getOperandNode();

        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, false);
        
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        Binding stem_tmp = currentScope.allocateTemp();
        result.addInstruction(OP_dup);
        result.addInstruction(stem_tmp.setlocal() );

        result.addAll(index);
        result.addInstruction(OP_dup);

        //  Get the initial value.
        Binding index_tmp = currentScope.allocateTemp();
        result.addInstruction(index_tmp.setlocal());
        result.addInstruction(arrayAccess(arrayIndexNode, OP_getproperty));

        //  Increment, and dup a copy onto 
        //  the stack as the value of this expression.
        result.addInstruction(OP_decrement);
        if( need_result )
            result.addInstruction(OP_dup);
        Binding result_tmp = currentScope.allocateTemp();
        result.addInstruction(result_tmp.setlocal());

        result.addInstruction(stem_tmp.getlocal() );
        result.addInstruction(index_tmp.getlocal() );
        result.addInstruction(result_tmp.getlocal() );
        result.addInstruction(arrayAccess(arrayIndexNode, OP_setproperty));

        currentScope.releaseTemp(stem_tmp);
        currentScope.releaseTemp(index_tmp);
        currentScope.releaseTemp(result_tmp);

        return result;
    }

    public InstructionList reduce_preDecMemberExpr(IASNode iNode, InstructionList stem, Binding field, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, false, field);
        
        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);
        result.addInstruction(OP_dup);
        result.addInstruction(OP_getproperty, field.getName());
        result.addInstruction(OP_decrement);

        Binding result_tmp = null;
        //  Save a copy of the result to use as the value of this expression.
        if( need_result )
        {
            result.addInstruction(OP_dup);
            result_tmp = currentScope.allocateTemp();
            result.addInstruction(result_tmp.setlocal() );
        }

        result.addInstruction(OP_setproperty, field.getName());

        if( need_result )
        {
            result.addInstruction(result_tmp.getlocal() );
            currentScope.releaseTemp(result_tmp);
        }
        
        return result;
    }

    public InstructionList reduce_preDecNameExpr(IASNode iNode, Binding unary, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, false, unary);

        InstructionList result = createInstructionList(iNode);

        if ( unary.isLocal() ) {
            ICompilerProject project = currentScope.getProject();

            IDefinition inType = SemanticUtils.resolveUnaryExprType(iNode, project);

            IDefinition intType = project.getBuiltinType(BuiltinType.INT);
            IDefinition numberType = project.getBuiltinType(BuiltinType.NUMBER);
            if( inType == intType)
            {
                // Decrementing a local, typed as int
                // we can use declocal_i since we know the result will be stored in an int
                result.addInstruction(unary.declocal_i());
                if( need_result )
                    result.addInstruction(unary.getlocal());
            }
            else if( inType == numberType)
            {
                // Decrementing a local, typed as Number
                // we can use declocal since we know the result will be stored in a Number
                result.addInstruction(unary.declocal());
                if( need_result )
                    result.addInstruction(unary.getlocal());
            }
            else
            {
                result.addInstruction(unary.getlocal());
                result.addInstruction(OP_decrement);
                if( need_result )
                    result.addInstruction(OP_dup);
                coerce(result, inType);
                result.addInstruction(unary.setlocal());
            }
        }
        else
        {
            Name n = unary.getName();
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_getproperty,n);
            result.addInstruction(OP_decrement);
            if( need_result )
                result.addInstruction(OP_dup);
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_swap);
            result.addInstruction(OP_setproperty,n);
        }

        return result;
    }

    public InstructionList reduce_preIncBracketExpr(IASNode iNode, InstructionList stem, InstructionList index, boolean need_result)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)((IUnaryOperatorNode)iNode).getOperandNode();

        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, true);
        InstructionList result = createInstructionList(iNode);

        result.addAll(stem);
        Binding stem_tmp = currentScope.allocateTemp();
        result.addInstruction(OP_dup);
        result.addInstruction(stem_tmp.setlocal() );

        result.addAll(index);
        result.addInstruction(OP_dup);

        //  Get the initial value.
        Binding index_tmp = currentScope.allocateTemp();
        result.addInstruction(index_tmp.setlocal() );
        result.addInstruction(arrayAccess(arrayIndexNode, OP_getproperty));

        //  Increment, and dup a copy onto 
        //  the stack as the value of this expression.
        result.addInstruction(OP_increment);
        if( need_result )
            result.addInstruction(OP_dup);
        Binding result_tmp = currentScope.allocateTemp();
        result.addInstruction(result_tmp.setlocal() );

        result.addInstruction(stem_tmp.getlocal() );
        result.addInstruction(index_tmp.getlocal());
        result.addInstruction(result_tmp.getlocal());
        result.addInstruction(arrayAccess(arrayIndexNode, OP_setproperty));

        currentScope.releaseTemp(stem_tmp);
        currentScope.releaseTemp(index_tmp);
        currentScope.releaseTemp(result_tmp);

        return result;
    }

    public InstructionList reduce_preIncMemberExpr(IASNode iNode, InstructionList stem, Binding field, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, true, field);

        InstructionList result = createInstructionList(iNode);
        result.addAll(stem);
        result.addInstruction(OP_dup);
        result.addInstruction(OP_getproperty, field.getName());
        result.addInstruction(OP_increment);

        Binding result_tmp = null;
        //  Save a copy of the result to use as the value of this expression.
        if( need_result )
        {
            result.addInstruction(OP_dup);
            result_tmp = currentScope.allocateTemp();
            result.addInstruction(result_tmp.setlocal());
        }
        
        result.addInstruction(OP_setproperty, field.getName());

        if( need_result )
        {
            result.addInstruction(result_tmp.getlocal());
            currentScope.releaseTemp(result_tmp);
        }

        return result;
    }

    public InstructionList reduce_preIncNameExpr(IASNode iNode, Binding unary, boolean need_result)
    {
        currentScope.getMethodBodySemanticChecker().checkIncDec(iNode, true, unary);
        
        InstructionList result = createInstructionList(iNode);

        if ( unary.isLocal() ) {
            ICompilerProject project = currentScope.getProject();

            IDefinition inType = SemanticUtils.resolveUnaryExprType(iNode, project);

            IDefinition intType = project.getBuiltinType(BuiltinType.INT);
            IDefinition numberType = project.getBuiltinType(BuiltinType.NUMBER);
            if( inType == intType)
            {
                // Incrementing a local, typed as int
                // we can use inclocal_i since we know the result will be stored in an int
                result.addInstruction(unary.inclocal_i());
                if( need_result )
                    result.addInstruction(unary.getlocal());
            }
            else if( inType == numberType)
            {
                // Incrementing a local, typed as Number
                // we can use inclocal since we know the result will be stored in a Number
                result.addInstruction(unary.inclocal());
                if( need_result )
                    result.addInstruction(unary.getlocal());
            }
            else
            {
                result.addInstruction(unary.getlocal());
                result.addInstruction(OP_increment);
                if( need_result )
                    result.addInstruction(OP_dup);
                coerce(result, inType);
                result.addInstruction(unary.setlocal());
            }
        }
        else
        {
            Name n = unary.getName();
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_getproperty,n);
            result.addInstruction(OP_increment);
            if( need_result )
                result.addInstruction(OP_dup);
            result.addAll(currentScope.findProperty(unary, true));
            result.addInstruction(OP_swap);
            result.addInstruction(OP_setproperty,n);
        }

        return result;
    }

    /**
     * Add instructions to the instructionlist passed in to coerce the top value of the stack
     * to the given type.
     *
     * This will generate a generic OP_coerce, or one of the more specific coercion/conversion opcodes
     * such as convert_d for Number, coerce_s for String, etc.
     *
     * Matches ASCs behavior.
     *
     * @param il        the InstructionList to add the instruction to
     * @param toType    the type you want to coerce the top stack value to
     */
    public void coerce(InstructionList il, IDefinition toType )
    {
        if ( toType == null )
            return;

        assert toType instanceof ITypeDefinition;

        ICompilerProject project = currentScope.getProject();
        
        if( toType == project.getBuiltinType(BuiltinType.ANY_TYPE) )
        {
            il.addInstruction(OP_coerce_a);
        }
        else if ( toType == project.getBuiltinType(BuiltinType.STRING) )
        {
            il.addInstruction(OP_coerce_s);
        }
        else if ( toType == project.getBuiltinType(BuiltinType.BOOLEAN) )
        {
            il.addInstruction(OP_convert_b);
        }
        else if( toType == project.getBuiltinType(BuiltinType.NUMBER) )
        {
            il.addInstruction(OP_convert_d);
        }
        else if( toType == project.getBuiltinType(BuiltinType.INT) )
        {
            il.addInstruction(OP_convert_i);
        }
        else if( toType == project.getBuiltinType(BuiltinType.UINT) )
        {
            il.addInstruction(OP_convert_u);
        }
        else
        {
            il.addInstruction(OP_coerce, ((DefinitionBase)toType).getMName(project));
        }
    }
    public InstructionList reduce_regexLiteral(IASNode iNode)
    {
        String flags = ((RegExpLiteralNode) iNode).getFlagString();
        
        // If flags are defined, additional pushstring instruction is needed
        InstructionList result = createInstructionList(iNode, (flags.isEmpty()) ? 4 : 5);

        result.addAll(currentScope.getPropertyValue(regexType, currentScope.getProject().getBuiltinType(BuiltinType.REGEXP)));
        result.addInstruction(OP_pushstring, getStringLiteralContent(iNode));
        
        if (!flags.isEmpty())
        {
            result.addInstruction(OP_pushstring, flags);
            result.addInstruction(OP_construct, 2);
        }
        else
        {
            result.addInstruction(OP_construct, 1);
        }
        
        return result;
    }

    public InstructionList reduce_requiredParameter(IASNode iNode, Name param_name, Binding param_type)
    {
        currentScope.makeParameter(getParameterContent(iNode), param_type.getName());
        return null;
    }

    public InstructionList reduce_restParameter(IASNode iNode, Name param_name, Binding param_type)
    {
        currentScope.getMethodBodySemanticChecker().checkRestParameter(iNode, param_type);
        currentScope.makeParameter(getParameterContent(iNode), param_type.getName());
        return null;
    }

    public InstructionList reduce_returnVoidSideEffect(IASNode iNode, InstructionList value)
	{
        currentScope.getMethodBodySemanticChecker().checkReturnValue(iNode);

		//  Evaluate the expression for possible side effects.
		InstructionList result = createInstructionList(iNode);
		result.addAll(value);
		result.addInstruction(OP_returnvoid);
		return result;
	}

    public InstructionList reduce_returnValue(IASNode iNode, InstructionList value)
    {
        currentScope.getMethodBodySemanticChecker().checkReturnValue(iNode);
        return reduce_returnWithSideEffects(iNode, value, OP_returnvalue);
    }

    public InstructionList reduce_returnVoidValue(IASNode iNode, InstructionList no_value)
    {
        currentScope.getMethodBodySemanticChecker().checkReturnVoid(iNode);
        return reduce_returnWithSideEffects(iNode, no_value, OP_returnvoid);
    }
    

    /**
     *  Reduce a return statement that may have side effects
     *  (either mutation or reading volatile state).
     *  @param iNode - the root IASNode of the return statement.
     *  @param value - the value to be returned, or just computed.
     *  @param opcode - OP_returnvalue or OP_returnvoid.
     */
    private InstructionList reduce_returnWithSideEffects(IASNode iNode, InstructionList value, int opcode)
    {
        //  Create two InstructionLists; the first, result list
        //  goes in the body of the try block.  It computes the
        //  result value and stores it in a temp -- this allows
        //  the control-flow unwinding code to pop scopes, etc.,
        //  with no effect on the AS3 program's observable computation.
        //  The second IL is a control-flow stub that fetches the
        //  return value from the temp and returns it; this stub
        //  goes to the control-flow manager to be massaged into
        //  the control-flow unwinding code required by the current
        //  control flow contexts, if any.
        //  HOWEVER: as an optimization, the temp and the stub IL
        //  are only used when the flow manager says they're needed.
        InstructionList result = createInstructionList(iNode);
        result.addAll(value);

        Binding result_temp = null;
        boolean need_temp = currentScope.getFlowManager().hasNontrivialFlowCharacteristics();

        if ( need_temp )
        {
            result_temp = currentScope.allocateTemp();
            result.addInstruction(result_temp.setlocal());
        }

        InstructionList controlFlowStub = null;
        FunctionDefinition function_def = SemanticUtils.getFunctionDefinition(iNode);
        if ( need_temp )
        {
            controlFlowStub = createInstructionList(iNode);
            controlFlowStub.addInstruction(result_temp.getlocal());
            addRelevantReturnOpcode(function_def, opcode, controlFlowStub);
        }
        else
        {
            addRelevantReturnOpcode(function_def, opcode, result);
        }

        try
        {
            if ( need_temp )
            {
                //  The controlFlowStub may be replaced by code that
                //  branches to some context unwinding.
                result.addAll(getNonLocalControlFlow(controlFlowStub, ControlFlowContextManager.FIND_ALL_CONTEXTS));
            }
            else
            {
                //  Ensure we get back the same IL as sent in,
                //  or the ABC will be incorrect.
                InstructionList prev_result = result;
                result = getNonLocalControlFlow(result, ControlFlowContextManager.FIND_ALL_CONTEXTS);
                assert result == prev_result;
            }
        }
        catch ( UnknownControlFlowTargetException cant_return )
        {
            currentScope.addProblem(new UnexpectedReturnProblem(iNode));
            return createInstructionList(iNode);
        }

        return result;
    }

    public InstructionList reduce_returnVoid(IASNode iNode)
    {
        InstructionList result = createInstructionList(iNode, 1);
        currentScope.getMethodBodySemanticChecker().checkReturnVoid(iNode);
        FunctionDefinition functionDef = SemanticUtils.getFunctionDefinition(iNode);
        addRelevantReturnOpcode(functionDef, OP_returnvoid, result);

        try
        {
            return getNonLocalControlFlow(result, ControlFlowContextManager.FIND_ALL_CONTEXTS);
        }
        catch ( UnknownControlFlowTargetException cant_return )
        {
            currentScope.addProblem(new UnexpectedReturnProblem(iNode));
            return createInstructionList(iNode);
        }

    }

    /**
     * When inlining a method, a jump opcode must be emitted rather than a return
     * 
     * @param functionDef the function definition from which we're returning
     * @param opcode the original opcode which may be translated when inlining a function
     * @param result the InstructionList onto which the instruction will be added
     */
    private void addRelevantReturnOpcode(FunctionDefinition functionDef, int opcode, InstructionList result)
    {
        if (currentScope.insideInlineFunction())
        {
            Label inlinedFunctionCallSiteLabel = ((InlineFunctionLexicalScope)currentScope).getInlinedFunctionCallSiteLabel();
            switch (opcode)
            {
                case OP_returnvoid:
                {
                    // returnvoid pushes undefined onto the stack, so mimic that behavior
                    result.addInstruction(OP_pushundefined);

                    // if the function returns a type, undefined is coerced to that type
                    if (functionDef != null)
                    {
                        TypeDefinitionBase returnType = (TypeDefinitionBase)functionDef.resolveReturnType(currentScope.getProject());
                        if (returnType != null &&
                            !returnType.equals(ClassDefinition.getVoidClassDefinition()) &&
                            !returnType.equals(ClassDefinition.getAnyTypeClassDefinition()))
                        {
                            result.addInstruction(OP_coerce, returnType.getMName(currentScope.getProject()));
                        }
                    }

                    result.addInstruction(OP_jump, inlinedFunctionCallSiteLabel);
                    break;
                }
                case OP_returnvalue:
                    result.addInstruction(OP_jump, inlinedFunctionCallSiteLabel);
                    break;
                default:
                    result.addInstruction(opcode);
            }
        }
        else
        {
            result.addInstruction(opcode);
        }
    }

    public InstructionList reduce_runtimeNameExpression(IASNode iNode, InstructionList expr)
    {
        return expr;
    }

    public Binding reduce_simpleName(IASNode iNode)
    {
        final Binding result;
        final IdentifierNode identifier = (IdentifierNode)iNode;
        if (identifier.getName().equals(IASLanguageConstants.ANY_TYPE) && SemanticUtils.isE4XWildcardProperty(identifier))
        {
            // TODO: This is a specific fix for CMP-1731. CMP-696 should be able
            // to cover this use case in a more generic and robust way. Revisit
            // this implementation when CMP-696 is fixed.
            final ICompilerProject project = currentScope.getProject();
            final Nsset qualifiers = SemanticUtils.getOpenNamespaces(iNode, project);
            final Name name = new Name(CONSTANT_Multiname, qualifiers, null);
            result = new Binding(iNode, name, identifier.resolve(project));
        }
        else
        {
            result = currentScope.resolveName(identifier);
            currentScope.getMethodBodySemanticChecker().checkSimpleName(iNode, result);
        }
        return result;
    }

    public Name reduce_declName(IASNode iNode )
    {
        // We are the name of a declaration, get the containing DefinitionNode and grab the
        // name from there
        BaseDefinitionNode bdn = (BaseDefinitionNode)iNode.getAncestorOfType(BaseDefinitionNode.class);
        DefinitionBase db = bdn.getDefinition();
        Name n = db.getMName(currentScope.getProject());
        return n;
    }
    
    public InstructionList reduce_strictneqExpr(IASNode iNode, InstructionList l, InstructionList r)
    {
        InstructionList result = binaryOp(iNode, l, r, OP_strictequals);
        result.addInstruction(OP_not);
        return result;
    }

    public Binding reduce_superAccess(IASNode iNode, Binding qualified_name)
    {
        currentScope.getMethodBodySemanticChecker().checkSuperAccess(iNode);
        qualified_name.setSuperQualified(true);
        return qualified_name;
    }

    public InstructionList reduce_superCallExpr(IASNode iNode, Vector<InstructionList> args)
    {
        currentScope.getMethodBodySemanticChecker().checkExplicitSuperCall(iNode, args);
        //  TODO: Investigate optimizing this.
        InstructionList result = createInstructionList(iNode);
        //  Special case first part: don't look for the "super" name,
        //  push "this" on the stack.
        result.addInstruction(OP_getlocal0);
        for ( InstructionList arg: args)
            result.addAll(arg);
        // Special case second part: call constructsuper.
        result.addInstruction(OP_constructsuper, args.size() );
        return result;
    }

    private static class LookupSwitchInfo
    {
        public int minCase = Integer.MAX_VALUE;
        public int maxCase = Integer.MIN_VALUE;
        public ConditionalFragment defaultCase;
    }

    public InstructionList reduce_switchStmt(IASNode iNode, InstructionList switch_expr, Vector<ConditionalFragment> cases)
    {
        if (cases.size() == 0)
        {
            return reduce_trivial_switchStmt(iNode, switch_expr);
        }
        else
        {
            IExpressionNode conditional = ((SwitchNode)iNode).getConditionalNode();
            LookupSwitchInfo lookupSwitchInfo = getLookupSwitchInfo(conditional, cases);

            if (lookupSwitchInfo != null)
                return reduce_lookup_switchStmt(iNode, switch_expr, cases, lookupSwitchInfo);
            else
                return reduce_ifelse_switchStmt(iNode, switch_expr, cases);
        }
    }

    /**
     * Inspect the switch cases to determine if a lookup switch can be used.  Any criteria
     * for using a lookup switch or if/else chain should be adjusted here.
     * 
     * @param conditional
     * @param cases
     * @return LookupSwitchInfo if a lookup switch can be used, otherwise null
     */
    private LookupSwitchInfo getLookupSwitchInfo(IExpressionNode conditional, Vector<ConditionalFragment> cases)
    {
        // only generate a lookup switch if the conditional type is of type int or uint
        IDefinition conditionalType = conditional.resolveType(currentScope.getProject());
        if (!SemanticUtils.isBuiltin(conditionalType, BuiltinType.INT, currentScope.getProject()) &&
            !SemanticUtils.isBuiltin(conditionalType, BuiltinType.UINT, currentScope.getProject()))
            return null;

        LookupSwitchInfo lookupSwitchInfo = new LookupSwitchInfo();

        boolean hasConditionalCases = false;
        for (ConditionalFragment currentCase : cases)
        {
            if (currentCase.isUnconditionalAlternative())
            {
                lookupSwitchInfo.defaultCase = currentCase;
                continue;
            }

            if (currentCase.constantCondition == null)
                return null;

            assert (SemanticUtils.isBuiltin(conditionalType, BuiltinType.INT, currentScope.getProject()) ||
                    SemanticUtils.isBuiltin(conditionalType, BuiltinType.UINT, currentScope.getProject())) : "only switching on type int or uint supported";

            long value;
            if (SemanticUtils.isBuiltin(conditionalType, BuiltinType.UINT, currentScope.getProject()))
                value = ECMASupport.toUInt32(currentCase.constantCondition);
            else
                value = ECMASupport.toInt32(currentCase.constantCondition);

            // We could potentially use longs here, but for now just fallback to an if/else
            // jump in the case where a value is outside the integeger range unless we find
            // real world code where it makes sense to handle longs too.
            if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE)
                return null;

            lookupSwitchInfo.minCase = Math.min((int)value, lookupSwitchInfo.minCase);
            lookupSwitchInfo.maxCase = Math.max((int)value, lookupSwitchInfo.maxCase);
            hasConditionalCases = true;
        }

        // if there are no conditional cases, don't generate lookup switch
        if (!hasConditionalCases)
            return null;

        int range = lookupSwitchInfo.maxCase - lookupSwitchInfo.minCase;

        // if the range is greater than 20 and if less than 50% ranges dense, then use if/else
        if ((range > 20) && (range < cases.size() * 2))
            return null;

        // limit the size of the jump table to cut down on compile time
        // memory building up the table, and avoid any potential player
        // bugs with massive lookup switches
        if (range > (2 ^ 16))
            return null;

        return lookupSwitchInfo;
    }

    private InstructionList reduce_lookup_switchStmt(IASNode iNode, InstructionList switch_expr, Vector<ConditionalFragment> cases, LookupSwitchInfo lookupSwitchInfo)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(switch_expr);
        result.addInstruction(OP_convert_i);

        // save some space in the case table, by not generating entries
        // for any values between 0 and the min case value
        int caseOffset = 0;
        if (lookupSwitchInfo.minCase > 0)
        {
            caseOffset = lookupSwitchInfo.minCase;
            lookupSwitchInfo.minCase = 0;
            lookupSwitchInfo.maxCase = lookupSwitchInfo.maxCase - caseOffset;
            result.addInstruction(OP_pushint, Integer.valueOf(caseOffset));
            result.addInstruction(OP_subtract_i);
        }
        // if we have negative values in the case expression, need
        // to offset from zero
        else if (lookupSwitchInfo.minCase < 0)
        {
            caseOffset = lookupSwitchInfo.minCase;
            lookupSwitchInfo.minCase = 0;
            lookupSwitchInfo.maxCase = lookupSwitchInfo.maxCase - caseOffset;
            result.addInstruction(OP_pushint, new Integer(lookupSwitchInfo.minCase + 1));
            result.addInstruction(OP_add_i);
        }

        Label switchTail = null;
        Label defaultLabel;

        if (lookupSwitchInfo.defaultCase != null)
            defaultLabel = lookupSwitchInfo.defaultCase.getLabel();
        else
            defaultLabel = switchTail = new Label();

        // generate the case table, maxCase+2, as count from zero
        // and add one for the default label at the end
        Label[] caseLabels = new Label[lookupSwitchInfo.maxCase + 2];

        // pre-fill the case label table with the default label.
        Arrays.fill(caseLabels, defaultLabel);

        // fill in specific labels for any specified values
        for (ConditionalFragment current_case : cases)
        {
            if (current_case.isUnconditionalAlternative())
                continue;

            Object caseValue = current_case.constantCondition;
            // a constant of value 90000 was in a SWC as a double even though
            // the type of the constant was int
            if (caseValue instanceof Double)
                caseValue = new Integer(((Double)caseValue).intValue());
            assert (caseValue instanceof Integer) : "reduce_lookup_switchStmt called on non integer case value";
            final int index = (Integer)caseValue - caseOffset;
            // if there is already a non-default value for this
            // index, ignore it, as only the first case counts
            if (caseLabels[index] != defaultLabel)
                continue;

            caseLabels[index] = current_case.getLabel();
        }

        result.addInstruction(OP_lookupswitch, caseLabels);

        Label default_case_label = null;
        for (ConditionalFragment current_case : cases)
        {
            if (current_case.isUnconditionalAlternative())
            {
                //  The parser rejects duplicate default alternatives
                //  in some situations, but not in others.
                if (default_case_label == null)
                    default_case_label = current_case.statement.getLabel();
                else
                    currentScope.addProblem(new MultipleSwitchDefaultsProblem(current_case.site));
            }

            result.addAll(current_case.statement);
        }

        switchTail = addInterstitialControlFlow(result, switchTail);

        //  No continue here, and thus there is no need
        //  to check for previous labeled flow contexts.
        currentScope.getFlowManager().finishSwitchControlFlowContext(result);

        if ( switchTail != null )
            result.labelNext(switchTail);

        return result;
    }

    private InstructionList reduce_ifelse_switchStmt(IASNode iNode, InstructionList switch_expr, Vector<ConditionalFragment> cases)
    {
        assert (cases.size() > 0) : "reduce_ifelse_switchStmt called on switch stmt with no cases";

        // need to convert any constant values back
        // to a conditional expression when not generating
        // a lookup switch
        convertConstantValueConditionsToInstructions(cases);

        //  TODO: Optimize InstructionList size.
        InstructionList result = createInstructionList(iNode);
        Label default_case_label = null;
        Label switch_tail = null;

        //  Get the switch value and save it in a temp.
        Binding switch_temp = currentScope.allocateTemp();
        result.addAll(switch_expr);
        result.addInstruction(switch_temp.setlocal());

        //  First, jump to the switch table.
        if ( ! cases.elementAt(0).isUnconditionalAlternative() || cases.size() == 1 )
            result.addInstruction(OP_jump, cases.elementAt(0).getLabel());
        else
            result.addInstruction(OP_jump, cases.elementAt(1).getLabel());


        for ( ConditionalFragment current_case: cases )
        {
            //  Ensure the case begins with a OP_label instruction
            //  so we can branch back to it.
            if ( current_case.statement.isEmpty() || current_case.statement.firstElement().getOpcode() != OP_label )
            {
                InstructionList labeled_list = createInstructionList(iNode);
                labeled_list.addInstruction(OP_label);
                labeled_list.addAll(current_case.statement);
                current_case.statement = labeled_list;
            }

            if ( current_case.isUnconditionalAlternative() )
            {
                //  The parser rejects duplicate default alternatives
                //  in some situations, but not in others.
                if ( default_case_label == null )
                    default_case_label = current_case.statement.getLabel();
                else
                    currentScope.addProblem(new MultipleSwitchDefaultsProblem(current_case.site));
            }
            // no need to check for duplicate cases, as the first case is always chosen in this situation

            current_case.getStatementLabel();  // Touch the label so it will be properly recorded.
            result.addAll(current_case.statement);
        }

        //  Jump to the tail.
        switch_tail = addInterstitialControlFlow(result, null);

        //  Emit the "switch table" as if/else statements.
        for ( ConditionalFragment current_case: cases )
        {
            if ( !current_case.isUnconditionalAlternative() )
            {
                result.addAll(current_case.condition);
                result.addInstruction(switch_temp.getlocal());
                result.addInstruction(OP_ifstricteq, current_case.getStatementLabel() );
            }
        }

        //  Emit the jump to the default case.
        if ( default_case_label != null )
        {
            result.addInstruction(OP_jump, default_case_label);
        }

        currentScope.releaseTemp(switch_temp);

        //  No continue here, and thus there is no need
        //  to check for previous labeled flow contexts.
        currentScope.getFlowManager().finishSwitchControlFlowContext(result);

        if ( switch_tail != null )
            result.labelNext(switch_tail);

        return result;
    }

    private InstructionList reduce_trivial_switchStmt(IASNode iNode, InstructionList switch_expr)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(switch_expr);
        //  Balance the stack!
        result.addInstruction(OP_pop);
        currentScope.getFlowManager().finishSwitchControlFlowContext(result);
        return result;
    }

    /**
     * If the optimized constant case of conditional fragements are not being used, need to go through
     * all cases and convert any constant conditionals back to a conditional instruction list for codegen.
     * 
     * @param cases
     */
    private void convertConstantValueConditionsToInstructions(Vector<ConditionalFragment> cases)
    {
        for (ConditionalFragment current_case : cases)
        {
            current_case.convertConstantConditionToInstruction();

            if (current_case.isConstantConditional())
            {
                current_case.condition = transform_constant_value(current_case.site, current_case.constantCondition);
            }
        }
    }

    public InstructionList reduce_ternaryExpr(IASNode iNode, InstructionList test, InstructionList when_true, InstructionList when_false)
    {
        // AIR (and not FlashPlayer) requires a coerce_a at the end of each clause if the results will be
        // assigned to a Dictionary.
        IBinaryOperatorNode binaryNode = (IBinaryOperatorNode)iNode.getAncestorOfType(IBinaryOperatorNode.class);
        boolean isBracketAssign = binaryNode != null && binaryNode.getOperator() == OperatorType.ASSIGNMENT
            && binaryNode.getLeftOperandNode() instanceof DynamicAccessNode;
        ITypeDefinition destinationType = null;
        if (isBracketAssign)
            destinationType = binaryNode.getLeftOperandNode().resolveType(currentScope.getProject());
        TernaryOperatorNode ternaryNode = (TernaryOperatorNode)iNode;
        
        IExpressionNode valueNode;        
        IDefinition type_def; //= valueNode.resolveType(currentScope.getProject()); //SemanticUtils.getDefinitionOfUnderlyingType(, 
                           // true, currentScope.getProject());
        boolean need_coerce = false;
        
        InstructionList result = createInstructionList(iNode, test.size() + when_true.size() + when_false.size() + 2);
        Label tail = new Label();

        result.addAll(test);
        result.addInstruction(OP_iffalse, when_false.getLabel());
        result.addAll(when_true);
        valueNode = ternaryNode.getLeftOperandNode();
        type_def = valueNode.resolveType(currentScope.getProject());
        need_coerce = type_def != null && !type_def.equals(destinationType);
        if (need_coerce && isBracketAssign)
            coerce(result, destinationType);
        result.addInstruction(OP_jump, tail);
        result.addAll(when_false);
        valueNode = ternaryNode.getRightOperandNode();
        type_def = valueNode.resolveType(currentScope.getProject());
        need_coerce = type_def != null && !type_def.equals(destinationType);
        if (need_coerce && isBracketAssign)
            coerce(result, destinationType);
        result.labelNext(tail);

        return result;
    }

    public InstructionList reduce_throwStmt(IASNode iNode, InstructionList tossable)
    {
        currentScope.getMethodBodySemanticChecker().checkThrow(iNode);

        InstructionList result = createInstructionList(iNode, tossable.size() + 1);
        result.addAll(tossable);
        result.addInstruction(OP_throw);
        return result;
    }

    public InstructionList reduce_tryCatchFinallyStmt(IASNode iNode, InstructionList try_stmt, InstructionList finally_stmt, Vector<CatchPrototype> catch_blocks)
    {
        InstructionList result = generateTryCatchFinally(try_stmt, catch_blocks, finally_stmt);
        currentScope.getFlowManager().finishExceptionContext();
        return result;
    }

    public InstructionList reduce_tryCatchStmt(IASNode iNode, InstructionList try_stmt, Vector<CatchPrototype> catch_blocks)
    {
        //  TODO: Optimize.
        InstructionList result = createInstructionList(iNode);

        if ( try_stmt.isEmpty() )
        {
            //  TODO: The catch clause gen may have
            //  side effects, so we can't skip this.
            try_stmt = createInstructionList(iNode);
            try_stmt.addInstruction(OP_nop);
        }

        Label catch_tail = new Label();

        result.addAll(try_stmt);
        result.addInstruction(OP_jump, catch_tail);

        //  Get labels for the start and end of the try block.
        Label try_start = result.getLabel();
        Label try_end   = result.getLastLabel();

        for ( CatchPrototype catch_proto: catch_blocks )
        {
            boolean is_last_catch = catch_proto.equals(catch_blocks.lastElement());

            InstructionList catch_body = generateCatchBlock(try_start, try_end, catch_proto);

            if( !is_last_catch && catch_body.canFallThrough() )
                catch_body.addInstruction(OP_jump, catch_tail);

            result.addAll(catch_body);
        }

        currentScope.getFlowManager().finishExceptionContext();

        result.labelNext(catch_tail);
        return result;
    }

    public InstructionList reduce_tryFinallyStmt(IASNode iNode, InstructionList try_stmt, InstructionList finally_stmt)
    {
        InstructionList result = generateTryCatchFinally(try_stmt, null, finally_stmt);
        currentScope.getFlowManager().finishExceptionContext();
        return result;
    }

    public InstructionList reduce_typedFunction_to_statement(IASNode iNode, InstructionList plist, Binding return_type, InstructionList block)
    {
        Binding nestedFunctionName = currentScope.resolveName((IdentifierNode)SemanticUtils.getNthChild(iNode, 0));

        InstructionList result = createInstructionList(iNode);

        this.generateNestedFunction(
            iNode,
            this.miniScopes.empty()? result: this.miniScopes.peek(),
            nestedFunctionName,
            return_type.getName(),
            block
        );

        currentScope.getMethodBodySemanticChecker().checkNestedFunctionDecl((IFunctionNode)iNode);

        return result;
    }

    public InstructionList reduce_typedVariableDecl(IASNode iNode, Name var_name, Binding var_type, Vector<InstructionList> chained_decls)
    {
        BaseVariableNode var_node = (BaseVariableNode)iNode;
        currentScope.getMethodBodySemanticChecker().checkVariableDeclaration(iNode);

        // Must check for this before we call makeVariable, but need to emit the instructions after
        // makeVariable so that Bindings are set up correctly with the right local register indexes.
        boolean needsHoistedInitInsns = currentScope.needsHoistedInitInsns(var_name, false);

        Binding var = currentScope.resolveName((IdentifierNode)var_node.getNameExpressionNode());
        currentScope.makeVariable(var, var_type.getName(), ((BaseDefinitionNode)iNode).getMetaInfos());

        // Now that makeVariable is done, emit the hoisted instructions if we needed them.
        if(needsHoistedInitInsns)
            addHoistedInstructionsForVarDecl(var_name, var_type);

        InstructionList result = createInstructionList(iNode);


        for ( InstructionList decl: chained_decls )
            result.addAll(decl);

        return result;
    }

    /**
     * Helper method to add hoisted init instructions for a given variable.
     *
     * This is neccessary when local vars live in registers, and they are referenced before they are inited.
     * If we don't emit the init insns at the top of the method, then the locals could have the wrong values/types
     * when they're referenced resulting in incorrect behavior at runtime
     * @param var_name  the name of the local var
     * @param var_type  the type of the local var
     */
    private void addHoistedInstructionsForVarDecl (Name var_name, Binding var_type)
    {
        Binding var_binding = currentScope.getLocalBinding(var_name);
        if ( var_binding != null && var_binding.isLocal() )
        {
            //  Add initializer code to the init instructions.
            InstructionList init_insns = currentScope.getHoistedInitInstructions();

            ICompilerProject project = currentScope.getProject();

            IDefinition type_def = var_type.getDefinition();

            if  (
                    type_def == project.getBuiltinType(BuiltinType.INT) ||
                    type_def == project.getBuiltinType(BuiltinType.UINT)
                )
            {
                init_insns.addInstruction(OP_pushbyte, 0);
                init_insns.addInstruction(var_binding.setlocal());
            }
            else if ( type_def == project.getBuiltinType(BuiltinType.BOOLEAN) )
            {
                init_insns.addInstruction(OP_pushfalse);
                init_insns.addInstruction(var_binding.setlocal());
            }
            else if ( type_def == project.getBuiltinType(BuiltinType.NUMBER) )
            {
                init_insns.addInstruction(OP_pushnan);
                init_insns.addInstruction(var_binding.setlocal());
            }
            else if ( type_def == project.getBuiltinType(BuiltinType.ANY_TYPE) )
            {
                init_insns.addInstruction(OP_pushundefined);
                init_insns.addInstruction(var_binding.setlocal());
            }
            else if (
                        type_def instanceof ITypeDefinition &&
                        ((ITypeDefinition)type_def).isInstanceOf((ITypeDefinition)project.getBuiltinType(BuiltinType.OBJECT), project)
                )
            {
                init_insns.addInstruction(OP_pushnull);
                init_insns.addInstruction(var_binding.setlocal());
            }
            else
            {
                init_insns.addInstruction(OP_pushundefined);
                init_insns.addInstruction(var_binding.setlocal());
            }
        }
    }

    public InstructionList reduce_typedVariableDeclWithInitializer(IASNode iNode, Name var_name, Binding var_type, InstructionList var_initializer, Vector<InstructionList> chained_decls)
    {
        BaseVariableNode var_node = (BaseVariableNode)iNode;

        currentScope.getMethodBodySemanticChecker().checkVariableDeclaration(iNode);

        // Must check for this before we call makeVariable, but need to emit the instructions after
        // makeVariable so that Bindings are set up correctly with the right local register indexes.
        boolean refedBeforeInited = currentScope.needsHoistedInitInsns(var_name, true);
        
        Binding var = currentScope.resolveName((IdentifierNode)var_node.getNameExpressionNode());
        currentScope.makeVariable(var, var_type.getName(), ((BaseDefinitionNode)iNode).getMetaInfos());

        // If the binding has already been referenced, then we need to emit some hoisted init instructions
        // so that the initial value will be correct.
        if( refedBeforeInited )
            addHoistedInstructionsForVarDecl(var_name, var_type);

        currentScope.getMethodBodySemanticChecker().checkInitialization(iNode, var);
        InstructionList result = generateAssignment(iNode, var, var_initializer);
        for ( InstructionList decl: chained_decls )
            result.addAll(decl);

        return result;
    }

    public InstructionList reduce_typedVariableDeclWithConstantInitializer(IASNode iNode, Name var_name, Binding var_type, Object constant_var_initializer, Vector<InstructionList> chained_decls)
    {
        BaseVariableNode var_node = (BaseVariableNode)iNode;
        PooledValue transformed_constant_initializer =
            currentScope.getMethodBodySemanticChecker().checkInitialValue(var_node, var_type, new PooledValue(constant_var_initializer));

        // if this definition isn't a const, then just use the normal variable initialization, as
        // we only initialize the const slots and not var slots
        if (!SemanticUtils.isConst(iNode, currentScope.getProject()))
        {
            InstructionList var_initializer = transform_pooled_value(iNode, transformed_constant_initializer);
            return reduce_typedVariableDeclWithInitializer(iNode, var_name, var_type, var_initializer, chained_decls);
        }

        currentScope.getMethodBodySemanticChecker().checkVariableDeclaration(iNode);
        InstructionList result = createInstructionList(iNode);
        Binding var = currentScope.resolveName((IdentifierNode)var_node.getNameExpressionNode());
        currentScope.makeVariable(var, var_type.getName(), ((BaseDefinitionNode)iNode).getMetaInfos(), transformed_constant_initializer.getValue());

        //  If the variable is in a local, then it needs to be initialized at the start of the method.
        if ( var.isLocal() )
        {
            InstructionList var_initializer = transform_pooled_value(iNode, transformed_constant_initializer);
            currentScope.getHoistedInitInstructions().addAll(reduce_typedVariableDeclWithInitializer(iNode, var_name, var_type, var_initializer, new Vector<InstructionList>()));
        }

        for ( InstructionList decl: chained_decls )
            result.addAll(decl);

        return result;
    }

    public InstructionList reduce_typedBindableVariableDecl(IASNode iNode, Name name, Binding var_type, Vector<InstructionList> chained_decls)
    {
        BaseVariableNode vn = (BaseVariableNode)iNode;
        currentScope.getMethodBodySemanticChecker().checkBindableVariableDeclaration(iNode, vn.getDefinition());
        InstructionList result = createInstructionList(iNode);
        Binding var = currentScope.resolveName((IdentifierNode)vn.getNameExpressionNode());
        currentScope.makeBindableVariable(var, var_type.getName(), vn.getMetaInfos());
        for ( InstructionList decl: chained_decls )
             result.addAll(decl);

        return result;
    }
    public InstructionList reduce_typedBindableVariableDeclWithInitializer(IASNode iNode, Name var_name, Binding var_type, InstructionList var_initializer, Vector<InstructionList> chained_decls)
    {
        BaseVariableNode vn = (BaseVariableNode)iNode;
        currentScope.getMethodBodySemanticChecker().checkBindableVariableDeclaration(iNode, vn.getDefinition());
        Binding var = currentScope.resolveName((IdentifierNode)vn.getNameExpressionNode());
        currentScope.makeBindableVariable(var, var_type.getName(), vn.getMetaInfos());
        // pass in null as definition so the assignment goes to the backing var and not the setter
        // maybe we'll have to get the actual var def someday.
        InstructionList result = generateAssignment(iNode, new Binding(iNode, BindableHelper.getBackingPropertyName(var_name), null), var_initializer);
        for ( InstructionList decl: chained_decls )
             result.addAll(decl);

        return result;
    }
    public Binding reduce_typedVariableExpression(IASNode iNode, Name var_name, Binding var_type)
    {
        VariableExpressionNode var_expr_node = (VariableExpressionNode)iNode;
        BaseVariableNode var_node = (BaseVariableNode) var_expr_node.getTargetVariable();
        currentScope.getMethodBodySemanticChecker().checkVariableDeclaration(SemanticUtils.getNthChild(iNode, 0));
        Binding var = currentScope.resolveName((IdentifierNode)var_node.getNameExpressionNode());
        currentScope.makeVariable(var, var_type.getName(), var_node.getMetaInfos());

        return var;
    }

    public InstructionList reduce_typelessFunction(IASNode iNode, InstructionList plist, InstructionList block)
    {
        Binding nestedFunctionName = currentScope.resolveName((IdentifierNode)SemanticUtils.getNthChild(iNode, 0));

        InstructionList result = createInstructionList(iNode);

        this.generateNestedFunction(
            iNode,
            this.miniScopes.empty()? result: this.miniScopes.peek(),
            nestedFunctionName,
            null,
            block
        );

        currentScope.getMethodBodySemanticChecker().checkNestedFunctionDecl((IFunctionNode)iNode);

        return result;
    }

    public InstructionList reduce_typeof_expr(IASNode iNode, InstructionList operand)
    {
        InstructionList result = unaryOp(iNode, operand, OP_typeof);
        this.typeofCount--;
        return result;
    }

    public InstructionList reduce_typeof_name(IASNode iNode, Binding binding)
    {
        InstructionList result = null;

        if ( binding.getDefinition() != null )
        {
            ITypeDefinition typezo = binding.getDefinition().resolveType(currentScope.getProject());
            
            ICompilerProject project = currentScope.getProject();

            if ( typezo == project.getBuiltinType(BuiltinType.STRING) )
            {
                result = createInstructionList(iNode);
                result.addInstruction(OP_pushstring, "string");
            }
            else if ( 
                typezo == project.getBuiltinType(BuiltinType.NUMBER) ||
                typezo == project.getBuiltinType(BuiltinType.INT) ||
                typezo == project.getBuiltinType(BuiltinType.UINT) 
            )
            {
                result = createInstructionList(iNode);
                result.addInstruction(OP_pushstring, "number");
            }
            else if ( typezo == project.getBuiltinType(BuiltinType.BOOLEAN) )
            {
                result = createInstructionList(iNode);
                result.addInstruction(OP_pushstring, "boolean");
            }
        }


        if ( result == null )
        {
            result = createInstructionList(iNode);
            generateAccess(binding, AccessType.Lenient, result);
            result.addInstruction(OP_typeof);
        }

        this.typeofCount--;
        return result;
    }

    public InstructionList reduce_useNamespaceDirective(IASNode iNode, Binding ns_name)
    {
        currentScope.getMethodBodySemanticChecker().checkUseNamespaceDirective(iNode, ns_name);
        return createInstructionList(iNode);
    }

    public InstructionList reduce_variableExpression(IASNode iNode, Vector<InstructionList> decls)
    {
        InstructionList result = createInstructionList(iNode);

        for ( InstructionList var_decl: decls )
            result.addAll(var_decl);
        return result;
    }

    public InstructionList reduce_vectorLiteral(IASNode iNode, Binding type_param, Vector<InstructionList> elements)
    {
        currentScope.getMethodBodySemanticChecker().checkVectorLiteral(iNode, type_param);
        InstructionList result = createInstructionList(iNode);

        Nsset ns_set = new Nsset(new Namespace(CONSTANT_PackageNs, IASLanguageConstants.Vector_impl_package));
        Name vector_name = new Name(CONSTANT_Qname, ns_set, IASLanguageConstants.Vector);

        result.addAll(currentScope.getPropertyValue(vector_name, currentScope.getProject().getBuiltinType(BuiltinType.VECTOR)));
        generateTypeNameParameter(type_param, result);
        result.addInstruction(OP_applytype, 1);
        result.pushNumericConstant(elements.size());
        result.addInstruction(OP_construct, 1);

        //  Share this instruction; there may be many elements.
        Instruction setter = arrayAccess(iNode, OP_setproperty);

        for ( int i = 0; i < elements.size(); i++ )
        {
            result.addInstruction(OP_dup);
            result.pushNumericConstant(i);
            result.addAll(elements.elementAt(i));
            result.addInstruction(setter);
        }

        return result;
    }

    public InstructionList reduce_voidExpr_to_expression(IASNode iNode)
    {
        InstructionList il = createInstructionList(iNode);
        il.addInstruction(OP_pushundefined);
        return il;
    }

    public Binding reduce_voidExpr_to_return_type_name(IASNode node)
    {
        return new Binding(node, voidType, null);
    }

    public Binding reduce_voidExpr_to_type_name(IASNode node)
    {
        getProblems().add(new VoidTypeProblem(node));
        return new Binding(node, voidType, null);
    }

    public Object reduce_void0Literal_to_constant_value(IASNode iNode)
    {
        return UNDEFINED_VALUE;
    }

    public InstructionList reduce_void0Literal_to_object_literal(IASNode iNode)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addInstruction(OP_pushundefined);
        return result;
    }

    public InstructionList reduce_instructionListExpression(IASNode iNode)
    {
        return ((InstructionListNode)iNode).getInstructions();
    }

    public InstructionList reduce_void0Operator(IASNode iNode)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addInstruction(OP_pushundefined);
        return result;
    }

    public Object reduce_voidOperator_to_constant_value(IASNode iNode, Object constant_value)
    {
        return UNDEFINED_VALUE;
    }

    public InstructionList reduce_voidOperator_to_expression(IASNode iNode, InstructionList expr)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addAll(expr);
        result.addInstruction(OP_pop);
        result.addInstruction(OP_pushundefined);
        return result;
    }

    public InstructionList reduce_whileStmt(IASNode iNode, InstructionList cond, InstructionList body)
    {
        InstructionList result = createInstructionList(iNode, cond.size() + body.size() + 5);
        currentScope.getFlowManager().resolveContinueLabel(cond);

        //  Jump to the test.
        result.addInstruction(OP_jump, cond.getLabel());

        //  Create an emitter-time label, and attach
        //  it to an OP_label instruction for the
        //  backwards branch.
        result.addInstruction(OP_label);
        Label loop = result.getLastLabel();
        result.addAll(body);

        result.addAll(cond);
        result.addInstruction(OP_iftrue, loop);

        currentScope.getFlowManager().finishLoopControlFlowContext(result);

        return result;
    }

    public InstructionList reduce_withStmt(IASNode iNode, InstructionList new_scope, InstructionList body)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(new_scope);

        if ( currentScope.getFlowManager().hasWithStorage())
        {
            result.addInstruction(OP_dup);
            result.addInstruction(currentScope.getFlowManager().getWithStorage().setlocal());
        }

        result.addInstruction(OP_pushwith);
        result.addAll(body);
        result.addInstruction(OP_popscope);

        currentScope.getFlowManager().finishWithContext(result);
        return result;
    }

    /**
     *  The enumeration of states that the code generator finds interesting in an XML literal.
     *  There are states here than the reducer, below, doesn't consider especially interesting;
     *  see computeXMLContentStateMatrix() for their usage.
     */
    private enum XMLContentState { TagStart, TagLiteral, TagName, Attr, ValueNeedsEquals, Value, TagEnd, ContentLiteral, ContentExpression };

    public InstructionList reduce_XMLContent(IASNode iNode, Vector<InstructionList> exprs)
    {
        InstructionList result = createInstructionList(iNode);

        result.addAll(currentScope.getPropertyValue(xmlType, currentScope.getProject().getBuiltinType(BuiltinType.XML)));

        //  Add all the arguments up into a single String.

        XMLContentState[] content_state = computeXMLContentStateMatrix(exprs);

        result.addAll(exprs.elementAt(0));

        for ( int i = 1; i < exprs.size(); i++ )
        {
            result.addAll(exprs.elementAt(i));

            switch ( content_state[i] )
            {
                case TagName:
                    {
                        //  Parser elides whitespace after tag name expressions.
                        result.addInstruction(OP_pushstring, " ");
                        result.addInstruction(OP_add);
                    }
                    break;
                case Attr:
                    {
                        //  Parser elides whitespace before attribute name expressions.
                        if ( content_state[i-1] != XMLContentState.TagName )
                        {
                            result.addInstruction(OP_pushstring, " ");
                            result.addInstruction(OP_swap);
                            result.addInstruction(OP_add);
                        }
                    }
                    break;
                case ValueNeedsEquals:
                    {
                        if ( content_state[i-1] == XMLContentState.Attr )
                        {
                            //  Parser elided this token.
                            result.addInstruction(OP_pushstring, "=");
                            result.addInstruction(OP_swap);
                            result.addInstruction(OP_add);
                        }
                    }
                    //  falls through
                case Value:
                    {
                        result.addInstruction(OP_esc_xattr);

                        //  The attribute will need quote marks for the AVM's XML parser.
                        result.addInstruction(OP_pushstring, "\"");
                        result.addInstruction(OP_swap);
                        result.addInstruction(OP_add);
                        result.addInstruction(OP_pushstring, "\"");
                        result.addInstruction(OP_add);
                    }
                    break;
                case ContentExpression:
                    result.addInstruction(OP_esc_xelem);
            }

            result.addInstruction(OP_add);
        }

        result.addInstruction(OP_construct, 1);
        return result;
    }

    public InstructionList reduce_XMLList(IASNode iNode, Vector<InstructionList> exprs)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(currentScope.getPropertyValue(xmlListType, currentScope.getProject().getBuiltinType(BuiltinType.XMLLIST)));
        //  The first and last elements are the <> and </> brackets.
        //  An empty XMLList <></> should be reduced by the constant
        //  case, below, so we know we have at least one element.
        result.addAll(exprs.get(1));
        for ( int i = 2; i < exprs.size() - 1; i++ )
        {
            result.addAll(exprs.get(i));
            result.addInstruction(OP_add);
        }
        result.addInstruction(OP_construct, 1);
        return result;
    }

    public InstructionList reduce_XMLListConst(IASNode iNode, Vector<String> elements)
    {
        InstructionList result = createInstructionList(iNode);
        result.addAll(currentScope.getPropertyValue(xmlListType, currentScope.getProject().getBuiltinType(BuiltinType.XMLLIST)));
        StringBuilder buffer = new StringBuilder();
        //  The first and last elements are the <> and </> brackets.
        for ( int i = 1; i < elements.size() -1; i++ )
            buffer.append(elements.elementAt(i));
        result.addInstruction(OP_pushstring, buffer.toString());
        result.addInstruction(OP_construct, 1);
        return result;
    }

    /**
     *  Clone an InstructionList.
     *  @return the clone, appropriately cast.
     *  @note clone() always returns Object.
     */
    InstructionList replicate(InstructionList prototype)
    {
        return (InstructionList)prototype.clone();
    }

    /**
     *  Set this reducer's list of a priori instructions;
     *  typically these are field initializers passed in to
     *  a constructor routine.
     */
    public void setInstanceInitializers(InstructionList insns)
    {
        this.instanceInitializers = insns; 
    }

    /**
     *  Set this reducer's initial LexicalScope.
     */
    public void setCurrentscope(LexicalScope scope)
    {
        this.currentScope = scope;
    }

    /*
     *  ******************************
     *  **  Transformation routines **
     *  ******************************
     */

    public InstructionList transform_boolean_constant(IASNode iNode, Boolean boolean_constant)
    {
        InstructionList result = createInstructionList(iNode, 1);

        if ( Boolean.TRUE.equals(boolean_constant) )
            result.addInstruction(OP_pushtrue);
        else
            result.addInstruction(OP_pushfalse);

        return result;
    }

    public InstructionList transform_double_constant(IASNode iNode, Double double_constant)
    {
        InstructionList result = createInstructionList(iNode, 1);
        pushNumericConstant(result, double_constant, SemanticUtils.resolveType(iNode, currentScope.getProject()));
        return result;
    }

    public InstructionList transform_numeric_constant(IASNode iNode, Number numeric_constant)
    {
        if( numeric_constant instanceof Integer)
            return transform_integer_constant(iNode, (Integer)numeric_constant);
        if( numeric_constant instanceof Long )
            return transform_long_constant(iNode, (Long)numeric_constant);
        if( numeric_constant instanceof Double)
            return transform_double_constant(iNode, (Double)numeric_constant);
        return createInstructionList(iNode, 1);
    }

    /**
     * Transform any PooledValue into an expression, so we can constant fold all sorts of expressions.
     * @param iNode            the node that generated the constant_value
     * @param pooled_value     the pooled value
     * @return                 an InstructionList that contains instructions to push the pooled_value onto the stack.
     */
    public InstructionList transform_pooled_value(IASNode iNode, PooledValue pooled_value )
    {
        return transform_constant_value(iNode, pooled_value.getValue());
    }

    /**
     * Transform any constant_value into an expression, so we can constant fold all sorts of expressions.
     * @param iNode            the node that generated the constant_value
     * @param constant_value   the constant value
     * @return                 an InstructionList that contains instructions to push the constant_value onto the stack.
     */
    public InstructionList transform_constant_value(IASNode iNode, Object constant_value )
    {
        assert (!(constant_value instanceof PooledValue)) : "transform_constant_value should not be called with a PooledValue";

        if( constant_value instanceof Boolean )
        {
            return transform_boolean_constant(iNode, (Boolean)constant_value);
        }
        if( constant_value instanceof Number )
        {
            return transform_numeric_constant(iNode, (Number)constant_value);
        }
        if( constant_value instanceof String )
        {
            return transform_string_constant(iNode, (String)constant_value);
        }

        InstructionList result = createInstructionList(iNode, 1);
        if( constant_value instanceof Namespace)
        {
            result.addInstruction(OP_pushnamespace, constant_value);
        }
        else if( constant_value == ABCConstants.NULL_VALUE )
        {
            result.addInstruction(OP_pushnull);
        }
        else if( constant_value == ABCConstants.UNDEFINED_VALUE )
        {
            result.addInstruction(OP_pushundefined);
        }
        else
        {
            assert false : "unknown constant type";
        }

        return result;
    }
    /**
     *  transform a string_constant to a constant_value - essentially a no-op, but need a reduction
     *  so we can assign it a cost
     */
    public Object transform_string_constant_to_constant(IASNode iNode, String string_constant)
    {
        return string_constant;
    }

    /**
     *  transform a boolean_constant to a constant_value - essentially a no-op, but need a reduction
     *  so we can assign it a cost
     */
    public Object transform_boolean_constant_to_constant(IASNode iNode, Boolean boolean_constant)
    {
        return boolean_constant;
    }

    /**
     *  transform a numeric_constant to a constant_value - essentially a no-op, but need a reduction
     *  so we can assign it a cost
     */
    public Object transform_numeric_constant_to_constant(IASNode iNode, Number numeric_constant)
    {
        return numeric_constant;
    }

    public InstructionList transform_expression_to_conditionalJump(IASNode iNode, InstructionList expression)
    {
        InstructionList result = createInstructionList(iNode, expression.size() + 1);
        result.addAll(expression);
        result.addInstruction(InstructionFactory.getTargetableInstruction(OP_iftrue));
        return result;
    }

    public Object transform_expression_to_constant_value(IASNode iNode, InstructionList expression)
    {
        //  return null - something higher up will report any appropriate diagnostics.
        return null;
    }

    public InstructionList transform_expression_to_void_expression(IASNode iNode, InstructionList expression)
    {
        InstructionList result = createInstructionList(iNode, expression.size() + 1);
        result.addAll(expression);
        result.addInstruction(OP_pop);
        return result;
    }

    public InstructionList transform_integer_constant(IASNode iNode, Integer integer_constant)
    {
        InstructionList result = createInstructionList(iNode, 1);

        pushNumericConstant(result, integer_constant, SemanticUtils.resolveType(iNode, currentScope.getProject()));
        return result;
    }

    public InstructionList transform_long_constant(IASNode iNode, Long long_constant)
    {
        InstructionList result = createInstructionList(iNode, 1);

        pushNumericConstant(result, long_constant, SemanticUtils.resolveType(iNode, currentScope.getProject()));
        return result;
    }

    public Object transform_name_to_constant_value(IASNode iNode)
    {
        currentScope.getMethodBodySemanticChecker().checkConstantValue(iNode);
        
        return SemanticUtils.transformNameToConstantValue(iNode, currentScope.getProject());
    }

    public InstructionList transform_name_to_expression(IASNode iNode, Binding name)
    {
        return generateAccess(name, determineAccessType(iNode));
    }

    public InstructionList transform_non_resolving_identifier(IASNode iNode, String non_resolving_identifier)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addInstruction(OP_pushstring, non_resolving_identifier);
        return result;
    }

    public InstructionList transform_runtime_name_expression(IASNode iNode, RuntimeMultiname runtime_name_expression)
    {
        return runtime_name_expression.generateRvalue(iNode);
    }

    public InstructionList transform_string_constant(IASNode iNode, String string_constant)
    {
        InstructionList result = createInstructionList(iNode, 1);
        result.addInstruction(OP_pushstring, string_constant);
        return result;
    }

    public InstructionList transform_uint_constant(IASNode iNode, Long uint_constant)
    {
        InstructionList result = createInstructionList(iNode, 1);
        pushNumericConstant(result, uint_constant, SemanticUtils.resolveType(iNode, currentScope.getProject()));
        return result;
    }

    /**
     *  Generate a unary operator.
     *  @param operand - the operand expression.
     *  @param opcode - the operator's opcode.
     *  @return an InstructionList that applies the operator to the operand.
     */
    InstructionList unaryOp(IASNode iNode, InstructionList operand, int opcode)
    {
        checkUnaryOp(iNode, opcode);
        InstructionList result = createInstructionList(iNode, operand.size() + 1);
        result.addAll(operand);
        result.addInstruction(opcode);
        return result;
    }

    public void checkUnaryOp (IASNode iNode, int opcode)
    {
        currentScope.getMethodBodySemanticChecker().checkUnaryOperator(iNode, opcode);
    }

    /**
     *  Walk a syntax tree and note any construct that 
     *  will cause the ABC function to need an activation record.
     */
    void scanFunctionBodyForActivations(IASNode n)
    {
        if ( n != null )
        {
            switch ( n.getNodeID() )
            {
                case WithID:
                case AnonymousFunctionID:
                case FunctionID:
                {
                    currentScope.setNeedsActivation();
                    break;
                }
                default:
                {
                    // Note: There is no need to create an activation
                    // for catch or finally.  See ActivationSanityTest
                    // for examples which prove this.

                    for ( int i = 0; i < n.getChildCount(); i++ )
                        scanFunctionBodyForActivations(n.getChild(i));
                }
            }
        }
    }

    /**
     *  Is this expression a string literal?
     *  @return true if the expression is a string literal, i.e.,
     *  it has one pushstring instruction.
     */
    public static boolean isStringLiteral(InstructionList insns)
    {
        return insns.lastElement().getOpcode() == OP_pushstring;
    }

    /**
     *  Extract the string literal from an InstructionList.
     *  @param insns - the InstructionList of interest.
     *  @return the string literal from insns' final
     *  (and presumably only executable) instruction.
     */
    public static String getStringLiteral(InstructionList insns)
    {
        assert isStringLiteral(insns);
        return insns.lastElement().getOperand(0).toString();
    }

    /**
     *  Work around the linear presentation of XML initializer elements from the parser
     *  by doing ad-hoc pattern matching.
     *  @param exprs - a Vector of expressions.
     *  @return A state transition matrix to generate code for the elements.
     *  @see "ECMA-357 11.1.4 : XML Initialiser"
     *  Expressions may be used to compute parts of an XML initialiser.
     *  Expressions are delimited by curly braces and may appear inside tags or element content.
     *  Inside a tag, expressions may be used to compute a tag name, attribute name, or attribute value.
     *  Inside an element, expressions may be used to compute element content.
     */
    private XMLContentState[] computeXMLContentStateMatrix( Vector<InstructionList> exprs)
    {
        XMLContentState[] result = new XMLContentState[exprs.size()];

        //  First element must be a string or the parser wouldn't have put us here.
        //  But it may be a simple < or </ literal or a <foo literal; the former 
        //  imply that the next expression is going to be a TagName, the latter just
        //  is a TagLiteral that puts us into the middle of things.

        assert isStringLiteral(exprs.elementAt(0)) : exprs.elementAt(0);
        String first_element = getStringLiteral(exprs.elementAt(0));

        if ( first_element.equals("<") || first_element.equals("</") )
            result[0] = XMLContentState.TagStart;
        else
            result[0] = XMLContentState.TagLiteral;

        for ( int i = 1; i < exprs.size(); i++ )
        {
            InstructionList insns = exprs.elementAt(i);
            if ( isStringLiteral(insns) )
            {
                switch ( result[i-1] )
                {
                    case TagStart:
                    case TagLiteral:
                    case TagName:
                    case Attr:
                    case Value:
                    case ValueNeedsEquals:
                    {
                        if ( getStringLiteral(insns).matches(".*>") )
                            result[i] = XMLContentState.TagEnd;
                        else
                            result[i] = XMLContentState.TagLiteral;
                        break;
                    }
                    case TagEnd:
                    case ContentLiteral:
                    case ContentExpression:
                        if ( getStringLiteral(insns).matches("<.*") )
                            result[i] = XMLContentState.TagStart;
                        else
                            result[i] = XMLContentState.ContentLiteral;
                }
            }
            else
            {
                //  Now the fun starts.
                //  The most important thing to do here is to get the
                //  Value, and ContentExpression states right;
                //  these are the entities that require special instructions.
                switch ( result[i-1] )
                {
                    case TagStart:
                        result[i] = XMLContentState.TagName;
                        break;
                    //  An expression following a tag name or
                    //  an attribute value should be an attribute name.
                    case TagName:
                    case Value:
                        result[i] = XMLContentState.Attr;
                        break;
                    //  An expression following an attribute name
                    //  should be an attribute value.
                    case Attr:
                        result[i] = XMLContentState.ValueNeedsEquals;
                        break;
                    case TagEnd:
                    case ContentLiteral:
                    case ContentExpression:
                        result[i] = XMLContentState.ContentExpression;
                        break;
                    case TagLiteral:
                    {
                        //  The literal is free-form input and needs
                        //  to be analyzed.
                        switch ( getXMLLiteralContentState(getStringLiteral(exprs.elementAt(i-1)) ) )
                        {
                            case TagStart:
                                result[i] = XMLContentState.TagName;
                                break;
                            case Attr:
                                //  Since Attr here implies we saw
                                //  a '=' character, the XML string
                                //  won't need one appended.
                                result[i] = XMLContentState.Value;
                                break;
                            case Value: 
                                result[i] = XMLContentState.Attr;
                                break;
                            default:
                                result[i] = XMLContentState.ContentExpression;
                        }
                        break;
                    }
                    default:
                        assert false: "Unhandled case " + result[i-1];
                }
                
            }
        }

        return result;
    }

    /**
     *  Analyze an XML literal and see what state its last character implies.
     *  @return the XMLContentState corresponding to the significance 
     *    of the last literal; e.g., "foo=" returns Attr, "foo" returns Value.
     */
    private XMLContentState getXMLLiteralContentState(String literal)
    {
        char lastChar = literal.charAt(literal.length()-1);

        if ( lastChar == '<' )
        {
            return XMLContentState.TagStart;
        }
        else if ( lastChar ==  '=' )
        {
            return XMLContentState.Attr;
        }

        return XMLContentState.ContentExpression;
    }

    /**
     * @return return the opcode to use to convert the top stack value to a numeric
     * or not
     */
    int op_unplus ()
    {
        return OP_convert_d;
    }

    /**
     * Reduce a array index expression ( a[x] ) in an MXML data binding
     * destination to: a[x] = firstParam
     */
    public InstructionList reduce_arrayIndexExpr_to_mxmlDataBindingSetter(IASNode iNode, InstructionList stem, InstructionList index, boolean isSuper)
    {
        IDynamicAccessNode arrayIndexNode = (IDynamicAccessNode)iNode;
        
        int stemInstructionCount = isSuper ? 1 : stem.size();
        InstructionList result =
            createInstructionList(arrayIndexNode, stemInstructionCount + index.size() + 3 + 1); // +1 for the returnvoid
        
        if (isSuper)
            result.addInstruction(OP_getlocal0);
        else
            result.addAll(stem);
        result.addAll(index);
        result.addInstruction(OP_getlocal1);
        int opCode = isSuper ? OP_setsuper : OP_setproperty;
        result.addInstruction(arrayAccess(arrayIndexNode, opCode));
        return result;
    }

    /**
     * Reduce a member access expression ( a.b ) in an MXML data binding
     * destination to: a.b = firstParam
     */
    public InstructionList reduce_memberAccessExpr_to_mxmlDataBindingSetter(IASNode memberAccessExpr, InstructionList stem, Binding member)
    {
        currentScope.getMethodBodySemanticChecker().checkLValue(memberAccessExpr, member);
        InstructionList result =
            createInstructionList(memberAccessExpr, stem.size() + 2 + 1); // +1 for the returnvoid
        result.addAll(stem);
        result.addInstruction(OP_getlocal1);
        result.addInstruction(OP_setproperty, member.getName());
        return result;
    }

    /**
     * Reduce a qualified member access expression ( a.ns::b ) in an MXML data binding
     * destination to: a.ns::b = firstParam
     */
    public InstructionList reduce_qualifiedMemberAccessExpr_to_mxmlDataBindingSetter(IASNode qualifiedMemberAccessExpr, InstructionList stem, Binding qualifier, Binding member)
    {
        InstructionList result =
            createInstructionList(qualifiedMemberAccessExpr);
        
        //  We may need to work around CMP-751 by recreating 
        //  the correct (trivial) qualifier for base.*::foo.
        Name member_name = member.getName();

        result.addAll(stem);

        if ( !isNamespace(qualifier) )
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
        }
        //  else the qualifier's namespace is already present in the name.
        result.addInstruction(OP_getlocal1);
        result.addInstruction(OP_setproperty, member_name);

        return result;
    }

    /**
     * Reduce a qualified member access expression ( a.ns::["b"] ) in an MXML data binding
     * destination to: a.ns::["b"] = firstParam
     */
    public InstructionList reduce_qualifiedMemberRuntimeNameExpr_to_mxmlDataBindingSetter(IASNode qualifiedMemberRuntimeExpr, InstructionList stem, Binding qualifier, InstructionList runtime_member)
    {
        InstructionList result = createInstructionList(qualifiedMemberRuntimeExpr);

        result.addAll(stem);
        if ( isNamespace(qualifier) )
        {
            result.addAll(runtime_member);
            //  Extract the URI from the namespace and use it to construct a qualified name.
            NamespaceDefinition ns_def = (NamespaceDefinition)qualifier.getDefinition();
            Name qualified_name = new Name(CONSTANT_MultinameL, new Nsset(ns_def.resolveAETNamespace(currentScope.getProject())), null);
            result.addInstruction(OP_getlocal1);
            result.addInstruction(OP_setproperty, qualified_name);
        }
        else
        {
            generateAccess(qualifier, result);
            //  Verifier insists on this.
            result.addInstruction(OP_coerce, namespaceType);
            result.addAll(runtime_member);
            result.addInstruction(OP_getlocal1);
            result.addInstruction(OP_setproperty, new Name(CONSTANT_RTQnameL, null, null));
        }
        return result;
    }

    /**
     * Reduce a runtime name ( nsVar::x ) in an MXML data binding
     * destination to: nsVar::x = firstParam
     * <p>
     * This reduction is used when the qualifer is not a compiler time constant namespace.
     */
    public InstructionList reduceRuntimeName_to_mxmlDataBindingSetter(IASNode runtimeNameNode, RuntimeMultiname runtime_name_expression)
    {
        InstructionList rhs = new InstructionList(1);
        rhs.addInstruction(OP_getlocal1);
        return runtime_name_expression.generateGetOrSet(runtimeNameNode, OP_setproperty, rhs);
    }

    /**
     * Reduce a compile time constant name ( x ) in an MXML data binding
     * destination to: x = firstParam.
     */
    public InstructionList reduceName_to_mxmlDataBindingSetter(IASNode nameNode, Binding name)
    {
        currentScope.getMethodBodySemanticChecker().checkLValue(nameNode, name);
        InstructionList result = new InstructionList(3 + 1); // +1 because of the returnvoid
        result.addAll(currentScope.findProperty(name, true));
        result.addInstruction(ABCConstants.OP_getlocal1);
        result.addInstruction(OP_setproperty, name.getName());
        return result;
    }
    
    /**
     *  Synthesize an array access instruction 
     *  with the correct runtime multiname.
     *  <p>
     *  This handles <code>whatever[...]</code>,
     *  including <code>this[...]</code> and <code>super[...]</code>.
     *  
     *  @param iNode - an IDynamicAccessNode from the construct
     *    that needs an array access instruction.
     *  @param opcode - the opcode of the instruction desired.
     *  @return an instruction with the specified opcode
     *    and the set of open namespaces at the given node.
     */
    private Instruction arrayAccess(IASNode iNode, int opcode)
    {
        ICompilerProject project = currentScope.getProject();

        // Determine if iNode represents super[...] (either as an l-value or an r-value).
        // If so, the namespace set will be slightly different; it will have
        // ProtectedNs(thisClass) instead of ProtectedNs(superClass>.
        IDefinition superDef = null;
        if (iNode instanceof IDynamicAccessNode)
        {
            IExpressionNode arrayNode = ((IDynamicAccessNode)iNode).getLeftOperandNode();
            if (arrayNode instanceof ILanguageIdentifierNode &&
                ((ILanguageIdentifierNode)arrayNode).getKind() == LanguageIdentifierKind.SUPER)
            {
                IIdentifierNode superNode = (IIdentifierNode)arrayNode;
                superDef = superNode.resolveType(project);
            }
        }

        Nsset nsSet = superDef != null ?
                      SemanticUtils.getOpenNamespacesForSuper(iNode, project, superDef) :
                      SemanticUtils.getOpenNamespaces(iNode, project);
        
        Name name = new Name(ABCConstants.CONSTANT_MultinameL, nsSet, null);
        
        return InstructionFactory.getInstruction(opcode, name);
    }

    /**
     *  Determine the proper access type for a name.
     *  @param iNode - the name's AST.
     *  @return AccessType.Lenient if the node is a unqualified
     *    name or the member reference leaf of a member access
     *    node, AccessType.Strict in all other cases.
     */
    private AccessType determineAccessType(IASNode iNode)
    {
        if ( iNode.getParent() instanceof MemberAccessExpressionNode)
        {
            MemberAccessExpressionNode maen = (MemberAccessExpressionNode)iNode.getParent();
            if ( !maen.isMemberReference(iNode) )
            {
                return AccessType.Strict;
            }
        }

        return (this.typeofCount > 0)?
            AccessType.Lenient:
            AccessType.Strict;
    }
}
