/*
 *
 *  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.semantics;

import static org.apache.flex.abc.ABCConstants.OP_findproperty;
import static org.apache.flex.abc.ABCConstants.OP_findpropstrict;
import static org.apache.flex.abc.ABCConstants.OP_getlex;
import static org.apache.flex.abc.ABCConstants.OP_getouterscope;
import static org.apache.flex.abc.ABCConstants.OP_getscopeobject;
import static org.apache.flex.abc.ABCConstants.OP_newactivation;
import static org.apache.flex.abc.ABCConstants.OP_newcatch;
import static org.apache.flex.abc.ABCConstants.OP_newclass;
import static org.apache.flex.abc.ABCConstants.OP_newfunction;
import static org.apache.flex.abc.ABCConstants.OP_popscope;
import static org.apache.flex.abc.ABCConstants.OP_pushscope;
import static org.apache.flex.abc.ABCConstants.OP_pushwith;
import static org.apache.flex.abc.ABCConstants.OP_returnvalue;
import static org.apache.flex.abc.ABCConstants.OP_returnvoid;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.flex.abc.ABCConstants;
import org.apache.flex.abc.graph.IBasicBlock;
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.MethodInfo;
import org.apache.flex.abc.semantics.MethodBodyInfo;
import org.apache.flex.abc.semantics.Name;
import org.apache.flex.abc.semantics.PooledValue;
import org.apache.flex.compiler.common.ISourceLocation;
import org.apache.flex.compiler.common.ModifiersSet;
import org.apache.flex.compiler.common.ASModifier;
import org.apache.flex.compiler.constants.IASKeywordConstants;
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.IClassDefinition;
import org.apache.flex.compiler.definitions.IConstantDefinition;
import org.apache.flex.compiler.definitions.IDefinition;
import org.apache.flex.compiler.definitions.IFunctionDefinition;
import org.apache.flex.compiler.definitions.IGetterDefinition;
import org.apache.flex.compiler.definitions.IInterfaceDefinition;
import org.apache.flex.compiler.definitions.INamespaceDefinition;
import org.apache.flex.compiler.definitions.ISetterDefinition;
import org.apache.flex.compiler.definitions.ITypeDefinition;
import org.apache.flex.compiler.definitions.IVariableDefinition;
import org.apache.flex.compiler.definitions.references.INamespaceReference;
import org.apache.flex.compiler.internal.definitions.AmbiguousDefinition;
import org.apache.flex.compiler.internal.definitions.VariableDefinition;
import org.apache.flex.compiler.problems.*;
import org.apache.flex.compiler.projects.ICompilerProject;
import org.apache.flex.compiler.tree.as.IASNode;
import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
import org.apache.flex.compiler.tree.as.ICompoundAssignmentNode;
import org.apache.flex.compiler.tree.as.IContainerNode;
import org.apache.flex.compiler.tree.as.IExpressionNode;
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.IMemberAccessExpressionNode;
import org.apache.flex.compiler.tree.as.INamespaceDecorationNode;
import org.apache.flex.compiler.tree.as.INumericLiteralNode;
import org.apache.flex.compiler.tree.as.IParameterNode;
import org.apache.flex.compiler.tree.as.IReturnNode;
import org.apache.flex.compiler.tree.as.IUnaryOperatorNode;
import org.apache.flex.compiler.tree.as.IVariableNode;
import org.apache.flex.compiler.internal.as.codegen.ABCGeneratingReducer;
import org.apache.flex.compiler.internal.as.codegen.Binding;
import org.apache.flex.compiler.internal.as.codegen.InlineFunctionLexicalScope;
import org.apache.flex.compiler.internal.as.codegen.LexicalScope;
import org.apache.flex.compiler.internal.definitions.AccessorDefinition;
import org.apache.flex.compiler.internal.definitions.ClassDefinition;
import org.apache.flex.compiler.internal.definitions.ClassTraitsDefinition;
import org.apache.flex.compiler.internal.definitions.ConstantDefinition;
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.InterfaceDefinition;
import org.apache.flex.compiler.internal.definitions.NamespaceDefinition;
import org.apache.flex.compiler.internal.definitions.ParameterDefinition;
import org.apache.flex.compiler.internal.definitions.SetterDefinition;
import org.apache.flex.compiler.internal.definitions.TypeDefinitionBase;
import org.apache.flex.compiler.internal.scopes.ASScope;
import org.apache.flex.compiler.internal.semantics.SemanticUtils.MultiDefinitionType;
import org.apache.flex.compiler.internal.tree.as.BaseDefinitionNode;
import org.apache.flex.compiler.internal.tree.as.BinaryOperatorLogicalAndNode;
import org.apache.flex.compiler.internal.tree.as.BinaryOperatorLogicalOrNode;
import org.apache.flex.compiler.internal.tree.as.ClassNode;
import org.apache.flex.compiler.internal.tree.as.ExpressionNodeBase;
import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
import org.apache.flex.compiler.internal.tree.as.FunctionNode;
import org.apache.flex.compiler.internal.tree.as.IdentifierNode;
import org.apache.flex.compiler.internal.tree.as.LanguageIdentifierNode;
import org.apache.flex.compiler.internal.tree.as.LiteralNode;
import org.apache.flex.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.flex.compiler.internal.tree.as.ModifierNode;
import org.apache.flex.compiler.internal.tree.as.ModifiersContainerNode;
import org.apache.flex.compiler.internal.tree.as.NamespaceAccessExpressionNode;
import org.apache.flex.compiler.internal.tree.as.NamespaceNode;
import org.apache.flex.compiler.internal.tree.as.NodeBase;
import org.apache.flex.compiler.internal.tree.as.NumericLiteralNode;
import org.apache.flex.compiler.internal.tree.as.PackageNode;
import org.apache.flex.compiler.internal.tree.as.ParameterNode;
import org.apache.flex.compiler.internal.tree.as.ScopedBlockNode;
import org.apache.flex.compiler.internal.tree.as.TernaryOperatorNode;
import org.apache.flex.compiler.internal.tree.as.VariableNode;
import org.apache.flex.compiler.internal.tree.as.VectorLiteralNode;
import org.apache.flex.compiler.internal.tree.mxml.MXMLDocumentNode;

/**
 *  The MethodBodySemanticChecker contains the logic that checks method body semantics.
 */
public class MethodBodySemanticChecker
{
    /**
     *  The current LexicalScope for this compilation.
     */
    private LexicalScope currentScope;

    /**
     *  The current ICompilerProject for this compilation.
     */
    private final ICompilerProject project;

    /**
     *  Semantic utilities, which know how to interface with name resolution
     */
    private final SemanticUtils utils;


    /**
     *  Current state of diagnostics regarding "super" 
     */
    private enum SuperState { Invalid, Initial, Armed };

    /**
     *  Current state of diagnostics regarding "super" 
     */
    private SuperState superState = SuperState.Invalid;

    /**
     *  Construct a new MethodBodySemanticChecker from the current lexical scope.
     */
    public MethodBodySemanticChecker(LexicalScope current_scope)
    {
        this.currentScope = current_scope;
        this.project = currentScope.getProject();
        this.utils = new SemanticUtils(this.project);
    }

    /**
     * Do a semantic analysis of all the arguments of a function
     *
     * @param funcNode is the function to be analyzed
     */
    public void checkFunctionDecl(IFunctionNode funcNode )
    {
        IParameterNode[] paramNodes = funcNode.getParameterNodes();
        for (IParameterNode paramNode : paramNodes)
        {
            IDefinition paramDef = paramNode.getDefinition();

            ITypeDefinition paramTypeDef = ((IVariableDefinition)paramDef).resolveType(project);
            if (!SemanticUtils.isType(paramTypeDef) )
            {
                IExpressionNode typeExpression = paramNode.getVariableTypeNode();
                String typeName =  paramDef.getTypeAsDisplayString();
                addTypeProblem(typeExpression, paramTypeDef, typeName, true);
            }
        }
    }

    /**
     * Semantic analysis of a function declared inside another function.  This is only for function declarations,
     * and not function expressions.
     * @param funcNode  The node of the nested function
     */
    public void checkNestedFunctionDecl(IFunctionNode funcNode)
    {
        IFunctionDefinition funcDef = funcNode.getDefinition();
        List<IDefinition> defs = SemanticUtils.findPotentialFunctionConflicts(currentScope.getProject(), funcDef);

        // Check for potential dups - functions can be redeclared and won't be ambiguous, but in strict mode
        // we want to issue an error.
        // Don't need to worry about getter/setter pairs as you can't declare nested getter/setters
        if( defs.size() > 1 )
        {
            ICompilerProblem problem = new DuplicateFunctionDefinitionProblem(funcNode, funcDef.getBaseName());
            this.currentScope.addProblem(problem);
        }
    }

    /**
     *  Convenience method to add a problem.
     *  @param problem - the problem to add.
     */
    private void addProblem(ICompilerProblem problem)
    {
        //  Some of the "figure out this error scenario"
        //  methods pass in null to mean "ignore."
        if ( problem != null )
            this.currentScope.addProblem(problem);
    }

    /**
     *  Perform semantic checks on an assignment.
     */
    public void checkAssignment(IASNode iNode, Binding binding)
    {
        checkLValue(iNode, binding);

        if ( SemanticUtils.isUnprotectedAssignmentInConditional(iNode) )
            addProblem(new AssignmentInConditionalProblem(SemanticUtils.getNthChild(iNode, 0)));

        //  Check the assignment's type logic and values.
        ITypeDefinition leftType = null;
        if ( binding.getDefinition() != null )
        {
            IDefinition leftDef = binding.getDefinition();
            leftType = binding.getDefinition().resolveType(project);
            
            IASNode rightNode = SemanticUtils.getNthChild(iNode, 1);
       
            checkImplicitConversion(rightNode, leftType, null);
            checkAssignmentValue(leftDef, rightNode);
        }
    }
    
    /**
     * Checks that the value (RHS) is appropriate, given the type of the LHS
     * @param leftDefinition is the definition of the variable on the LHS
     * @param rightNode is the tree node for the RHS of the assignment
     */
    public void checkAssignmentValue( IDefinition leftDefinition, IASNode rightNode)
    {
        ITypeDefinition leftType = leftDefinition.resolveType(project);
        
        if (rightNode instanceof IExpressionNode)
        {
            IDefinition rightType = ((IExpressionNode)rightNode).resolveType(project);
            final boolean leftIsNumericOrBoolean = SemanticUtils.isNumericTypeOrBoolean(leftType, project);   
            final boolean rightIsNull =  SemanticUtils.isBuiltin(rightType, BuiltinType.NULL, project);
            
            if (leftIsNumericOrBoolean && rightIsNull)
            {
                final boolean leftIsConstant = leftDefinition instanceof IConstantDefinition;
                addProblem(leftIsConstant ?
                        new IncompatibleDefaultValueOfTypeNullProblem(rightNode, leftType.getBaseName()) :
                        new NullUsedWhereOtherExpectedProblem(rightNode, leftType.getBaseName()));
            }
        }
    }
    
    /**
     * Perform semantic checks on an initialization
     */
    public void checkInitialization(IASNode iNode, Binding binding)
    {
        //  Check the assignment's type logic.
        if ( binding.getDefinition() != null )
            checkImplicitConversion(SemanticUtils.getNthChild(iNode, 2), binding.getDefinition().resolveType(project), null);
    }
    
    /**
     *  Perform semantic checks on an x[i] = rvalue assignment expression.
     */
    public void checkAssignToBracketExpr(IASNode iNode)
    {
    }

    /**
     *  Check a binary operator.
     *  @param iNode - the operator node.
     *  @param opcode - the opcode.
     */
    public void checkBinaryOperator(IASNode iNode, int opcode)
    {
        final IASNode left = ((IBinaryOperatorNode)iNode).getLeftOperandNode();
        final IASNode right = ((IBinaryOperatorNode)iNode).getRightOperandNode();
        checkBinaryOperator(iNode, left, right, opcode);
    }

    /**
     *  Check a (possibly implicit) binary operator.
     *  @param root - the operator node.
     *  @param left - the left-hand operand.
     *  @param right - the right-hand operand.
     *  @param opcode - the opcode.
     */
    public void checkBinaryOperator(IASNode root, IASNode left, IASNode right, final int opcode)
    {
        switch(opcode)
        {
            case ABCConstants.OP_multiply:
            case ABCConstants.OP_divide:
            case ABCConstants.OP_modulo:
            case ABCConstants.OP_subtract:
            case ABCConstants.OP_lshift:
            case ABCConstants.OP_rshift:
            case ABCConstants.OP_urshift:
            case ABCConstants.OP_bitand:
            case ABCConstants.OP_bitor:
            case ABCConstants.OP_bitxor:
                checkImplicitConversion(left, utils.numberType(), null);
                checkImplicitConversion(right, utils.numberType(), null);
                break;

            case ABCConstants.OP_istypelate:
            case ABCConstants.OP_astypelate:
                checkTypeCheckImplicitConversion(right);
                break;
            case ABCConstants.OP_equals:
            case ABCConstants.OP_strictequals:
            case ABCConstants.OP_lessthan:
            case ABCConstants.OP_lessequals:
            case ABCConstants.OP_greaterthan:
            case ABCConstants.OP_greaterequals:

                if ((left instanceof IExpressionNode) && (right instanceof IExpressionNode))
                {
                    checkComparison((IExpressionNode)left, (IExpressionNode)right);
                }
                break;
            case ABCConstants.OP_instanceof:
                addProblem(new InstanceOfProblem(root));
                break;
        }
    }

