/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.flex.compiler.internal.as.codegen;

import static org.apache.flex.abc.ABCConstants.OP_add;
import static org.apache.flex.abc.ABCConstants.OP_getlocal0;
import static org.apache.flex.abc.ABCConstants.OP_pushscope;
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.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import org.apache.flex.abc.ABCConstants;
import org.apache.flex.abc.instructionlist.InstructionList;
import org.apache.flex.abc.semantics.MethodBodyInfo;
import org.apache.flex.abc.semantics.MethodInfo;
import org.apache.flex.abc.semantics.Name;
import org.apache.flex.abc.visitors.IMethodBodyVisitor;
import org.apache.flex.abc.visitors.IMethodVisitor;
import org.apache.flex.abc.visitors.IScriptVisitor;
import org.apache.flex.abc.visitors.IVisitor;
import org.apache.flex.compiler.definitions.references.IReference;
import org.apache.flex.compiler.exceptions.BURMAbortException;
import org.apache.flex.compiler.exceptions.CodegenInterruptedException;
import org.apache.flex.compiler.exceptions.MissingBuiltinException;
import org.apache.flex.compiler.internal.as.codegen.ICodeGenerator.IConstantValue;
import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
import org.apache.flex.compiler.internal.definitions.ParameterDefinition;
import org.apache.flex.compiler.internal.definitions.TypeDefinitionBase;
import org.apache.flex.compiler.internal.embedding.EmbedData;
import org.apache.flex.compiler.internal.scopes.ASScope;
import org.apache.flex.compiler.internal.testing.NodesToXMLStringFormatter;
import org.apache.flex.compiler.internal.tree.as.FunctionNode;
import org.apache.flex.compiler.internal.tree.mxml.MXMLFileNode;
import org.apache.flex.compiler.internal.units.requests.ABCBytesRequestResult;
import org.apache.flex.compiler.problems.CodegenInternalProblem;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.MissingBuiltinProblem;
import org.apache.flex.compiler.projects.ICompilerProject;
import org.apache.flex.compiler.tree.as.IASNode;
import org.apache.flex.compiler.tree.as.IExpressionNode;
import org.apache.flex.compiler.units.ICompilationUnit;
import org.apache.flex.compiler.units.ICompilationUnit.Operation;
import org.apache.flex.compiler.units.requests.IABCBytesRequestResult;

import com.google.common.util.concurrent.Futures;

/**
 * ABCGenerator is the public interface to the code generator.
 */

/**
 * JSGenerator is modeled after from ABCGenerator and called by
 * JSCompilationUnit. JSGenerator owns the JSSharedData singleton. Ideally
 * JSGenerator and ABCGenerator should be derived from the same base class, i.e.
 * Generator. Some of the code in JSGenerator and ABCGenerator could be shared
 * if Generator used a burm factory in generateInstructions(). ABCGenerator
 * creates and uses a CmcEmitter, while JSGenerator uses a CmcJSEmitter. This
 * implementation is part of FalconJS. For more details on FalconJS see
 * org.apache.flex.compiler.JSDriver
 */
public class JSGenerator implements ICodeGenerator
{
    public ICompilationUnit m_compilationUnit = null;
    private Boolean m_needsSecondPass = false;
    private CmcJSEmitter m_cmcJSEmitter = null;
    private JSGeneratingReducer m_burm = null;
    private ICompilationUnit.Operation m_buildPhase = Operation.GET_ABC_BYTES;
    private JSEmitter m_emitter = null;

    public JSGenerator()
    {
        m_cmcJSEmitter = JSSharedData.backend.createCmcJSEmitter();
        m_cmcJSEmitter.reducer = JSSharedData.backend.createReducer();
        m_burm = m_cmcJSEmitter.reducer;
    }

    // If JSEmitter.needsSecondPass() returns true, JSGenerator.generate() will return null during scanning, 
    // which will result in JSCompilationUnit::handleSemanticProblemsRequest not caching any abcBytes for 
    // handleABCBytesRequest. The net result is that JSGenerator.generate() will be called again in handleABCBytesRequest. 
    // This mechanic will ensure selective two-pass compilation. 
    public Boolean needsSecondPass()
    {
        return m_needsSecondPass;
    }

