Added FlexJS JS emitter and backend

In order to be able to handle FlexJS specific JS output, a new emitter and 
supporting files are added.

Signed-off-by: Erik de Bruin <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/38ca8a6c
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/38ca8a6c
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/38ca8a6c

Branch: refs/heads/develop
Commit: 38ca8a6c0bea2f01d209ca5d5c5dbab1472b84e3
Parents: 43e9b3c
Author: Erik de Bruin <[email protected]>
Authored: Wed Mar 27 16:26:55 2013 +0100
Committer: Erik de Bruin <[email protected]>
Committed: Wed Mar 27 16:29:59 2013 +0100

----------------------------------------------------------------------
 .../codegen/js/flexjs/IJSFlexJSEmitter.java        |   30 ++
 .../codegen/js/flexjs/JSFlexJSEmitter.java         |  368 +++++++++++++++
 .../internal/driver/js/flexjs/FlexJSBackend.java   |   42 ++
 3 files changed, 440 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/38ca8a6c/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java
----------------------------------------------------------------------
diff --git 
a/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java
 
b/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java
new file mode 100644
index 0000000..038c5ce
--- /dev/null
+++ 
b/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java
@@ -0,0 +1,30 @@
+/*
+ *
+ *  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.codegen.js.flexjs;
+
+import org.apache.flex.compiler.codegen.js.goog.IJSGoogEmitter;
+
+/**
+ * @author Erik de Bruin
+ */
+public interface IJSFlexJSEmitter extends IJSGoogEmitter
+{
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/38ca8a6c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
----------------------------------------------------------------------
diff --git 
a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
 
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
new file mode 100644
index 0000000..dd4d137
--- /dev/null
+++ 
b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java
@@ -0,0 +1,368 @@
+/*
+ *
+ *  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.codegen.js.flexjs;
+
+import java.io.FilterWriter;
+
+import org.apache.flex.compiler.codegen.js.flexjs.IJSFlexJSEmitter;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitter;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.flex.compiler.internal.definitions.AccessorDefinition;
+import org.apache.flex.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.projects.ICompilerProject;
+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.IFunctionCallNode;
+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.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.ISetterNode;
+import org.apache.flex.compiler.utils.ASNodeUtils;
+
+/**
+ * Concrete implementation of the 'goog' JavaScript production.
+ * 
+ * @author Michael Schmalle
+ * @author Erik de Bruin
+ */
+public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter
+{
+
+    public JSFlexJSEmitter(FilterWriter out)
+    {
+        super(out);
+    }
+
+    @Override
+    protected void emitAccessors(IAccessorNode node)
+    {
+        if (node.getNodeID() == ASTNodeID.GetterID)
+        {
+            emitGetAccessor((IGetterNode) node);
+        }
+        else if (node.getNodeID() == ASTNodeID.SetterID)
+        {
+            emitSetAccessor((ISetterNode) node);
+        }
+    }
+
+    @Override
+    public void emitIdentifier(IIdentifierNode node)
+    {
+        ICompilerProject project = getWalker().getProject();
+
+        IClassNode cnode = (IClassNode) node
+                .getAncestorOfType(IClassNode.class);
+
+        IDefinition def = ((IIdentifierNode) node).resolve(project);
+
+        ITypeDefinition type = ((IIdentifierNode) node).resolveType(project);
+
+        IASNode pnode = node.getParent();
+        ASTNodeID inode = pnode.getNodeID();
+
+        boolean writeSelf = false;
+        if (cnode != null)
+        {
+            IDefinitionNode[] members = cnode.getAllMemberNodes();
+            for (IDefinitionNode mnode : members)
+            {
+                if ((type != null && type.getQualifiedName().equalsIgnoreCase(
+                        IASLanguageConstants.Function))
+                        || (def != null && def.getQualifiedName()
+                                .equalsIgnoreCase(mnode.getQualifiedName())))
+                {
+                    if (!(pnode instanceof FunctionNode)
+                            && inode != ASTNodeID.MemberAccessExpressionID)
+                    {
+                        writeSelf = true;
+                        break;
+                    }
+                    else if (inode == ASTNodeID.MemberAccessExpressionID
+                            && !def.isStatic())
+                    {
+                        String tname = type.getQualifiedName();
+                        writeSelf = !tname.equalsIgnoreCase(cnode
+                                .getQualifiedName())
+                                && 
!tname.equals(IASLanguageConstants.Function);
+                        break;
+                    }
+                }
+            }
+        }
+
+        // XXX (erikdebruin) I desperately needed a way to bypass the addition
+        //                   of the 'self' prefix when running the tests... Or 
+        //                   I'd have to put the prefix in ~150 asserts!
+        boolean isRunningInTestMode = cnode != null
+                && cnode.getQualifiedName().equalsIgnoreCase("A");
+
+        if (writeSelf && !isRunningInTestMode)
+        {
+            write(JSGoogEmitterTokens.SELF);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+        }
+        else
+        {
+            String pname = (type != null) ? type.getPackageName() : "";
+            if (cnode != null
+                    && pname != ""
+                    && !pname.equalsIgnoreCase(cnode.getPackageName())
+                    && inode != ASTNodeID.ArgumentID
+                    && inode != ASTNodeID.VariableID
+                    && inode != ASTNodeID.TypedExpressionID)
+            {
+                write(pname);
+                write(ASEmitterTokens.MEMBER_ACCESS);
+            }
+        }
+
+        if (def instanceof AccessorDefinition)
+        {
+            IASNode anode = node
+                    .getAncestorOfType(BinaryOperatorAssignmentNode.class);
+
+            boolean isLeftSide = anode != null
+                    && (pnode.equals(anode.getChild(0)) || node.equals(anode
+                            .getChild(0)));
+
+            write((anode != null && isLeftSide) ? "set_" : "get_");
+            write(node.getName());
+            write(ASEmitterTokens.PAREN_OPEN);
+
+            IExpressionNode rightSide = null;
+
+            if (anode != null)
+            {
+                if (isLeftSide)
+                {
+                    rightSide = ((BinaryOperatorAssignmentNode) anode)
+                            .getRightOperandNode();
+
+                    getWalker().walk(rightSide);
+                }
+                else
+                {
+                    rightSide = ((IBinaryOperatorNode) pnode)
+                            .getRightOperandNode();
+                }
+            }
+
+            write(ASEmitterTokens.PAREN_CLOSE);
+
+            if (anode != null
+                    && !isLeftSide && pnode instanceof IBinaryOperatorNode
+                    && !(pnode instanceof IMemberAccessExpressionNode))
+            {
+                rightSide = ((IBinaryOperatorNode) 
pnode).getRightOperandNode();
+
+                if (rightSide != null)
+                {
+                    write(ASEmitterTokens.SPACE);
+
+                    writeToken(((IBinaryOperatorNode) pnode).getOperator()
+                            .getOperatorText());
+
+                    getWalker().walk(rightSide);
+                }
+            }
+        }
+        else
+        {
+            write(node.getName());
+        }
+    }
+
+    @Override
+    protected void emitSuperCall(IASNode node, String type)
+    {
+        IFunctionNode fnode = (node instanceof IFunctionNode) ? 
(IFunctionNode) node
+                : null;
+        IFunctionCallNode fcnode = (node instanceof IFunctionCallNode) ? 
(FunctionCallNode) node
+                : null;
+
+        if (type == CONSTRUCTOR_EMPTY)
+        {
+            indentPush();
+            writeNewline();
+            indentPop();
+        }
+        else if (type == SUPER_FUNCTION_CALL)
+        {
+            if (fnode == null)
+                fnode = (IFunctionNode) fcnode
+                        .getAncestorOfType(IFunctionNode.class);
+        }
+
+        write(JSGoogEmitterTokens.GOOG_BASE);
+        write(ASEmitterTokens.PAREN_OPEN);
+        write(ASEmitterTokens.THIS);
+
+        if (fnode != null && !fnode.isConstructor())
+        {
+            writeToken(ASEmitterTokens.COMMA);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            if (fnode.getNodeID() == ASTNodeID.GetterID)
+                write("get_");
+            else if (fnode.getNodeID() == ASTNodeID.SetterID)
+                write("set_");
+
+            write(fnode.getName());
+            write(ASEmitterTokens.SINGLE_QUOTE);
+        }
+
+        IASNode[] anodes = null;
+        boolean writeArguments = false;
+        if (fcnode != null)
+        {
+            anodes = fcnode.getArgumentNodes();
+
+            writeArguments = anodes.length > 0;
+        }
+        else if (fnode.isConstructor())
+        {
+            anodes = fnode.getParameterNodes();
+
+            writeArguments = (anodes != null && anodes.length > 0);
+        }
+
+        if (writeArguments)
+        {
+            int len = anodes.length;
+            for (int i = 0; i < len; i++)
+            {
+                writeToken(ASEmitterTokens.COMMA);
+
+                getWalker().walk(anodes[i]);
+            }
+        }
+
+        write(ASEmitterTokens.PAREN_CLOSE);
+
+        if (type == CONSTRUCTOR_FULL)
+        {
+            write(ASEmitterTokens.SEMICOLON);
+            writeNewline();
+        }
+        else if (type == CONSTRUCTOR_EMPTY)
+        {
+            write(ASEmitterTokens.SEMICOLON);
+        }
+    }
+
+    @Override
+    public void emitBinaryOperator(IBinaryOperatorNode node)
+    {
+        ASTNodeID id = node.getNodeID();
+        if (id == ASTNodeID.Op_IsID
+                || id == ASTNodeID.Op_AsID || id == ASTNodeID.Op_InID
+                || id == ASTNodeID.Op_LogicalAndAssignID
+                || id == ASTNodeID.Op_LogicalOrAssignID)
+        {
+            super.emitBinaryOperator(node);
+        }
+        else
+        {
+            IExpressionNode leftSide = node.getLeftOperandNode();
+
+            IExpressionNode property = null;
+            int leftSideChildCount = leftSide.getChildCount();
+            if (leftSideChildCount > 0)
+                property = (IExpressionNode) leftSide
+                        .getChild(leftSideChildCount - 1);
+            else
+                property = leftSide;
+
+            IDefinition def = null;
+            if (property instanceof IIdentifierNode)
+                def = ((IIdentifierNode) property).resolve(getWalker()
+                        .getProject());
+
+            if (def instanceof AccessorDefinition)
+            {
+                getWalker().walk(leftSide);
+            }
+            else
+            {
+                if (ASNodeUtils.hasParenOpen(node))
+                    write(ASEmitterTokens.PAREN_OPEN);
+
+                getWalker().walk(leftSide);
+
+                if (node.getNodeID() != ASTNodeID.Op_CommaID)
+                    write(ASEmitterTokens.SPACE);
+
+                writeToken(node.getOperator().getOperatorText());
+
+                getWalker().walk(node.getRightOperandNode());
+
+                if (ASNodeUtils.hasParenClose(node))
+                    write(ASEmitterTokens.PAREN_CLOSE);
+            }
+        }
+    }
+
+    @Override
+    protected void emitObjectDefineProperty(IAccessorNode node)
+    {
+        /*
+        Class.prototype.get_property = function()
+        {
+            // body;
+        };
+        */
+
+        FunctionNode fn = (FunctionNode) node;
+        fn.parseFunctionBody(problems);
+
+        IFunctionDefinition definition = node.getDefinition();
+        ITypeDefinition type = (ITypeDefinition) definition.getParent();
+        write(type.getQualifiedName());
+        if (!node.hasModifier(ASModifier.STATIC))
+        {
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSEmitterTokens.PROTOTYPE);
+        }
+
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write((node instanceof IGetterNode) ? "get_" : "set_");
+        writeToken(node.getName());
+        writeToken(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.FUNCTION);
+        emitParamters(node.getParameterNodes());
+        //writeNewline();
+        emitMethodScope(node.getScopedNode());
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/38ca8a6c/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java
----------------------------------------------------------------------
diff --git 
a/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java
 
b/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java
new file mode 100644
index 0000000..9a7d92e
--- /dev/null
+++ 
b/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java
@@ -0,0 +1,42 @@
+/*
+ *
+ *  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.driver.js.flexjs;
+
+import java.io.FilterWriter;
+
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter;
+import org.apache.flex.compiler.internal.driver.js.goog.GoogBackend;
+
+/**
+ * @author Erik de Bruin
+ */
+public class FlexJSBackend extends GoogBackend
+{
+
+    @Override
+    public IJSEmitter createEmitter(FilterWriter out)
+    {
+        IJSEmitter emitter = new JSFlexJSEmitter(out);
+        emitter.setDocEmitter(createDocEmitter(emitter));
+        return emitter;
+    }
+    
+}

Reply via email to