    /**
     *  Check an implicit conversion.
     *  @param iNode - the expression being checked.
     *  @param expected_type - the type to convert to.
     */
    
    public void checkImplicitConversion(IASNode iNode, IDefinition expected_type, FunctionDefinition func)
    {
        if (iNode instanceof BinaryOperatorLogicalOrNode ||
             iNode instanceof BinaryOperatorLogicalAndNode ||
             iNode instanceof TernaryOperatorNode)
        {
            // For these logical nodes, just check both sides with a recursive call.
            // Note that we need to recurse, because this may be a tree of binary logical nodes
            final IExpressionNode leftOp = ((IBinaryOperatorNode)iNode).getLeftOperandNode();
            checkImplicitConversion(leftOp, expected_type, null);
            final IExpressionNode rightOp = ((IBinaryOperatorNode)iNode).getRightOperandNode();
            checkImplicitConversion(rightOp, expected_type, null);
        }

        else if (iNode instanceof ExpressionNodeBase)
        {
            checkImplicitConversion(iNode, ((ExpressionNodeBase)iNode).resolveType(project), expected_type, func);
        }
    }

    /**
     * Check an implicit conversion in an 'is' or 'as' binop
     * @param iNode - the expression being checked.
     */
    public void checkTypeCheckImplicitConversion(IASNode iNode)
    {
        if (!(iNode instanceof ExpressionNodeBase))
            return;

        final IDefinition actual_type = ((ExpressionNodeBase)iNode).resolveType(project);
        // expected type is always of type CLASS;
        final IDefinition expected_type = utils.getBuiltinType(BuiltinType.CLASS);

        if (!SemanticUtils.isValidTypeConversion(expected_type, actual_type, project, currentScope.getInInvisibleCompilationUnit()))
        {
            addProblem(new ImplicitTypeCheckCoercionToUnrelatedTypeProblem(iNode, actual_type.getBaseName(), expected_type.getBaseName()));
        }
        else
        {
            SpecialValue value = getSpecialValue((IExpressionNode)iNode);
            if (value == SpecialValue.UNDEFINED) // test for undefined
            {
                addProblem(new ImplicitTypeCheckCoercionToUnrelatedTypeProblem(iNode, IASLanguageConstants.UNDEFINED, expected_type.getBaseName()));                
            }
            else if (iNode instanceof LiteralNode && IASKeywordConstants.NULL.equals(((LiteralNode)iNode).getValue())) // test for null
            {
                addProblem(new ImplicitTypeCheckCoercionToUnrelatedTypeProblem(iNode, IASKeywordConstants.NULL, expected_type.getBaseName()));
            }
        }
    }

    enum SpecialValue { NONE, NAN, UNDEFINED }
    SpecialValue getSpecialValue(IExpressionNode node)
    {
        SpecialValue ret = SpecialValue.NONE;
        IDefinition def = node.resolve(project);
        
        if (def instanceof IConstantDefinition)
        {
            // it's easy to find the word "undefined", just compare to the
            // singleton definition
            if (def == project.getUndefinedValue())
            {
                ret = SpecialValue.UNDEFINED;
            }
            else
            {
                Object initialValue = ((ConstantDefinition) def).resolveValueFrom(project, (NodeBase)node);
                if (initialValue != null)
                {
                    if (initialValue instanceof Double)
                    {
                        Double d = (Double)initialValue;
                        if (ECMASupport.isNan(d))
                            ret = SpecialValue.NAN;
                    }
                }
            }
        }
        return ret;
    }
    
    /**
     * determine if it is reasonable to compare two operands of perhaps different types.
     * Create a CompilerProblem if not.
     * 
     */
    private void checkComparison(IExpressionNode leftNode, IExpressionNode rightNode)
    {
        SpecialValue leftValue = getSpecialValue(leftNode);
        SpecialValue rightValue = getSpecialValue(rightNode);
        
        if (leftValue == SpecialValue.NAN || rightValue == SpecialValue.NAN)
        {
           addProblem( new IllogicalComparionWithNaNProblem(leftNode));
        }
        
       
        
        IDefinition left_type = leftNode.resolveType(project);
        IDefinition right_type = rightNode.resolveType(project);
        
        if (left_type==null || right_type==null)
        {
            return; // if we can't resolve both side, some other check will catch it.
        }
        
       
        final IDefinition anyType = project.getBuiltinType(BuiltinType.ANY_TYPE);
        if (rightValue == SpecialValue.UNDEFINED && !left_type.equals(anyType))
        {
           addProblem(new IllogicalComparisonWithUndefinedProblem(leftNode));
        }
        
        if (leftValue == SpecialValue.UNDEFINED && !right_type.equals(anyType))
        {
           addProblem(new IllogicalComparisonWithUndefinedProblem(rightNode));
        }
        // Harmless pre-optimizition. If both types are the same they must be comparable.
        // (but only after we have checked special value cases above.
        if (left_type.equals(right_type))
        {
            return;
        }
        
        final boolean leftIsNumeric = SemanticUtils.isNumericType(left_type, project);
        final boolean rightIsNumeric = SemanticUtils.isNumericType(right_type, project);
        final boolean leftIsNull =  SemanticUtils.isBuiltin(left_type, BuiltinType.NULL, project);
        final boolean rightIsNull =  SemanticUtils.isBuiltin(right_type, BuiltinType.NULL, project);
        
        // Interfaces can be compared against any Object
        if ((left_type instanceof IInterfaceDefinition && !rightIsNumeric) ||
                ( right_type instanceof IInterfaceDefinition && !leftIsNumeric))
        {
            return;
        }
        
         
        boolean isBad = false;
        
        // Numeric types can never be null
        if ((leftIsNumeric&&rightIsNull) || (rightIsNumeric&&leftIsNull))
        {
            isBad = true;
        }
        
        // If all the speical cases have passed, the try isValidTypeConversion in both directions.
        if (!isBad)
        {
            if (SemanticUtils.isValidTypeConversion(left_type, right_type, project, this.currentScope.getInInvisibleCompilationUnit()))
                return;
            if (SemanticUtils.isValidTypeConversion(right_type, left_type, project, this.currentScope.getInInvisibleCompilationUnit()))
                return;
        }
        
        addProblem(new ComparisonBetweenUnrelatedTypesProblem(leftNode, left_type.getBaseName(), right_type.getBaseName()));
    }

    /**
     *  Check a compound assignment.
     *  @param iNode - the node at the root of the assignment subtree.
     *  @param lvalue - the resolved lvalue (which is also an implicit rvalue).
     *  @param opcode - the opcode of the implied binary operator.
     */
    public void checkCompoundAssignment(IASNode iNode, Binding lvalue, final int opcode)
    {
        ICompoundAssignmentNode compoundNode = (ICompoundAssignmentNode)iNode;
        IBinaryOperatorNode  binop = (IBinaryOperatorNode)iNode;

        checkLValue(iNode, lvalue);

        if ( SemanticUtils.isUnprotectedAssignmentInConditional(iNode) )
            addProblem(new AssignmentInConditionalProblem(binop.getLeftOperandNode()));

        //  Check the implicit binary operator.
        checkBinaryOperator(iNode, binop.getLeftOperandNode(), binop.getRightOperandNode(), opcode);

        //  Check the assignment's types are compatible.
        if ( lvalue.getDefinition() != null )
        {
            //  Do own checks, then call common logic to emit diagnostics.
            ITypeDefinition lhsType = lvalue.getDefinition().resolveType(this.project);
            ITypeDefinition compoundType = compoundNode.resolveTypeOfRValue(this.project);

            if ( ! SemanticUtils.isValidImplicitOpAssignment(lhsType, compoundType, opcode, this.project, this.currentScope.getInInvisibleCompilationUnit()) )
            {
                checkImplicitConversion(binop.getRightOperandNode(), lhsType, null);
            }
            else if ( opcode == ABCConstants.OP_iffalse || opcode == ABCConstants.OP_iftrue )
            {
                //  check the RHS type of a logical operation on its own;
                //  this is rather strange behavior, but it replicates ASC's logic.
                checkImplicitConversion(binop.getRightOperandNode(), lhsType, null);
            }
        }
    }

    /**
     *  Check an implicit conversion.
     *  @param actual_type   - the type of the expression being checked.
     *  @param expected_type - the type to convert to.
     */
    private void checkImplicitConversion(IASNode iNode, IDefinition actual_type, IDefinition expected_type, FunctionDefinition func)
    {
        if ( !SemanticUtils.isValidTypeConversion(expected_type, actual_type, this.project, this.currentScope.getInInvisibleCompilationUnit()) )
        {
            if (project.isValidTypeConversion(iNode, actual_type, expected_type, func))
                return;
            
            // If we're assigning to a class, this will generate an "Illegal assignment to class" error,
            // so we don't need another error for implicit coercion
            if( !(expected_type instanceof ClassTraitsDefinition) )
            {
                if ( utils.isInstanceOf(expected_type, actual_type) )
                {
                    addProblem(new ImplicitCoercionToSubtypeProblem(iNode, actual_type.getBaseName(), expected_type.getBaseName()));
                }
                else
                {
                    addProblem(new ImplicitCoercionToUnrelatedTypeProblem(iNode, actual_type.getBaseName(), expected_type.getBaseName()));
                }
            }
        }
    }

    /**
     * Check if we are allowed to declare a bindable variable at this location.
     */
    public void checkBindableVariableDeclaration(IASNode iNode, IDefinition d)
    {

        assert d != null;

        if( !(d.getParent() instanceof IClassDefinition))
        {
            this.currentScope.addProblem(new LocalBindablePropertyProblem(iNode));
        }
    }
    
    /**
     * Check a constant value used in a non-initializer context.
     */
    public void checkConstantValue(IASNode iNode)
    {
        // Check for a node resolving to a deprecated constant definition.
        if (iNode instanceof IExpressionNode)
        {
            IDefinition definition = ((IExpressionNode)iNode).resolve(project);
            checkDeprecated(iNode, definition);
        }
    }

    /**
     *  Check that a synthetic super() call is allowed by the class' superclass.
     */
    public void checkDefaultSuperCall(IASNode iNode)
    {
        //  This occurs in some error cases.
        if ( iNode == null )
            return;

        ClassNode enclosing_class = (ClassNode) iNode.getAncestorOfType(ClassNode.class);

        if ( enclosing_class != null )
        {
            IClassDefinition super_def = enclosing_class.getDefinition().resolveBaseClass(project);
            if (super_def != null)
            {
                IFunctionDefinition ctor = super_def.getConstructor();

                if (ctor instanceof FunctionDefinition)
                {
                    FunctionDefinition func = (FunctionDefinition)ctor;
                    if (func.getParameters() != null && func.getParameters().length != 0)
                    {
                        ParameterDefinition first_param = func.getParameters()[0];

                        if ( !first_param.hasDefaultValue() && ! first_param.isRest() )
                        {
                            if ( enclosing_class.getDefinition().getConstructor().isImplicit()) {
                                //in this case the Error reporting site should point to the class node,
                                //because there is no 'real' constructor node to reference in the source code
                                addProblem(new NoDefaultConstructorInBaseClassProblem(enclosing_class, super_def.getBaseName()));
                            }
                            else addProblem(new NoDefaultConstructorInBaseClassProblem(iNode, super_def.getBaseName()));
                        }
                    }
                }
            }
        }
    }
    
    /**
     *  Perform semantic checks on a delete expression.
     */
    public void checkDeleteExpr(IASNode iNode, Binding binding)
    {
        IDefinition def = binding.getDefinition();

        if (def != null)
        {
            // If we can resolve to a definition, check to be sure we are not trying
            // to delete a non-dynamic properly
            if (!(utils.hasDynamicBase(binding) || SemanticUtils.isInWith(iNode)))
                addProblem(new AttemptToDeleteFixedPropertyProblem(iNode, binding.getName()));
        }
        else if (SemanticUtils.hasBaseNode(binding) && !utils.hasDynamicBase(binding))
        {
            // If we are trying to delete a member of a class, but the member doesn't exists,
            // The log the problem for that
            addProblem(new AccessUndefinedMemberProblem(
                    roundUpUsualSuspects(binding, iNode),
                    binding.getName().getBaseName(),
                    utils.getTypeOfBase(binding.getNode())));
        }
        else
        {
            // This checked knows about packages and undefined properties,
            // could use the more specific  
            //     addProblem(accessUndefinedProperty(binding, roundUpUsualSuspects(binding, iNode)));
            checkLValue(iNode, binding);
        }
    }

    /**
     *  Check a super() or super(a,b,c) call.
     */
    public void checkExplicitSuperCall(IASNode iNode, Vector<? extends Object> args)
    {
        LanguageIdentifierNode super_node = (LanguageIdentifierNode)((IFunctionCallNode)iNode).getNameNode();

        //  Check that this super() call is in a constructor.
        if ( !SemanticUtils.isInConstructor(iNode) )
        {
            addProblem(new InvalidSuperStatementProblem(iNode));
        }
        else
        {
            //  Check that this super call does not follow a construct
            //  that invalidates it.
            if ( this.superState != SuperState.Initial )
                addProblem(new ExtraneousSuperStatementProblem(iNode));
            else
                this.superState = SuperState.Armed;
        }

        //  Check parameters if possible.
        ClassDefinition super_def = (ClassDefinition) super_node.resolveType(project);

        if (super_def != null)
        {
            IFunctionDefinition ctor = super_def.getConstructor();

            if (ctor instanceof FunctionDefinition)
            {
                checkFormalsVsActuals(super_node, (FunctionDefinition)ctor, args);
            }
        }
    }