    /*
     * There are currently a lot of problems with the DependencyGraph: -
     * ImportNode::resolveRefs() has not been implemented. - import and
     * expression dependencies are not being recognized. If
     * useOwnDependencyGraph() returns true we use our own (old) DependencyGraph
     * implementation that used to drive the while loop in
     * JSGenerator.generate() using nextJS. - JSDriver does a second pass -
     * JSGlobalDirectiveProcessor::processImportDirective() registers imported
     * classes.
     */
    public static Boolean useOwnDependencyGraph()
    {
        // return true;
        return false;
    }

    /**
     * Generate an ABC file equivalent to the input syntax tree.
     * 
     * @param synthetic_name_prefix Prefix to prepend to all synthetic names
     * @param root_node the root of the syntax tree.
     * @param project {@link ICompilerProject} whose symbol table is used to
     * resolve references to definitions.
     * @throws InterruptedException
     */
    @SuppressWarnings("nls")
    public ABCBytesRequestResult generate(String synthetic_name_prefix, IASNode root_node, ICompilerProject project) throws InterruptedException
    {
        return generate(null, false, synthetic_name_prefix, root_node, project, false, Collections.<String, String>emptyMap());    	
    }
    
    @Override
	public ABCBytesRequestResult generate(ExecutorService executorService, boolean useParallelCodegen,
	                                      String synthetic_name_prefix, IASNode root_node,
	                                      ICompilerProject project, boolean inInvisibleCompilationUnit,
	                                      Map<String, String> encodedDebugFiles)
        throws InterruptedException
	{
        m_needsSecondPass = false;
        if (root_node instanceof MXMLFileNode)
        	m_emitter = new JSMXMLEmitter(JSSharedData.instance, m_buildPhase, project, this);
        else
        	m_emitter = JSSharedData.backend.createEmitter(m_buildPhase, project, this);
        m_emitter.visit(ABCConstants.VERSION_ABC_MAJOR_FP10, ABCConstants.VERSION_ABC_MINOR_FP10);

        IScriptVisitor sv = m_emitter.visitScript();
        sv.visit();
        MethodInfo init_method = new MethodInfo();
        sv.visitInit(init_method);

        MethodBodyInfo init_body = new MethodBodyInfo();
        init_body.setMethodInfo(init_method);

        IMethodVisitor mv = m_emitter.visitMethod(init_method);
        IMethodBodyVisitor mbv = mv.visitBody(init_body);
        mbv.visit();

        //  Set up the global lexical scope.
        final LexicalScope global_scope = new GlobalLexicalScope(project, this, synthetic_name_prefix, m_emitter);
        global_scope.traitsVisitor = sv.visitTraits();
        global_scope.setMethodInfo(init_method);
        global_scope.methodBodyVisitor = mbv;

        //  Process global directives.
        GlobalDirectiveProcessor top_level_processor = JSSharedData.backend.createGlobalDirectiveProcessor(this, global_scope, m_emitter);
        boolean fatal_error_encountered = false;
        try
        {
            top_level_processor.traverse(root_node);
        }
        catch (MissingBuiltinException e)
        {
            global_scope.addProblem(new MissingBuiltinProblem(root_node, e.getBuiltinName()));
            fatal_error_encountered = true;
        }
        catch (CodegenInterruptedException e)
        {
            //  Unwrap the InterruptedException and rethrow it.
            throw e.getException();
        }

        byte[] generatedBytes = IABCBytesRequestResult.ZEROBYTES;

        if (!fatal_error_encountered)
        {
            //  Initialize the init script.
            InstructionList script_init_insns = new InstructionList();

            script_init_insns.addInstruction(OP_getlocal0);
            script_init_insns.addInstruction(OP_pushscope);

            script_init_insns.addAll(global_scope.getInitInstructions());
            script_init_insns.addAll(top_level_processor.directiveInsns);

            if (script_init_insns.canFallThrough() || script_init_insns.hasPendingLabels())
                script_init_insns.addInstruction(OP_returnvoid);

            //  Allocate temps beginning with register 1,
            //  register 0 is reserved for "this" global.
            global_scope.initializeTempRegisters(1);

            mbv.visitInstructionList(script_init_insns);
            mbv.visitEnd();
            mv.visitEnd();
            sv.visitEnd();

            try
            {
                generatedBytes = m_emitter.emit();
            }
            catch (Throwable cant_generate)
            {
                global_scope.addProblem(new CodegenInternalProblem(root_node, cant_generate));
            }
        }

        ICompilerProblem[] problemsArray = global_scope.getProblems().toArray(IABCBytesRequestResult.ZEROPROBLEMS);
        return new ABCBytesRequestResult(generatedBytes, problemsArray, Collections.<EmbedData> emptySet());
    }

