You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by er...@apache.org on 2013/01/08 16:05:32 UTC

svn commit: r1430315 - in /flex/whiteboard/mschmalle/falconjx: compiler.jx.tests/src/org/apache/flex/compiler/internal/js/codegen/goog/ compiler.jx/src/org/apache/flex/compiler/as/codegen/ compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ c...

Author: erikdebruin
Date: Tue Jan  8 15:05:32 2013
New Revision: 1430315

URL: http://svn.apache.org/viewvc?rev=1430315&view=rev
Log:
- refactored a bit to give control over 'binary operator' handling to the emitter instead of the walker
- moved 'emitVarDeclaration' and 'emitFunctionObject' overrides to JSEmitter
- created 'emitBinaryOperator' on JSGoogEmitter to handle the various 'goog' specific workarounds
- created TestGoogExpressions and made overrides for JS (and/or 'goog') specific implementations

Added:
    flex/whiteboard/mschmalle/falconjx/compiler.jx.tests/src/org/apache/flex/compiler/internal/js/codegen/goog/TestGoogExpressions.java   (with props)
Modified:
    flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/as/codegen/IASEmitter.java
    flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASBlockWalker.java
    flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASEmitter.java
    flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/JSEmitter.java
    flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/goog/JSGoogEmitter.java

Added: flex/whiteboard/mschmalle/falconjx/compiler.jx.tests/src/org/apache/flex/compiler/internal/js/codegen/goog/TestGoogExpressions.java
URL: http://svn.apache.org/viewvc/flex/whiteboard/mschmalle/falconjx/compiler.jx.tests/src/org/apache/flex/compiler/internal/js/codegen/goog/TestGoogExpressions.java?rev=1430315&view=auto
==============================================================================
--- flex/whiteboard/mschmalle/falconjx/compiler.jx.tests/src/org/apache/flex/compiler/internal/js/codegen/goog/TestGoogExpressions.java (added)
+++ flex/whiteboard/mschmalle/falconjx/compiler.jx.tests/src/org/apache/flex/compiler/internal/js/codegen/goog/TestGoogExpressions.java Tue Jan  8 15:05:32 2013
@@ -0,0 +1,163 @@
+/*
+ *
+ *  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.js.codegen.goog;
+
+import org.apache.flex.compiler.clients.IBackend;
+import org.apache.flex.compiler.internal.as.codegen.TestExpressions;
+import org.apache.flex.compiler.internal.js.driver.goog.GoogBackend;
+import org.apache.flex.compiler.internal.tree.as.NamespaceAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IIfNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author Michael Schmalle
+ * @author Erik de Bruin
+ */
+public class TestGoogExpressions extends TestExpressions
+{
+	
+    //----------------------------------
+    // Primary expression keywords
+    //----------------------------------
+
+    //----------------------------------
+    // Logical
+    //----------------------------------
+
+    @Override
+	@Test
+    public void testVisitBinaryOperatorNode_LogicalAndAssignment()
+    {
+        IBinaryOperatorNode node = getBinaryNode("a &&= b");
+        visitor.visitBinaryOperator(node);
+        assertOut("a = a && b");
+    }
+
+    @Override
+    @Test
+    public void testVisitBinaryOperatorNode_LogicalOrAssignment()
+    {
+        IBinaryOperatorNode node = getBinaryNode("a ||= b");
+        visitor.visitBinaryOperator(node);
+        assertOut("a = a || b");
+    }
+
+    //----------------------------------
+    // Other
+    //----------------------------------
+
+    @Override
+    @Test
+    public void testAnonymousFunction()
+    {
+        IVariableNode node = (IVariableNode) getNode("var a = function(){};",
+                IVariableNode.class);
+        visitor.visitVariable(node);
+        assertOut("var a = function() {\n}");
+    }
+
+    @Override
+    @Test
+    public void testAnonymousFunctionWithParamsReturn()
+    {
+        IVariableNode node = (IVariableNode) getNode(
+                "var a:Object = function(foo:int, bar:String = 'goo'):int{return -1;};",
+                IVariableNode.class);
+        visitor.visitVariable(node);
+        assertOutDebug("var a = function(foo, bar) {\n\tbar = typeof bar !== 'undefined' ? bar : 'goo';\n\treturn -1;\n}");
+    }
+
+    @Override
+    @Test
+    public void testAnonymousFunctionAsArgument()
+    {
+        // TODO (mschmalle) using IIfNode in expressions test, any other way to do this without statement?
+        IIfNode node = (IIfNode) getNode(
+                "if (a) {addListener('foo', function(event:Object):void{doit();});}",
+                IIfNode.class);
+        visitor.visitIf(node);
+        assertOut("if (a) {\n\taddListener('foo', function(event) {\n\t\tdoit();\n\t});\n}");
+    }
+
+    @Override
+    @Test
+    public void testVisitAs()
+    {
+    	// TODO (erikdebruin) the assert is a placeholder for the eventual workaround
+        IBinaryOperatorNode node = getBinaryNode("a as b");
+        visitor.visitBinaryOperator(node);
+        assertOut("as(a, b)");
+    }
+
+    @Override
+    @Test
+    public void testVisitBinaryOperator_Instancof()
+    {
+    	// TODO (erikdebruin) check if the AS and JS implementations match
+        IBinaryOperatorNode node = getBinaryNode("a instanceof b");
+        visitor.visitBinaryOperator(node);
+        assertOut("a instanceof b");
+    }
+
+    @Override
+    @Test
+    public void testVisitBinaryOperator_Is()
+    {
+    	// TODO (erikdebruin) the assert is a placeholder for the eventual workaround
+        IBinaryOperatorNode node = getBinaryNode("a is b");
+        visitor.visitBinaryOperator(node);
+        assertOut("is(a, b)");
+    }
+
+    @Ignore
+    @Override
+    @Test
+    public void testVisitBinaryOperator_NamespaceAccess_1()
+    {
+        // TODO (mschmalle) this needs INamespaceAccessExpressionNode interface
+    	// TODO (erikdebruin) JS implementation?
+    	NamespaceAccessExpressionNode node = (NamespaceAccessExpressionNode) getExpressionNode(
+                "a::b", NamespaceAccessExpressionNode.class);
+        visitor.visitNamespaceAccessExpression(node);
+        assertOut("a::b");
+    }
+
+    @Ignore
+    @Override
+    @Test
+    public void testVisitBinaryOperator_NamespaceAccess_2()
+    {
+        // TODO (mschmalle) this needs INamespaceAccessExpressionNode interface
+    	// TODO (erikdebruin) JS implementation?
+        NamespaceAccessExpressionNode node = (NamespaceAccessExpressionNode) getExpressionNode(
+                "a::b::c", NamespaceAccessExpressionNode.class);
+        visitor.visitNamespaceAccessExpression(node);
+        assertOut("a::b::c");
+    }
+
+    protected IBackend createBackend()
+    {
+        return new GoogBackend();
+    }
+
+}