    /**
     *  Check that formal and actual parameters correspond and are compatible.
     */
    private void checkFormalsVsActuals(IASNode iNode, FunctionDefinition func, Vector<? extends Object> actuals)
    {

        //  If the call is through a function variable then we don't know much about it.
        //  If we get a setter function assume a getter is what was meant since calling a setter
        //  directly is not legal and resolving the name for a getter/setter could
        //  return either. Code generation does the right thing so changing this check
        //  to just return for setters as well.
        if ( func instanceof GetterDefinition || func instanceof SetterDefinition)
            return;

        //  Check the formal parameter definitions, and ensure we have
        //  a corresponding number of actual parameters.
        ParameterDefinition[] formals = func.getParameters();

        if ( formals == null )
            return;
        
        boolean last_is_rest   = formals.length > 0 && formals[formals.length - 1].isRest();

        int required_count = 0;

        if ( actuals.size() > formals.length && !last_is_rest )
        {
            addProblem(new TooManyFunctionParametersProblem(iNode, formals.length));
        }

        //  Compute the number of required parameters.
        for ( int i = 0; i < formals.length; i++ )
        {
            if ( formals[i].hasDefaultValue() || formals[i].isRest() )
                break;

            required_count++;
        }

        if ( actuals.size() < required_count )
        {
            addProblem(new TooFewFunctionParametersProblem(iNode, required_count));
        }

        //  Check that the actuals are compatible with the formals.
        IASNode actuals_container = null;
        if( iNode instanceof FunctionCallNode )
            actuals_container = ((FunctionCallNode)iNode).getArgumentsNode();

        if ( actuals_container != null )
        {
            for ( int i = 0; i < actuals_container.getChildCount() && i < formals.length; i++ )
            {
                if ( !formals[i].isRest() )
                    checkImplicitConversion( actuals_container.getChild(i), formals[i].resolveType(project), func );
            }
        }
    }

    /**
     *  Check a function body's overall characteristics.
     */
    public void checkFunctionBody(IASNode iNode)
    {
        if ( iNode instanceof FunctionNode )
        {
            FunctionNode func = (FunctionNode)iNode;

            IDefinition def = func.getDefinition();

            if ( !( def.hasModifier(ASModifier.NATIVE ) || def.hasModifier(ASModifier.DYNAMIC) || func.isConstructor() ) )
            {
                if ( !func.hasBody() )
                {
                    addProblem(new FunctionWithoutBodyProblem(SemanticUtils.getFunctionProblemNode(func)));
                }
            }
        }
    }

    public void checkNativeMethod(IASNode iNode)
    {
        if( iNode instanceof FunctionNode )
        {
            if ( ((FunctionNode)iNode).hasBody() )
            {
                addProblem(new NativeMethodWithBodyProblem(iNode));
            }
        }
    }


    /**
     *  Check a function call.
     */
    public void checkFunctionCall(IASNode iNode, Binding method_binding, Vector<? extends Object>actuals)
    {
        //  Skip synthetic calls.
        if ( method_binding.getName() == null )
            return;

        //  Check for calls to attributes.
        if ( method_binding.getName().isAttributeName() )
        {
            addProblem(new AttributesAreNotCallableProblem(roundUpUsualSuspects(method_binding, iNode)));
        }

        IDefinition def = method_binding.getDefinition();

        if ( def == null && utils.definitionCanBeAnalyzed(method_binding) )
        {
            if ( utils.isInaccessible(iNode, method_binding) )
            {
                addProblem(new InaccessibleMethodReferenceProblem( 
                    roundUpUsualSuspects(method_binding, iNode), 
                    method_binding.getName().getBaseName(),
                    utils.getTypeOfStem(iNode)
                ));
            }
            else if ( SemanticUtils.hasExplicitStem(iNode) && utils.hasUnderlyingType(iNode) )
            {
                addProblem(new StrictUndefinedMethodProblem( 
                    roundUpUsualSuspects(method_binding, iNode), 
                    method_binding.getName().getBaseName(),
                    utils.getTypeOfStem(iNode)
                ));
            }
            else
            {
                addProblem(new CallUndefinedMethodProblem( 
                    roundUpUsualSuspects(method_binding, iNode), 
                    method_binding.getName().getBaseName()
                ));
            }
        }
        else if ( def instanceof FunctionDefinition )
        {
            FunctionDefinition func = (FunctionDefinition)def;
            checkFormalsVsActuals(iNode, func, actuals);
        }
        else if ( def instanceof VariableDefinition )
        {
            VariableDefinition varDef = (VariableDefinition)def;
            IDefinition varType = varDef.resolveType(project);
            if (varType != null && // Null here means the ANY_TYPE
                    (varType.equals(project.getBuiltinType(BuiltinType.NUMBER)) ||
                    varType.equals(project.getBuiltinType(BuiltinType.BOOLEAN)) ||
                    varType.equals(project.getBuiltinType(BuiltinType.INT)) ||
                    varType.equals(project.getBuiltinType(BuiltinType.UINT)) ||
                    varType.equals(project.getBuiltinType(BuiltinType.STRING))))
            {
                addProblem(new CallNonFunctionProblem(iNode, method_binding.getName().getBaseName()));
            }
        }
        else if ( def == project.getBuiltinType(BuiltinType.ARRAY) )
        {
            // Warn about calling Array as a function because developers
            // may not understand that this always creates a new array.
            // The warning is different when there is one argument
            // of type Array, Object, or *; in that case developers
            // may think they are downcasting.
            boolean downcast = false;
            if (actuals.size() == 1)
            {
                IExpressionNode argument = ((IFunctionCallNode)iNode).getArgumentNodes()[0];
                IDefinition argumentType = argument.resolveType(project);
                
                if (argumentType == null || // Null here means the ANY_TYPE
                    argumentType.equals(project.getBuiltinType(BuiltinType.ARRAY)) ||
                    argumentType.equals(project.getBuiltinType(BuiltinType.OBJECT)) ||
                    argumentType.equals(project.getBuiltinType(BuiltinType.ANY_TYPE)))
                {
                     downcast = true;
                }
            }
            if (downcast)
                addProblem(new ArrayDowncastProblem(iNode));
            else
                addProblem(new ArrayCastProblem(iNode));
        }
        else if (def != null &&
                 // If def is an AmbiguousDefinition,
                 // getQualifiedName() will throw an exception.
                 !AmbiguousDefinition.isAmbiguous(def) &&
                 def.getQualifiedName().equals(IASLanguageConstants.Date))
        {
            if (actuals.size() > 0)
                addProblem(new DateCastProblem(iNode));
        }
        else if ( def instanceof ITypeDefinition )
        {
            // We've already handled the special cases of Array(...) and Date(...)
            // For other cast-like calls, there should be one and only one parameter.
            switch ( actuals.size() )
            {
                case 0:
                {
                        addProblem(new TooFewFunctionParametersProblem(iNode, 1));
                    break;
                    }
                case 1:
                {
                    //  Correct number of parameters.
                        break;
                }
                default:
                {
                    addProblem(new TooManyFunctionParametersProblem(iNode, 1));
                    break;
            }
        }
        }
        checkReference(method_binding);
    }

    /**
     *  Check a function definition.
     *  @param iNode - the top-level definition node.
     *  @param def - the function's definition.
     */
    public void checkFunctionDefinition(IFunctionNode iNode, FunctionDefinition def )
    {
        SemanticUtils.checkReturnValueHasNoTypeDeclaration(this.currentScope, iNode, def);
        
        if (SemanticUtils.isInFunction(iNode))
        {
            if (iNode instanceof BaseDefinitionNode)
                checkForNamespaceInFunction((BaseDefinitionNode)iNode, currentScope);
        }
        ParameterDefinition[] formals = def.getParameters();

        if ( formals == null )
            return;

        boolean found_optional = false;

        for ( int i = 0; i < formals.length; i++ )
        {
            //  Check the structure of the formals; 
            //  required parameters, then optionals,
            //  then the rest parameter, if present.
            if ( formals[i].hasDefaultValue() )
            {
                found_optional = true;
                if( def instanceof ISetterDefinition )
                {
                    addProblem(new SetterCannotHaveOptionalProblem(formals[i].getNode()));
                }
            }
            else if ( formals[i].isRest() )
            {
                if ( i != formals.length -1 )
                    addProblem(new RestParameterMustBeLastProblem(formals[i].getNode()));
                // TODO: Add a check for kError_InvalidRestDecl once CMP-279 is fixed.
            }
            else
            {
                if ( found_optional )
                {
                    addProblem(new RequiredParameterAfterOptionalProblem(formals[i].getNode()));
                }
            }

        }

        //  Check the return type.
        TypeDefinitionBase return_type = (TypeDefinitionBase)def.resolveReturnType(project);
        if ( return_type == null )
        {
            //  Error already emitted.
        }
        // Setter return type can only be 'void' or '*'
        else if( def instanceof ISetterDefinition &&
                // Error says return type must be void, but ASC allows '*' as well
                (return_type != project.getBuiltinType(BuiltinType.VOID) &&
                 return_type != project.getBuiltinType(BuiltinType.ANY_TYPE)) )
        {
            addProblem(new BadSetterReturnTypeProblem(iNode.getReturnTypeNode()));
        }

        if( def instanceof IAccessorDefinition )
        {
            IAccessorDefinition accessorDef = (IAccessorDefinition)def;
            ITypeDefinition thisType = accessorDef.resolveType(project);
            IAccessorDefinition other = null;
            if( (other = accessorDef.resolveCorrespondingAccessor(project)) != null)
            {
                ITypeDefinition otherType = other.resolveType(project);
                
                IDefinition anyType = project.getBuiltinType(BuiltinType.ANY_TYPE);

                if( otherType != thisType
                        // Don't complain if one of the types is '*'
                        && otherType != anyType && thisType != anyType )
                {
                    addProblem(new AccessorTypesMustMatchProblem(getAccessorTypeNode(iNode)));
                }
            }
            if( def instanceof IGetterDefinition )
            {
                if (formals.length > 0 )
                {
                    addProblem(new GetterCannotHaveParametersProblem(formals[0].getNode()));
                }
                
                if (SemanticUtils.isBuiltin(thisType, BuiltinType.VOID, project))
                {
                    addProblem( new GetterMustNotBeVoidProblem(iNode.getReturnTypeNode()));
                }
            }
       
            if( def instanceof ISetterDefinition )
            {
                if( formals.length != 1 )
                {
                    addProblem(new SetterMustHaveOneParameterProblem(iNode.getNameExpressionNode()));
                }
            }
        }

        checkNamespaceOfDefinition(iNode, def, project);
    }

    /**
     * Helper to get the node to report a problem with the "type" of a getter/setter.  Will return the
     * return type node for a setter, or the first parameter node for a getter, or the name node of the
     * accessor if the return type or parameter does not exist
     */
    private IASNode getAccessorTypeNode(IFunctionNode iNode)
    {
        IASNode result = iNode.getNameExpressionNode();
        if( iNode.isSetter() )
        {
            IExpressionNode returnType = iNode.getReturnTypeNode();
            if( returnType != null )
                result = returnType;
        }
        else if( iNode.isGetter() )
        {
            IParameterNode[] params = iNode.getParameterNodes();
            if( params != null && params.length > 0)
                result = params[0];
        }
        return result;
    }

    /**
     *  Check a simple name reference.
     */
    public void checkSimpleName(IASNode iNode, Binding binding)
    {
        if ( SemanticUtils.isThisKeyword(iNode) )
        {
           LanguageIdentifierNode.Context context = ((LanguageIdentifierNode)iNode).getContext();

           if ( context == LanguageIdentifierNode.Context.STATIC_CONTEXT || context == LanguageIdentifierNode.Context.PACKAGE_CONTEXT)
           {
               addProblem(new ThisUsedInStaticFunctionProblem(iNode));
           }
        }
        else if ( SemanticUtils.isArgumentsReference(binding) )
        {
            FunctionDefinition functionDef = SemanticUtils.getFunctionDefinition(iNode);
            if (functionDef != null)
            {
                ParameterDefinition[] parameters = functionDef.getParameters();
                for (ParameterDefinition param : parameters)
                {
                    if (param.isRest())
                    {
                        addProblem(new RestParamAndArgumentsUsedTogetherProblem(iNode));
                        break;
                    }
                }
            }
        }

        if( binding.getDefinition() == null && isPackageReference(binding) )
        {
            // A simple name only counts as a package reference if it did not resolve to anything
            addProblem(new PackageCannotBeUsedAsValueProblem(iNode, binding.getName().getBaseName()));
        }
    }

    /**
     * Translate a {@link PooledValue} into a {@link BuiltinType}.
     * @param value The {@link PooledValue} to translate.
     * @return The {@link BuiltinType} for the specified {@link PooledValue}.
     */
    private static BuiltinType getBuiltinTypeOfPooledValue(PooledValue value)
    {
        switch ( value.getKind() )
        {
            case ABCConstants.CONSTANT_Int:
                return BuiltinType.INT;
            case ABCConstants.CONSTANT_UInt:
                return BuiltinType.UINT;
            case ABCConstants.CONSTANT_Double:
                return BuiltinType.NUMBER;
            case ABCConstants.CONSTANT_Utf8:
                return BuiltinType.STRING;
            case ABCConstants.CONSTANT_True:
            case ABCConstants.CONSTANT_False:
                return BuiltinType.BOOLEAN;
            case ABCConstants.CONSTANT_Undefined:
                return BuiltinType.VOID;
            case ABCConstants.CONSTANT_Null:
                return BuiltinType.NULL;
            case ABCConstants.CONSTANT_Namespace:
            case ABCConstants.CONSTANT_PrivateNs:
            case ABCConstants.CONSTANT_PackageNs:
            case ABCConstants.CONSTANT_PackageInternalNs:
            case ABCConstants.CONSTANT_ProtectedNs:
            case ABCConstants.CONSTANT_ExplicitNamespace:
            case ABCConstants.CONSTANT_StaticProtectedNs:
                return BuiltinType.NAMESPACE;
            default:
                assert false : "Unknown default value kind " + value.getKind();
        }
        return BuiltinType.ANY_TYPE;
    }
    