    /**
     * Translate an AST into ABC instructions.
     * 
     * @param subtree - the CM subtree.
     * @param goal_state - the desired goal state. One of the nonterminal states
     * in CmcJSEmitter, or 0 if you're feeling lucky and are willing to accept
     * whatever instruction sequence the BURM decides is optimal.
     * @param scope - the active lexical scope.
     * @return a list of ABC instructions.
     */
    public InstructionList generateInstructions(IASNode subtree, int goal_state, LexicalScope scope)
    {
        return generateInstructions(subtree, goal_state, scope, null);
    }

    /**
     * Translate an AST into ABC instructions.
     * 
     * @param subtree - the CM subtree.
     * @param goal_state - the desired goal state. One of the nonterminal states
     * in CmcJSEmitter, or 0 if you're feeling lucky and are willing to accept
     * whatever instruction sequence the BURM decides is optimal.
     * @param scope - the active lexical scope.
     * @param instance_init_insns - a list of instance initialization
     * instructions collected outside a constructor body that must be included
     * in the constructor.
     * @post if instance_init_insns is not null then the method will have been
     * processed as and marked as a constructor.
     * @return a list of ABC instructions.
     */
    public InstructionList generateInstructions(IASNode subtree, int goal_state, LexicalScope scope, InstructionList instance_init_insns)
    {
        m_burm.setCurrentscope(scope);
        m_burm.setInstanceInitializers(instance_init_insns);
        m_burm.setAprioriinstructions(instance_init_insns);
        m_burm.setFunctionNode(subtree);

        InstructionList list = new InstructionList();

        try
        {
            m_cmcJSEmitter.burm(subtree, goal_state);

            // TODO: cmcJSEmitter.getResult() now returns a String, which needs to be wrapped into an InstructionList
            // return ((InstructionList)cmcJSEmitter.getResult());
            list.addInstruction(JSSharedData.OP_JS, m_cmcJSEmitter.getResult());

            // If JSEmitter.needsSecondPass() returns true, JSGenerator.generate() will return null during scanning, 
            // which will result in JSCompilationUnit::handleSemanticProblemsRequest not caching any abcBytes for 
            // handleABCBytesRequest. The net result is that JSGenerator.generate() will be called again in handleABCBytesRequest. 
            // This mechanic will ensure selective two-pass compilation. 
            if (m_burm.needsSecondPass())
            {
                m_needsSecondPass = true;
            }
        }
        catch (Exception cant_reduce)
        {
            handleBurmError(m_cmcJSEmitter, subtree, cant_reduce, scope);
        }

        return list;
    }

    /**
     * Generate code for a function declaration, and put its initialization code
     * on the relevant instruction list.
     * 
     * @param func - the function declaration node.
     * @param enclosing_scope - the lexical scope in which the function was
     * defined.
     * @param a_priori_insns - instructions generated by an enclosing subsystem
     * that should be included in the function (e.g., a constructor needs a
     * priori instructions to initialize instance vars).
     */
    public MethodInfo generateFunction(FunctionNode func, LexicalScope enclosing_scope, InstructionList a_priori_insns)
    {
        m_burm.setCurrentscope(enclosing_scope);
        MethodInfo mi = createMethodInfo(m_burm, m_emitter, enclosing_scope, func);
        if (mi.isNative())
        {
            generateNativeMethod(func, mi, enclosing_scope);
        }
        else
        {
            /*
             * Now done in JSEmitter: // support for class inits. // If this is
             * a static function and the owner class has a class init then call
             * __static_init() final IDefinition fdef = func.getDefinition();
             * if( fdef.isStatic() && fdef.getParent() != null &&
             * fdef.getParent() instanceof ClassDefinition ) { final IDefinition
             * cdef = fdef.getParent(); final String fullName =
             * JSGeneratingReducer
             * .createFullNameFromDefinition(enclosing_scope.getProject(),cdef);
             * if( JSSharedData.instance.hasClassInit(fullName) ) { final String
             * callInit = fullName + "." + JSSharedData.STATIC_INIT + "();\n";
             * if( a_priori_insns == null ) a_priori_insns = new
             * InstructionList(); a_priori_insns.addInstruction(
             * JSSharedData.OP_JS, callInit ); } }
             */
            m_burm.startFunction(func);
            generateMethodBodyForFunction(mi, func, enclosing_scope, a_priori_insns);
            m_burm.endFunction(func);
        }

        return mi;
    }
    
