incubator-flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject svn commit: r1413061 [10/14] - in /incubator/flex/falcon/trunk/compiler.js: ./ bin/ build/ in/ intermediates/ localization/ localization/src/ localization/src/org/ localization/src/org/apache/ localization/src/org/apache/flex/ localization/src/org/apac...
Date Fri, 23 Nov 2012 20:58:56 GMT
Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGeneratingReducer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGenerator.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGenerator.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGenerator.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGenerator.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,706 @@
+/*
+ *
+ *  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_returnvoid;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Vector;
+
+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.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.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.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.units.ICompilationUnit;
+import org.apache.flex.compiler.units.ICompilationUnit.Operation;
+import org.apache.flex.compiler.units.requests.IABCBytesRequestResult;
+
+/**
+ * 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
+{
+    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
+    {
+        m_needsSecondPass = false;
+        m_emitter = JSSharedData.backend.createEmitter(m_buildPhase, project);
+        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, null, 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);
+            mi = generateMethodBodyForFunction(mi, func, enclosing_scope, a_priori_insns);
+            m_burm.endFunction(func);
+        }
+
+        return mi;
+    }
+
+    /**
+     * 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).
+     */
+    MethodInfo generateMethodBodyForFunction(MethodInfo mi, IASNode node,
+            LexicalScope enclosing_scope,
+            InstructionList a_priori_insns)
+    {
+        return 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);
+
+        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;
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * 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 Object 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 result;
+    }
+
+    /**
+     * 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;
+    }
+
+}

Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGlobalDirectiveProcessor.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGlobalDirectiveProcessor.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGlobalDirectiveProcessor.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGlobalDirectiveProcessor.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,323 @@
+/*
+ *
+ *  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.IClassVisitor;
+import org.apache.flex.abc.visitors.ITraitVisitor;
+import org.apache.flex.abc.visitors.ITraitsVisitor;
+import org.apache.flex.compiler.common.DependencyType;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
+import org.apache.flex.compiler.internal.scopes.ASScope;
+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.PackageNode;
+import org.apache.flex.compiler.internal.tree.as.VariableNode;
+import org.apache.flex.compiler.problems.DuplicateFunctionDefinitionProblem;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.scopes.IASScope;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+
+/**
+ * A GlobalDirectiveProcessor translates directives at global scope into ABC.
+ * JSGlobalDirectiveProcessor is derived from GlobalDirectiveProcessor and adds
+ * workarounds necessary for FalconJS. Ideally FalconJS should use
+ * GlobalDirectiveProcessor and retire JSGlobalDirectiveProcessor. This
+ * implementation is part of FalconJS. For more details on FalconJS see
+ * org.apache.flex.compiler.JSDriver
+ */
+public class JSGlobalDirectiveProcessor extends GlobalDirectiveProcessor
+{
+    JSGenerator m_generator;
+
+    private String m_packageName = null;
+
+    /**
+     * @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.
+     */
+    public JSGlobalDirectiveProcessor(JSGenerator generator, LexicalScope current_scope, IABCVisitor emitter)
+    {
+        super(current_scope, emitter);
+        m_generator = generator;
+    }
+
+    @Override
+    void declareFunction(FunctionNode f)
+    {
+        //  No modifiers allowed at global scope.
+        // super.verifyModifiers(f);
+
+        // MISSING in GlobalDirectiveProcessor
+        MethodInfo mi = m_generator.generateFunction(f, currentScope, null);
+        if (mi != null)
+        {
+            FunctionDefinition funcDef = f.getDefinition();
+            JSSharedData.instance.registerDefinition(funcDef);
+
+            // TODO: generalize excluding functions using metadata annotations.
+            final String packageName = funcDef.getPackageName();
+            if (!packageName.equals("com.jquery"))
+            {
+                final IClassVisitor cv = ((JSEmitter)emitter).visitPackage(m_packageName);
+                cv.visit();
+                this.currentScope.traitsVisitor = cv.visitClassTraits();
+                cv.visitEnd();
+                /*
+                 * InstanceInfo iinfo = new InstanceInfo(); iinfo.name =
+                 * JSGeneratingReducer.makeName(packageName); IClassVisitor cv =
+                 * emitter.visitClass(iinfo, new ClassInfo()); cv.visit();
+                 * cv.visitInstanceTraits(); ITraitsVisitor ctraits =
+                 * cv.visitClassTraits(); final Name funcName =
+                 * funcDef.getMName(currentScope.getProject(),
+                 * currentScope.getProblems()); final ITraitVisitor tv =
+                 * ctraits.visitMethodTrait(TRAIT_Method, funcName, 0, mi);
+                 * tv.visitAttribute(Trait.TRAIT_FINAL, Boolean.TRUE);
+                 */
+                /*
+                 * final String key = packageName; ICompilationUnit cu =
+                 * m_generator.m_compilationUnit; ICompilationUnit registeredCU
+                 * = JSSharedData.instance.getCompilationUnit(key); if( cu !=
+                 * registeredCU ) { // make the current cu dependent on the
+                 * registered cu. if( registeredCU != null ) { final
+                 * CompilerProject compilerProject =
+                 * (CompilerProject)cu.getProject();
+                 * compilerProject.addDependency(cu, registeredCU,
+                 * DependencyType.INHERITANCE); } else {
+                 * JSSharedData.instance.registerCompilationUnit(key, cu); } }
+                 */
+            }
+
+            Name funcName = funcDef.getMName(this.currentScope.getProject());
+
+            if (funcName == null)
+            {
+                //  getMName() emitted a diagnostic, 
+                //  repair and continue.
+                funcName = new Name("<invalid>");
+            }
+
+            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)
+                {
+                    // Functions at the global scope create a var of type '*'
+                    // TODO: this should be typed as 'Function' if strict mode is on
+                    if (f.isGetter() || f.isSetter())
+                    {
+                        tv = this.currentScope.traitsVisitor.visitMethodTrait(
+                                DirectiveProcessor.functionTraitKind(f, ABCConstants.TRAIT_Var),
+                                funcName,
+                                ITraitsVisitor.RUNTIME_DISP_ID,
+                                mi);
+                    }
+                    else
+                    {
+                        tv = this.currentScope.traitsVisitor.visitSlotTrait(
+                                DirectiveProcessor.functionTraitKind(f, ABCConstants.TRAIT_Var),
+                                funcName,
+                                ITraitsVisitor.RUNTIME_SLOT,
+                                LexicalScope.anyType,
+                                LexicalScope.noInitializer);
+
+                        /*
+                         * 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(DirectiveProcessor.functionTraitKind(f, ABCConstants.TRAIT_Method), funcName, 0, mi);
+                }
+
+                if (tv != null)
+                {
+                    this.currentScope.processMetadata(tv, funcDef.getAllMetaTags());
+                }
+            }
+            else
+            {
+                ICompilerProblem problem = new DuplicateFunctionDefinitionProblem(f, funcName.getBaseName());
+                this.currentScope.addProblem(problem);
+            }
+        }
+    }
+
+    /**
+     * Declare a class.
+     */
+    @Override
+    void declareClass(ClassNode c)
+    {
+        verifyClassModifiers(c);
+        verifySkinning(c.getDefinition());
+        currentScope.getMethodBodySemanticChecker().checkNamespaceOfDefinition(c, c.getDefinition(), currentScope.getProject());
+        JSClassDirectiveProcessor cp = JSSharedData.backend.createClassDirectiveProcessor(m_generator, 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 = JSSharedData.backend.createInterfaceDirectiveProcessor(m_generator, interface_ast, this.currentScope, this.emitter);
+        ip.traverse(interface_ast.getScopedNode());
+        ip.finishInterfaceDefinition();
+    }
+
+    /**
+     * Process a random directive, which at the global level is probably a loose
+     * instruction.
+     */
+    @Override
+    void processDirective(IASNode n)
+    {
+        // Use nodes have no effect
+        /*
+         * if(n.getNodeID() == ASTNodeID.UseID ) { if(
+         * !JSSharedData.GENERATE_EMBED_WRAPPER ) return; }
+         */
+
+        // workaround for Falcon bug.
+        // DirectiveProcessor is observing NamespaceIdentifierID instead of NamespaceID
+        if (n.getNodeID() == ASTNodeID.NamespaceID)
+        {
+            try
+            {
+                final IClassVisitor cv = ((JSEmitter)emitter).visitPackage(m_packageName);
+                cv.visit();
+                this.currentScope.traitsVisitor = cv.visitClassTraits();
+                cv.visitEnd();
+
+                m_generator.generateInstructions(n, CmcEmitter.__statement_NT, this.currentScope);
+                // assert(stmt_insns == null);
+            }
+            finally
+            {
+                // this.currentScope.traitsVisitor = null;
+            }
+            return;
+        }
+
+        //  Handle a loose statement.
+        InstructionList stmt_insns = m_generator.generateInstructions(n, CmcJSEmitter.__statement_NT, currentScope);
+        if (stmt_insns != null)
+            directiveInsns.addAll(stmt_insns);
+    }
+
+    @Override
+    void declarePackage(PackageNode p)
+    {
+        m_packageName = p.getName();
+        ((JSEmitter)emitter).visitPackage(m_packageName);
+        JSSharedData.instance.registerPackage(m_packageName);
+        super.declarePackage(p);
+    }
+
+    /**
+     * Declare a variable.
+     */
+    @Override
+    void declareVariable(VariableNode var)
+    {
+        super.declareVariable(var);
+    }
+
+    /**
+     * Translate a ImportNode AST into ABC. Subclasses should override this if
+     * they can process imports.
+     * 
+     * @param imp - the import's AST.
+     */
+    @Override
+    void processImportDirective(ImportNode imp)
+    {
+        String importName = imp.getImportName();
+        if (!importName.contains("."))
+        {
+            final IASScope scope = JSGeneratingReducer.getScopeFromNode(imp);
+            final IDefinition def = ((ASScope)scope).findProperty(currentScope.getProject(), imp.getImportName(), DependencyType.INHERITANCE);
+            if (def == null)
+            {
+                importName = null;
+            }
+            else
+            {
+                // workaround for Falcon bug.
+                // Falcon does not always recognize dependencies to package functions provided by SWCs.
+                // In this workaround we explicitly set a EXPRESSION dependency. 
+                /*
+                 * if( def != null ) { final ICompilationUnit fromCU =
+                 * m_generator.m_compilationUnit; final CompilerProject
+                 * compilerProject = (CompilerProject)currentScope.project;
+                 * final ASProjectScope projectScope =
+                 * compilerProject.getScope(); final ICompilationUnit toCU =
+                 * projectScope.getCompilationUnitForDefinition(def); if( fromCU
+                 * != toCU ) { // sharedData.verboseMessage(
+                 * "Adding dependency: " + className );
+                 * compilerProject.addDependency(fromCU, toCU,
+                 * DependencyGraph.DependencyType.EXPRESSION); } }
+                 */
+
+                // skip imports from the same package.
+                if (def.getPackageName().equals(m_packageName))
+                    importName = null;
+                else
+                    importName = JSGeneratingReducer.definitionToString(currentScope.getProject(), def);
+            }
+        }
+
+        if (importName != null)
+        {
+            JSEmitter emitter = (JSEmitter)this.currentScope.getEmitter();
+            emitter.visitImport(importName, imp.getImportKind());
+        }
+    }
+
+}

Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSGlobalDirectiveProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSInterfaceDirectiveProcessor.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSInterfaceDirectiveProcessor.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSInterfaceDirectiveProcessor.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSInterfaceDirectiveProcessor.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,118 @@
+/*
+ *
+ *  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.*;
+
+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.IMethodVisitor;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
+import org.apache.flex.compiler.definitions.references.INamespaceReference;
+import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
+import org.apache.flex.compiler.internal.definitions.InterfaceDefinition;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.InterfaceNode;
+import org.apache.flex.compiler.problems.BadAccessInterfaceMemberProblem;
+import org.apache.flex.compiler.problems.InterfaceNamespaceAttributeProblem;
+
+/**
+ * The InterfaceDirectiveProcessor translates an InterfaceNode AST and children
+ * into an interface declaration and definition in the ABC and the init script,
+ * respectively.
+ */
+public class JSInterfaceDirectiveProcessor extends InterfaceDirectiveProcessor
+{
+    private JSGenerator m_generator;
+
+    /**
+     * Create an InterfaceDirectiveProcessor and set up the basic AET
+     * structures.
+     * 
+     * @param in - the InterfaceNode.
+     * @param enclosing_scope - the lexical scope that encloses this interface
+     * declaration. Either the global scope or a package scope.
+     * @param emitter - the active ABC emitter.
+     */
+    public JSInterfaceDirectiveProcessor(JSGenerator jsGenerator, InterfaceNode in, LexicalScope enclosing_scope, IABCVisitor emitter)
+    {
+        super(in, addDefinition(enclosing_scope, in.getDefinition()), emitter);
+        m_generator = jsGenerator;
+    }
+
+    private static LexicalScope addDefinition(LexicalScope enclosing_scope, InterfaceDefinition idef)
+    {
+        JSSharedData.instance.registerDefinition(idef);
+        return enclosing_scope;
+    }
+
+    /**
+     * Declare a function.
+     */
+    @Override
+    void declareFunction(FunctionNode func)
+    {
+        verifyFunctionModifiers(func);
+
+        INamespaceReference ns_ref = func.getDefinition().getNamespaceReference();
+
+        if (ns_ref instanceof INamespaceDefinition.IInterfaceNamespaceDefinition)
+        {
+            //  Allowed, continue
+        }
+        else if (ns_ref instanceof INamespaceDefinition.ILanguageNamespaceDefinition)
+        {
+            interfaceScope.addProblem(new BadAccessInterfaceMemberProblem(func));
+        }
+        else
+        // if ( ns_ref instanceof UserDefinedNamespaceDefinition )
+        {
+            interfaceScope.addProblem(new InterfaceNamespaceAttributeProblem(func));
+        }
+
+        // workaround for Falcon bug.
+        // InterfaceDirectiveProcessor currently does not record return type and default values of optional parameters.
+        // In order to do so InterfaceDirectiveProcessor needs to do what ClassDirectiveProcessor::declareFunction
+        // is doing, which is letting the ABCGenerator kick off CmcEmitter.burm() etc.
+        // This is the stack trace for the JS backend implementation:
+        //      JSGenerator.generateInstructions() 
+        //      JSGenerator.generateMethodBody()  
+        //      JSGenerator.generateFunction()
+        //      JSClassDirectiveProcessor.declareFunction() 
+        // The workaround below achieves the same by directly calling JSGenerator.generateFunction(), which is robust 
+        // enough to handle situations where there is no IMethodBodyVisitor registered.
+
+        // MethodInfo mi = m_generator.createMethodInfo(this.interfaceScope, func);
+        MethodInfo mi = m_generator.generateFunction(func, this.interfaceScope, null);
+
+        IMethodVisitor mv = this.emitter.visitMethod(mi);
+        mv.visit();
+        mv.visitEnd();
+
+        FunctionDefinition funcDef = func.getDefinition();
+        Name funcName = funcDef.getMName(interfaceScope.getProject());
+        if (mi.getReturnType() == null && funcDef.getReturnTypeReference() != null)
+            mi.setReturnType(funcDef.getReturnTypeReference().getMName(interfaceScope.getProject(), funcDef.getContainedScope()));
+
+        itraits.visitMethodTrait(functionTraitKind(func, TRAIT_Method), funcName, 0, mi);
+    }
+
+}

Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSInterfaceDirectiveProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSSharedData.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSSharedData.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSSharedData.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSSharedData.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,988 @@
+/*
+ *
+ *  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.PrintStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.semantics.Namespace;
+import org.apache.flex.abc.semantics.Nsset;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.IMemberedDefinition;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
+import org.apache.flex.compiler.definitions.metadata.IMetaTag;
+import org.apache.flex.compiler.internal.driver.IBackend;
+import org.apache.flex.compiler.internal.legacy.MemberedDefinitionUtils;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.AccessValue;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.ClassificationValue;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.SearchScopeValue;
+import org.apache.flex.compiler.internal.workspaces.Workspace;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.swf.SWFFrame;
+
+import static org.apache.flex.abc.ABCConstants.OP_nop;
+
+/**
+ * JSSharedData contains information that is being shared across
+ * JSCompilationUnit, JSGenerator, and JSEmitter instances.
+ * JSSharedData.COMPILER_VERSION holds FalconJS's version, which uses the Falcon
+ * change list number as the major revision number. The minor revision number
+ * represents FalconJS's internal version within the Falcon change list number
+ * it is based on. This implementation is part of FalconJS. For more details on
+ * FalconJS see org.apache.flex.compiler.JSDriver
+ */
+public class JSSharedData
+{
+    public static String COMPILER_NAME = "MXMLJSC";
+    public final static String COMPILER_VERSION = "329449.1";
+
+    public final static JSSharedData instance = new JSSharedData();
+    public static IBackend backend = null;
+    public static Workspace workspace = null;
+
+    public final static String JS_FRAMEWORK_NAME = "adobe";
+    public final static String ROOT_NAME = ""; // JS_FRAMEWORK_NAME + ".root.";
+    public static String FRAMEWORK_CLASS = "browser.JQueryFramework";
+    public static String BUILT_IN = "builtin.abc";
+    public static String MAIN = null;
+    public static Boolean NO_EXPORTS = true;
+    public static Boolean OUTPUT_TIMESTAMPS = true;
+    public static Boolean OUTPUT_ISOLATED = true;
+    public static Boolean GENERATE_TEST_CASE = false;
+    public static Boolean WARN_PERFORMANCE_LOSS = false;
+    public static Boolean WARN_RUNTIME_NAME_LOOKUP = false; // JSWarnRuntimeNameLookupProblem
+    public static Boolean WARN_CLASS_INIT = false; // JSWarnClassInitProblem
+    public static Boolean DEBUG = false;
+    public static Boolean OPTIMIZE = false;
+    public static Boolean EXTEND_DOM = true;
+    public static Boolean KEEP_GENERATED_AS = false;
+
+    public static PrintStream STDOUT = System.out;
+    public static PrintStream STDERR = System.err;
+    public static String OUTPUT_FOLDER = ".";
+    public static String OUTPUT_EXTENSION = "js";
+    public static String SDK_PATH = null;
+
+    public static String CLOSURE_compilation_level = "SIMPLE_OPTIMIZATIONS";
+    public static List<String> CLOSURE_externs = null;
+    public static List<String> CLOSURE_js = null;
+    public static String CLOSURE_create_source_map = null;
+    public static String CLOSURE_formatting = null;
+
+    // public final static String FRAMEWORK_CLASS = "browser.ClosureFramework";
+    public final static String m_superCalledMarker = "___SUPER_HAS_BEEN_CALLED___ ";
+    public final static String THIS = "self";
+    public final static String SUPER = "super";
+    public final static String _SUPER = "_super";
+    public final static String THIS_SUPER = THIS + "." + SUPER;
+    public final static String JS_THIS = "this";
+    public final static Boolean m_useClosureLib = false;
+    public final static Boolean m_useSelfParameter = false;
+    public final static int OP_JS = OP_nop;
+    public final static String GETTER_PREFIX = "get_";
+    public final static String SETTER_PREFIX = "set_";
+    public final static String CTOR_NAME = "init";
+    public final static String EXTERN_INTERFACE_NAME = "IExtern";
+    public final static String SYMBOL_INTERFACE_NAME = "ISymbol";
+    public final static String FRAMEWORK_INTERFACE_NAME = "IFramework";
+    public final static String CLASS_NAME = "_CLASS";
+    public final static String SYMBOL_GET_LINKAGE = "getLinkage"; // see browser.ISymbol 
+    public final static String SYMBOL_INIT = "init"; // see browser.ISymbol 
+    public final static String SYMBOL_INSTANCE = "instance"; // see browser.ISymbol 
+    public final static String GENERATE_CLASSINFO = "GenerateClassInfo"; // see browser.ISymbol 
+    public final static String CONVERT_LOCAL_VARS_TO_MEMBERS = "ConvertLocalVarsToMembers";
+    // public final static String JS_STATIC_INITS = JS_FRAMEWORK_NAME + ".m_staticInits";
+    public final static String JS_RUN_STATIC_INITS = JS_FRAMEWORK_NAME + ".runStaticInits";
+    public final static String JS_SYMBOLS = JS_FRAMEWORK_NAME + ".m_symbols";
+    public final static String JS_CLASSES = JS_FRAMEWORK_NAME + ".classes";
+    public final static String JS_TESTCASES = JS_FRAMEWORK_NAME + ".testCases";
+    public final static String JS_INT_CLASS = JS_FRAMEWORK_NAME + ".intClass";
+    public final static String JS_UINT_CLASS = JS_FRAMEWORK_NAME + ".uintClass";
+    public final static String JS_EMPTY_FUNCTION = JS_FRAMEWORK_NAME + ".emptyFunction";
+    public final static String REQUIRED_TAG_MARKER = "__REQUIRED__";
+    public final static String EXTERN_METATAG = "Extern";
+    public final static String DATACLASS_METATAG = "DataClass";
+    public final static String TESTCASE_METATAG = "TestCase";
+    public final static String AS3XML = "browser.AS3XML";
+    public final static String AS3XMLList = "browser.AS3XMLList";
+    public final static String STATIC_INIT = "__static_init";
+
+    public final static byte CONSTANT_Namespace = 1;
+    public final static byte CONSTANT_PackageNs = 2;
+    public final static byte CONSTANT_PackageInternalNs = 3;
+    public final static byte CONSTANT_ProtectedNs = 4;
+    public final static byte CONSTANT_ExplicitNamespace = 5;
+    public final static byte CONSTANT_StaticProtectedNs = 6;
+    public final static byte CONSTANT_PrivateNs = 7;
+    public final static byte CONSTANT_ClassPrivateNS = 8;
+
+    private Set<String> m_packages = new TreeSet<String>();
+    private final ReadWriteLock m_packagesLock = new ReentrantReadWriteLock();
+
+    private Map<Name, Name> m_classes = new HashMap<Name, Name>();
+    private final ReadWriteLock m_classesLock = new ReentrantReadWriteLock();
+
+    private Map<Name, Set<Name>> m_interfaces = new HashMap<Name, Set<Name>>();
+    private final ReadWriteLock m_interfacesLock = new ReentrantReadWriteLock();
+
+    private Map<String, String> m_externs = new HashMap<String, String>();
+    private final ReadWriteLock m_externsLock = new ReentrantReadWriteLock();
+
+    private Map<String, String> m_varTypes = new HashMap<String, String>();
+    private final ReadWriteLock m_varTypesLock = new ReentrantReadWriteLock();
+
+    private Boolean m_verbose = false;
+    private final ReadWriteLock m_verboseLock = new ReentrantReadWriteLock();
+
+    private Object m_codeGenMonitor = new Object();
+    private long m_codeGenCounter = 0;
+    private final ReadWriteLock m_codeGenCounterLock = new ReentrantReadWriteLock();
+
+    private Set<Name> m_emittedClasses = new HashSet<Name>();
+    private final ReadWriteLock m_emittedClassesLock = new ReentrantReadWriteLock();
+
+    private Map<String, INamespaceDefinition> m_uriToNamespace = new HashMap<String, INamespaceDefinition>();
+    private Map<String, INamespaceDefinition> m_qnameToNamespace = new HashMap<String, INamespaceDefinition>();
+    private final ReadWriteLock m_uriToNamespaceLock = new ReentrantReadWriteLock();
+
+    private Map<String, String> m_classToSymbol = new HashMap<String, String>();
+    private final ReadWriteLock m_classToSymbolLock = new ReentrantReadWriteLock();
+
+    // private Map<IDefinition,Set<IDefinition>> m_dependencies = new HashMap<IDefinition,Set<IDefinition>>();
+    // private final ReadWriteLock m_dependenciesLock = new ReentrantReadWriteLock();
+
+    private Map<String, String> m_compilationUnitToJS = new HashMap<String, String>();
+    private final ReadWriteLock m_compilationUnitToJSLock = new ReentrantReadWriteLock();
+
+    private Map<SWFFrame, ICompilationUnit> m_swfFrameToCompilationUnit = new HashMap<SWFFrame, ICompilationUnit>();
+    private final ReadWriteLock m_swfFrameToCompilationUnitLock = new ReentrantReadWriteLock();
+
+    private Set<String> m_referencedDefinitions = new HashSet<String>();
+    private final ReadWriteLock m_referencedDefinitionsLock = new ReentrantReadWriteLock();
+
+    private Map<String, IDefinition> m_definitions = new HashMap<String, IDefinition>();
+    private final ReadWriteLock m_definitionsLock = new ReentrantReadWriteLock();
+
+    private Set<String> m_usedExterns = new HashSet<String>();
+    private final ReadWriteLock m_usedExternsLock = new ReentrantReadWriteLock();
+
+    private Set<String> m_scriptInfos = new HashSet<String>();
+    private final ReadWriteLock m_scriptInfosLock = new ReentrantReadWriteLock();
+
+    private Map<String, Integer> m_propertyNames = new HashMap<String, Integer>();
+    private final ReadWriteLock m_propertyNamesLock = new ReentrantReadWriteLock();
+
+    private Set<String> m_accessedPropertyNames = new HashSet<String>();
+    private final ReadWriteLock m_accessedPropertyNamesLock = new ReentrantReadWriteLock();
+
+    private Set<String> m_classInit = new HashSet<String>();
+    private final ReadWriteLock m_classInitLock = new ReentrantReadWriteLock();
+
+    private Map<String, String> m_pathToUUID = new HashMap<String, String>();
+    private final ReadWriteLock m_pathToUUIDLock = new ReentrantReadWriteLock();
+
+    private Set<String> m_encryptedJS = new HashSet<String>();
+    private final ReadWriteLock m_encryptedJSLock = new ReentrantReadWriteLock();
+
+    private Map<String, Set<String>> m_methods = new HashMap<String, Set<String>>();
+    private final ReadWriteLock m_methodsLock = new ReentrantReadWriteLock();
+
+    public void reset()
+    {
+        m_packages.clear();
+        m_classes.clear();
+        m_interfaces.clear();
+        m_externs.clear();
+        m_varTypes.clear();
+        m_verbose = false;
+        // m_codeGenMonitor
+        m_emittedClasses.clear();
+        m_uriToNamespace.clear();
+        m_qnameToNamespace.clear();
+        m_classToSymbol.clear();
+        // m_dependencies.clear();
+        m_compilationUnitToJS.clear();
+        m_swfFrameToCompilationUnit.clear();
+        m_referencedDefinitions.clear();
+        m_definitions.clear();
+        m_usedExterns.clear();
+        m_scriptInfos.clear();
+        m_propertyNames.clear();
+        m_accessedPropertyNames.clear();
+        m_classInit.clear();
+        // m_pathToUUID.clear();
+        m_encryptedJS.clear();
+        m_methods.clear();
+    }
+
+    /**
+     * @param m_packages the m_packages to set
+     */
+    public void registerPackage(String packageName)
+    {
+        // TODO: generalize, avoid hard-coded "goog"
+        if (packageName != null && !packageName.isEmpty() && !packageName.startsWith("goog"))
+        {
+            m_packagesLock.writeLock().lock();
+            this.m_packages.add(packageName);
+            m_packagesLock.writeLock().unlock();
+        }
+    }
+
+    /**
+     * @return the m_packages
+     */
+    public Boolean hasPackage(String packageName)
+    {
+        m_packagesLock.readLock().lock();
+        final Boolean val = m_packages.contains(packageName);
+        m_packagesLock.readLock().unlock();
+        return val;
+    }
+
+    /**
+     * @return the m_packages
+     */
+    @SuppressWarnings("unchecked")
+    public Set<String> getPackages()
+    {
+        Set<String> packages = null;
+        m_packagesLock.readLock().lock();
+        Object clone = ((TreeSet<String>)m_packages).clone();
+        if (clone != null && clone instanceof Set<?>)
+            packages = (Set<String>)(clone);
+        m_packagesLock.readLock().unlock();
+        return packages;
+    }
+
+    /**
+     * @param m_varTypes the m_varTypes to set
+     */
+    public void registerVarType(String varName, String varType)
+    {
+        m_varTypesLock.writeLock().lock();
+        this.m_varTypes.put(varName, varType);
+        m_varTypesLock.writeLock().unlock();
+    }
+
+    /**
+     * @return the m_varTypes
+     */
+    public String getVarType(String varName)
+    {
+        m_varTypesLock.readLock().lock();
+        final String val = m_varTypes.get(varName);
+        m_varTypesLock.readLock().unlock();
+        return val;
+    }
+
+    public Boolean hasVarName(String varName)
+    {
+        m_varTypesLock.readLock().lock();
+        final Boolean val = m_varTypes.containsKey(varName);
+        m_varTypesLock.readLock().unlock();
+        return val;
+    }
+
+    /**
+     * @param m_classes the m_classes to set
+     */
+    public void registerClass(Name className, Name superName)
+    {
+        m_classesLock.writeLock().lock();
+        this.m_classes.put(className, superName);
+        m_classesLock.writeLock().unlock();
+    }
+
+    /**
+     * @return the m_classes
+     */
+    public Name getSuperClass(Name className)
+    {
+        m_classesLock.readLock().lock();
+        final Name val = m_classes.get(className);
+        m_classesLock.readLock().unlock();
+        return val;
+    }
+
+    public Boolean hasClass(Name className)
+    {
+        m_classesLock.readLock().lock();
+        final Boolean val = m_classes.containsKey(className);
+        m_classesLock.readLock().unlock();
+        return val;
+    }
+
+    public Map<String, String> getClassInfo()
+    {
+        // copying the whole m_classes is the only thing you can do 
+        // if you want to stay thread safe.
+        Map<String, String> info = new HashMap<String, String>();
+
+        m_classesLock.readLock().lock();
+        Iterator<Map.Entry<Name, Name>> it = m_classes.entrySet().iterator();
+        while (it.hasNext())
+        {
+            Map.Entry<Name, Name> pair = it.next();
+            final Name _class = pair.getKey();
+            final Name _super = pair.getValue();
+            if (_super != null)
+                info.put(_class.getBaseName(), _super.getBaseName());
+            else
+                info.put(_class.getBaseName(), "Object");
+        }
+        m_classesLock.readLock().unlock();
+
+        return info;
+    }
+
+    public Set<Name> getClasses()
+    {
+        m_classesLock.readLock().lock();
+
+        Set<Name> info = new HashSet<Name>();
+        info.addAll(m_classes.keySet());
+        m_classesLock.readLock().unlock();
+
+        return info;
+    }
+
+    public void setVerbose(Boolean value)
+    {
+        m_verboseLock.writeLock().lock();
+        this.m_verbose = value;
+        m_verboseLock.writeLock().unlock();
+    }
+
+    public Boolean isVerbose()
+    {
+        m_verboseLock.readLock().lock();
+        final Boolean val = m_verbose;
+        m_verboseLock.readLock().unlock();
+        return val;
+    }
+
+    public void stdout(String s)
+    {
+        if (STDOUT != null)
+        {
+            m_verboseLock.writeLock().lock();
+            STDOUT.println(s);
+            m_verboseLock.writeLock().unlock();
+        }
+    }
+
+    public void stderr(String s)
+    {
+        if (STDERR != null)
+        {
+            m_verboseLock.writeLock().lock();
+            STDERR.println(s);
+            m_verboseLock.writeLock().unlock();
+        }
+    }
+
+    public void verboseMessage(String s)
+    {
+        if (isVerbose() && STDOUT != null)
+        {
+            m_verboseLock.writeLock().lock();
+            STDOUT.println(s);
+            m_verboseLock.writeLock().unlock();
+        }
+    }
+
+    public void beginCodeGen()
+    {
+        m_codeGenCounterLock.writeLock().lock();
+        m_codeGenCounter++;
+        m_codeGenCounterLock.writeLock().unlock();
+    }
+
+    public void endCodeGen()
+    {
+        m_codeGenCounterLock.writeLock().lock();
+        final long currentCounter = --m_codeGenCounter;
+        m_codeGenCounterLock.writeLock().unlock();
+
+        if (currentCounter == 0)
+        {
+            synchronized (m_codeGenMonitor)
+            {
+                m_codeGenMonitor.notifyAll();
+            }
+        }
+    }
+
+    /*
+     * private long getCodeGenCounter() {
+     * m_codeGenCounterLock.readLock().lock(); final long val =
+     * m_codeGenCounter; m_codeGenCounterLock.readLock().unlock(); return val; }
+     * private void waitUntilCodeGenHasFinished() throws InterruptedException {
+     * if( getCodeGenCounter() == 0 ) { synchronized (m_codeGenMonitor) {
+     * m_codeGenMonitor.wait(); } } }
+     */
+
+    public void registerInterface(Name className, Name interfaceName)
+    {
+        m_interfacesLock.writeLock().lock();
+        Set<Name> interfaces = m_interfaces.get(className);
+        if (interfaces == null)
+        {
+            interfaces = new HashSet<Name>();
+            this.m_interfaces.put(className, interfaces);
+        }
+        interfaces.add(interfaceName);
+        m_interfacesLock.writeLock().unlock();
+    }
+
+    @SuppressWarnings("unchecked")
+    public Map<Name, Set<Name>> getAllInterfaces()
+    {
+        // copying the whole m_classes is the only thing you can do 
+        // if you want to stay thread safe.
+        Map<Name, Set<Name>> info = new HashMap<Name, Set<Name>>();
+
+        m_interfacesLock.readLock().lock();
+        Iterator<Map.Entry<Name, Set<Name>>> it = m_interfaces.entrySet().iterator();
+        while (it.hasNext())
+        {
+            Map.Entry<Name, Set<Name>> pair = it.next();
+            final Name _class = pair.getKey();
+            final HashSet<Name> interfaces = (HashSet<Name>)pair.getValue();
+            info.put(_class, (Set<Name>)(interfaces.clone()));
+        }
+        m_interfacesLock.readLock().unlock();
+
+        return info;
+    }
+
+    public void registerExtern(Name name)
+    {
+        final IDefinition def = getDefinition(name);
+        if (def == null)
+            throw backend.createException("registerExtern: can't find definition for " + name.toString());
+        registerExtern(def);
+    }
+
+    public void registerExtern(IDefinition def)
+    {
+        final IMetaTag extern = def.getMetaTagByName(EXTERN_METATAG);
+        if (extern != null)
+        {
+            String externName = extern.getAttributeValue("name");
+            if (externName == null)
+                externName = def.getBaseName();
+
+            m_externsLock.writeLock().lock();
+            m_externs.put(def.getQualifiedName(), externName);
+            m_externsLock.writeLock().unlock();
+        }
+    }
+
+    public Boolean isExtern(String name)
+    {
+        m_externsLock.readLock().lock();
+        final Boolean val = m_externs.containsKey(name);
+        m_externsLock.readLock().unlock();
+        return val;
+    }
+
+    public String getExternName(String name)
+    {
+        m_externsLock.readLock().lock();
+        final String val = m_externs.get(name);
+        m_externsLock.readLock().unlock();
+        return val;
+    }
+
+    public Set<String> getExterns()
+    {
+        final Set<String> externs = new HashSet<String>();
+        m_externsLock.readLock().lock();
+        externs.addAll(m_externs.keySet());
+        m_externsLock.readLock().unlock();
+        return externs;
+    }
+
+    public void registerEmittedClass(Name classOrInterfaceName)
+    {
+        m_emittedClassesLock.writeLock().lock();
+        this.m_emittedClasses.add(classOrInterfaceName);
+        m_emittedClassesLock.writeLock().unlock();
+    }
+
+    public Boolean hasClassBeenEmitted(Name classOrInterfaceName)
+    {
+        m_emittedClassesLock.readLock().lock();
+        final Boolean val = m_emittedClasses.contains(classOrInterfaceName);
+        m_emittedClassesLock.readLock().unlock();
+        return val;
+    }
+
+    public void registerSymbol(String className, String symbolName)
+    {
+        m_classToSymbolLock.writeLock().lock();
+        this.m_classToSymbol.put(className, symbolName);
+        m_classToSymbolLock.writeLock().unlock();
+    }
+
+    public String getSymbol(String className)
+    {
+        m_classToSymbolLock.writeLock().lock();
+        final String symbol = this.m_classToSymbol.get(className);
+        m_classToSymbolLock.writeLock().unlock();
+        return symbol;
+    }
+
+    public Boolean hasSymbols()
+    {
+        m_classToSymbolLock.writeLock().lock();
+        final Boolean hasSymbols = !this.m_classToSymbol.isEmpty();
+        m_classToSymbolLock.writeLock().unlock();
+        return hasSymbols;
+    }
+
+    public List<String> getSymbols()
+    {
+        // copying the whole m_classes is the only thing you can do 
+        // if you want to stay thread safe.
+        List<String> info = new ArrayList<String>();
+        m_classToSymbolLock.readLock().lock();
+        info.addAll(m_classToSymbol.values());
+        m_classToSymbolLock.readLock().unlock();
+
+        return info;
+    }
+
+    public void registerNamespace(String uri, INamespaceDefinition ns)
+    {
+        m_uriToNamespaceLock.writeLock().lock();
+        this.m_uriToNamespace.put(uri, ns);
+        this.m_qnameToNamespace.put(ns.getQualifiedName(), ns);
+        m_uriToNamespaceLock.writeLock().unlock();
+    }
+
+    public Map<String, INamespaceDefinition> getNamespaces()
+    {
+        // Copy the whole m_uriToNamespace for thread-safety
+        Map<String, INamespaceDefinition> namespaces = new HashMap<String, INamespaceDefinition>();
+        m_uriToNamespaceLock.writeLock().lock();
+        namespaces.putAll(m_uriToNamespace);
+        m_uriToNamespaceLock.writeLock().unlock();
+        return namespaces;
+    }
+
+    public INamespaceDefinition getNamespace(String uri)
+    {
+        m_uriToNamespaceLock.writeLock().lock();
+        final INamespaceDefinition ns = this.m_uriToNamespace.get(uri);
+        m_uriToNamespaceLock.writeLock().unlock();
+        return ns;
+    }
+
+    public INamespaceDefinition getNamespaceForQName(String qname)
+    {
+        m_uriToNamespaceLock.writeLock().lock();
+        final INamespaceDefinition ns = this.m_qnameToNamespace.get(qname);
+        m_uriToNamespaceLock.writeLock().unlock();
+        return ns;
+    }
+
+    /*
+     * // returns true if def1 depends on def2 private Boolean dependsOn(
+     * IDefinition def1, IDefinition def2 ) { Set<IDefinition> defs =
+     * m_dependencies.get(def2); if( defs.contains(def1) ) return true; for(
+     * IDefinition next: defs ) { if( dependsOn(def1, next) ) return true; }
+     * return false; } // workaround for Falcon bugs // Falcon's DependencyGraph
+     * does not work correctly for Definitions // implemented by SWCs. // def1
+     * depends on def2 public void addDependency( IDefinition def1, IDefinition
+     * def2 ) { if( def1 != def2 ) { m_dependenciesLock.writeLock().lock();
+     * Set<IDefinition> defs = m_dependencies.get(def1); if( defs == null ) {
+     * defs = new HashSet<IDefinition>(); m_dependencies.put( def1, defs ); }
+     * else { if( !defs.contains(def2) && dependsOn(def2, def1) ) throw new
+     * Error( "addDependency: circular dependencies!" ); } defs.add(def2);
+     * m_dependenciesLock.writeLock().unlock(); } } public Set<IDefinition>
+     * getDependencies( IDefinition def ) {
+     * m_dependenciesLock.writeLock().lock(); final Set<IDefinition> defs =
+     * m_dependencies.get(def); m_dependenciesLock.writeLock().unlock(); return
+     * defs; }
+     */
+
+    public void registerJavaScript(String className, String jsCode)
+    {
+        m_compilationUnitToJSLock.writeLock().lock();
+        m_compilationUnitToJS.put(className, jsCode);
+        m_compilationUnitToJSLock.writeLock().unlock();
+    }
+
+    public void registerJavaScript(Map<String, String> classNameToJS)
+    {
+        m_compilationUnitToJSLock.writeLock().lock();
+        m_compilationUnitToJS.putAll(classNameToJS);
+        m_compilationUnitToJSLock.writeLock().unlock();
+    }
+
+    public Boolean hasJavaScript(String className)
+    {
+        m_compilationUnitToJSLock.writeLock().lock();
+        final Boolean found = m_compilationUnitToJS.containsKey(className);
+        m_compilationUnitToJSLock.writeLock().unlock();
+        return found;
+    }
+
+    public String getJavaScript(String className)
+    {
+        m_compilationUnitToJSLock.writeLock().lock();
+        final String jsCode = m_compilationUnitToJS.get(className);
+        m_compilationUnitToJSLock.writeLock().unlock();
+        return jsCode;
+    }
+
+    public void registerSWFFrame(SWFFrame frame, ICompilationUnit cu)
+    {
+        m_swfFrameToCompilationUnitLock.writeLock().lock();
+        m_swfFrameToCompilationUnit.put(frame, cu);
+        m_swfFrameToCompilationUnitLock.writeLock().unlock();
+    }
+
+    public ICompilationUnit getCompilationUnit(SWFFrame frame)
+    {
+        m_swfFrameToCompilationUnitLock.writeLock().lock();
+        final ICompilationUnit cu = m_swfFrameToCompilationUnit.get(frame);
+        m_swfFrameToCompilationUnitLock.writeLock().unlock();
+        return cu;
+    }
+
+    public void registerReferencedDefinition(String name)
+    {
+        m_referencedDefinitionsLock.writeLock().lock();
+        m_referencedDefinitions.add(name);
+        m_referencedDefinitionsLock.writeLock().unlock();
+    }
+
+    public Boolean isReferencedDefinition(String name)
+    {
+        m_referencedDefinitionsLock.readLock().lock();
+        final Boolean val = m_referencedDefinitions.contains(name);
+        m_referencedDefinitionsLock.readLock().unlock();
+        return val;
+    }
+
+    public void registerDefinition(IDefinition def)
+    {
+        m_definitionsLock.writeLock().lock();
+        final String qName = def.getQualifiedName();
+        this.m_definitions.put(qName, def);
+        m_definitionsLock.writeLock().unlock();
+
+        // register this definition as an extern if necessary.
+        final IMetaTag extern = def.getMetaTagByName(JSSharedData.EXTERN_METATAG);
+        if (extern != null)
+            registerExtern(def);
+    }
+
+    public IDefinition getDefinition(String qualifiedName)
+    {
+        m_definitionsLock.readLock().lock();
+        final IDefinition val = m_definitions.get(qualifiedName);
+        m_definitionsLock.readLock().unlock();
+        return val;
+    }
+
+    public IDefinition getDefinition(Name name)
+    {
+        m_definitionsLock.readLock().lock();
+
+        IDefinition val = null;
+        final String baseName = name.getBaseName();
+        if (baseName != null)
+        {
+            final Nsset nsset = name.getQualifiers();
+            if (nsset != null)
+            {
+                for (Namespace ns : nsset)
+                {
+                    String defName = ns.getName();
+                    if (!defName.isEmpty())
+                        defName += ".";
+                    defName += name.getBaseName();
+                    val = m_definitions.get(defName);
+                    if (val != null)
+                        break;
+                }
+            }
+        }
+
+        if (val == null)
+            val = m_definitions.get(baseName);
+
+        m_definitionsLock.readLock().unlock();
+        return val;
+    }
+
+    public String getQualifiedName(Name name)
+    {
+        final IDefinition def = getDefinition(name);
+        if (def != null)
+            return def.getQualifiedName();
+        return null;
+    }
+
+    public void registerUsedExtern(String name)
+    {
+        m_usedExternsLock.writeLock().lock();
+        m_usedExterns.add(name);
+        m_usedExternsLock.writeLock().unlock();
+    }
+
+    public Boolean isUsedExtern(String name)
+    {
+        m_usedExternsLock.readLock().lock();
+        final Boolean val = m_usedExterns.contains(name);
+        m_usedExternsLock.readLock().unlock();
+        return val;
+    }
+
+    public Set<String> getUsedExterns()
+    {
+        final Set<String> externs = new HashSet<String>();
+        m_scriptInfosLock.readLock().lock();
+        externs.addAll(m_scriptInfos);
+        m_scriptInfosLock.readLock().unlock();
+        return externs;
+    }
+
+    public void registerScriptInfo(String name)
+    {
+        m_scriptInfosLock.writeLock().lock();
+        m_scriptInfos.add(name);
+        m_scriptInfosLock.writeLock().unlock();
+    }
+
+    public Set<String> getScriptInfos()
+    {
+        final Set<String> scriptInfos = new HashSet<String>();
+        m_scriptInfosLock.readLock().lock();
+        scriptInfos.addAll(m_scriptInfos);
+        m_scriptInfosLock.readLock().unlock();
+        return scriptInfos;
+    }
+
+    public void registerPropertyName(String name)
+    {
+        m_propertyNamesLock.writeLock().lock();
+
+        if (m_propertyNames.containsKey(name))
+        {
+            final Integer uses = m_propertyNames.get(name);
+            m_propertyNames.put(name, uses + 1);
+        }
+        else
+        {
+            m_propertyNames.put(name, 1);
+        }
+        m_propertyNamesLock.writeLock().unlock();
+    }
+
+    public Boolean isUniquePropertyName(String name)
+    {
+        Boolean isUnique = true;
+        m_propertyNamesLock.readLock().lock();
+        if (m_propertyNames.containsKey(name))
+        {
+            final Integer uses = m_propertyNames.get(name);
+            if (uses > 1)
+                isUnique = false;
+        }
+        m_propertyNamesLock.readLock().unlock();
+        return isUnique;
+    }
+
+    // called whenever we have to emit adobe.get/set/call property.
+    public void registerAccessedPropertyName(String name)
+    {
+        m_accessedPropertyNamesLock.writeLock().lock();
+        m_accessedPropertyNames.add(name);
+        m_accessedPropertyNamesLock.writeLock().unlock();
+    }
+
+    public Boolean isAccessedPropertyName(String name)
+    {
+        m_accessedPropertyNamesLock.readLock().lock();
+        final Boolean val = m_accessedPropertyNames.contains(name);
+        m_accessedPropertyNamesLock.readLock().unlock();
+        return val;
+    }
+
+    public static Boolean usingAdvancedOptimizations()
+    {
+        return CLOSURE_compilation_level.equals("ADVANCED_OPTIMIZATIONS");
+    }
+
+    // called whenever we have to emit adobe.get/set/call property.
+    public void registerClassInit(String fullClassName)
+    {
+        if (fullClassName != null && !fullClassName.isEmpty())
+        {
+            m_classInitLock.writeLock().lock();
+            m_classInit.add(fullClassName);
+            m_classInitLock.writeLock().unlock();
+        }
+    }
+
+    public Boolean hasClassInit(String fullClassName)
+    {
+        m_classInitLock.readLock().lock();
+        final Boolean val = m_classInit.contains(fullClassName);
+        m_classInitLock.readLock().unlock();
+        return val;
+    }
+
+    public Boolean hasAnyClassInit()
+    {
+        m_classInitLock.readLock().lock();
+        final Boolean val = m_classInit.isEmpty();
+        m_classInitLock.readLock().unlock();
+        return !val;
+    }
+
+    public void registerUUID(String path, String uuid)
+    {
+        m_pathToUUIDLock.writeLock().lock();
+        m_pathToUUID.put(path, uuid);
+        m_pathToUUIDLock.writeLock().unlock();
+    }
+
+    public String getUUID(String path)
+    {
+        m_pathToUUIDLock.readLock().lock();
+        final String val = m_pathToUUID.get(path);
+        m_pathToUUIDLock.readLock().unlock();
+        return val;
+    }
+
+    public void registerEncryptedJS(String name)
+    {
+        m_encryptedJSLock.writeLock().lock();
+        m_encryptedJS.add(name);
+        m_encryptedJSLock.writeLock().unlock();
+    }
+
+    public Boolean hasEncryptedJS(String name)
+    {
+        m_encryptedJSLock.readLock().lock();
+        final Boolean val = m_encryptedJS.contains(name);
+        m_encryptedJSLock.readLock().unlock();
+        return val;
+    }
+
+    public Boolean hasAnyEncryptedJS()
+    {
+        m_encryptedJSLock.readLock().lock();
+        final Boolean val = !m_encryptedJS.isEmpty();
+        m_encryptedJSLock.readLock().unlock();
+        return val;
+    }
+
+    public void registerMethod(String methodName, String className)
+    {
+        m_methodsLock.writeLock().lock();
+        Set<String> classes = m_methods.get(methodName);
+        if (classes == null)
+        {
+            classes = new HashSet<String>();
+            m_methods.put(methodName, classes);
+        }
+        classes.add(className);
+        m_methodsLock.writeLock().unlock();
+    }
+
+    // poor man's type inference.
+    public void registerMethods(ICompilerProject project, IMemberedDefinition memberedDef)
+    {
+        final String className = memberedDef.getQualifiedName();
+        final ASDefinitionFilter memberFilter = new ASDefinitionFilter(
+                ClassificationValue.FUNCTIONS, SearchScopeValue.INHERITED_MEMBERS,
+                AccessValue.ALL, memberedDef);
+
+        for (IDefinition member : MemberedDefinitionUtils.getAllMembers(memberedDef, project, memberFilter))
+        {
+            /*
+             * class method registered as eventListener gets global when class
+             * instance is in an array
+             * http://watsonexp.corp.adobe.com/#bug=3040108 We need register
+             * only methods with unique signatures. In other words overridden
+             * methods must be excluded.
+             */
+            if (member instanceof IFunctionDefinition && !member.isOverride())
+            {
+                final INamespaceDefinition ns = member.resolveNamespace(project);
+                if (ns != null && ns.isPublicOrInternalNamespace())
+                    registerMethod(member.getBaseName(), className);
+            }
+        }
+    }
+
+    // poor man's type inference.
+    public Set<IFunctionDefinition> getMethods(ICompilerProject project, String methodName)
+    {
+        Set<IFunctionDefinition> defs = new HashSet<IFunctionDefinition>();
+        m_methodsLock.readLock().lock();
+        final Set<String> classes = m_methods.get(methodName);
+        if (classes != null)
+        {
+            for (String className : classes)
+            {
+                final IDefinition def = getDefinition(className);
+                if (def != null && def instanceof IMemberedDefinition)
+                {
+                    final ASDefinitionFilter memberFilter = new ASDefinitionFilter(
+                            ClassificationValue.FUNCTIONS, SearchScopeValue.INHERITED_MEMBERS,
+                            AccessValue.ALL, def);
+                    final IMemberedDefinition memberedDef = (IMemberedDefinition)def;
+                    final IDefinition mdef = MemberedDefinitionUtils.getMemberByName(
+                            memberedDef, project, methodName, memberFilter);
+                    if (mdef instanceof IFunctionDefinition)
+                    {
+                        final IFunctionDefinition fdef = (IFunctionDefinition)mdef;
+                        defs.add(fdef);
+                    }
+                }
+            }
+        }
+        m_methodsLock.readLock().unlock();
+        return defs;
+    }
+
+}

Propchange: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSSharedData.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message