    /**
     *  Translate a {@link PooledValue} into an {@link IDefinition} type.
     *  @return the {@link IDefinition} for the value's type.
     */
    private IDefinition getTypeOfPooledValue(PooledValue value)
    {
        BuiltinType builtinType = getBuiltinTypeOfPooledValue(value);

        return utils.getBuiltinType(builtinType);
    }

    /**
     * Helper method called by
     * {@link #checkInitialValue(IVariableNode, Binding, PooledValue)}.
     * <p>
     * Conversion rules:
     * <table>
     * <tr>
     * <td></td>
     * <td>*</td>
     * <td>Object</td>
     * <td>void</td>
     * <td>Array</td>
     * <td>XML</td>
     * <td>Function</td>
     * <td>Class</td>
     * <td>String</td>
     * <td>Boolean</td>
     * <td>Number</td>
     * <td>uint</td>
     * <td>int</td>
     * </tr>
     * <tr>
     * <td>CONSTANT_Int</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>Error/transform to null</td> <!-- Array -->
     * <td>Error/transform to null</td> <!-- XML -->
     * <td>Error/transform to null</td> <!-- Function -->
     * <td>Error/transform to null</td> <!-- Class -->
     * <td>Error/coerce to string</td> <!-- String -->
     * <td>Error/coerce to Boolean</td> <!-- Boolean -->
     * <td>No Error</td> <!-- Number -->
     * <td>If negative error and coerce otherwise no error</td> <!-- uint -->
     * <td>-</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_UInt</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>Error/transform to null</td> <!-- Array -->
     * <td>Error/transform to null</td> <!-- XML -->
     * <td>Error/transform to null</td> <!-- Function -->
     * <td>Error/transform to null</td> <!-- Class -->
     * <td>Error/coerce to string</td> <!-- String -->
     * <td>Error/coerce to Boolean</td> <!-- Boolean -->
     * <td>No Error</td> <!-- Number -->
     * <td>-</td> <!-- uint -->
     * <td>Error/coerce if not an integer in int range</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_Double</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>Error/transform to null</td> <!-- Array -->
     * <td>Error/transform to null</td> <!-- XML -->
     * <td>Error/transform to null</td> <!-- Function -->
     * <td>Error/transform to null</td> <!-- Class -->
     * <td>Error/coerce to string</td> <!-- String -->
     * <td>Error/coerce to Boolean</td> <!-- Boolean -->
     * <td>-</td> <!-- Number -->
     * <td>Error/coerce if not a positive error in uint range</td> <!-- uint -->
     * <td>Error/coerce if not an integer in int range</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_Utf8</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>Error/transform to null</td> <!-- Array -->
     * <td>Error/transform to null</td> <!-- XML -->
     * <td>Error/transform to null</td> <!-- Function -->
     * <td>Error/transform to null</td> <!-- Class -->
     * <td>-</td> <!-- String -->
     * <td>Error/coerce to Boolean</td> <!-- Boolean -->
     * <td>Error/coerce to Number</td> <!-- Number -->
     * <td>Error/coerce to uint</td> <!-- uint -->
     * <td>Error/coerce to int</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_True</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>Error/transform to null</td> <!-- Array -->
     * <td>Error/transform to null</td> <!-- XML -->
     * <td>Error/transform to null</td> <!-- Function -->
     * <td>Error/transform to null</td> <!-- Class -->
     * <td>Error/coerce to string</td> <!-- String -->
     * <td>-</td> <!-- Boolean -->
     * <td>Error/coerce to Number</td> <!-- Number -->
     * <td>Error/coerce to uint</td> <!-- uint -->
     * <td>Error/coerce to int</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_False</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>Error/transform to null</td> <!-- Array -->
     * <td>Error/transform to null</td> <!-- XML -->
     * <td>Error/transform to null</td> <!-- Function -->
     * <td>Error/transform to null</td> <!-- Class -->
     * <td>Error/coerce to string</td> <!-- String -->
     * <td>-</td> <!-- Boolean -->
     * <td>Error/coerce to Number</td> <!-- Number -->
     * <td>Error/coerce to uint</td> <!-- uint -->
     * <td>Error/coerce to int</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_Undefined</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>No error</td> <!-- Array -->
     * <td>No error</td> <!-- XML -->
     * <td>No error</td> <!-- Function -->
     * <td>No error</td> <!-- Class -->
     * <td>No error</td> <!-- String -->
     * <td>No error</td> <!-- Boolean -->
     * <td>No error</td> <!-- Number -->
     * <td>No error</td> <!-- uint -->
     * <td>No error</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_Null</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>No error</td> <!-- Array -->
     * <td>No error</td> <!-- XML -->
     * <td>No error</td> <!-- Function -->
     * <td>No error</td> <!-- Class -->
     * <td>No error</td> <!-- String -->
     * <td>Error/coerce to Boolean</td> <!-- Boolean -->
     * <td>Error/coerce to Number</td> <!-- Number -->
     * <td>Error/coerce to uint</td> <!-- uint -->
     * <td>Error/coerce to int</td> <!-- int -->
     * </tr>
     * <tr>
     * <td>CONSTANT_Namespace, CONSTANT_*Ns</td>
     * <td>No error</td> <!-- * -->
     * <td>No error</td> <!-- Object -->
     * <td>No error</td> <!-- void -->
     * <td>Error/transform to null</td> <!-- Array -->
     * <td>Error/transform to null</td> <!-- XML -->
     * <td>Error/transform to null</td> <!-- Function -->
     * <td>Error/transform to null</td> <!-- Class -->
     * <td>Error/transform to null</td> <!-- String -->
     * <td>Error/transform to true</td> <!-- Boolean -->
     * <td>Error/transform to 0</td> <!-- Number -->
     * <td>Error/transform to 0</td> <!-- uint -->
     * <td>Error/transform to 0</td> <!-- int -->
     * </tr>
     * <tr>
     * </table>
     * 
     * @param initial_value_location The {@link ISourceLocation} for the
     * variable's initializer expression.
     * @param desired_type {@link IDefinition} that the initial value's type
     * should be compatible with.
     * @param initial_value {@link PooledValue} containing the constant
     * initializer for the variable.
     * @return A {@link PooledValue} whose type is compatible with desired_type.
     */
    private PooledValue checkInitialValue(ISourceLocation initial_value_location, IDefinition desired_type, PooledValue initial_value)
    {
        IDefinition value_type = getTypeOfPooledValue(initial_value);
        if  (desired_type == null ||
             desired_type.equals(value_type) ||
             utils.isInstanceOf(value_type, desired_type))
        {
            return initial_value;
        }
        else if (utils.isBuiltin(desired_type, BuiltinType.OBJECT) ||
                 utils.isBuiltin(desired_type, BuiltinType.ANY_TYPE))
        {
            return initial_value;
        }
        else if (utils.isBuiltin(value_type, BuiltinType.VOID))
        {
            return initial_value;
        }
        else if (
            utils.isBuiltin(desired_type, BuiltinType.ARRAY) ||
            utils.isBuiltin(desired_type, BuiltinType.XML) ||
            utils.isBuiltin(desired_type, BuiltinType.FUNCTION) ||
            utils.isBuiltin(desired_type, BuiltinType.CLASS)
            )
        {
            if (utils.isBuiltin(value_type, BuiltinType.NULL))
                return initial_value;
            addProblem(new IncompatibleInitializerTypeProblem(initial_value_location, value_type.getBaseName(), desired_type.getBaseName(), "null"));
            // transform initial_value to null.
            return new PooledValue(ABCConstants.NULL_VALUE);
        }
        else if (utils.isBuiltin(desired_type, BuiltinType.STRING))
        {
            assert !(utils.isBuiltin(value_type, BuiltinType.STRING));
            if (utils.isBuiltin(value_type, BuiltinType.NULL))
                return initial_value;
            String initial_value_string = ECMASupport.toString(initial_value.getValue());
            String initial_value_quoted = "\"" + initial_value_string + "\"";
            addProblem(new IncompatibleInitializerTypeProblem(initial_value_location, value_type.getBaseName(), desired_type.getBaseName(), initial_value_quoted));
            // transform initial_value to a string constant.
            return new PooledValue(initial_value_string);
        }
        else if (utils.isBuiltin(desired_type, BuiltinType.BOOLEAN))
        {
            assert !(utils.isBuiltin(value_type, BuiltinType.BOOLEAN));
            // transform initial_value to a boolean constant.
            boolean initial_value_boolean = ECMASupport.toBoolean(initial_value.getValue());
            // tell the programmer about the transformation we did.
            addProblem(new IncompatibleInitializerTypeProblem(initial_value_location, value_type.getBaseName(), desired_type.getBaseName(), String.valueOf(initial_value_boolean)));
            return new PooledValue(initial_value_boolean);
                
        }
        else if (utils.isBuiltin(desired_type, BuiltinType.NUMBER))
        {
            if (utils.isBuiltin(value_type, BuiltinType.INT) ||
                utils.isBuiltin(value_type, BuiltinType.UINT) ||
                utils.isBuiltin(value_type, BuiltinType.NUMBER))
                return initial_value;
            Number initial_value_numeric = ECMASupport.toNumeric(initial_value.getValue());
            double initial_value_double = initial_value_numeric != null ? initial_value_numeric.doubleValue() : 0;
            addProblem(new IncompatibleInitializerTypeProblem(initial_value_location, value_type.getBaseName(), desired_type.getBaseName(), String.valueOf(initial_value_double)));
            return new PooledValue(initial_value_double);
        }
        else if (utils.isBuiltin(desired_type, BuiltinType.UINT))
        {
            return checkInitialUIntValue(initial_value_location, desired_type, initial_value, value_type);
        }
        else if (utils.isBuiltin(desired_type, BuiltinType.INT))
        {
            return checkInitialIntValue(initial_value_location, desired_type, initial_value, value_type);
        }
        
        addProblem(new IncompatibleInitializerTypeProblem(initial_value_location, value_type.getBaseName(), desired_type.getBaseName(), "null"));
        return new PooledValue(ABCConstants.NULL_VALUE);
    }

    /**
     * Helper method called by
     * {@link #checkInitialValue(ISourceLocation, IDefinition, PooledValue)}.
     * 
     * @param initial_value_location The {@link ISourceLocation} for the
     * variable's initializer expression.
     * @param desired_type {@link IDefinition} that the initial value's type
     * should be compatible with. This should always by the {@link IDefinition}
     * for int. This is passed in as a convenience.
     * @param initial_value {@link PooledValue} containing the constant
     * initializer for the variable.
     * @param value_type {@link IDefinition} for the type of value contained by
     * the specified {@link PooledValue}.
     * @return A {@link PooledValue} whose type is compatible with desired_type.
     */
    private PooledValue checkInitialIntValue(ISourceLocation initial_value_location, IDefinition desired_type, PooledValue initial_value, IDefinition value_type)
    {
        assert !(utils.isBuiltin(value_type, BuiltinType.INT));
        if (utils.isBuiltin(value_type, BuiltinType.UINT))
        {
            long initial_value_long = initial_value.getLongValue();
            if (initial_value_long > Integer.MAX_VALUE)
                return addIntOutOfRangeProblem(initial_value_location, desired_type, initial_value_long);
            else
                return initial_value;
        }
        else if (utils.isBuiltin(value_type, BuiltinType.NUMBER))
        {
            double initial_value_double = initial_value.getDoubleValue();
            double initial_value_rounded = ECMASupport.toInteger(initial_value_double);
            int initial_value_int = ECMASupport.toInt32(initial_value_double);
            if (initial_value_rounded != initial_value_double)
            {
                addProblem(new InitializerValueNotAnIntegerProblem(
                        initial_value_location,
                        desired_type.getBaseName(),
                        String.valueOf(initial_value_double), String.valueOf(initial_value_int)));
                return new PooledValue(initial_value_int);
            }
            else if ((initial_value_rounded < Integer.MIN_VALUE) || (initial_value_rounded > Integer.MAX_VALUE))
            {
                return addIntOutOfRangeProblem(initial_value_location, desired_type, initial_value_rounded);
            }
            else
            {
                // transform the number that happens to be an integer into
                // an integer.
                return new PooledValue(initial_value_int);
            }
        }
        else
        {
            Number initial_value_numeric = ECMASupport.toNumeric(initial_value.getValue());
            double initial_value_double = initial_value_numeric != null ? initial_value_numeric.doubleValue() : 0;
            int initial_value_int = ECMASupport.toInt32(initial_value_double);
            addProblem(new IncompatibleInitializerTypeProblem(initial_value_location, value_type.getBaseName(), desired_type.getBaseName(), String.valueOf(initial_value_int)));
            return new PooledValue(initial_value_int);
        }
    }