    public GenerateFunctionInParallelResult generateFunctionInParallel (ExecutorService executorService, FunctionNode func, LexicalScope enclosing_scope)
    {
    	/** AJH commented out for now
        MethodInfo mi = createMethodInfo(enclosing_scope, func);
        if (mi.isNative())
        {
            generateNativeMethod(func, mi, enclosing_scope);
            return new GenerateFunctionInParallelResult(Futures.immediateFuture(null), mi, Collections.<IVisitor>emptyList());
        }
        GenerateFunctionRunnable runnable = new GenerateFunctionRunnable(mi, func, enclosing_scope);
        Future<?> future = executorService.submit(runnable);
        return new GenerateFunctionInParallelResult(future, mi, runnable.getDeferredVisitEndsList());
        */
    	System.out.println("unhandled call to generateFunctionInParallel");
    	return null;
    }

    /**
     * Helper method used by <code>generateFunction()</code>.
     * 
     * @param func - the function declaration node.
     * @param mi - the MethodInfo describing the signature
     * @param enclosing_scope - the lexical scope in which the handler method is
     * autogenerated.
     */
    static void generateNativeMethod(FunctionNode func, MethodInfo mi,
                                     LexicalScope enclosing_scope)
    {
        enclosing_scope.getMethodBodySemanticChecker().checkNativeMethod(func);

        // don't need to create a new scope, so just use the enclosing scope
        // to get a handle to the emitter
        IMethodVisitor mv = enclosing_scope.getEmitter().visitMethod(mi);

        // Just visit the method info.  Do NOT generate a body
        // for native methods
        mv.visit();

        // func.getReturnType() returns a short name string.
        // But we need a real name. ctors don't have return types.
        if (!func.isConstructor())
        {
            final ASScope scope = (ASScope)JSGeneratingReducer.getScopeFromNode(func);
            final FunctionDefinition fdef = func.getDefinition();
            final IReference ref = fdef.getReturnTypeReference();
            final Name returnTypeName = ref.getMName(enclosing_scope.getProject(), scope);
            mi.setReturnType(returnTypeName);
        }

        // For non native methods, the return type is set by the burm,
        // but for native types, as the burm isn't run, we need to set
        // the return type here.
        // String returnType = func.getReturnType();
        // mi.setReturnType(new Name(returnType));

        mv.visitEnd();
    }

    /**
     * Helper method used by <code>generateFunction()</code> (and also by
     * <code>generateEventHandler()</code> in MXMLDocumentDirectiveProcessor).
     * 
     * @param mi - the MethodInfo describing the signature
     * @param node - the FunctionNode or MXMLEventSpecifierNode. may be null
     * when generating method bodies for purely synthetic functions, such as
     * theIEventDispatcher methods that [Bindable] introduces.
     * @param enclosing_scope - the lexical scope in which the handler method is
     * autogenerated.
     * @param a_priori_insns - instructions generated by an enclosing subsystem
     * that should be included in the function (e.g., a constructor needs a
     * priori instructions to initialize instance vars).
     */
    public void generateMethodBodyForFunction(MethodInfo mi, IASNode node,
            LexicalScope enclosing_scope,
            InstructionList a_priori_insns)
    {
        generateMethodBody(mi, node, enclosing_scope, a_priori_insns, CmcEmitter.__function_NT, null);
    }

