flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cd...@apache.org
Subject [14/51] [partial] - Migrated the directory structure to a more Maven style structure. - Started migrating the Parser from Antlr2+3 and JFlex to Antlr4.
Date Tue, 22 Jul 2014 13:35:40 GMT
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ControlFlowContextManager.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ControlFlowContextManager.java b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ControlFlowContextManager.java
new file mode 100644
index 0000000..f01b95a
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ControlFlowContextManager.java
@@ -0,0 +1,877 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.as.codegen;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Vector;
+
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.abc.semantics.Label;
+import org.apache.flex.compiler.exceptions.DuplicateLabelException;
+import org.apache.flex.compiler.exceptions.UnknownControlFlowTargetException;
+import org.apache.flex.compiler.internal.tree.as.LabeledStatementNode;
+import org.apache.flex.compiler.internal.tree.as.SwitchNode;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.ICatchNode;
+import org.apache.flex.compiler.tree.as.ITryNode;
+
+import static org.apache.flex.abc.ABCConstants.*;
+
+/**
+ *  The ControlFlowContextManager is the code generator's
+ *  keeper of active control-flow contexts and the associated
+ *  (implicit in the configuration of contexts) model of the scope stack.
+ *
+ *  Control-flow contexts come in several varieties:
+ *  <ul>
+ *  <li>  Ordinary control-flow contexts, established by a 
+ *        labeled statement or a statement with break/continue semantics.
+ *  <li>  Exception-handling contexts, established by try 
+ *        with a catch or finally.
+ *  <li>  With statements.
+ *  </ul>
+ *
+ *  These various types of context have few common elements, aside
+ *  from participating in the model of control flow and the scope
+ *  stack, so this class manages the active configuration of contexts
+ *  and embodies the code generator's control-flow and scope stack model.
+ */
+public class ControlFlowContextManager
+{
+    /**
+     *  The LexicalScope that established this 
+     *  ControlFlowContextManager.
+     *  Used to allocate temporary storage,
+     *  report problems, etc.
+     */
+    final LexicalScope currentScope;
+
+    /**
+     * Base class for all control flow context search criteria
+     * classes.
+     * All subclass are anonymous classes.
+     */
+    static abstract class ControlFlowContextSearchCriteria
+    {
+        /**
+         * Determines if this search criteria matches the specified
+         * {@link ControlFlowContext}.
+         * 
+         * @param c {@link ControlFlowContext} to check.
+         * @return true if this search criteria matches the specified
+         * {@link ControlFlowContext}, false otherwise.
+         */
+        abstract boolean match(ControlFlowContext c);
+        
+        /**
+         * Gets the {@link Label} in the specified {@link ControlFlowContext}
+         * that should be jumped to when this criteria matches the specified
+         * {@link ControlFlowContext}.
+         * 
+         * @param c {@link ControlFlowContext} containing a label that should be
+         * jumped to.
+         * @return The {@link Label} that should be jumped to.
+         */
+        abstract Label getLabel(ControlFlowContext c);
+        
+        /**
+         * Determines whether the control flow context is search from the inner
+         * most control flow context to the outer most or vice versa, when
+         * searching for a control flow context that matches this search
+         * criteria.
+         * 
+         * @return true if the control flow context stack should be search from
+         * inner most to outer most, false if the stack should be search outer
+         * most to inner most.
+         */
+        abstract boolean innerToOuter();
+    }
+    
+    /**
+     *  Search criterion which finds all active contexts.
+     */
+    public static final ControlFlowContextSearchCriteria FIND_ALL_CONTEXTS =
+        new ControlFlowContextSearchCriteria()
+    {
+
+        @Override
+        boolean match(ControlFlowContext c)
+        {
+            return true;
+        }
+
+        @Override
+        Label getLabel(ControlFlowContext c)
+        {
+            return null;
+        }
+
+        @Override
+        boolean innerToOuter()
+        {
+            return false;
+        }
+        
+    };
+    
+    /**
+     * A {@link ControlFlowContextSearchCriteria} which finds the first enclosing
+     * context that can be targetted with a break with no label.
+     */
+    static ControlFlowContextSearchCriteria breakWithOutLabelCriteria =
+        new ControlFlowContextSearchCriteria()
+    {
+        @Override
+        boolean match(ControlFlowContext c)
+        {
+            return c.hasDefaultBreakLabel();
+        }
+
+        @Override
+        Label getLabel(ControlFlowContext c)
+        {
+            assert match(c);
+            return c.getBreakLabel();
+        }
+
+        @Override
+        boolean innerToOuter()
+        {
+            return true;
+        }
+        
+    };
+    
+    /**
+     * A {@link ControlFlowContextSearchCriteria} which finds the first
+     * enclosing context that can be targetted with a continue with no label.
+     */
+    static ControlFlowContextSearchCriteria continueWithOutLabelCriteria =
+        new ControlFlowContextSearchCriteria()
+    {
+        @Override
+        boolean match(ControlFlowContext c)
+        {
+            return c.hasDefaultContinueLabel();
+        }
+
+        @Override
+        Label getLabel(ControlFlowContext c)
+        {
+            assert match(c);
+            return c.getContinueLabel();
+        }
+
+        @Override
+        boolean innerToOuter()
+        {
+            return true;
+        } 
+    };
+    
+    /**
+     * Creates a {@link ControlFlowContextSearchCriteria} which finds the first
+     * enclosing context that contains a labeled statement with the specified
+     * label and whose
+     * {@link ControlFlowContextSearchCriteria#getLabel(ControlFlowContext)}
+     * will return the break label for the found context.
+     * 
+     * @param label Name of the label to find.
+     * @return A {@link ControlFlowContextSearchCriteria} which finds the first
+     * enclosing context that contains a labeled statement with the specified
+     * label and whose
+     * {@link ControlFlowContextSearchCriteria#getLabel(ControlFlowContext)}
+     * will return the break label for the found context.
+     */
+    ControlFlowContextSearchCriteria breakWithLabelCriteria(final String label)
+    {
+        return new ControlFlowContextSearchCriteria()
+        {
+            @Override
+            boolean match(ControlFlowContext c)
+            {
+                return c.hasBreakLabel(label);
+            }
+
+            @Override
+            Label getLabel(ControlFlowContext c)
+            {
+                assert match(c);
+                return c.getBreakLabel();
+            }
+
+            @Override
+            boolean innerToOuter()
+            {
+                return false;
+            } 
+        };
+    }
+    
+    /**
+     * Creates a {@link ControlFlowContextSearchCriteria} which finds the first
+     * enclosing context that contains a labeled loop statement with the
+     * specified label and whose
+     * {@link ControlFlowContextSearchCriteria#getLabel(ControlFlowContext)}
+     * will return the continue label for the found context.
+     * 
+     * @param label Name of the label to find.
+     * @return A {@link ControlFlowContextSearchCriteria} which finds the first
+     * enclosing context that contains a labeled loop statement with the
+     * specified label and whose
+     * {@link ControlFlowContextSearchCriteria#getLabel(ControlFlowContext)}
+     * will return the continue label for the found context.
+     */
+    ControlFlowContextSearchCriteria continueWithLabelCriteria(final String label)
+    {
+        return new ControlFlowContextSearchCriteria()
+        {
+            @Override
+            boolean match(ControlFlowContext c)
+            {
+                return c.hasContinueLabel(label);
+            }
+
+            @Override
+            Label getLabel(ControlFlowContext c)
+            {
+                assert match(c);
+                return c.getContinueLabel();
+            }
+
+            @Override
+            boolean innerToOuter()
+            {
+                return false;
+            } 
+        };
+    }
+    
+
+    /**
+     * Creates a {@link ControlFlowContextSearchCriteria} which finds the first
+     * enclosing context that contains a labeled statement with the specified
+     * label and whose
+     * {@link ControlFlowContextSearchCriteria#getLabel(ControlFlowContext)}
+     * will return the goto label for the found context.
+     * 
+     * @param label Name of the label to find.
+     * @return A {@link ControlFlowContextSearchCriteria} which finds the first
+     * enclosing context that contains a labeled statement with the specified
+     * label and whose
+     * {@link ControlFlowContextSearchCriteria#getLabel(ControlFlowContext)}
+     * will return the goto label for the found context.
+     */
+    ControlFlowContextSearchCriteria gotoLabelCriteria(final String label, final boolean allowDuplicates)
+    {
+        return new ControlFlowContextSearchCriteria()
+        {
+            @Override
+            boolean match(ControlFlowContext c)
+            {
+                return c.hasGotoLabel(label, allowDuplicates);
+            }
+
+            @Override
+            Label getLabel(ControlFlowContext c)
+            {
+                assert match(c);
+                return c.getGotoLabel(label);
+            }
+
+            @Override
+            boolean innerToOuter()
+            {
+                return true;
+            } 
+        };
+    }
+    
+    
+    /**
+     *  @param current_scope - the active LexicalScope
+     *    at the time the ControlFlowContextManager was built.
+     */
+    ControlFlowContextManager(LexicalScope current_scope)
+    {
+        this.currentScope = current_scope;
+        IASNode initialControlFlowRegionNode = currentScope.getInitialControlFlowRegionNode();
+        if (initialControlFlowRegionNode != null)
+        {
+            LabelScopeControlFlowContext rootContext = new LabelScopeControlFlowContext(initialControlFlowRegionNode);
+            activeFlowContexts.add(rootContext);
+        }
+    }
+
+    /**
+     *  The stack of currently active control flow contexts.
+     */
+    Vector<ControlFlowContext> activeFlowContexts = new Vector<ControlFlowContext>();
+
+    /**
+     *  @return the index of the topmost control-flow context on the stack.
+     */
+    private int getTopControlFlowContextIndex()
+    {
+        int result = activeFlowContexts.size() - 1;
+        while ( result >= 0 && !(activeFlowContexts.elementAt(result) instanceof LoopControlFlowContext) )
+            result--;
+        
+        return result;
+    }
+    
+    /**
+     *  @return the topmost control-flow context in the stack, which the caller
+     *  knows to be a {@link LoopControlFlowContext}.
+     */
+    private LoopControlFlowContext peekActiveLoopControlFlowContext()
+    {
+        int idx = getTopControlFlowContextIndex();
+        assert(idx >= 0): "no non-finally flow context";
+        return (LoopControlFlowContext)activeFlowContexts.elementAt(idx);
+    }
+
+    /**
+     *  Pop the current context off the stack.
+     *  @return the popped context.
+     */
+    private Object popContext()
+    {
+        assert(! activeFlowContexts.isEmpty()): "no active control-flow context";
+        return activeFlowContexts.remove(activeFlowContexts.size()-1);
+    }
+    
+
+    /**
+     *  Pop the topmost control-flow context off the stack,  which the caller
+     *  knows to be a {@link SwitchControlFlowContext}.
+     *  @return The context popped off the stack.
+     */
+    private SwitchControlFlowContext popSwitchControlFlowContext()
+    {
+        return (SwitchControlFlowContext)popContext();
+    }
+    
+    /**
+     *  Pop the topmost control-flow context off the stack,  which the caller
+     *  knows to be a {@link LabeledStatementControlFlowContext}.
+     *  @return The context popped off the stack.
+     */
+    private LabeledStatementControlFlowContext popLabeledStatementControlFlowContext()
+    {
+        return (LabeledStatementControlFlowContext)popContext();
+    }
+
+    /**
+     *  Pop the topmost control-flow context off the stack,  which the caller
+     *  knows to be a {@link LoopControlFlowContext}.
+     *  @return The context popped off the stack.
+     */
+    private LoopControlFlowContext popLoopControlFlowContext()
+    {
+        return (LoopControlFlowContext)popContext();
+    }
+
+    /**
+     *  Pop the current exception handling context off the stack.
+     *  @return the popped context.
+     */
+    private ExceptionHandlingContext popExceptionHandlingContext()
+    {
+        // pops the LabelScopeControlFlowObject that is left on the stack
+        // by the last catch or finally context.
+        popContext(); 
+        return (ExceptionHandlingContext)popContext();
+    }
+
+    /**
+     * Called by a reduction's Prologue section to establish an active
+     * {@link LoopControlFlowContext}.
+     * 
+     * @param loopContents The syntax tree node containing the contents of the
+     * body of the loop. This node is used to establish a new scope for labels
+     * referenced by goto statements.
+     */
+    public void startLoopControlFlowContext(IASNode loopContents)
+    {
+        activeFlowContexts.add(new LoopControlFlowContext(loopContents));
+    }
+    
+    /**
+     * Called by a reduction's Prologue section to establish an active
+     * {@code SwitchControlFlowContext}.
+     * 
+     * @param node The syntax tree node for the switch statement.
+     */
+    public void startSwitchContext(SwitchNode node)
+    {
+        activeFlowContexts.add(new SwitchControlFlowContext(node));
+    }
+    
+    /**
+     * Called by a reduction's Prologue section to establish an active
+     * {@link LabeledStatementControlFlowContext}.
+     * 
+     * @param labeledStatement The syntax tree node for the labeled statement.
+     */
+    public void startLabeledStatementControlFlowContext(LabeledStatementNode labeledStatement)
+        throws DuplicateLabelException
+    {
+        String labelName = labeledStatement.getLabel();
+        //  Scan the active control-flow contexts for a duplicate label.
+        boolean is_duplicate = findControlFlowContextNoError(breakWithLabelCriteria(labelName)) != CONTEXT_NOT_FOUND;
+        activeFlowContexts.add(new LabeledStatementControlFlowContext(labeledStatement, labelName));
+
+        //  Throw the exception after establishing the (duplicate) context
+        //  so that the control-flow context teardown code works for this case.
+        if ( is_duplicate )
+        {
+            throw new DuplicateLabelException(labelName);
+        }
+    }
+    
+    /** Manifest constant used by control-flow search routines for "not found" */
+    public static final int CONTEXT_NOT_FOUND = -1;
+    
+    /**
+     * Uses the specified {@link ControlFlowContextSearchCriteria} to find the
+     * index of the first matching control flow context on the control flow
+     * context stack.
+     * 
+     * @param criterion
+     * @return the index of the first matching control flow context on the
+     * control flow context stack.
+     */
+    private final int findControlFlowContextNoError(ControlFlowContextSearchCriteria criterion)
+    {
+        final int nContexts = activeFlowContexts.size();
+        
+        if (nContexts == 0)
+            return CONTEXT_NOT_FOUND;
+        
+        if (criterion == FIND_ALL_CONTEXTS)
+            return 0;
+        
+        // The criterion object can specify whether or not the
+        // stack of control flow contexts should be searched from
+        // the inner most context to the outer most context or vice
+        // versa.  tharwood does not remember why we don't just
+        // always search from inner to outer, so it would be worth
+        // doing an experiment at some point.
+        if (criterion.innerToOuter())
+        {
+            for ( int i = nContexts - 1; i >= 0; i--)
+            {
+                ControlFlowContext context = activeFlowContexts.elementAt(i);
+                if (criterion.match(context))
+                    return i;
+            }
+            return CONTEXT_NOT_FOUND;
+        }
+        else
+        {
+            for ( int i = 0; i < nContexts; i++)
+            {
+                ControlFlowContext context = activeFlowContexts.elementAt(i);
+                if (criterion.match(context))
+                    return i;
+            }
+            return CONTEXT_NOT_FOUND;
+        }
+    }
+    
+    /**
+     * Uses the specified {@link ControlFlowContextSearchCriteria} to find the
+     * index of the first matching control flow context on the control flow
+     * context stack.
+     * 
+     * @param criterion
+     * @return the index of the first matching control flow context on the
+     * control flow context stack.
+     * @throws UnknownControlFlowTargetException When no matching context could
+     * be found.
+     */
+    private int findControlFlowContext(ControlFlowContextSearchCriteria criterion)
+    throws UnknownControlFlowTargetException
+    {
+        int result = findControlFlowContextNoError(criterion);
+
+        if ( result == CONTEXT_NOT_FOUND )
+        {
+            //  Callers catch this exception and report
+            //  the error in context.
+            throw new UnknownControlFlowTargetException(criterion);
+        }
+
+        return result;
+    }
+
+    /**
+     *  Called by a reduction's Prologue section to establish
+     *  an active exception handling context.
+     */
+    void startExceptionContext(ITryNode tryNode)
+    {
+        ExceptionHandlingContext finally_context = new ExceptionHandlingContext(this);
+
+        finally_context.finallyReturns = new Vector<ExceptionHandlingContext.FinallyReturn>();
+        finally_context.finallyBlock = new Label();
+        finally_context.finallyDoRethrow = new Label();
+        finally_context.finallyDoFallthrough = new Label("finallyDoFallthrough");
+        finally_context.finallyReturnStorage = currentScope.allocateTemp();
+
+        activeFlowContexts.add(finally_context);
+        
+        finally_context.startTryControlState();
+        // Add a new label scope for labels that are referenced by
+        // goto statements in the try block.
+        activeFlowContexts.add(new LabelScopeControlFlowContext(tryNode.getStatementContentsNode()));
+        
+    }
+    
+    /**
+     * @param finallyStatements Sub-tree containing all the statements in the
+     * finally block. This node is used to establish as scope for labels that
+     * can be referenced by goto statements.
+     */
+    void startFinallyContext(IASNode finallyStatements)
+    {
+        getFinallyContext().startFinallyControlState();
+
+        popContext();  // Pop off the LabelScopeControlFlowContext from the try block.
+        activeFlowContexts.add(new LabelScopeControlFlowContext(finallyStatements));
+    }
+    
+    void endFinallyContext()
+    {
+        getFinallyContext().endFinallyControlState();
+    }
+    
+    void startCatchContext(ICatchNode catchNode)
+    {
+        getFinallyContext().startCatchControlState();
+        popContext(); // Pop off the LabelScopeControlFlowContext from the try block or
+                      // the finally block.
+        activeFlowContexts.add(new LabelScopeControlFlowContext(catchNode.getStatementContentsNode()));
+    }
+    
+    void endCatchContext()
+    {
+        getFinallyContext().endCatchControlState();
+    }
+
+    /**
+     *  @return the computed GOTO that implements the "return" from a finally block.
+     */
+    public InstructionList getFinallySwitch()
+    {
+        InstructionList result = new InstructionList();
+
+        ExceptionHandlingContext finally_context = getFinallyContext();
+        int n_alternatives = getFinallyAlternativesSize();
+
+        Label[] finally_labels;
+        if ( 0 == n_alternatives )
+        {
+            finally_labels = new Label[] { finally_context.finallyDoFallthrough, finally_context.finallyDoRethrow };
+        }
+        else
+        {
+            finally_labels = new Label[n_alternatives + 2];
+            finally_labels[0] = finally_context.finallyDoFallthrough;
+
+            int i = 1;
+            for ( ExceptionHandlingContext.FinallyReturn ret: getFinallyContext().finallyReturns )
+                finally_labels[i++] = ret.getLabel();
+
+            finally_labels[i] = finally_context.finallyDoRethrow;
+        }
+        result.addInstruction(OP_lookupswitch, finally_labels);
+        return result;
+    }
+
+    /**
+     *  Find all active scopes enclosing the currently active scope,
+     *  and synthesize an instruction fragment to re-initialize
+     *  the scope stack.
+     *  @return the instruction fragment that re-initializes the
+     *    enclosing scopes on the scope stack.
+     */
+    public InstructionList getScopeStackReinit()
+    {
+        InstructionList result = new InstructionList();
+        assert activeFlowContexts.size() >= 2;
+        assert activeFlowContexts.lastElement() instanceof LabelScopeControlFlowContext;
+        
+        for ( int i = 0; i < activeFlowContexts.size() - 2; i++ )
+        {
+            ControlFlowContext context = activeFlowContexts.elementAt(i);
+            context.addExceptionHandlerEntry(result);
+        }
+        return result;
+    }
+
+    /**
+     *  Find all active exception handling blocks or scopes,
+     *  and set up finally return sequences and/or popscopes.
+     */
+    InstructionList getNonLocalControlFlow(InstructionList original, ControlFlowContextSearchCriteria criterion)
+        throws UnknownControlFlowTargetException
+    {
+        int criterion_index = findControlFlowContext(criterion);
+
+        //  Synthesize an instruction sequence that re-balances the
+        //  stack to its condition on entry to this control flow region.
+        InstructionList result = original;
+
+        for (int i = criterion_index; i < activeFlowContexts.size(); i++ )
+        {
+            ControlFlowContext context = activeFlowContexts.elementAt(i);
+            result = context.addExitPath(result);
+        }
+
+        return result;
+    }
+
+    /**
+     *  @return the ExceptionHandlingContext on top of the stack.
+     */
+    public ExceptionHandlingContext getFinallyContext()
+    {
+        ExceptionHandlingContext current_context;
+        assert activeFlowContexts.size() >= 2;
+        assert activeFlowContexts.lastElement() instanceof LabelScopeControlFlowContext;
+        current_context = (ExceptionHandlingContext)activeFlowContexts.get(activeFlowContexts.size() - 2);
+        return current_context;
+    }
+
+    /**
+     *  @return the number of callers to a finally block.
+     */
+    public int getFinallyAlternativesSize()
+    {
+        return getFinallyContext().finallyReturns.size();
+    }
+
+    /**
+     *  @return a code fragment that sets up the "fail" finally return.
+     */
+    public InstructionList getFinallyFailSignal()
+    {
+        InstructionList result = new InstructionList();
+        //  Allow for the "success" alternative.
+        CmcEmitter.pushNumericConstant(getFinallyAlternativesSize() + 1, result);
+        return result;
+    }
+
+    /**
+     *  Pop the active exception handling context off the stack.
+     */
+    void finishExceptionContext()
+    {
+        popExceptionHandlingContext();
+    }
+
+    /**
+     * Gets the {@link Label} for a labeled statement with the specified name.
+     * This code is used to assign the target of the returned {@link Label} when
+     * reducing the labeled statement node. The label may be created before we
+     * reduce the label statement node if there is a forward reference to the
+     * label.
+     * <p>
+     * This method will return null if a label specified specified name could
+     * not be found or if more than one label with the specified label was
+     * found.
+     * 
+     * @param label Name of the label to return.
+     * @return {@link Label} for a labeled statement with the specified name, or
+     * null if no visible label with the specified name could be found.
+     */
+    Label getGotoLabel(String label)
+    {
+        ControlFlowContextSearchCriteria criterion = gotoLabelCriteria(label, false);
+        int context_idx = findControlFlowContextNoError(criterion);
+        if (context_idx == CONTEXT_NOT_FOUND)
+            return null;
+        ControlFlowContext ctx = activeFlowContexts.elementAt(context_idx);
+        assert ctx.hasGotoLabel(label, false);
+        return ctx.getGotoLabel(label);
+    }
+    
+    /**
+     * Generates a jump instruction to the appropriate label in the context
+     * matched by the specified {@link ControlFlowContextSearchCriteria}.
+     * @param criterion
+     * @return {@link InstructionList} containing a jump.
+     * @throws UnknownControlFlowTargetException
+     */
+    InstructionList getBranchTarget(ControlFlowContextSearchCriteria criterion)
+        throws UnknownControlFlowTargetException
+    {
+
+        InstructionList result = new InstructionList();
+
+        int context_idx = findControlFlowContext(criterion);
+        ControlFlowContext ctx = activeFlowContexts.elementAt(context_idx);
+
+        result.addInstruction(OP_jump, criterion.getLabel(ctx));
+        return result;
+    }
+    
+    /**
+     * Finds all the labeled statements current in scope in the control flow
+     * context stack that a goto with a specified label might refer to. This is
+     * used to generate compiler problems for ambiguous goto statements.
+     * 
+     * @param label Name of the labeled statements to return.
+     * @return all the labeled statements current in scope in the control flow
+     * context stack that a goto with a specified label might refer to.
+     */
+    Collection<LabeledStatementNode> getGotoLabels(String label)
+    {
+        ControlFlowContextSearchCriteria criterion = gotoLabelCriteria(label, true);
+        int context_idx = findControlFlowContextNoError(criterion);
+        if (context_idx == CONTEXT_NOT_FOUND)
+            return Collections.emptyList();
+        LabelScopeControlFlowContext context =
+            (LabelScopeControlFlowContext)activeFlowContexts.elementAt(context_idx);
+        return context.getLabelNodes(label);
+    }
+    
+    /**
+     * Finish the current context which is known by the caller of this method
+     * to be a labeled statement control flow context.
+     * @param insns The instruction stream of the statement that established
+     * the control flow context.
+     */
+    void finishLabeledStatementControlFlowContext(InstructionList insns)
+    {
+        LabeledStatementControlFlowContext context = popLabeledStatementControlFlowContext();
+        if (context.hasActiveBreak())
+            insns.labelNext(context.getBreakLabel());
+    }
+    
+    /**
+     * Finish the current context which is known by the caller of this method
+     * to be a labeled statement control flow context.
+     * @param insns The instruction stream of the statement that established
+     * the control flow context.
+     */
+    void finishSwitchControlFlowContext(InstructionList insns)
+    {
+        SwitchControlFlowContext context = popSwitchControlFlowContext();
+        if (context.hasActiveBreak())
+            insns.labelNext(context.getBreakLabel());
+    }
+
+    /**
+     *  Finish the current control flow context; if a break statement 
+     *  targeted this context, ensure an appropriate instruction gets 
+     *  labeled as the break target.
+     *  @param insns - the instruction stream of the statement
+     *    that established the control flow context
+     */
+    void finishLoopControlFlowContext(InstructionList insns)
+    {
+        LoopControlFlowContext current_context = popLoopControlFlowContext();
+
+        if ( current_context.hasActiveBreak() )
+            insns.labelNext(current_context.getBreakLabel());
+    }
+
+    /**
+     *  If a continue statement referenced the active CF context,
+     *  attach the continue target label to the target InstructionList.
+     *  @param continue_target - the InstructionList to continue to.
+     *  @pre The InstructionList must still be valid, i.e., it cannot
+     *    have been added to another InstructionList.  This forces 
+     *    resolveContinueLabel() calls further up the reduction logic
+     *    than finishControlFlowContext() calls, which are almost invariably
+     *    the last operation in a reduction.  resolveContinueLabel() 
+     *    calls are usually among the first operations in the reduction.
+     */
+    void resolveContinueLabel(InstructionList continue_target)
+    {
+        LoopControlFlowContext context = peekActiveLoopControlFlowContext();
+        if ( context.hasActiveContinue() )
+            continue_target.labelFirst(context.getContinueLabel());
+    }
+
+    /**
+     *  Called by a reduction's Prologue section 
+     *  to establish an active with scope.
+     */
+    void startWithContext(IASNode withContents)
+    {
+        WithContext with_context = new WithContext(withContents, this);
+
+        activeFlowContexts.add(with_context);
+    }
+
+    /**
+     *  Finish a with context; propagate the lifecycle event
+     *  to the with context, then pop it off the stack.
+     */
+    void finishWithContext(InstructionList result)
+    {
+        WithContext with_context = (WithContext) activeFlowContexts.lastElement();
+        with_context.finish(result);
+        popContext();
+    }
+
+    /**
+     *  @return the current with scope's temp storage.
+     *  @post The with scope will allocate a temp
+     *    if one was not previously allocated.
+     *  @see #hasWithStorage()
+     */
+    Binding getWithStorage()
+    {
+        WithContext with_context = (WithContext) activeFlowContexts.lastElement();
+        return with_context.getWithStorage();
+    }
+
+    /**
+     *  @return true if the current with scope
+     *    has allocated temporary storage for
+     *    its with scope.
+     */
+    boolean hasWithStorage()
+    {
+        WithContext with_context = (WithContext) activeFlowContexts.lastElement();
+        return with_context.hasWithStorage();
+    }
+
+    /**
+     *  @return true if the active control-flow contexts
+     *    contain any context that requires the caller to
+     *    cache a return value (i.e., exception handling 
+     *    contexts or with statement contexts).
+     */
+    boolean hasNontrivialFlowCharacteristics()
+    {
+        for ( ControlFlowContext ctx : activeFlowContexts )
+            if ( ctx instanceof WithContext || ctx instanceof ExceptionHandlingContext )
+                return true;
+
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DirectiveProcessor.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DirectiveProcessor.java b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DirectiveProcessor.java
new file mode 100644
index 0000000..6efcdc3
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DirectiveProcessor.java
@@ -0,0 +1,264 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.as.codegen;
+
+import java.util.Collection;
+
+
+
+import org.apache.flex.compiler.internal.tree.as.ClassNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.ImportNode;
+import org.apache.flex.compiler.internal.tree.as.InterfaceNode;
+import org.apache.flex.compiler.internal.tree.as.NamespaceIdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.PackageNode;
+import org.apache.flex.compiler.internal.tree.as.VariableNode;
+
+import static org.apache.flex.abc.ABCConstants.TRAIT_Getter;
+import static org.apache.flex.abc.ABCConstants.TRAIT_Setter;
+
+import org.apache.flex.compiler.problems.BURMDiagnosticNotAllowedHereProblem;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.mxml.IMXMLDocumentNode;
+
+
+/**
+ * A DirectiveProcessor is the outer shell of the code generator;
+ * the DirectiveProcessor contains logic to navigate the directives'
+ * ASTs, and subclasses implement "builder" methods to translate
+ * specific directives into ABC terms.
+ */
+class DirectiveProcessor
+{
+    private Collection<ICompilerProblem> problems = null;
+
+    protected DirectiveProcessor(Collection<ICompilerProblem> problems)
+    {
+        this.problems = problems;
+    }
+
+    /**
+     * Translate a ClassNode AST into ABC.
+     * Subclasses should override this if
+     * they can process class definitions.
+     * @param c - the class' AST.
+     */
+    void declareClass(ClassNode c)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(c));
+    }
+    
+    /**
+     * Translate an InterfaceNode AST into ABC.
+     * Subclasses should override this if
+     * they can process interface definitions.
+     * @param in - the interface's AST.
+     */
+    void declareInterface(InterfaceNode in)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(in));
+    }
+    
+    /**
+     * Translate a FunctionNode AST into ABC.
+     * Subclasses should override this if
+     * they can process function definitions.
+     * @param f - the function's AST.
+     */
+    void declareFunction(FunctionNode f)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(f));
+    }
+    
+    /**
+     * Translate a PackageNode AST into ABC.
+     * Subclasses should override this if
+     * they can process packages.
+     * @param p - the package's AST.
+     */
+    void declarePackage(PackageNode p)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(p));
+    }
+    
+    /**
+     * Translate a VaribleNode AST into ABC.
+     * Subclasses should override this if
+     * they can process variable definitions.
+     * @param var - the variable's AST.
+     * @param modifiers - static, const
+     */
+    void declareVariable(VariableNode var)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(var));
+    }
+
+    /**
+     * Translate a VaribleNode AST into ABC, and adding bindable support.
+     * Subclasses should override this if
+     * they can process bindable variable definitions.
+     * @param var - the variable's AST.
+     * @param modifiers - static, const
+     */
+    void declareBindableVariable(VariableNode var)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(var));
+    }
+
+    /**
+     * Translate an MXMLDocumentNode AST into ABC.
+     * Subclasses should override this if
+     * they can process document nodes.
+     * @param c - the document's AST.
+     */
+    void declareMXMLDocument(IMXMLDocumentNode d)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(d));
+    }
+
+    /**
+     * Translate other directives' ASTs into ABC.
+     * Subclasses should override this if
+     * they can process ad-hoc directives.
+     * @param n - the directive's AST.
+     */
+    void processDirective(IASNode n)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(n));
+    }
+    
+    /**
+     * Translate a NamespaceIdentifierNode AST into ABC.
+     * Subclasses should override this if
+     * they can process namespace identifiers.
+     * @param ns - the namespace identifier's AST.
+     */
+    void processNamespaceIdentifierDirective(NamespaceIdentifierNode ns)
+    {
+        problems.add(new BURMDiagnosticNotAllowedHereProblem(ns));
+    }
+    
+    /**
+     * Translate a ImportNode AST into ABC.
+     * Subclasses should override this if
+     * they can process imports.
+     * @param imp - the import's AST.
+     */
+    void processImportDirective(ImportNode imp)
+    {
+        processDirective(imp);
+    }
+
+    /**
+     * Look through a CONFIG block marker into its contents.
+     * @param n - the CONFIG block marker.
+     */
+    void processConfigBlock(IASNode n)
+    {
+        traverse(n);
+    }
+    
+    /**
+     * Traverse the children of a root node and process them.
+     * @param root - the root node.  The root is not processed.
+     */
+    void traverse(IASNode root)
+    {
+        for ( int i = 0; root != null && i < root.getChildCount(); i++ )
+        {
+            processNode(root.getChild(i));
+        }
+    }
+    
+    /**
+     * Process an individual directive.
+     * @param n - the directive's AST.
+     */
+    void processNode(IASNode n)
+    {
+        // In malformed trees, children can be null.
+        // For example, an MXMLFileNode may not have an MXMLDocumentNode.
+        if (n == null)
+            return;
+        
+        switch ( n.getNodeID() )
+        {
+            case ClassID:
+                declareClass((ClassNode)n);
+                break;
+            case InterfaceID:
+                declareInterface((InterfaceNode)n);
+                break;
+            case FunctionID:
+            case GetterID:
+            case SetterID:
+                declareFunction((FunctionNode)n);
+                break;
+            case ImportID:
+                processImportDirective((ImportNode)n);
+                break;
+            case NamespaceIdentifierID:
+                processNamespaceIdentifierDirective((NamespaceIdentifierNode)n);
+                break;
+            case PackageID:
+                declarePackage((PackageNode)n);
+                break;
+            case VariableID:
+                declareVariable((VariableNode)n);
+                break;
+            case BindableVariableID:
+                declareBindableVariable((VariableNode)n);
+                break;
+            case MXMLDocumentID:
+                declareMXMLDocument((IMXMLDocumentNode)n);
+                break;
+            case MetaTagsID:
+                break;
+            case ConfigBlockID:
+                processConfigBlock(n);
+                break;
+            default:
+                processDirective(n);
+        }
+    }
+    
+    /**
+     *  Getter/Setter functions need to be declared with a specific
+     *  trait kind; do so here.
+     *  @param func - a FunctionNode.
+     *  @param default_kind - the trait kind to use if the function
+     *    is not a getter or setter.  Varies depending on caller's context.
+     *  @return the trait kind to use to declare the input function.
+     */
+    public static int functionTraitKind(FunctionNode func, int default_kind)
+    {
+        switch(func.getNodeID())
+        {
+            case GetterID:
+                return TRAIT_Getter;
+            case SetterID:
+                return TRAIT_Setter;
+            default:
+                return default_kind;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DumpBURMState.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DumpBURMState.java b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DumpBURMState.java
new file mode 100644
index 0000000..e1a5f28
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/DumpBURMState.java
@@ -0,0 +1,80 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.as.codegen;
+
+import java.io.File;
+import java.util.Date;
+
+import org.apache.flex.compiler.internal.testing.NodesToXMLStringFormatter;
+import org.apache.flex.compiler.tree.as.IASNode;
+
+/**
+ * Class containing debug code that dumps BURM state to an XML file.
+ */
+final class DumpBURMState
+{
+    static void dump(CmcEmitter burm, IASNode n)
+    {
+        // un-comment the following line to enable dumping of BURM errors.
+        // doDump(burm, n);
+    }
+    
+    /**
+     * Helper method that dumps BURM state to aid in debugginer BURM errors.
+     * There should be no calls to this method checked into version control.
+     * @param burm
+     * @param n
+     */
+    @SuppressWarnings("unused")
+    private static synchronized void doDump(CmcEmitter burm, IASNode n)
+    {
+        java.io.PrintWriter dumper;
+        
+ 
+        try
+        {
+            File dump_file = File.createTempFile("failedBurm-", ".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)
+        {
+            System.err.println("Unable to dump due to: " + e.toString());
+            try
+            {
+                System.err.println(new NodesToXMLStringFormatter(n).toString());
+            } 
+            catch ( Exception cantformat)
+            {
+                //  Probably an error in the AST itself, diagnosed above.
+            }
+        }
+        
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ExceptionHandlingContext.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ExceptionHandlingContext.java b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ExceptionHandlingContext.java
new file mode 100644
index 0000000..8a5660e
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/ExceptionHandlingContext.java
@@ -0,0 +1,301 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.as.codegen;
+
+import java.util.Vector;
+
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.abc.semantics.Label;
+
+import static org.apache.flex.abc.ABCConstants.*;
+
+
+/**
+ *  An ExceptionHandlingContext manages the tree-crossing
+ *  state of a try/catch/finally composite statement; its
+ *  actual processing state (try, catch, and finally have
+ *  slightly different requirements), and most importantly
+ *  the return instruction fragments for the finally block's
+ *  "callers."
+ */
+public final class ExceptionHandlingContext extends ControlFlowContext
+{
+
+    /**
+     *  @param flow_mgr - the flow manager that owns this context.
+     */
+    ExceptionHandlingContext( ControlFlowContextManager flow_mgr)
+    {
+        super(null);
+        this.flowMgr = flow_mgr;
+    }
+
+    /**
+     *  The flow manager that owns this context.
+     *  Used to find the associated LexicalScope and
+     *  allocate temporaries.
+     */
+    ControlFlowContextManager flowMgr;
+
+    /**
+     *  The finally block's label, if there is a finally block.
+     */
+    Label finallyBlock = null;
+
+    /**
+     *  The "error return" from the finally.
+     */
+    Label finallyDoRethrow = null;
+
+    /**
+     *  The "normal return" from the finally.
+     */
+    Label finallyDoFallthrough = null;
+
+    /**
+     *  A local set to a distinct value by each caller;
+     *  corresponds with the position of that caller's 
+     *  finally return fragment in the returns array.
+     */
+    Binding finallyReturnStorage = null;
+
+    /**
+     *  A local used to store the exception scope; needed to
+     *  restore nested exception scopes in an inner catch.
+     */
+    Binding exceptionStorage = null;
+
+    /**
+     *  The possible states of the exception-handling context.
+     *  There's an edge from TRY to FINALLY, from FINALLY to 
+     *  CATCH, and from TRY to CATCH (if there's no FINALLY).
+     *  @see #setFinallyControlState(boolean)
+     *  @see #setCatchControlState(boolean)
+     */
+    enum TryCatchFinallyState
+    {
+        INITIAL,
+        TRY,
+        FINALLY,
+        CATCH
+    };
+
+    /**
+     *  This exception-handling context's state.
+     */
+    TryCatchFinallyState tryCatchFinallyState = TryCatchFinallyState.INITIAL;
+
+    /**
+     *  Finally return fragments and their labels.
+     *  The labels go into the finally's concluding
+     *  lookupswitch a.k.a. computed GOTO instruction.
+     */
+    public static class FinallyReturn 
+    {
+        Label finallyLabel;
+        InstructionList finallyInsns;
+
+        FinallyReturn(Label label, InstructionList list)
+        {
+            this.finallyLabel = label;
+            this.finallyInsns = list;
+        }
+
+        Label getLabel()
+        { 
+            return finallyLabel;
+        }
+
+        InstructionList getInstructions()
+        {
+            return finallyInsns;
+        }
+    };
+
+    /**
+     *  The marshalled finally returns.
+     *  @warn order is significant; the order here must match
+     *    the order of the callers' "return index" saved into
+     *    the finallyReturnStorage local.
+     *  @see finallyReturnStorage
+     */
+    Vector<FinallyReturn> finallyReturns = null;
+
+    /**
+     *  true => this exception handling context has a finally block.
+     */
+    boolean hasFinally = false;
+
+    @Override
+    InstructionList addExitPath(InstructionList exitBranch)
+    {
+        InstructionList result = exitBranch;
+        
+        //  Enter any finally blocks
+        //  that are not already active.
+        if ( hasFinallyBlock() )
+        {
+            if ( ! isActiveFinally() )
+                result = addFinallyReturn(result);
+            
+        }
+
+        //  Pop the scope of any active catch blocks.
+        if ( isActiveCatchBlock() )
+        {
+            InstructionList catch_fixup = new InstructionList();
+            catch_fixup.addInstruction(OP_popscope);
+            catch_fixup.addInstruction(getExceptionStorage().kill());
+
+            catch_fixup.addAll(result);
+            result = catch_fixup;
+        }
+        return result;
+    }
+    
+    @Override
+    void addExceptionHandlerEntry(InstructionList exceptionHandler)
+    {
+        if ( isActiveCatchBlock() )
+        {
+            exceptionHandler.addInstruction(getExceptionStorage().getlocal());
+            exceptionHandler.addInstruction(OP_pushscope);
+        }
+    }
+
+
+
+    /**
+     *  Add a return fragment to the active finally clause.
+     *  @param retblock - the instructions that make up the 
+     *    finally return sequence.
+     *  @return the substitute return sequence that sets up
+     *    the finallyReturnStorage local and jumps to the 
+     *    finally block.
+     */
+    private InstructionList addFinallyReturn(InstructionList retblock)
+    {
+        assert(this.finallyReturns != null): "Not a finally context.";
+
+        Label retblock_label = new Label();
+        retblock.labelFirst(retblock_label);
+        finallyReturns.add(new FinallyReturn(retblock_label, retblock));
+
+        InstructionList result = new InstructionList();
+        CmcEmitter.pushNumericConstant(finallyReturns.size(), result);
+        result.addInstruction(OP_coerce_a);
+        result.addInstruction(finallyReturnStorage.setlocal());
+        result.addInstruction(OP_jump, finallyBlock);
+        return result;
+    }
+
+    /**
+     *  @return this exception-handling context's exceptionStorage local.
+     *  @note generated on demand.
+     */
+    public Binding getExceptionStorage()
+    {
+        if ( this.exceptionStorage == null )
+            this.exceptionStorage = flowMgr.currentScope.allocateTemp();
+        return this.exceptionStorage;
+    }
+
+    /**
+     * Transition from the initial state into the try processing state. There is
+     * no method to end the try control state because the BURM does not have
+     * reduction for the try block, instead we implicitly end the try processing
+     * state when we start a finally or catch processing state.
+     */
+    void startTryControlState()
+    {
+        assert ( this.tryCatchFinallyState == TryCatchFinallyState.INITIAL );
+        this.tryCatchFinallyState = TryCatchFinallyState.TRY;
+    }
+
+    /**
+     *  Transition into the finally processing state.
+     */
+    void startFinallyControlState()
+    {
+        assert ( this.tryCatchFinallyState == TryCatchFinallyState.TRY );
+        this.tryCatchFinallyState = TryCatchFinallyState.FINALLY;
+    }
+    
+    /**
+     * Transition out of the finally processing state into
+     * the catch state.
+     */
+    void endFinallyControlState()
+    {
+        assert ( this.tryCatchFinallyState == TryCatchFinallyState.FINALLY );
+        this.tryCatchFinallyState = TryCatchFinallyState.CATCH;
+    }
+
+    /**
+     * Enter the catch control state.
+     */
+    void startCatchControlState()
+    {
+        //  All of the three processing states
+        //  are valid previous states.
+        this.tryCatchFinallyState = TryCatchFinallyState.CATCH;
+    }
+    
+    void endCatchControlState()
+    {
+        assert (TryCatchFinallyState.CATCH == this.tryCatchFinallyState) :
+            "leaving catch, but control state is " + this.tryCatchFinallyState;
+    }
+
+    /**
+     *  @return true if the exception handling context is in
+     *    catch processing state.
+     */
+    private boolean isActiveCatchBlock()
+    {
+        return TryCatchFinallyState.CATCH == this.tryCatchFinallyState;
+    }
+
+    /**
+     *  @return true if the exception handling context is in
+     *    finally processing state.
+     */
+    private boolean isActiveFinally()
+    {
+        return TryCatchFinallyState.FINALLY == this.tryCatchFinallyState;
+    }
+
+    /**
+     * @return true if the exception handling context has a finally block.
+     */
+    private boolean hasFinallyBlock()
+    {
+        return this.hasFinally;
+    }
+
+    /**
+     * Marks this context as having a finally block.
+     * @param has_finally true if this context has a finally block, false otherwise.
+     */
+    void setHasFinallyBlock(boolean has_finally)
+    {
+        this.hasFinally = has_finally;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GenerateFunctionInParallelResult.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GenerateFunctionInParallelResult.java b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GenerateFunctionInParallelResult.java
new file mode 100644
index 0000000..01e3abc
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GenerateFunctionInParallelResult.java
@@ -0,0 +1,77 @@
+/*
+ *
+ *  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 org.apache.flex.abc.semantics.MethodInfo;
+import org.apache.flex.abc.visitors.IVisitor;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * Object that is returned by
+ * {@link org.apache.flex.compiler.internal.as.codegen.ICodeGenerator#generateFunctionInParallel(java.util.concurrent.ExecutorService, org.apache.flex.compiler.internal.tree.as.FunctionNode, LexicalScope)}
+ * .
+ * <p>
+ * A wad containing the future for the code generation work happening in
+ * parallel and the method info for the function being generated.
+ */
+public class GenerateFunctionInParallelResult
+{
+    GenerateFunctionInParallelResult (Future<?> future, MethodInfo methodInfo, List<IVisitor> deferredVisitEndsList)
+    {
+        assert future != null;
+        assert methodInfo != null;
+        this.future = future;
+        this.methodInfo = methodInfo;
+        this.deferredVisitEnds = deferredVisitEndsList;
+    }
+
+    private final Future<?> future;
+    private final MethodInfo methodInfo;
+    private final List<IVisitor> deferredVisitEnds;
+
+    /**
+     * Blocks until the code generation work that this object corresponds to
+     * is completed.
+     */
+    public void finish() throws InterruptedException, ExecutionException
+    {
+        future.get();
+        for (IVisitor v : deferredVisitEnds)
+        {
+            v.visitEnd();
+        }
+    }
+
+    /**
+     * Gets the {@link org.apache.flex.abc.semantics.MethodInfo} for the function for which code is being
+     * generated. Thie method may be called immediately after this object is
+     * constructed.
+     *
+     * @return The {@link org.apache.flex.abc.semantics.MethodInfo} for the function for which code is
+     * being generated.
+     */
+    public MethodInfo getMethodInfo()
+    {
+        return methodInfo;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GlobalDirectiveProcessor.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GlobalDirectiveProcessor.java b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GlobalDirectiveProcessor.java
new file mode 100644
index 0000000..5a7c499
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/internal/as/codegen/GlobalDirectiveProcessor.java
@@ -0,0 +1,558 @@
+/*
+ *
+ *  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 org.apache.flex.abc.ABCConstants;
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.abc.semantics.MethodInfo;
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.visitors.IABCVisitor;
+import org.apache.flex.abc.visitors.ITraitVisitor;
+import org.apache.flex.abc.visitors.ITraitsVisitor;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.ModifiersSet;
+import org.apache.flex.compiler.constants.IMetaAttributeConstants;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.internal.definitions.ClassDefinition;
+import org.apache.flex.compiler.internal.definitions.DefinitionBase;
+import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
+import org.apache.flex.compiler.internal.definitions.TypeDefinitionBase;
+import org.apache.flex.compiler.internal.projects.CompilerProject;
+import org.apache.flex.compiler.internal.semantics.SemanticUtils;
+import org.apache.flex.compiler.internal.tree.as.ClassNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.InterfaceNode;
+import org.apache.flex.compiler.internal.tree.as.NamespaceIdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.PackageNode;
+import org.apache.flex.compiler.internal.tree.as.VariableNode;
+import org.apache.flex.compiler.internal.tree.mxml.MXMLDocumentNode;
+import org.apache.flex.compiler.problems.DynamicNotOnClassProblem;
+import org.apache.flex.compiler.problems.EmbedOnlyOnClassesAndVarsProblem;
+import org.apache.flex.compiler.problems.FinalOutsideClassProblem;
+import org.apache.flex.compiler.problems.GlobalBindablePropertyProblem;
+import org.apache.flex.compiler.problems.InterfaceModifierProblem;
+import org.apache.flex.compiler.problems.NativeNotOnFunctionProblem;
+import org.apache.flex.compiler.problems.NativeVariableProblem;
+import org.apache.flex.compiler.problems.OverrideOutsideClassProblem;
+import org.apache.flex.compiler.problems.StaticOutsideClassProblem;
+import org.apache.flex.compiler.problems.VirtualOutsideClassProblem;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.tree.mxml.IMXMLDocumentNode;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * A GlobalDirectiveProcessor translates directives at
+ * global scope into ABC.
+ */
+class GlobalDirectiveProcessor extends DirectiveProcessor
+{
+    /** Instructions to implement directives as they're encountered. */
+    InstructionList directiveInsns = new InstructionList();
+    
+    /** The top of the lexical scope chain. */
+    protected LexicalScope currentScope;
+    
+    /** The AET emitter generating code for this script. */
+    protected IABCVisitor emitter;
+
+    /** 
+     *  Set when processing a package, which inplies some different
+     *  strategies for declaring traits.
+     */
+    protected boolean processingPackage = false;
+    
+    private final List<GenerateFunctionInParallelResult> parallelCodeGenList;
+    
+    /**
+     * {@link ExecutorService} used to generation function
+     * bodies in background threads.
+     */
+    private final ExecutorService executorService;
+    
+    /**
+     * Flag to enabling or disabling use of background threads
+     * to generate function bodies.
+     */
+    private final boolean useParallelCodeGen;
+
+    /**
+     * @param current_scope the scope to use. It may be created a priori by the
+     * caller, so it's not created by nesting an enclosing scope.
+     * @param emitter the ABC emitter.
+     */
+    GlobalDirectiveProcessor(LexicalScope current_scope, IABCVisitor emitter)
+    {
+        this(null, false, current_scope, emitter);
+    }
+    
+    /**
+     * @param executorService {@link ExecutorService} used to schedule
+     * generation of function bodies on background threads. This may be null if
+     * useParallelCodeGen is false.
+     * @param useParallelCodeGen Flag to enabling or disabling use of background
+     * threads to generate function bodies.
+     * @param current_scope the scope to use. It may be created a priori by the
+     * caller, so it's not created by nesting an enclosing scope.
+     * @param emitter the ABC emitter.
+     */
+    GlobalDirectiveProcessor(ExecutorService executorService, boolean useParallelCodeGen, LexicalScope current_scope, IABCVisitor emitter)
+    {
+        super(current_scope.getProblems());
+        assert (!useParallelCodeGen) || (executorService != null) : "Parallel code generation requires access to an ExecutorService";
+        
+        this.currentScope = current_scope;
+        this.emitter = emitter;
+        this.parallelCodeGenList = new LinkedList<GenerateFunctionInParallelResult>();
+        this.executorService = executorService;
+        this.useParallelCodeGen = useParallelCodeGen;
+    }
+    
+    /**
+     * Start generation of the specified function in a background thread if
+     * parallel code generation is enabled, otherwise generate code for the
+     * specified function in the calling thread
+     * 
+     * @param f Function to generate code for.
+     * @return {@link MethodInfo} for the specified function.
+     */
+    private MethodInfo startFunctionGeneration(FunctionNode f)
+    {
+        if (this.useParallelCodeGen)
+        {
+            assert this.executorService != null : "Parallel codegen requires an ExecutorService!";
+            final GenerateFunctionInParallelResult parallelCodeGen =
+                currentScope.getGenerator().generateFunctionInParallel(this.executorService, f, this.currentScope);
+            
+            this.parallelCodeGenList.add(parallelCodeGen);
+            
+            return parallelCodeGen.getMethodInfo();
+        }
+        else
+        {
+            f.parseFunctionBody(currentScope.getProblems());
+            return currentScope.getGenerator().generateFunction(f, this.currentScope, null, null);
+        }
+    }
+    
+    /**
+     * Declare a function.
+     */
+    @Override
+    void declareFunction(FunctionNode f)
+    {
+        verifyFunctionModifiers(f);
+
+        final MethodInfo mi = startFunctionGeneration(f);
+        if ( mi != null )
+        {
+            FunctionDefinition funcDef = f.getDefinition();
+            Name funcName = funcDef.getMName(this.currentScope.getProject());
+            
+            SemanticUtils.checkScopedToDefaultNamespaceProblem(this.currentScope, f, funcDef, null);
+            
+
+            boolean conflictsWithOtherDefinition = false;
+            if ( funcName == null )
+            {
+                //  getMName() emitted a diagnostic, 
+                //  repair and continue.
+                funcName = new Name("<invalid>");
+            }
+            else
+            {
+                conflictsWithOtherDefinition = currentScope.getMethodBodySemanticChecker().checkFunctionForConflictingDefinitions(f, funcDef);
+            }
+       
+            ITraitVisitor tv = null;
+
+            int traitKind = this.processingPackage?
+                DirectiveProcessor.functionTraitKind(f, ABCConstants.TRAIT_Method):
+                DirectiveProcessor.functionTraitKind(f, ABCConstants.TRAIT_Var);
+
+            if (! this.currentScope.traitsVisitor.getTraits().containsTrait(traitKind, funcName) )
+            {
+                this.currentScope.declareVariableName(funcName);
+
+                if ( ! this.processingPackage )
+                {
+                    if ( f.isGetter() || f.isSetter() )
+                    {
+                        tv = this.currentScope.traitsVisitor.visitMethodTrait(
+                            traitKind, 
+                            funcName, 
+                            ITraitsVisitor.RUNTIME_DISP_ID,
+                            mi);
+                        assert tv != null : "visitMethodTrait should never return null!";
+                    }
+                    else
+                    {
+                        tv = this.currentScope.traitsVisitor.visitSlotTrait(
+                            traitKind,
+                            funcName,
+                            ITraitsVisitor.RUNTIME_SLOT,
+                            LexicalScope.anyType,
+                            LexicalScope.noInitializer);
+                        assert tv != null : "visitSlotTrait should never return null!";
+    
+                        this.currentScope.getInitInstructions().addInstruction(ABCConstants.OP_getglobalscope);
+                        this.currentScope.getInitInstructions().addInstruction(ABCConstants.OP_newfunction, mi);
+                        this.currentScope.getInitInstructions().addInstruction(ABCConstants.OP_setproperty, funcName);
+                    }
+                    
+    
+                }
+                else
+                {
+                    tv = this.currentScope.traitsVisitor.visitMethodTrait(traitKind, funcName, 0, mi);
+                    assert tv != null : "visitMethodTrait should never return null!";
+                }
+                
+                if ( tv != null )
+                {
+                    this.currentScope.processMetadata(tv, funcDef.getAllMetaTags());
+                    tv.visitEnd();
+                }
+            }
+            else if (!conflictsWithOtherDefinition)
+            {
+                // Duplicate that is not a "conflict" - must be a global, where dupes are "allowed" as 
+                // per ECMA
+                // In strict mode (only) we issue a warning for this. Which is the behavior of the old compiler
+                // (as well as being the "right" thing to do)
+                
+                // But - our simple criteria for "conflicts with other definitions" will give a false positive for
+                // Getter/setter pairs, so only emit the warning if this is not the case.
+                //
+                // Updater: the warning is detected elsewhere, so all we are doing here is
+                // generating code to create the new function as per ECMAS
+
+                ICompilerProject project = currentScope.getProject();
+                List<IDefinition> defs = SemanticUtils.findPotentialFunctionConflicts(project, funcDef);
+
+                if (!SemanticUtils.isGetterSetterPair(defs, project))
+                {
+                    // This is a new funciton, so generate code for it
+                    //  Add initialization logic to the init instructions.
+                    if ( ! ( this.processingPackage || f.isGetter() || f.isSetter() ) )
+                    {
+                        this.currentScope.getInitInstructions().addInstruction(ABCConstants.OP_getglobalscope);
+                        this.currentScope.getInitInstructions().addInstruction(ABCConstants.OP_newfunction, mi);
+                        this.currentScope.getInitInstructions().addInstruction(ABCConstants.OP_setproperty, funcName);
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * validate the modifiers used on a function decl.
+     */
+    protected void verifyFunctionModifiers(FunctionNode f)
+    {
+        ModifiersSet modifiersSet = f.getModifiers();
+        if (modifiersSet == null)
+            return;
+
+        ASModifier[] modifiers = modifiersSet.getAllModifiers();
+        IExpressionNode site = f.getNameExpressionNode();
+        for (ASModifier modifier : modifiers)
+        {
+            verifyModifier(site, modifier);
+        }
+        currentScope.getMethodBodySemanticChecker().checkForDuplicateModifiers(f);
+    }
+
+    /**
+     * validate the modifiers used on a var decl
+     */
+    protected void verifyVariableModifiers(VariableNode v)
+    {
+        ModifiersSet modifiersSet = v.getModifiers();
+        if (modifiersSet == null)
+            return;
+
+        ASModifier[] modifiers = modifiersSet.getAllModifiers();
+        IExpressionNode site = v.getNameExpressionNode();
+        for (ASModifier modifier : modifiers)
+        {
+            // native on a variable generates a different error
+            if (modifier == ASModifier.NATIVE)
+            {
+                currentScope.addProblem(new NativeVariableProblem(site));
+            }
+            else if( modifier == ASModifier.DYNAMIC )
+            {
+                currentScope.addProblem(new DynamicNotOnClassProblem(site));
+            }
+            else
+            {
+                verifyModifier(site, modifier);
+            }
+        }
+        currentScope.getMethodBodySemanticChecker().checkForDuplicateModifiers(v);
+    }
+
+    /**
+     * validate the modifiers used on a class decl
+     */
+    protected void verifyClassModifiers(ClassNode c)
+    {
+        ModifiersSet modifiersSet = c.getModifiers();
+        if (modifiersSet == null)
+            return;
+
+        ASModifier[] modifiers = modifiersSet.getAllModifiers();
+        IExpressionNode site = c.getNameExpressionNode();
+        for (ASModifier modifier : modifiers)
+        {
+            // final allowed on a class
+            if( modifier == ASModifier.FINAL || modifier == ASModifier.DYNAMIC)
+            {
+                continue;
+            }
+            // native generates different error for class/interface
+            else if (modifier == ASModifier.NATIVE)
+            {
+                currentScope.addProblem(new NativeNotOnFunctionProblem(site) );
+            }
+            else
+            {
+                verifyModifier(site, modifier);
+            }
+        }
+        currentScope.getMethodBodySemanticChecker().checkForDuplicateModifiers(c);
+    }
+
+    /**
+     * validate the skinning data used on a class decl
+     */
+    protected void verifySkinning(ClassDefinition classDefinition)
+    {
+        // call these skinPart/skinState methods to collect any problems
+        // with the metadata.
+        classDefinition.getSkinParts(currentScope.getProblems());
+        classDefinition.getSkinStates(currentScope.getProblems());
+
+        classDefinition.verifyHostComponent((CompilerProject)currentScope.getProject(), currentScope.getProblems());
+    }
+
+    /**
+     * Validate the modifiers used on an interface decl
+     */
+    protected void verifyInterfaceModifiers(InterfaceNode i)
+    {
+        ModifiersSet modifiersSet = i.getModifiers();
+        if (modifiersSet == null)
+            return;
+
+        ASModifier[] modifiers = modifiersSet.getAllModifiers();
+        IExpressionNode site = i.getNameExpressionNode();
+        for (ASModifier modifier : modifiers)
+        {
+            // final generates a different error for an interface
+            if( modifier == ASModifier.FINAL || modifier == ASModifier.DYNAMIC)
+            {
+                currentScope.addProblem(new InterfaceModifierProblem(site, modifier.toString()));
+            }
+            // native generates different error for class/interface
+            else if (modifier == ASModifier.NATIVE)
+            {
+                currentScope.addProblem(new NativeNotOnFunctionProblem(site) );
+                //  ASC also emits this for good measure.
+                currentScope.addProblem(new InterfaceModifierProblem(site, modifier.toString()));
+            }
+            else
+            {
+                verifyModifier(site, modifier);
+            }
+        }
+        currentScope.getMethodBodySemanticChecker().checkForDuplicateModifiers(i);
+    }
+
+    /**
+     * verify a modifier used in global scope - issues errors that are common for all different decls
+     * at this scope.
+     * @param site      location to use if a problem is reported
+     * @param modifier  the modifier to check
+     */
+    protected void verifyModifier(IASNode site, ASModifier modifier)
+    {
+        if( modifier == ASModifier.STATIC )
+            currentScope.addProblem(new StaticOutsideClassProblem(site));
+        else if( modifier == ASModifier.FINAL )
+            currentScope.addProblem(new FinalOutsideClassProblem(site));
+        else if( modifier == ASModifier.OVERRIDE )
+            currentScope.addProblem(new OverrideOutsideClassProblem(site));
+        else if( modifier == ASModifier.VIRTUAL )
+            currentScope.addProblem(new VirtualOutsideClassProblem(site));
+    }
+
+    /**
+     * Declare a class.
+     */
+    @Override
+    void declareClass(ClassNode c)
+    {
+        verifyClassModifiers(c);
+        verifySkinning(c.getDefinition());
+        currentScope.getMethodBodySemanticChecker().checkNamespaceOfDefinition(c, c.getDefinition(), currentScope.getProject());
+        ClassDirectiveProcessor cp = new ClassDirectiveProcessor(c, this.currentScope, this.emitter);
+        cp.traverse(c.getScopedNode());
+        cp.finishClassDefinition();
+    }
+
+    /**
+     * Declare an interface.
+     */
+    @Override
+    void declareInterface(InterfaceNode interface_ast)
+    {
+        verifyInterfaceModifiers(interface_ast);
+        currentScope.getMethodBodySemanticChecker().checkNamespaceOfDefinition(interface_ast, interface_ast.getDefinition(), currentScope.getProject());
+        InterfaceDirectiveProcessor ip = new InterfaceDirectiveProcessor(interface_ast, this.currentScope, this.emitter);
+        ip.traverse(interface_ast.getScopedNode());
+        ip.finishInterfaceDefinition();
+    }
+    
+    /**
+     * "Declare" a package.
+     */
+    @Override
+    void declarePackage(PackageNode p)
+    {
+        try
+        {
+            this.processingPackage = true;
+            traverse(p.getScopedNode());
+        }
+        finally
+        {
+            this.processingPackage = false;
+        }
+    }
+    
+    /**
+     * Declare a variable.
+     */
+    @Override
+    void declareVariable(VariableNode var)
+    {
+        verifyVariableModifiers(var);
+
+        if (var.getMetaTags() != null && var.getMetaTags().hasTagByName(IMetaAttributeConstants.ATTRIBUTE_EMBED))
+        {
+            currentScope.addProblem(new EmbedOnlyOnClassesAndVarsProblem(var));
+        }
+
+        DefinitionBase varDef = var.getDefinition();
+        SemanticUtils.checkScopedToDefaultNamespaceProblem(this.currentScope, var, varDef, null);
+        if ( var.hasModifier(ASModifier.STATIC))
+        {
+            
+            ICompilerProject project = this.currentScope.getProject();
+
+            Name var_name = varDef.getMName(project);
+
+            TypeDefinitionBase typeDef = (TypeDefinitionBase)varDef.resolveType(project);
+            Name var_type = typeDef != null ? typeDef.getMName(project) : null;
+            
+            //  It's not necessary to check for duplicates
+            //  in the traits because that is a semantic error
+            //  in this context.
+            ITraitVisitor tv = this.currentScope.traitsVisitor.visitSlotTrait(ABCConstants.TRAIT_Const, var_name, ITraitsVisitor.RUNTIME_SLOT, var_type, LexicalScope.noInitializer);
+            this.currentScope.declareVariableName(var_name);
+            this.currentScope.processMetadata(tv, varDef.getAllMetaTags());
+            tv.visitEnd();
+        }
+        //  Run the BURM to process any initialization instructions.
+        processDirective(var);
+    }
+
+    /**
+     * Declare a bindable variable.
+     */
+    @Override
+    void declareBindableVariable(VariableNode var)
+    {
+        currentScope.addProblem(new GlobalBindablePropertyProblem(var));
+    }
+
+    /**
+     * Declare an MXML document.
+     */
+    @Override
+    void declareMXMLDocument(IMXMLDocumentNode d)
+    {
+        verifySkinning((ClassDefinition)d.getDefinition());
+        MXMLClassDirectiveProcessor dp = new MXMLClassDirectiveProcessor(d, this.currentScope, this.emitter);
+        ((MXMLDocumentNode)d).cdp = dp;
+        dp.processMainClassDefinitionNode(d);
+        dp.finishClassDefinition();
+    }
+
+    /**
+     * Process a namespace directive.
+     */
+    @Override
+    void processNamespaceIdentifierDirective(NamespaceIdentifierNode ns)
+    {
+        traverse(ns);
+    }
+    
+    /**
+     * Process a random directive, which at the global level
+     * is probably a loose instruction.
+     */
+    @Override
+    void processDirective(IASNode n)
+    {
+        //  Handle a loose statement.
+        InstructionList stmt_insns = currentScope.getGenerator().generateInstructions(n, CmcEmitter.__statement_NT, currentScope);
+        if ( stmt_insns != null )
+            directiveInsns.addAll(stmt_insns);
+    }
+    
+    /**
+     * Block until all function generation is complete and flush all ABC data to
+     * the {@link IABCVisitor} we are generating code into.
+     * 
+     * @throws InterruptedException
+     */
+    void finish() throws InterruptedException
+    {
+        try
+        {
+            for (GenerateFunctionInParallelResult parallelCodeGen : this.parallelCodeGenList)
+            {
+                parallelCodeGen.finish();
+            }
+        }
+        catch (ExecutionException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+    }
+}


Mime
View raw message