    /**
     * Helper method called by
     * {@link #checkInitialValue(ISourceLocation, IDefinition, PooledValue)}.
     * 
     * @param initial_value_location The {@link ISourceLocation} for the
     * variable's initializer expression.
     * @param desired_type {@link IDefinition} that the initial value's type
     * should be compatible with. This should always by the {@link IDefinition}
     * for uint. This is passed in as a convenience.
     * @param initial_value {@link PooledValue} containing the constant
     * initializer for the variable.
     * @param value_type {@link IDefinition} for the type of value contained by
     * the specified {@link PooledValue}.
     * @return A {@link PooledValue} whose type is compatible with desired_type.
     */
    private PooledValue checkInitialUIntValue(ISourceLocation initial_value_location, IDefinition desired_type, PooledValue initial_value, IDefinition value_type)
    {
        assert !(utils.isBuiltin(value_type, BuiltinType.UINT));
        if (utils.isBuiltin(value_type, BuiltinType.INT))
        {
            int initial_value_int = initial_value.getIntegerValue();
            
            if (initial_value_int < 0)
                return addUIntOutOfRangeProblem(initial_value_location, desired_type, initial_value_int);
            else
                return initial_value;
        }
        else if (utils.isBuiltin(value_type, BuiltinType.NUMBER))
        {
            double initial_value_double = initial_value.getDoubleValue();
            double initial_value_int = ECMASupport.toInteger(initial_value_double);
            long initial_value_long = ECMASupport.toUInt32(initial_value_int);
            if (initial_value_double != initial_value_int)
            {
                addProblem(new InitializerValueNotAnIntegerProblem(
                        initial_value_location,
                        desired_type.getBaseName(),
                        String.valueOf(initial_value_double), String.valueOf(initial_value_long)));
                return new PooledValue(initial_value_long);
            }
            else if ((initial_value_int < 0) || (initial_value_int > 0xFFFFFFFFL))
            {
                return addUIntOutOfRangeProblem(initial_value_location, desired_type, initial_value_int);
            }
            else
            {
                // transform the number that happens to be an unsigned integer into
                // an unsigned integer.
                return new PooledValue(initial_value_long);
            }
        }
        else
        {
            Number initial_value_numeric = ECMASupport.toNumeric(initial_value.getValue());
            double initial_value_double = initial_value_numeric != null ? initial_value_numeric.doubleValue() : 0;
            long initial_value_long = ECMASupport.toUInt32(initial_value_double);
            addProblem(new IncompatibleInitializerTypeProblem(initial_value_location, value_type.getBaseName(), desired_type.getBaseName(), String.valueOf(initial_value_long)));
            return new PooledValue(initial_value_long);
        }
    }
    
    private PooledValue addUIntOutOfRangeProblem(ISourceLocation initial_value_location, IDefinition required_type, double initial_value_int)
    {
        long initial_value_long = ECMASupport.toUInt32(initial_value_int);
        addProblem(new InitializerValueOutOfRangeProblem(
                initial_value_location, 
                required_type.getBaseName(),
                String.valueOf((long)initial_value_int),
                "0",
                String.valueOf(0xFFFFFFFFL),
                String.valueOf(initial_value_long)));
        return new PooledValue(initial_value_long);
    }

    private PooledValue addIntOutOfRangeProblem(ISourceLocation initial_value_location, IDefinition required_type, double initial_value_double)
    {
        int initial_value_int = ECMASupport.toInt32(initial_value_double);
        addProblem(new InitializerValueOutOfRangeProblem(
                initial_value_location, 
                required_type.getBaseName(),
                String.valueOf((long)initial_value_double),
                String.valueOf(Integer.MIN_VALUE),
                String.valueOf(Integer.MAX_VALUE),
                String.valueOf(initial_value_int)));
        return new PooledValue(initial_value_int);
    }


    /**
     *  Check a getproperty operation.
     *  @param binding - the Binding which is being fetched.
     */
    public void checkGetProperty(Binding binding)
    {
        Name name = binding.getName();
        assert name != null;

        if ( utils.isWriteOnlyDefinition(binding.getDefinition()) )
        {
            addProblem(new PropertyIsWriteOnlyProblem(
                binding.getNode(),
                name.getBaseName()
            ));
        }
        
        switch ( name.getKind() )
        {
            case ABCConstants.CONSTANT_QnameA:
            case ABCConstants.CONSTANT_MultinameA:
            case ABCConstants.CONSTANT_MultinameLA:
            case ABCConstants.CONSTANT_RTQnameA:
            case ABCConstants.CONSTANT_RTQnameLA:
                {
                    //  TODO: Attribute checks
                    break;
                }
            case ABCConstants.CONSTANT_TypeName:
                {
                    //  TODO: Type name checks
                    break;
                }
            case ABCConstants.CONSTANT_RTQname:
            case ABCConstants.CONSTANT_RTQnameL:
            case ABCConstants.CONSTANT_MultinameL:
                {
                    //  Not much to be done with these.
                }
            default:
                {
                    if ( binding.getDefinition() == null && SemanticUtils.definitionCanBeAnalyzed(binding, this.project) )
                    {
                        addProblem(accessUndefinedProperty(binding, binding.getNode()));
                    }
                    checkReference(binding);
                }
        }
    }

    /**
     * Check for possible problems with a reference for an r-value.
     * This will find 2 kinds of problems:
     *  1. Ambiguous references
     *  2. References to deprecated symbols
     *
     * @param b the binding to check
     */
    public void checkReference(Binding b)
    {
        checkReference(b, false);
    }

    /**
     * Check for possible problems with a reference.
     * This will find 2 kinds of problems:
     *  1. Ambiguous references
     *  2. References to deprecated symbols
     *
     * @param b the binding to check
     * @param forLValue Whether the binding is for an l-value.
     */
    public void checkReference(Binding b, boolean forLValue)
    {
        if (b != null)
        {
            IDefinition definition = b.getDefinition();
            
            if (definition != null)
            {
                // Since the BURM doesn't currently understand whether a Binding
                // is for an l-value or an r-value, a Binding for an l-value
                // may contain a getter and a Binding for an r-value may contain
                // a setter. If that's the case, we need to find the corresponding
                // accessor.
                if (forLValue && definition instanceof IGetterDefinition ||
                    !forLValue && definition instanceof ISetterDefinition)
                {
                     definition = ((IAccessorDefinition)definition).resolveCorrespondingAccessor(project);
                }
                
                IASNode node = b.getNode();

                checkAmbiguousReference(b);
                checkDeprecated(node, definition);
            }
        }
    }

    /**
     * Log a problem if the binding is an ambiguous reference
     * @param b the binding to check
     */
    private void checkAmbiguousReference(Binding b)
    {
        if( SemanticUtils.isAmbiguousReference(b) )
        {
            addProblem(new AmbiguousReferenceProblem(b.getNode(), b.getName().getBaseName()));
        }
    }

    /**
     * Log a problem if the definition passed in has been marked deprecated
     * and the node passed in is not within a deprecated API.
     * 
     * @param site  the Node to use to obtain location info for any problems
     * @param def   the definition to check
     */
    private void checkDeprecated(IASNode site, IDefinition def)
    {
        if (def != null && def.isDeprecated())
        {
            if (!SemanticUtils.hasDeprecatedAncestor(site))
            {
                ICompilerProblem problem = SemanticUtils.createDeprecationProblem(def, site);
                addProblem(problem);
            }
        }
    }

    /**
     * Check the initial value of an {@link IVariableNode}. The specified
     * {@link IVariableNode} could be:
     * <ul>
     * <li>an {@link IParameterNode} for a function parameter.</li>
     * <li>an {@link IVariableNode} for a var or const in any scope.</li>
     * </ul>
     * This method will create {@link ICompilerProblem}s if the specified
     * initial value is not the correct type and will return an initializer
     * value that is the correct type that was created by apply the AS3 coercion
     * rules.
     * 
     * @param iNode The {@link IVariableNode} whose initializer value should be
     * checked.
     * @param type A {@link Binding} for the specified {@link IVariableNode}'s
     * type annotation.
     * @param initial_value A {@link PooledValue} that contains the constant
     * initializer value computed by the constant propagation code.
     * @return A {@link PooledValue} with the correct type to initialize the
     * specified {@link IVariableNode}. This can be the same as the specified
     * {@link PooledValue} if it was already of the correct type.
     */
    public PooledValue checkInitialValue(IVariableNode iNode, Binding type, PooledValue initial_value)
    {
        assert initial_value != null : "Caller's should generate a compiler problem when a default_value is missing and *not* call this method!";
        ISourceLocation assignedValueExpressionLocation = iNode.getAssignedValueNode();
        IDefinition target_type = type.getDefinition();
        
        return checkInitialValue(assignedValueExpressionLocation, target_type, initial_value);
        
    }

    /**
     *  Analyze an undefined binding and create an appropriate problem.
     *  @return the problem that best fits this error condition.
     */
    private ICompilerProblem accessUndefinedProperty(Binding b, IASNode iNode)
    {
        ICompilerProblem problem;
        
        String unknown_name = null;

        if ( b.getName() != null )
            unknown_name = b.getName().getBaseName();
        else if (SemanticUtils.isThisKeyword(iNode))
            unknown_name = "this";
        else
            return null;

        if ( b.getNode() instanceof MemberAccessExpressionNode )
        {
            MemberAccessExpressionNode maex = (MemberAccessExpressionNode)b.getNode();

            if ( maex.stemIsPackage() && maex.getLeftOperandNode() instanceof IdentifierNode )
            {
                return new AccessUndefinedPropertyInPackageProblem(
                    iNode, 
                    unknown_name,
                    ((IdentifierNode)maex.getLeftOperandNode()).getName()
                );
            }
        }
        else if ((problem = isMissingMember(b.getNode())) != null)
        {
            return problem;
        }
        else if ( utils.isInInstanceFunction(iNode) && utils.isInaccessible((ASScope)utils.getEnclosingFunctionDefinition(iNode).getContainingScope(), b) )
        {
            return new InaccessiblePropertyReferenceProblem(
                    iNode, 
                    b.getName().getBaseName(), 
                    utils.getEnclosingClassName(iNode)
                );
        }

        return new AccessUndefinedPropertyProblem(iNode, unknown_name);
    }
    
    public ICompilerProblem isMissingMember(IASNode iNode)
    {
        if (iNode instanceof IdentifierNode && iNode.getParent() instanceof MemberAccessExpressionNode)
        {
            MemberAccessExpressionNode mae = (MemberAccessExpressionNode)(iNode.getParent());
            if (iNode == mae.getRightOperandNode())
            {
                ITypeDefinition leftDef = mae.getLeftOperandNode().resolveType(project);
                if (!leftDef.isDynamic())
                    return new AccessUndefinedMemberProblem(iNode, ((IdentifierNode)iNode).getName(), leftDef.getQualifiedName());
            }
        }
        return null;
    }
    
    /**
     *  Ensure a super-qualified access is in an instance method.
     */
    public void checkSuperAccess(IASNode iNode)
    {
        IDefinition def = utils.getDefinition(iNode);
        
        //  If def isn't null, then we know this is a valid expression.
        //  if def is null, allow super.foo if the reference is in an
        //  instance function.
        if ( def == null && !utils.isInInstanceFunction(iNode) )
        {
            addProblem(new InvalidSuperExpressionProblem(iNode));
        }
        
        // For super.f(...), check whether f is deprecated.
        if (iNode instanceof IFunctionCallNode)
        {
            IExpressionNode nameNode = ((IFunctionCallNode)iNode).getNameNode();
            IExpressionNode site = ((IMemberAccessExpressionNode)nameNode).getRightOperandNode();
            def = ((IFunctionCallNode)iNode).resolveCalledExpression(project);
            checkDeprecated(site, def);
        }

        if ( this.superState == SuperState.Initial )
            this.superState = SuperState.Armed;
    }

    private boolean isPackageReference(Binding b)
    {
        IASNode n = b.getNode();
        return n instanceof ExpressionNodeBase && ((ExpressionNodeBase)n).isPackageReference();
    }

    /**
     *  Check foo++ and foo-- expressions.
     */
    public void checkIncDec(IASNode iNode, boolean is_incr)
    {
        IASNode operand = ((IUnaryOperatorNode)iNode).getOperandNode();

        checkImplicitConversion(operand, utils.numberType(), null);

        IDefinition def = utils.getDefinition(operand);
        
        if ( utils.isReadOnlyDefinition(def) )
        {
            if ( is_incr )
                addProblem(new InvalidIncrementOperandProblem(iNode));
            else
                addProblem(new InvalidDecrementOperandProblem(iNode));
        }
        else if ( def instanceof SetterDefinition || def instanceof GetterDefinition )
        {
            // No error, just avoid the else if ( def instanceof IFunctionDefinition ) below
        }
        else if ( def instanceof IFunctionDefinition ||  def instanceof ClassDefinition )
        {
            if ( is_incr )
                addProblem(new InvalidIncrementOperandProblem(iNode));
            else
                addProblem(new InvalidDecrementOperandProblem(iNode));
        }
        else if ( SemanticUtils.isConstDefinition(def) )
        {
            //  TODO: See CMP-1177; enhanced error message would be appropriate.
            if ( is_incr )
                addProblem(new InvalidIncrementOperandProblem(iNode));
            else
                addProblem(new InvalidDecrementOperandProblem(iNode));
        }
    }

    /**
     *  Check foo++ and foo-- expressions.
     *  @param iNode  the inc/dec Node
     *  @param is_incr whether this is an increment or decrement operation
     *  @param binding the binding for the name we are incrementing/decrementing
     */
    public void checkIncDec(IASNode iNode, boolean is_incr, Binding binding)
    {
        checkIncDec(iNode, is_incr);
        if ( binding.getName() != null )
        {
            checkGetProperty(binding);
        }
        else
        {
            addProblem(
                is_incr?
                    new IncrementMustBeReferenceProblem(iNode):
                    new DecrementMustBeReferenceProblem(iNode)
            );
        }
    }