    /**
     * Helper methods used by databinding codegen to emit anonymous functions
     * based on an expression node.
     * 
     * @param mi - the MethodInfo describing the signature
     * @param node - the expression node whose code will start the function. may
     * be null when generating method bodies for purely synthetic functions,
     * such as theIEventDispatcher methods that [Bindable] introduces.
     * @param enclosing_scope
     * @param insns_to_append - typically some massaging of the TOS and a return
     * function
     */
    public MethodInfo generateFunctionFromExpression(MethodInfo mi, IASNode node,
            LexicalScope enclosing_scope,
            InstructionList insns_to_append)
    {
        return generateMethodBody(mi, node, enclosing_scope, null, CmcEmitter.__expression_NT, insns_to_append);
    }

    /**
     * Helper methods used by databinding codegen to emit anonymous functions
     * based on an expression node.
     * 
     * @param mi - the MethodInfo describing the signature
     * @param nodes - a list of expression nodes whose code will start the
     * function. May have the following values: null when generating method
     * bodies for purely synthetic functions, such as theIEventDispatcher
     * methods that [Bindable] introduces. an IASNode for an expression that
     * will be code-gen'd a List of IASNodes. This is a special case where we
     * code-gen the sum of all the expressions
     * @param enclosing_scope
     * @param insns_to_append - typically some massaging of the TOS and a return
     * function
     */

    public MethodInfo generateFunctionFromExpressions(MethodInfo mi, List<? extends IASNode> nodes,
             LexicalScope enclosing_scope,
             InstructionList insns_to_append)
    {
        return generateMethodBody(mi, nodes, enclosing_scope, null, CmcEmitter.__expression_NT, insns_to_append);
    }

    /**
     * General method body maker. see the public documentation, above, for more
     * into
     */
    MethodInfo generateMethodBody(MethodInfo mi, Object node,
                                         LexicalScope enclosing_scope,
                                         InstructionList a_priori_insns,
                                         int goal_state,
                                         InstructionList insns_to_append)
    {
        //  Set up a lexical scope for this function.
        LexicalScope function_scope = enclosing_scope.pushFrame();

        IMethodVisitor mv = function_scope.getEmitter().visitMethod(mi);
        mv.visit();

        MethodBodyInfo mbi = new MethodBodyInfo();
        mbi.setMethodInfo(mi);

        IMethodBodyVisitor mbv = mv.visitBody(mbi);
        mbv.visit();

        function_scope.methodBodyVisitor = mbv;
        function_scope.traitsVisitor = mbv.visitTraits();
        function_scope.setMethodInfo(mi);
        
        System.out.println(mi.getMethodName());
        if (mi.getMethodName().contains("loginInternal"))
        {
        	System.out.println("got it");
        }

        InstructionList insns = null;
        if (node == null)
        {
            // node may be null when generating method bodies for purely synthetic functions, such as the
            // IEventDispatcher methods that [Bindable] introduces.
            insns = new InstructionList();
        }
        else if (node instanceof IASNode)
        {
            // If we are passed a single node, generate its instructions
            insns = generateInstructions((IASNode)node, goal_state, function_scope, a_priori_insns);
        }
        else if (node instanceof List<?>)
        {
            List<?> nodes = (List<?>)node;

            // for a list of nodes, generate all their instructions and add the results together.
            // typically we are doing this to concatenate strings
            for (int nodeIndex = 0; nodeIndex < nodes.size(); ++nodeIndex)
            {
                IASNode n = (IASNode)nodes.get(nodeIndex);
                if (nodeIndex == 0)
                {
                    // First one in the list makes a new IL and puts
                    // instructions into it
                    insns = generateInstructions(n, goal_state, function_scope, a_priori_insns);
                }
                else
                {
                    // successive children generate into the same IS, then add the results
                    insns.addAll(generateInstructions(n, goal_state, function_scope, a_priori_insns));
                    insns.addInstruction(OP_add);
                }
            }
        }
        else
        {
            assert false; // Illegal type passed as node parameter
        }
        assert insns != null;

        // If caller passed in instructions to get after the BURM-generated stuff,
        // add them to the instruction stream
        if (insns_to_append != null)
        {
            insns.addAll(insns_to_append);
        }

        mbv.visitInstructionList(insns);

        if (function_scope.needsActivation())
        {
            mi.setFlags((byte)(mi.getFlags() | ABCConstants.NEED_ACTIVATION));
        }

        mbv.visitEnd();
        mv.visitEnd();

        return mi;
    }