Propchange: flex/whiteboard/mschmalle/falconjx/compiler.jx.tests/src/org/apache/flex/compiler/internal/js/codegen/goog/TestGoogExpressions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/as/codegen/IASEmitter.java
URL: http://svn.apache.org/viewvc/flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/as/codegen/IASEmitter.java?rev=1430315&r1=1430314&r2=1430315&view=diff
==============================================================================
--- flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/as/codegen/IASEmitter.java (original)
+++ flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/as/codegen/IASEmitter.java Tue Jan  8 15:05:32 2013
@@ -22,6 +22,7 @@ package org.apache.flex.compiler.as.code
 import java.io.Writer;
 
 import org.apache.flex.compiler.internal.tree.as.FunctionObjectNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
 import org.apache.flex.compiler.tree.as.IExpressionNode;
 import org.apache.flex.compiler.tree.as.IFunctionNode;
 import org.apache.flex.compiler.tree.as.IGetterNode;
@@ -161,4 +162,15 @@ public interface IASEmitter
 
     void emitFunctionBlockHeader(IFunctionNode node);
 
+    //--------------------------------------------------------------------------
+    // Operators
+    //--------------------------------------------------------------------------
+
+    /**
+     * Emit an operator statement.
+     * 
+     * @param node The {@link IBinaryOperatorNode} or chain of variable nodes.
+     */
+    void emitBinaryOperator(IBinaryOperatorNode node);
+
 }

Modified: flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASBlockWalker.java
URL: http://svn.apache.org/viewvc/flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASBlockWalker.java?rev=1430315&r1=1430314&r2=1430315&view=diff
==============================================================================
--- flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASBlockWalker.java (original)
+++ flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASBlockWalker.java Tue Jan  8 15:05:32 2013
@@ -1008,12 +1008,8 @@ public class ASBlockWalker implements IA
     {
         debug("visitBinaryOperator(" + node.getOperator().getOperatorText()
                 + ")");
-        walk(node.getLeftOperandNode());
-        if (node.getNodeID() != ASTNodeID.Op_CommaID)
-            emitter.write(" ");
-        emitter.write(node.getOperator().getOperatorText());
-        emitter.write(" ");
-        walk(node.getRightOperandNode());
+        
+        emitter.emitBinaryOperator(node);
     }
 
     @Override