    /**
     *  Perform semantic checks on an lvalue,
     *  i.e., the target of an assignment
     *  or other storage-mutating operation.
     */
    public void checkLValue(IASNode iNode, Binding binding)
    {
        IDefinition def = binding.getDefinition();

        if ( SemanticUtils.isThisKeyword(binding.getNode()) )
        {
            addProblem(new AssignToNonReferenceValueProblem(binding.getNode()));
        }
        else if ( def == null && !utils.hasDynamicBase(binding) && !SemanticUtils.isInWith(binding.getNode()))
        {
            addProblem(accessUndefinedProperty(binding, roundUpUsualSuspects(binding, iNode)));
        }
        else if ( def instanceof IConstantDefinition )
        {
            addProblem(new AssignToConstProblem(iNode));
        }
        else if ( utils.isReadOnlyDefinition(def) )
        {
            addProblem(new AssignToReadOnlyPropertyProblem(iNode, binding.getName().getBaseName()));
        }
        else if ( def instanceof SetterDefinition || def instanceof GetterDefinition)
        {
            // No error, just avoid the else if ( def instanceof IFunctionDefinition ) below
        }
        else if ( def instanceof IFunctionDefinition )
        {
            addProblem(new AssignToFunctionProblem(iNode, binding.getName().getBaseName()));
        }
        else if ( def instanceof ClassDefinition )
        {
            addProblem(new IllegalAssignmentToClassProblem(
                roundUpUsualSuspects(binding, iNode),
                binding.getName().getBaseName()
            ));
        }

        checkReference(binding, true);
    }

    /**
     *  Check a member access expression.
     */
    public void checkMemberAccess(IASNode iNode, Binding member, int opcode)
    {
        //  Don't check synthetic bindings.
        IASNode member_node = member.getNode();

        if ( member_node == null )
            return;

        IDefinition def = utils.getDefinition(member_node);

        if ( def == null && utils.definitionCanBeAnalyzed(member) )
        {
            // if it is foo.mx_internal::someProp, just say it passes
            if (member_node.getParent() instanceof NamespaceAccessExpressionNode)
                return;
            
            if ( utils.isInaccessible(iNode, member) )
            {
                addProblem(new InaccessiblePropertyReferenceProblem(
                    member_node, 
                    member.getName().getBaseName(), 
                    utils.getTypeOfStem(iNode))
                );
            }
            else
            {
                ICompilerProblem p = null;
                // Look for the special case of "something." (empty right hand side).
                // Return a less perplexing error for this case.
                if (iNode instanceof IMemberAccessExpressionNode)
                {
                    IMemberAccessExpressionNode maen = (IMemberAccessExpressionNode)iNode;
                    IExpressionNode right = maen.getRightOperandNode();
                    if (right instanceof IIdentifierNode)
                    {
                        if (((IIdentifierNode)right).getName().isEmpty())
                        {
                            p = new MissingPropertyNameProblem(right);
                        }
                    }
                }
                if (p== null)
                {
                    // If right side not blank, then use normal undefined member
                    p = new AccessUndefinedMemberProblem(
                            member_node, 
                            member.getName().getBaseName(), 
                            utils.getTypeOfStem(iNode));
                }
                addProblem(p);
            }
        }
        else if ( utils.isWriteOnlyDefinition(member.getDefinition()) )
        {
            addProblem(new PropertyIsWriteOnlyProblem(
                member_node,
                member.getName().getBaseName()
            ));
        }
        else
        {
            checkReference(member);
        }

    }
    
    /**
     * Check a "new expression".
     * 
     * @param call_node {@link FunctionCallNode} that has the "new" call.
     */
    public void checkNewExpr(IASNode call_node)
    {
        final ExpressionNodeBase name = ((FunctionCallNode)call_node).getNameNode();
        if (name instanceof MemberAccessExpressionNode)
        {
            final MemberAccessExpressionNode func_name = (MemberAccessExpressionNode)name;
            final IDefinition def = func_name.resolve(project);
            if ( def instanceof InterfaceDefinition )
            {
                addProblem(new InterfaceCannotBeInstantiatedProblem(call_node));
            }
            else if ( def instanceof ClassDefinition )
            {
                // pass
            }
            else if ( def instanceof GetterDefinition )
            {
                // pass
            }
            else if (def instanceof FunctionDefinition)
            {
                final FunctionDefinition func_def = (FunctionDefinition)def;
                switch (func_def.getFunctionClassification())
                {
                    case CLASS_MEMBER:
                    case INTERFACE_MEMBER:
                        addProblem(new MethodCannotBeConstructorProblem(call_node));
                        break;
                }
            }
        }
    }

    /**
     *  Check a new expression.
     */
    public void checkNewExpr(IASNode iNode, Binding class_binding, Vector<? extends Object> args)
    {
        IDefinition def = class_binding.getDefinition();

        if ( class_binding.isLocal() )
        {
            //  No checking required.
        }
        else if ( def == null && utils.definitionCanBeAnalyzed(class_binding) && !(class_binding.getName().isTypeName()) )
        {
            // Note: don't have to check accessability because
            // AS3 mandates constructors be public.

            addProblem(new CallUndefinedMethodProblem(
                roundUpUsualSuspects(class_binding, iNode),
                class_binding.getName().getBaseName()
            ));
        }
        else if ( def instanceof InterfaceDefinition )
        {
            addProblem(new InterfaceCannotBeInstantiatedProblem(
                roundUpUsualSuspects(class_binding, iNode)
            ));
        }
        else if ( def instanceof ClassDefinition )
        {
            ClassDefinition class_def = (ClassDefinition)def;

            IFunctionDefinition ctor = class_def.getConstructor();

            if ( ctor instanceof FunctionDefinition )
            {
                FunctionDefinition func = (FunctionDefinition)ctor;
                checkFormalsVsActuals(iNode, func, args);
            }
        }
        else if ( def instanceof GetterDefinition )
        {
        }
        else if ( def instanceof FunctionDefinition )
        {
            FunctionDefinition func_def = (FunctionDefinition) def;

            IFunctionDefinition.FunctionClassification func_type = func_def.getFunctionClassification();

            if ( func_type.equals(IFunctionDefinition.FunctionClassification.CLASS_MEMBER) || func_type.equals(IFunctionDefinition.FunctionClassification.INTERFACE_MEMBER) )
            {
                addProblem(new MethodCannotBeConstructorProblem(
                    roundUpUsualSuspects(class_binding, iNode)
                ));
            }
        }

        checkReference(class_binding);
    }

    /**
     *  Check a return expression that returns a value.
     *  @param iNode - the return statement.  
     *    Known to have a child 0 expression.
     */
    public void checkReturnValue(IASNode iNode)
    {
        FunctionDefinition func_def = SemanticUtils.getFunctionDefinition(iNode);
        
        if ( func_def != null )
        {
            try
            {
                IExpressionNode returnExpression = ((IReturnNode)iNode).getReturnValueNode();
                IDefinition return_type = func_def.resolveReturnType(project);

                //  void has its own special type logic.
                if ( ClassDefinition.getVoidClassDefinition().equals(return_type) )
                {
                    IDefinition value_type = ((ExpressionNodeBase)returnExpression).resolveType(project);
                    if ( value_type != null && ! value_type.equals(ClassDefinition.getVoidClassDefinition()) )
                        addProblem(new ReturnValueMustBeUndefinedProblem(returnExpression));
                }
                else if ( func_def.isConstructor() )
                {
                    addProblem(new ReturnValueInConstructorProblem(returnExpression));
                }
                else
                {
                    checkImplicitConversion(returnExpression, return_type, null);
                }
            }
            catch ( Exception namerezo_problem )
            {
                //  Ignore until CMP-869 is fixed.
            }
        }
        else if ( isInPackageDefinition(iNode) )
        {
            addProblem(new ReturnCannotBeUsedInPackageProblem(iNode));
        }
        else if ( isInClassDefinition(iNode) )
        {
            addProblem(new ReturnCannotBeUsedInStaticProblem(iNode));
        }
        else if ( iNode.getAncestorOfType(MXMLDocumentNode.class) != null )
        {
            //  TODO: Remove this once CMP-874 is resolved.
        }
        else
        {
            addProblem(new ReturnCannotBeUsedInGlobalProblem(iNode));
        }

        if ( this.superState == SuperState.Initial )
            this.superState = SuperState.Armed;
    }
  
    /**
     *  Check a return expression that returns void.
     *  @param iNode - the return statement.  
     */
    public void checkReturnVoid(IASNode iNode)
    {
        if ( SemanticUtils.isInFunction(iNode) )
        {
            if ( SemanticUtils.functionMustReturnValue(iNode, this.project) )
                addProblem(new ReturnMustReturnValueProblem(iNode));
        }
        else if ( isInClassDefinition(iNode) )
        {
            addProblem(new ReturnCannotBeUsedInStaticProblem(iNode));
        }
        else if ( isInPackageDefinition(iNode) )
        {
            addProblem(new ReturnCannotBeUsedInPackageProblem(iNode));
        }
        else if ( iNode.getAncestorOfType(MXMLDocumentNode.class) != null )
        {
            //  TODO: Remove this once CMP-874 is resolved.
        }
        else
        {
            addProblem(new ReturnCannotBeUsedInGlobalProblem(iNode));
        }

        if ( this.superState == SuperState.Initial )
            this.superState = SuperState.Armed;
    }

    /**
     *  Perform semantic checks that require flow-aware analysis.
     *  @param iNode - an AST within a function.
     *  @param mi - the function's MethodInfo.
     *  @param mbi - the function's MethodBodyInfo.
     */
    public void checkControlFlow(IASNode iNode, MethodInfo mi, MethodBodyInfo mbi)
    {
        InstructionList il = mbi.getInstructionList();

        //  Walk the control flow graph if there are any issues that
        //  require it.
        if  ( 
                il.size() > 0 &&
                il.lastElement() == ABCGeneratingReducer.synthesizedReturnVoid && 
                SemanticUtils.functionMustReturnValue(iNode, this.project)
            )
        {
            for ( IBasicBlock b: mbi.getCfg().blocksInControlFlowOrder() )
            {
                if ( b.size() > 0 )
                {
                    //  If at some point it's necessary to walk the CFG regardless,
                    //  then this check can be for any OP_returnvoid and the alternate
                    //  problem injection site in checkReturnVoid can be removed.
                    if ( b.get(b.size()-1) == ABCGeneratingReducer.synthesizedReturnVoid )
                    {
                        addProblem(new ReturnMustReturnValueProblem(iNode));
                        break;
                    }
                }
            }
        }
    }

    /**
     *  Check a throw statement.
     */
    public void checkThrow(IASNode iNode)
    {
        if ( this.superState == SuperState.Initial )
            this.superState = SuperState.Armed;
    }

    /**
     *  Check an import directive.
     *  @param importNode - the import node.
     */
    public void checkImportDirective(IImportNode importNode)
    {
        IASNode site = importNode.getImportNameNode();
        
        if (!SemanticUtils.isValidImport(importNode, project, currentScope.getInInvisibleCompilationUnit()))
        {
            String importName = importNode.getImportName();
            if (importNode.isWildcardImport())
                addProblem(new UnknownWildcardImportProblem(site, importName));
            else
                addProblem(new UnknownImportProblem(site, importName));
        }
        
        // Check if a deprecated definition is being imported.
        if (!importNode.isWildcardImport())
        {
            IDefinition importedDefinition = importNode.resolveImport(project);
            checkDeprecated(site, importedDefinition);
        }
    }

    /**
     *  Check a use namespace directive.
     *  @param iNode - the use namespace node.
     *  @param ns_name - the namespace's Binding.
     */
    public void checkUseNamespaceDirective(IASNode iNode, Binding ns_name)
    {
        if ( ns_name.getDefinition() == null && ns_name.getName() != null )
        {
            // For error reporting, let's get the fully qualified name of the namespace, if possible
            String fullNamespaceName=null;
            IASNode n = ns_name.getNode();
            if (n instanceof IIdentifierNode)
            {
                // In cases I've seen we go through this path
                fullNamespaceName = ((IIdentifierNode)n).getName();
            }
            else
            {
                // This is purely defensive programming - if for some reason we can't get the full name,
                // go back to this older code that gets the short name.
                fullNamespaceName = ns_name.getName().getBaseName();
            }
           
            addProblem(
                new UnknownNamespaceProblem (
                    roundUpUsualSuspects(ns_name, iNode),
                    fullNamespaceName
                )
            );
        }
        
        checkReference(ns_name);
    }

    /**
     *  Check a unary operator.
     *  @param iNode - the operator's i-node.
     *  @param opcode - the corresponding opcode.
     */
    public void checkUnaryOperator(IASNode iNode, int opcode)
    {
        switch(opcode)
        {
            case ABCConstants.OP_negate:
            case ABCConstants.OP_convert_d:
            case ABCConstants.OP_bitnot:
                checkImplicitConversion(((IUnaryOperatorNode)iNode).getOperandNode(), utils.numberType(), null);
                break;
        }
    }

    /**
     *  @return true if the i-node is in a class definition.
     */
    private boolean isInClassDefinition(IASNode iNode)
    {
        return iNode.getAncestorOfType(ClassNode.class) != null;
    }

    /**
     *  @return true if the i-node is in a package definition.
     */
    private boolean isInPackageDefinition(IASNode iNode)
    {
        return iNode.getAncestorOfType(PackageNode.class) != null;
    }