    /**
     * Helper method used by mxml databinding codegen to emit an anonymous
     * function used by an mxml data binding destination function. Example:
     * <p>
     * If the expression node is a.b.c, this method will generate a funtion
     * whose source would look something like this:
     * 
     * <pre>
     * function (arg:*):void { a.b.c = arg; }
     * </pre>
     * 
     * @param mi - the MethodInfo describing the signature
     * @param setterExpression {@link IExpressionNode} that is the destination
     * expression of a mxml data binding.
     * @param enclosing_scope {@link LexicalScope} for the class initializer
     * that encloses the function being generated.
     */
    public void generateMXMLDataBindingSetterFunction (MethodInfo mi, IExpressionNode setterExpression, LexicalScope enclosing_scope)
    {
    	System.out.println("unhandled call to generateMXMLDataBindingSetterFunction");
    	/* AJH commented out for now
        IMethodVisitor methodVisitor = enclosing_scope.getEmitter().visitMethod(mi);
        methodVisitor.visit();
        MethodBodyInfo methodBodyInfo = new MethodBodyInfo();
        methodBodyInfo.setMethodInfo(mi);
        IMethodBodyVisitor methodBodyVisitor = methodVisitor.visitBody(methodBodyInfo);
        methodBodyVisitor.visit();
        
        //  Set up a lexical scope for this function.
        LexicalScope function_scope = enclosing_scope.pushFrame();
        
        function_scope.methodBodyVisitor = methodBodyVisitor;
        function_scope.traitsVisitor = methodBodyVisitor.visitTraits();
        function_scope.setMethodInfo(mi);
        

        InstructionList functionBody;
        if (setterExpression instanceof InstructionListNode)
            functionBody = ((InstructionListNode)setterExpression).getInstructions();
        else
            functionBody = generateInstructions(setterExpression, CmcEmitter.__mxml_data_binding_setter_expression_NT, function_scope, null);
        
        functionBody.addInstruction(OP_returnvoid);
        
        methodBodyVisitor.visitInstructionList(functionBody);
        methodBodyVisitor.visitEnd();
        methodVisitor.visitEnd();
        */
    }
    
    /**
     * Helper method used by databinding codegen to emit an anonymous function
     * based on a list of {@link IExpressionNode}'s. This method emits a
     * function that contains code that evaluates each expression in the list
     * and adds the expressions together with {@link ABCConstants#OP_add}.
     * 
     * @param mi - the MethodInfo describing the signature
     * @param nodes - a {@link List} of {@link IExpressionNode}'s to be
     * codegen'd.
     * @param enclosing_scope {@link LexicalScope} for the class initializer
     * that encloses the function being generated.
     */
     public void generateMXMLDataBindingGetterFunction (MethodInfo mi, List<IExpressionNode> nodes,
                                                        LexicalScope enclosing_scope)
     {
     	System.out.println("unhandled call to generateMXMLDataBindingSetterFunction");
    	 /* AJH commented out for now
         IMethodVisitor methodVisitor = enclosing_scope.getEmitter().visitMethod(mi);
         methodVisitor.visit();
         MethodBodyInfo methodBodyInfo = new MethodBodyInfo();
         methodBodyInfo.setMethodInfo(mi);
         IMethodBodyVisitor methodBodyVisitor = methodVisitor.visitBody(methodBodyInfo);
         methodBodyVisitor.visit();
         
         //  Set up a lexical scope for this function.
         LexicalScope function_scope = enclosing_scope.pushFrame();
         
         function_scope.methodBodyVisitor = methodBodyVisitor;
         function_scope.traitsVisitor = methodBodyVisitor.visitTraits();
         function_scope.setMethodInfo(mi);

         InstructionList functionBody = null;
         // for a list of nodes, generate all their instructions and add the results together.
         // typically we are doing this to concatenate strings
         for (IExpressionNode expressionNode : nodes)
         {
             InstructionList instructionsForExpression = generateInstructions(expressionNode, CmcEmitter.__expression_NT, function_scope, null);
             if (functionBody == null)
             {
                 // First one in the list makes a new IL and puts
                 // instructions into it
                 functionBody = instructionsForExpression;
             }
             else
             {
                 // successive children generate into the same IL, then add the results
                 functionBody.addAll(instructionsForExpression);
                 functionBody.addInstruction(OP_add);
             }
         }
         
         functionBody.addInstruction(OP_returnvalue);
         
         methodBodyVisitor.visitInstructionList(functionBody);
         function_scope.traitsVisitor.visitEnd();
         methodBodyVisitor.visitEnd();
         methodVisitor.visitEnd();
         */
    }