Modified: flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASEmitter.java
URL: http://svn.apache.org/viewvc/flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASEmitter.java?rev=1430315&r1=1430314&r2=1430315&view=diff
==============================================================================
--- flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASEmitter.java (original)
+++ flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/as/codegen/ASEmitter.java Tue Jan  8 15:05:32 2013
@@ -38,6 +38,7 @@ import org.apache.flex.compiler.problems
 import org.apache.flex.compiler.tree.ASTNodeID;
 import org.apache.flex.compiler.tree.as.IASNode;
 import org.apache.flex.compiler.tree.as.IAccessorNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
 import org.apache.flex.compiler.tree.as.IDefinitionNode;
 import org.apache.flex.compiler.tree.as.IExpressionNode;
 import org.apache.flex.compiler.tree.as.IFunctionNode;
@@ -542,7 +543,7 @@ public class ASEmitter implements IASEmi
         // TODO (mschmalle) FunctionObjectNode; does this need specific treatment?
         emitMethodScope(node);
     }
-
+    
     protected ITypeNode findTypeNode(IPackageNode node)
     {
         IScopedNode scope = node.getScopedNode();
@@ -569,4 +570,18 @@ public class ASEmitter implements IASEmi
         return null;
     }
 
+    //--------------------------------------------------------------------------
+    // Operators
+    //--------------------------------------------------------------------------
+
+    @Override
+    public void emitBinaryOperator(IBinaryOperatorNode node)
+    {
+        getWalker().walk(node.getLeftOperandNode());
+        if (node.getNodeID() != ASTNodeID.Op_CommaID)
+            write(" ");
+        write(node.getOperator().getOperatorText());
+        write(" ");
+        getWalker().walk(node.getRightOperandNode());
+    }
 }

Modified: flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/JSEmitter.java
URL: http://svn.apache.org/viewvc/flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/JSEmitter.java?rev=1430315&r1=1430314&r2=1430315&view=diff
==============================================================================
--- flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/JSEmitter.java (original)
+++ flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/JSEmitter.java Tue Jan  8 15:05:32 2013
@@ -23,8 +23,13 @@ import java.io.FilterWriter;
 
 import org.apache.flex.compiler.definitions.ITypeDefinition;
 import org.apache.flex.compiler.internal.as.codegen.ASEmitter;
+import org.apache.flex.compiler.internal.tree.as.ChainedVariableNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionObjectNode;
 import org.apache.flex.compiler.js.codegen.IJSEmitter;
 import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
 import org.apache.flex.compiler.tree.as.IFunctionNode;
 import org.apache.flex.compiler.tree.as.IVariableNode;
 
@@ -62,6 +67,20 @@ public class JSEmitter extends ASEmitter
     }
 
     @Override