    /**
     * Ensure that a definition does not have the same modifier more than once
     */
    public void checkForDuplicateModifiers(BaseDefinitionNode bdn)
    {
        ModifiersContainerNode mcn = bdn.getModifiersContainer();
        ModifiersSet modifierSet = bdn.getModifiers();
        if( mcn != null && modifierSet != null )
        {
            int modifierNodeCount = mcn.getChildCount();
            if( modifierNodeCount > modifierSet.getAllModifiers().length )
            {
                ModifiersSet tempSet = new ModifiersSet();
                // More children than modifiers - must have dups
                for( int i = 0; i < modifierNodeCount; ++i )
                {
                    IASNode node = mcn.getChild(i);
                    if( node instanceof ModifierNode )
                    {
                        ModifierNode modNode = (ModifierNode)node;
                        if( tempSet.hasModifier(modNode.getModifier()) )
                        {
                            currentScope.addProblem(new DuplicateAttributeProblem(modNode, modNode.getModifierString()));
                        }
                        tempSet.addModifier(modNode);
                    }
                }
            }
        }
    }
    
    /**
     * Looks for namespace prefixes on definitions inside of functions. 
     * Example:
     *  <code><pre>
     *  function foo() : void {
     *      private var bar:int;// this will give "Access modifier not allowed..."
     *      ns var baz:int;     // this will give "Namespace override not allowed ..."
     *  }
     *  </pre></code>
     *  
     *  This function must only be called for nodes that are in fact withing a function.
     */
    private void checkForNamespaceInFunction(BaseDefinitionNode node, LexicalScope scope)
    {
        assert SemanticUtils.isInFunction(node);
        DefinitionBase def = node.getDefinition();
        INamespaceReference nsRef = def.getNamespaceReference();
        if (!(nsRef instanceof NamespaceDefinition.IInternalNamespaceDefinition) &&
                !(nsRef instanceof NamespaceDefinition.IFilePrivateNamespaceDefinition))
        {
            IASNode site = node.getNamespaceNode();
            if (site == null)
                site = node;
            boolean isAccessor = nsRef instanceof NamespaceDefinition.ILanguageNamespaceDefinition;
           
            currentScope.addProblem(new NamespaceOverrideInsideFunctionProblem(site, isAccessor));
        }
    }

    /**
     *  Check a variable declaration.
     */
    public void checkVariableDeclaration(IASNode iNode)
    {
        VariableNode var = (VariableNode)iNode;
        ModifiersSet modifiersSet = var.getModifiers();

        boolean isInFunction = SemanticUtils.isInFunction(iNode);
         
        if (isInFunction)
        {
            checkForNamespaceInFunction(var, currentScope);
        }
        
        //  Variable decls inside methods can't have attributes other than namespaces.
        if ( isInFunction && modifiersSet != null)
        {
            IASNode site = var.getNameExpressionNode();
            for ( ASModifier modifier : modifiersSet.getAllModifiers() )
            {
                if( modifier == ASModifier.NATIVE )
                {
                    currentScope.addProblem(new NativeVariableProblem(site));
                }
                else if (modifier == ASModifier.DYNAMIC )
                {
                    currentScope.addProblem(new DynamicNotOnClassProblem(site));
                }
                else if( modifier == ASModifier.FINAL )
                {
                    currentScope.addProblem(new FinalOutsideClassProblem(site));
                }
                else if( modifier == ASModifier.OVERRIDE )
                {
                    currentScope.addProblem(new InvalidOverrideProblem(site));
                }
                else if( modifier == ASModifier.VIRTUAL )
                {
                    currentScope.addProblem(new VirtualOutsideClassProblem(site));
                }
                else if( modifier == ASModifier.STATIC )
                {
                    currentScope.addProblem(new StaticOutsideClassProblem(site));
                }
            }
        }

        //  Check for ambiguity.
        IDefinition def = utils.getDefinition(var);
        checkVariableForConflictingDefinitions(iNode, (VariableDefinition)def);

        checkNamespaceOfDefinition(var, def, project);
        
        /////////////////////////////////////
        // Check for a type on the variable declaration
        String type = var.getTypeName();
       
        if (type.isEmpty())     // empty string means no declaration at all (not *)
        {
            // don't check things that didn't come from source. They tend to give false negatives
            if (var.getStart() != var.getEnd())
            {
                // get a node that has the best display location for problem
                IASNode location = var;
                IExpressionNode nameExpression = var.getNameExpressionNode();
                if (nameExpression != null)
                    location = nameExpression;
                this.currentScope.addProblem( new VariableHasNoTypeDeclarationProblem(location, var.getShortName()));
            }
        }

        // check if thise is an assignment in this declaration.
        // If so, do checks on that
        final ExpressionNodeBase rightNode = var.getAssignedValueNode();
        if( var.isConst() && rightNode == null )
        {
            addProblem(new ConstNotInitializedProblem(var, var.getName()));
        }

        // if there is an initializer, check that the value is reasonable 
        if (rightNode != null)
        {
            checkAssignmentValue(def, rightNode);
        }

        if(SemanticUtils.isNestedClassProperty(iNode, (VariableDefinition)def))
        {
            // TODO: Issue a better, mor specific diagnostic
            // TODO: once we are allowed to add new error strings.
            addProblem(new BURMDiagnosticNotAllowedHereProblem(iNode));
        }
    }

    /**
     *  Verify that a named type exists.
     *  @param typename - the name of the type.
     */
    public void checkTypeName(Binding typename)
    {
        if ( typename.getNode() == null || typename.getName() == null )
        {
            //  Some kind of synthetic Binding, ignore.
        }
        else
        {
            IDefinition typeDef = utils.getDefinition(typename.getNode());
            if ( !SemanticUtils.isType(typeDef) )
            {
                Name name = typename.getName();
                while ( name != null && name.isTypeName() && name.getTypeNameParameter() != null )
                    name = name.getTypeNameParameter();

                if ( name != null )
                {
                    if ( !name.isTypeName() )
                    {
                        addTypeProblem(typename.getNode(), typeDef, name.getBaseName(), false);
                    }
                    else
                    {
                        //  Render as best able.
                        addTypeProblem(typename.getNode(), typeDef, name.toString(), false);
                    }
                }
            }
        }
        
        checkReference(typename);
    }

    /**
     *  Check a class field declaration.
     */
    public void checkClassField(VariableNode var)
    {
        checkVariableDeclaration(var);

        //  Check the variable's type.
        IASNode typeNode = var.getTypeNode();

        IDefinition typeDef = utils.getDefinition(typeNode);
        if ( !SemanticUtils.isType(typeDef))
        {
            IASNode problematicType = utils.getPotentiallyParameterizedType(typeNode);

            String typeDesc;

            if ( problematicType instanceof IdentifierNode )
            {
                typeDesc = ((IdentifierNode)problematicType).getName();
            }
            else
            {
                typeDesc = var.getTypeName();
            }

            addTypeProblem(problematicType, typeDef, typeDesc, true);
        }
    }

    /**
     * Add the appropriate Problem when a type annotation did not resolve to a Type
     * @param typeNode  the Node to use for location info for the problem
     * @param typeDef   The IDefinition the type annotation resolved to
     * @param typeDesc  A String to use as the description of the type annotation in the diagnostic
     * @param reportAmbiguousReference A flag indicating whether an AmbiguousReferenceProblem
     * should be reported, if the <code>typeDef</code> is ambiguous.
     */
    public void addTypeProblem (IASNode typeNode, IDefinition typeDef, String typeDesc, boolean reportAmbiguousReference)
    {
        if( AmbiguousDefinition.isAmbiguous(typeDef) )
        {
            if (reportAmbiguousReference)
                addProblem(new AmbiguousReferenceProblem(typeNode, typeDesc));
        }
        else
        {
            addProblem(new UnknownTypeProblem(typeNode, typeDesc));
        }
    }

    /**
     * Check the qualifier of a qualified name ('a' in 'a::foo')
     * @param iNode     the node representing the qualifier
     */
    public void checkQualifier(IASNode iNode)
    {
        IDefinition qualifier = utils.getDefinition(iNode);
        
        // If a qualifier is used in a context hwere it is not valid, then the qualifier will resolve
        // to the CM Implicit namespace.
        // This happens for code like:  private::foo
        // when the code is outside of a class (so there is no private).
        if( qualifier == NamespaceDefinition.getCodeModelImplicitDefinitionNamespace() )
        {
            INamespaceDecorationNode nsNode = (INamespaceDecorationNode)iNode;
            String nsString = nsNode.getName();
            if( nsString == IASKeywordConstants.PUBLIC )
            {
                addProblem(new InvalidPublicNamespaceProblem(nsNode) );
            }
            else if( nsString == IASKeywordConstants.PROTECTED )
            {
                addProblem(new InvalidProtectedNamespaceProblem(nsNode) );
            }
            else if( nsString == IASKeywordConstants.PRIVATE )
            {
                addProblem(new InvalidPrivateNamespaceProblem(nsNode));
            }
        }
        
        checkDeprecated(iNode, qualifier);
    }

    /**
     *  Check a namespace declaration.
     */
    public void checkNamespaceDeclaration(IASNode iNode, Binding ns_name)
    {
        NamespaceNode nsNode = (NamespaceNode)iNode;

        IDefinition def = utils.getDefinition(nsNode);

        checkNamespaceOfDefinition(nsNode, def, project);
        SemanticUtils.checkScopedToDefaultNamespaceProblem(currentScope, nsNode, def, null);
        
        if (SemanticUtils.isInFunction(iNode))
        {
            if (iNode instanceof BaseDefinitionNode)
                checkForNamespaceInFunction((BaseDefinitionNode)iNode, currentScope);
        }
        
        // Check whether the namespace is being initialized to a deprecated namespace.
        IExpressionNode namespaceInitialValueNode = nsNode.getNamespaceURINode();
        if (namespaceInitialValueNode != null)
        {
            IDefinition namespaceInitialvalueDefinition = namespaceInitialValueNode.resolve(project);
            checkDeprecated(namespaceInitialValueNode, namespaceInitialvalueDefinition);
        }
    }

    /**
     * Check that the namespace of the definition is valid
     */
    public void checkNamespaceOfDefinition(IASNode iNode, IDefinition def, ICompilerProject project)
    {
        INamespaceReference nsRef = def.getNamespaceReference();
        
        // If it's not a language namespace, then it is only valid if the def is declared in a class
        if( !nsRef.isLanguageNamespace() && !(def.getParent() instanceof IClassDefinition) )
        {
            // if in function, we will already generate the error that no overrides at all are allowed
            if (!SemanticUtils.isInFunction(iNode))
                addProblem(new InvalidNamespaceProblem(iNode instanceof BaseDefinitionNode ?
                                                    ((BaseDefinitionNode)iNode).getNamespaceNode() :
                                                    iNode));
        }

        if( nsRef == NamespaceDefinition.getCodeModelImplicitDefinitionNamespace()
                // constructors are left in the CMImplicit namespace so that FB continues to work right
                && !isConstructor(def) )
        {
            // This should only happen if an invalid access namespace was specified
            // e.g. private outside of a class
            BaseDefinitionNode bdn = iNode instanceof BaseDefinitionNode ? (BaseDefinitionNode)iNode : null;
            if( bdn != null )
            {
                INamespaceDecorationNode nsNode = bdn.getNamespaceNode();
                if( nsNode != null )
                {
                    String nsString = nsNode.getName();
                    if( nsString == IASKeywordConstants.PUBLIC )
                    {
                        addProblem(new InvalidPublicNamespaceAttrProblem(nsNode) );
                    }
                    else if( nsString == IASKeywordConstants.PROTECTED )
                    {
                        addProblem(new InvalidProtectedNamespaceAttrProblem(nsNode) );
                    }
                    else if( nsString == IASKeywordConstants.PRIVATE )
                    {
                        addProblem(new InvalidPrivateNamespaceAttrProblem(nsNode));
                    }
                }
            }
        }
        
        IASNode nsNode = iNode instanceof BaseDefinitionNode ?
                ((BaseDefinitionNode)iNode).getNamespaceNode() :
                iNode;

        INamespaceDefinition nsDef = nsRef.resolveNamespaceReference(project);
        
        if (nsRef.resolveNamespaceReference(project) == null)
            addProblem(new UnresolvedNamespaceProblem(nsNode));
        
        checkDeprecated(nsNode, nsDef);
    }

    private boolean isConstructor(IDefinition d)
    {
        if( d instanceof IFunctionDefinition && ((IFunctionDefinition)d).isConstructor() )
            return true;
        return false;
    }
    /**
     *  Check a Vector literal.
     */
    public void checkVectorLiteral(IASNode iNode, Binding type_param)
    {
        IDefinition type_def = type_param.getDefinition();
        IContainerNode contentsNode = ((VectorLiteralNode)iNode).getContentsNode();
        if ( type_def != null )
        {
            boolean isNumericTypeOrBoolean = SemanticUtils.isNumericTypeOrBoolean(type_def, project);
            String typeName = type_def.getBaseName();
            boolean isInt = SemanticUtils.isBuiltin(type_def, BuiltinType.INT, project);
            boolean isUint = SemanticUtils.isBuiltin(type_def, BuiltinType.UINT, project);

            for ( int i = 0; i < contentsNode.getChildCount(); i++ )
            {
                IASNode literal_element = contentsNode.getChild(i);

                if (isNumericTypeOrBoolean)
                {
                    // check for loss of precision
                    if ( literal_element instanceof NumericLiteralNode )
                    {
                        INumericLiteralNode.INumericValue numeric = ((NumericLiteralNode)literal_element).getNumericValue();
                        if ( (isInt && ( numeric.toNumber() != numeric.toInt32())) ||
                             (isUint && ( numeric.toNumber() != numeric.toUint32()))  )
                        {
                            addProblem(new LossyConversionProblem(literal_element, typeName));
                        }
                    }

                    // check for null values where they don't make sense
                    if (literal_element instanceof IExpressionNode)
                    {
                        IDefinition elementType = ((IExpressionNode)literal_element).resolveType(project);
                        boolean elementIsNull = SemanticUtils.isBuiltin(elementType, BuiltinType.NULL, project);
                        if (elementIsNull)
                        {
                            addProblem( new NullUsedWhereOtherExpectedProblem(literal_element, typeName));
                        }
                    }
                }
                checkImplicitConversion(literal_element, type_def, null);
            }
        }
        return;
    }