     /**
     * Creates a MethodInfo specifying the signature of a method declared by a
     * FunctionNode.
     * 
     * @param func - A FunctionNode representing a method declaration.
     * @return The MethodInfo specifying the signature of the method.
     */
    public static MethodInfo createMethodInfo(JSGeneratingReducer burm, JSEmitter emitter, LexicalScope scope, FunctionNode func)
    {
        MethodInfo mi = new MethodInfo();
        //  FIXME: FunctionNode.getQualifiedName() has
        //  preconditions that need to be understood!
        mi.setMethodName(func.getName());

        FunctionDefinition funcDef = func.getDefinition();
        //  Marshal the function's arguments.
        ParameterDefinition[] args = funcDef.getParameters();
        List<String> param_names = new ArrayList<String>();

        ICompilerProject project = scope.getProject();
        if (args.length > 0)
        {
            Vector<Name> method_args = new Vector<Name>();
            for (ParameterDefinition arg : args)
            {
                TypeDefinitionBase arg_type = arg.resolveType(project);
                Name type_name = arg_type != null ? arg_type.getMName(project) : null;

                if (arg.isRest())
                {
                    mi.setFlags((byte)(mi.getFlags() | ABCConstants.NEED_REST));
                    param_names.add(arg.getBaseName());
                }
                else
                {
                    method_args.add(type_name);
                    param_names.add(arg.getBaseName());
                }
            }
            mi.setParamTypes(method_args);
            mi.setParamNames(param_names);
        }

        // check for native modifier
        if (func.getDefinition().isNative())
        {
            mi.setFlags((byte)(mi.getFlags() | ABCConstants.NATIVE));
        }

        // The return type will be set by the BURM.

        // Falcon's IMethodVisitor only records a fraction of the FunctionDefinition.
        // For that reason we are registering every MethodInfo with its corresponding FunctionDefinition at the JSEmitter.
        emitter.visitFunctionDefinition(mi, funcDef);

        return mi;
    }

    // called by JSInterfaceDirectiveProcessor
    public MethodInfo createMethodInfo(LexicalScope scope, FunctionNode func)
    {
        return JSGenerator.createMethodInfo(m_burm, m_emitter, scope, func);
    }
    
    /**
     **
     * Creates a MethodInfo specifying the signature of a method
     * declared by a FunctionNode, and adds in the information for any
     * default argument values.
     * 
     * @param func - A FunctionNode representing a method declaration.
     * @return The MethodInfo specifying the signature of the method.
     * 
     * Will generate a compiler problem is the default value is bad
     */
    @Override
    public MethodInfo createMethodInfoWithDefaultArgumentValues (LexicalScope scope, FunctionNode func)
    {   
        return JSGenerator.createMethodInfo(m_burm, m_emitter, scope, func);
    }

    /**
     * Helper method to expose the constant folding code to clients outside of
     * the burm, such as
     * org.apache.flex.compiler.internal.as.definitions.ConstantDefinition.
     * 
     * @param subtree the tree to generate a constant value for
     * @param project the project to use to evaluate the tree
     * @return the constant value for the subtree, or null if a constant value
     * can't be determined
     */
    public IConstantValue generateConstantValue(IASNode subtree, ICompilerProject project)
    {
        Object result = null;

        LexicalScope scope = new GlobalLexicalScope(project, null, GlobalLexicalScope.EMPTY_NAME_PREFIX, m_emitter);

        if (subtree != null)
        {
            try
            {
                result = reduceSubtree(subtree, scope, CmcJSEmitter.__constant_value_NT);
            }
            catch (Exception cant_reduce)
            {
                // Can't generate a constant value, just return null
            }
        }

        return new ConstantValue(result, null);
    }