+    public void emitFunctionObject(IExpressionNode node)
+    {
+        FunctionObjectNode f = (FunctionObjectNode) node;
+        
+        FunctionNode fnode = f.getFunctionNode();
+        
+        write("function");
+        
+        emitParamters(fnode.getParameterNodes());
+       
+        emitFunctionScope(fnode.getScopedNode());
+    }
+
+    @Override
     public void emitField(IVariableNode node)
     {
         super.emitField(node);
@@ -80,41 +99,29 @@ public class JSEmitter extends ASEmitter
     @Override
     public void emitVarDeclaration(IVariableNode node)
     {
-        super.emitVarDeclaration(node);
-        //        getWalker().walk(node.getChild(0)); // VariableExpressionNode
-        //        write(" ");
-        //        getWalker().walk(node.getNameExpressionNode());
-        //        // add :Type
-        //        {
-        //            IExpressionNode tnode = node.getVariableTypeNode();
-        //            if (tnode instanceof ILanguageIdentifierNode)
-        //            {
-        //                ILanguageIdentifierNode lnode = (ILanguageIdentifierNode) tnode;
-        //                if (lnode.getKind() != ILanguageIdentifierNode.LanguageIdentifierKind.ANY_TYPE)
-        //                    write(":");
-        //            }
-        //            else
-        //            {
-        //                write(":");
-        //            }
-        //
-        //            getWalker().walk(node.getVariableTypeNode());
-        //        }
-        //        IExpressionNode vnode = node.getAssignedValueNode();
-        //        if (vnode != null)
-        //        {
-        //            write(" = ");
-        //            if (vnode instanceof FunctionObjectNode)
-        //            {
-        //                //getWalker().pushContext(TraverseContext.FUNCTION);
-        //                getWalker().walk(vnode.getChild(0)); // IFunctionNode
-        //                //getWalker().popContext(TraverseContext.FUNCTION);
-        //            }
-        //            else
-        //            {
-        //                getWalker().walk(vnode);
-        //            }
-        //        }
+        if (!(node instanceof ChainedVariableNode))
+        {
+            emitMemberKeyword(node);
+        }
+
+        emitDeclarationName(node);
+        emitAssignedValue(node.getAssignedValueNode());
+
+        if (!(node instanceof ChainedVariableNode))
+        {
+            // check for chained variables
+            int len = node.getChildCount();
+            for (int i = 0; i < len; i++)
+            {
+                IASNode child = node.getChild(i);
+                if (child instanceof ChainedVariableNode)
+                {
+                    write(",");
+                    write(" ");
+                    emitVarDeclaration((IVariableNode) child);
+                }
+            }
+        }
     }
 
     @Override

Modified: flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/goog/JSGoogEmitter.java
URL: http://svn.apache.org/viewvc/flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/goog/JSGoogEmitter.java?rev=1430315&r1=1430314&r2=1430315&view=diff
==============================================================================
--- flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/goog/JSGoogEmitter.java (original)
+++ flex/whiteboard/mschmalle/falconjx/compiler.jx/src/org/apache/flex/compiler/internal/js/codegen/goog/JSGoogEmitter.java Tue Jan  8 15:05:32 2013
@@ -41,11 +41,13 @@ import org.apache.flex.compiler.projects
 import org.apache.flex.compiler.tree.ASTNodeID;
 import org.apache.flex.compiler.tree.as.IASNode;
 import org.apache.flex.compiler.tree.as.IAccessorNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
 import org.apache.flex.compiler.tree.as.IClassNode;
 import org.apache.flex.compiler.tree.as.IDefinitionNode;
 import org.apache.flex.compiler.tree.as.IExpressionNode;
 import org.apache.flex.compiler.tree.as.IFunctionNode;
 import org.apache.flex.compiler.tree.as.IGetterNode;
+import org.apache.flex.compiler.tree.as.IIdentifierNode;
 import org.apache.flex.compiler.tree.as.IPackageNode;
 import org.apache.flex.compiler.tree.as.IParameterNode;
 import org.apache.flex.compiler.tree.as.IScopedNode;
@@ -576,4 +578,52 @@ public class JSGoogEmitter extends JSEmi
         // tail, no colon; parent container will add it
         write(")");
     }
+
+    //--------------------------------------------------------------------------
+    // Operators
+    //--------------------------------------------------------------------------
+
+    @Override
+    public void emitBinaryOperator(IBinaryOperatorNode node)
+    {
+    	ASTNodeID id = node.getNodeID();
+    	
+    	if (id == ASTNodeID.Op_AsID || id == ASTNodeID.Op_IsID)
+        {
+        	// TODO (erikdebruin) replace: this is a placeholder for the 
+    		//                    eventual implementation
+            write((id == ASTNodeID.Op_AsID) ? "as(" : "is(");
+            getWalker().walk(node.getLeftOperandNode());
+            write(", ");
+            getWalker().walk(node.getRightOperandNode());
+            write(")");
+        }
+        else
+        {
+        	getWalker().walk(node.getLeftOperandNode());
+
+            if (id != ASTNodeID.Op_CommaID)
+                write(" ");
+            
+            // (erikdebruin) rewrite 'a &&= b' to 'a = a && b'
+            if (id == ASTNodeID.Op_LogicalAndAssignID || id == ASTNodeID.Op_LogicalOrAssignID)
+            {
+            	IIdentifierNode lnode = (IIdentifierNode) node.getLeftOperandNode();
+            	
+                write("=");
+                write(" ");
+                write(lnode.getName());
+                write(" ");
+                write((id == ASTNodeID.Op_LogicalAndAssignID) ? ASTNodeID.Op_LogicalAndID.getParaphrase() : ASTNodeID.Op_LogicalOrID.getParaphrase());
+            }
+            else
+            {
+            	write(node.getOperator().getOperatorText());
+            }
+            
+            write(" ");
+            
+            getWalker().walk(node.getRightOperandNode());
+        }
+    }
 }