    /**
     *  Find at least some AS3 context for a diagnostic.
     *  @return the i-node from the problematic Binding, or the nearest
     *    known i-node if the Binding has no i-node (i.e., it's synthetic).
     */
    private IASNode roundUpUsualSuspects(Binding offender, IASNode bystander)
    {
        if (offender.getNode() != null)
            return offender.getNode();
        else
            return bystander;

    }

    /**
     *  Check a rest parameter declaration (...rest)
     *  @param iNode - the ParameterNode for the rest decl.
     *  @param param_type - the type of the rest param
     */
    public void checkRestParameter(IASNode iNode, Binding param_type)
    {
        IDefinition type = param_type.getDefinition();
        if( !utils.isBuiltin(type, BuiltinType.ARRAY) && !utils.isBuiltin(type, BuiltinType.ANY_TYPE) )
            addProblem(new InvalidRestParameterDeclarationProblem(((ParameterNode)iNode).getTypeNode()));
    }


    /**
     * Check for other definitions that might conflict with the function passed in.  This method will issue
     * a diagnostic if there are any definitions with the same name in the same declaring scope.  It will
     * not find conflicts in base classes - if a method conflicts in something in a base class some sort of
     * illegal override error will already have been issued.
     *
     * @param iNode     The Node that produced the function definition.  Used for location info for any diagnostics.
     * @param funcDef   The FunctionDefinition of the function to check
     */
    public boolean checkFunctionForConflictingDefinitions (IASNode iNode, FunctionDefinition funcDef)
    {
        boolean foundConflict = false;
        // Only have to check for dups in the current class if this is a class method
        // If a base class has a conflict some sort of illegal override error will have been generated already
        // if this is a global or nested function we don't have to check the base class as there won't be one
        switch( SemanticUtils.getMultiDefinitionType(funcDef, project))
        {
            case AMBIGUOUS:
                String namespaceName = getNamespaceStringFromDef(funcDef);
                addProblem(new ConflictingNameInNamespaceProblem(iNode, funcDef.getBaseName(), namespaceName));
                foundConflict = true;
                break;
            case NONE:
                break;
            case MULTIPLE:
                addProblem(new DuplicateFunctionDefinitionProblem(iNode, funcDef.getBaseName()));
                break;
            default:;
              assert false;     
        }
        
        // getter or setter with same name as a package gets a warning/
        // we don't return true, however, as it isn't "really" a multiple definition
        if (funcDef instanceof IAccessorDefinition)
        {
            ASScope cs = (ASScope)funcDef.getContainingScope();
            if (cs.isPackageName(funcDef.getBaseName()))
            {
                IFunctionNode funcNode = (IFunctionNode)iNode;
                IASNode funcNameNode = funcNode.getNameExpressionNode();
                addProblem(new DefinitionShadowedByPackageNameProblem(funcNameNode));
            }
        }
        return foundConflict;
    }

    /**
     * Check for other definitions that might conflict with the function passed in.  This method is for interface
     * functions, so it will check for dups in the current interface, and also look for any conflicts in base interfaces.
     *
     * @param iNode     The node that produced the function definition.  Used for location info for any diagnostics.
     * @param funcDef   The FunctionDefinition of the interface function to check
     */
    public void checkInterfaceFunctionForConflictingDefinitions (IASNode iNode, FunctionDefinition funcDef)
    {
        // Look for conflicts in this interface
        checkFunctionForConflictingDefinitions(iNode, funcDef);

        // Look for methods from base interfaces we may be overriding.
        List<IFunctionDefinition> conflicts = funcDef.resolveOverridenInterfaceFunctions(project);
        if( conflicts.size() > 0 )
        {
            for( IFunctionDefinition overriden : conflicts )
            {
            	if ((overriden instanceof SetterDefinition &&
            		funcDef instanceof GetterDefinition) ||
            		(overriden instanceof GetterDefinition &&
            		funcDef instanceof SetterDefinition))
            		continue;
                addProblem(new InterfaceMethodOverrideProblem(iNode, funcDef.getBaseName(), overriden.getParent().getBaseName()));
            }
        }

    }

    /**
     * Check for other definitions that might conflict with the variable passed in.  This method will check for conflicts
     * in the declaring scope of the variable, and if it is declared in a class it will check for conflicts in the base classes.
     *
     * @param iNode     The node that produced the variable definition.  Used for location info for any diagnostics.
     * @param varDef   The VariableDefinition of the variable to check
     */
    public void checkVariableForConflictingDefinitions( IASNode iNode, VariableDefinition varDef )
    {
        MultiDefinitionType ambiguity = SemanticUtils.getMultiDefinitionType(varDef, project);
        if (ambiguity != MultiDefinitionType.NONE)
        {
            final String varName = varDef.getBaseName();
            ICompilerProblem problem = null;
            if (ambiguity == MultiDefinitionType.AMBIGUOUS)
            {
                problem =  new ConflictingNameInNamespaceProblem(iNode, varName, getNamespaceStringFromDef(varDef));
            }
            else 
            {
                IVariableNode varNode = (IVariableNode)iNode;
                IASNode varNameNode = varNode.getNameExpressionNode();
                if (ambiguity == MultiDefinitionType.MULTIPLE)
                    problem = new DuplicateVariableDefinitionProblem(varNameNode, varName);
                else if (ambiguity == MultiDefinitionType.SHADOWS_PARAM)
                    problem = new VariableDefinitionDuplicatesParameterProblem(varNameNode, varName);
            }
            
            assert problem != null;
            if (problem != null)
                addProblem(problem);
        }

        if (!varDef.isStatic() && SemanticUtils.hasBaseClassDefinition(iNode, project))
        {
            addProblem(new ConflictingInheritedNameInNamespaceProblem(iNode, varDef.getBaseName(), getNamespaceStringFromDef(varDef) ));
        }
            
        // Now look to see if the variable name is also a package name
        ASScope cs = (ASScope)varDef.getContainingScope();
        if (cs.isPackageName(varDef.getBaseName()))
        {
            IVariableNode varNode = (IVariableNode)iNode;
            IASNode varNameNode = varNode.getNameExpressionNode();
            addProblem(new DefinitionShadowedByPackageNameProblem(varNameNode));
        }
    }

    private String getNamespaceStringFromDef (IDefinition funcDef)
    {
        String namespaceName = null;
        INamespaceDefinition n = funcDef.resolveNamespace(project);
        if (n != null)
        {
            namespaceName = n.getBaseName();
        }
        return namespaceName;
    }

    /**
     *  Signal the semantic checker that its caller is entering a constructor:
     *  initialize constructor-specific state variables.
     */
    public void enterConstructor()
    {
        assert this.superState == SuperState.Invalid: String.format("Unexpected super() tracking state %s", this.superState);
        this.superState = SuperState.Initial;
    }

    /**
     *  Signal the semantic checker that its caller is leaving a constructor:
     *  reset constructor-specific state variables.
     */
    public void leaveConstructor()
    {
        assert this.superState != SuperState.Invalid: String.format("Unexpected super() tracking state %s", this.superState);
        this.superState = SuperState.Invalid;
    }

    /**
     * Test whether the getter for the specified accessor can be inlined
     * 
     * @param accessor The accessor to test whether the getter can be inlined
     * @return true if the getter can be inlined
     */
    public boolean canGetterBeInlined(AccessorDefinition accessor)
    {
        if (accessor instanceof SetterDefinition)
            accessor = accessor.resolveCorrespondingAccessor(currentScope.getProject());

        if (accessor == null)
            return false;

        return canFunctionBeInlined(accessor);
    }

    /**
     * Test whether the setter for the specified accessor can be inlined
     * 
     * @param accessor The accessor to test whether the setter can be inlined
     * @return true if the setter can be inlined
     */
    public boolean canSetterBeInlined(AccessorDefinition accessor)
    {
        if (accessor instanceof GetterDefinition)
            accessor = accessor.resolveCorrespondingAccessor(currentScope.getProject());

        if (accessor == null)
            return false;

        return canFunctionBeInlined(accessor);
    }

    /**
     * Test whether the specified function can be inlined.  If the function
     * can't be inlined, a problem will be if the user explicity requested
     * the function be inlined, rather than the compiler trying to
     * inline it optimistically.
     * 
     * @param function The function to test whether it can be inlined
     * @return true if the function can be inlined
     */
    public boolean canFunctionBeInlined(FunctionDefinition function)
    {
        if (!currentScope.getProject().isInliningEnabled())
            return false;

        // only report a problem when a function can't be inlined if the
        // function has been explicitly marked as inline
        final boolean reportInlineProblems = function.isInline();

        // don't support inlining functions inside inlined functions
        if (currentScope.insideInlineFunction())
        {
            if (reportInlineProblems)
                currentScope.addProblem(new InlineNestedInliningNotSupportedProblem(function.getBaseName()));

            return false;
        }

        // can't inline the function if we don't have a node for it
        FunctionNode functionNode = (FunctionNode)function.getFunctionNode();
        if (functionNode == null)
        {
            if (reportInlineProblems)
                currentScope.addProblem(new InlineNoSourceProblem(function.getBaseName()));

            return false;
        }

        if (!function.inlineFunction())
        {
            if (reportInlineProblems)
                currentScope.addProblem(new InlineFunctionNotFinalStaticOrGlobalProblem(functionNode, function.getBaseName()));

            return false;
        }

        // Pass in a new collection for the compiler problems, as we don't care
        // about any problems parsing the body, as they will be reported when
        // parsing the non-inlined version of the function.
        functionNode.parseFunctionBody(new ArrayList<ICompilerProblem>());

        // If we meet all the requirements for an inlined method, parse and scan the
        // body to make sure there isn't any constructs we can't inline.
        final ScopedBlockNode functionBody = functionNode.getScopedNode();
        if (functionBodyHasNonInlineableNodes(functionBody, reportInlineProblems, function.getBaseName(), new AtomicInteger()))
        {
            functionNode.discardFunctionBody();
            return false;
        }

        return true;
    }

    /**
     * Check for any constructs we know we can't inline, or if the function is too large
     * 
     * @param n the node to test
     * @param reportInlineProblems whether or not to report inline problems
     * @param functionName the name of the function being inlined
     * @param exprCount a running count of the expressions in the body
     * @return true if the function contains un-inlineable nodes, false if
     * the function body can be inlined
     */
    public boolean functionBodyHasNonInlineableNodes(IASNode n, boolean reportInlineProblems, String functionName, AtomicInteger exprCount)
    {
        if (n == null)
            return false;

        if (n instanceof ExpressionNodeBase)
        {
            exprCount.getAndIncrement();

            if (exprCount.get() > InlineFunctionLexicalScope.MAX_EXPR_IN_BODY)
            {
                if (reportInlineProblems)
                    currentScope.addProblem(new InlineFunctionTooLargeProblem(functionName, exprCount.get(), InlineFunctionLexicalScope.MAX_EXPR_IN_BODY));

                return true;
            }
        }

        switch (n.getNodeID())
        {
            case AnonymousFunctionID:
            case CatchID:
            case FinallyID:
            case FunctionID:
            case FunctionObjectID:
            case TryID:
            case WithID:
            {
                if (reportInlineProblems)
                    currentScope.addProblem(new InlineUnsupportedNodeProblem(n, functionName));

                return true;
            }
            default:
            {
                for (int i = 0; i < n.getChildCount(); i++)
                {
                    if (functionBodyHasNonInlineableNodes(n.getChild(i), reportInlineProblems, functionName, exprCount))
                        return true;
                }
            }
        }

        return false;
    }

    /**
     * Iterate through the Instructions which are to be inlined and
     * ensure the can all be inlined.  Any Instruction which makes
     * use of the scope chain will cause the inline to fail.
     * 
     * @param insns inlined instructions
     * @param reportInlineProblems whether or not to report inline problems
     * @param functionName the name of the function being inlined
     * @return true if all instructions are OK to be inlined
     */
    public boolean functionBodyHasNonInlineableInstructions(InstructionList insns, boolean reportInlineProblems, String functionName)
    {
        // if there are no instructions in the function body, then something went wrong (bad AS)
        // doing codegen, so we can't inline this function
        if (insns.isEmpty())
            return true;

        for (Instruction insn : insns.getInstructions())
        {
            switch (insn.getOpcode())
            {
                case OP_pushwith:
                case OP_popscope:
                case OP_pushscope:
                case OP_newfunction:
                case OP_returnvoid:
                case OP_returnvalue:
                case OP_newactivation:
                case OP_newclass:
                case OP_newcatch:
                case OP_findpropstrict:
                case OP_findproperty:
                case OP_getlex:
                case OP_getscopeobject:
                case OP_getouterscope:
                {
                    if (reportInlineProblems)
                        currentScope.addProblem(new InlineUnsupportedInstructionProblem(functionName));

                    return true;
                }
            }
        }

        return false;
    }
}

