/*
 *
 *  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.0 && 1.0/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;
    }
}