    /**
     * Reduce an AST to its equivalent ABC structures.
     * 
     * @param subtree - the root of the AST subtree. May be null, in which case
     * this routine returns null.
     * @param scope - the active LexicalScope.
     * @param goal - the BURM's goal state. One of the CmcEmitter.__foo_NT
     * constants.
     * @return the result of reducing the subtree to the desired goal state, or
     * null if the input subtree was null.
     * @throws Exception from the BURM if the computation didn't succeed or was
     * interrupted.
     */
    public Object reduceSubtree(IASNode subtree, LexicalScope scope, int goal)
            throws Exception
    {
        CmcJSEmitter burm = m_cmcJSEmitter;
        burm.reducer = this.m_burm;
        burm.reducer.setCurrentscope(scope);

        burm.burm(subtree, CmcEmitter.__constant_value_NT);
        return burm.getResult();
    }

    /**
     * Handle an error from a BURM: emit diagnostics and bump the error count.
     * 
     * @param n - the subtree that was to be reduced.
     * @param ex - the exception.
     */
    @SuppressWarnings("nls")
    private static void handleBurmError(CmcJSEmitter burm, IASNode n, Exception ex, LexicalScope scope)
    {
        if (ex instanceof CodegenInterruptedException)
        {
            // If the exception is an InterruptedException, do nothing, as not
            // a real error.  The incremental flow kicked in and interrupted
            // the current work, so just throw away the current work and carry
            // on our merry way.
            // No problem should be reported in this case.
            scope.getProblems().clear();
            return;
        }
        else if (!(ex instanceof BURMAbortException))
        {
            scope.addProblem(new CodegenInternalProblem(n, ex));
        }

        java.io.PrintWriter dumper;

        String dump_dir = System.getenv("JBURG_DUMP_DIR");
        if (dump_dir != null)
        {
            try
            {
                String dump_file = dump_dir + "/failedBurm-" + Integer.toString(dumpCount++) + ".xml";
                dumper = new java.io.PrintWriter(new java.io.FileWriter(dump_file));
                dumper.println("<?xml version=\"1.0\"?>");
                dumper.println("<BurmDump date=\"" + new Date().toString() + "\">");
                burm.dump(dumper);
                dumper.println("<AST>");
                dumper.println(new NodesToXMLStringFormatter(n).toString());
                dumper.println("</AST>");
                dumper.println("</BurmDump>");
                dumper.flush();
                dumper.close();
            }
            catch (Exception e)
            {
                JSSharedData.instance.stderr("Unable to dump due to: " + e.toString());
                try
                {
                    JSSharedData.instance.stderr(new NodesToXMLStringFormatter(n).toString());
                }
                catch (Exception cantformat)
                {
                    //  Probably an error in the AST itself, diagnosed above.
                }
            }
        }
    }

    /**
     * Number of diagnostic dumps emitted by this compiler; used to generate
     * unique dump file names.
     */
    static int dumpCount = 0;

    public String toString()
    {
        return "JSGenerator: " + m_compilationUnit.toString();
    }

    public void setBuildPhase(ICompilationUnit.Operation op)
    {
        m_buildPhase = op;
        m_burm.setBuildPhase(op);
    }

    public JSGeneratingReducer getReducer()
    {
        return m_burm;
    }


    /**
     * Get an ICodeGeneratorFactory that will always return the same ABCGenerator instance
     */
    public static ICodeGeneratorFactory getABCGeneratorFactory()
    {
        return new ICodeGeneratorFactory()
        {
            public ICodeGenerator get ()
            {
                return new JSGenerator();
            }
        };
    }
    
    /**
     * Represents the result of {@link #generateConstantValue}(}.
     * <p>
     * In addition to producing the constant value itself,
     * the constant reduction process can also produce compiler problems.
     */
    public static final class ConstantValue implements IConstantValue
    {
        public ConstantValue(Object value, Collection<ICompilerProblem> problems)
        {
            this.value = value;
            this.problems = problems;
        }
        
        private final Object value;
        private final Collection<ICompilerProblem> problems;
        
        @Override
        public Object getValue()
        {
            return value;
        }

        @Override
        public Collection<ICompilerProblem> getProblems()
        {
            return problems;
        }
    }
}
