randori.compiler.internal.codegen.js.RandoriEmitter.java Source code

Java tutorial

Introduction

Here is the source code for randori.compiler.internal.codegen.js.RandoriEmitter.java

Source

/***
 * Copyright 2013 Teoti Graphix, LLC.
 * 
 * Licensed 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.
 * 
 * 
 * @author Michael Schmalle <mschmalle@teotigraphix.com>
 */

package randori.compiler.internal.codegen.js;

import java.io.FilterWriter;
import java.util.List;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.flex.compiler.definitions.IDefinition;
import org.apache.flex.compiler.definitions.IFunctionDefinition;
import org.apache.flex.compiler.definitions.IPackageDefinition;
import org.apache.flex.compiler.internal.tree.as.FunctionNode;
import org.apache.flex.compiler.internal.tree.as.FunctionObjectNode;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.tree.ASTNodeID;
import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
import org.apache.flex.compiler.tree.as.IClassNode;
import org.apache.flex.compiler.tree.as.IContainerNode;
import org.apache.flex.compiler.tree.as.IDefinitionNode;
import org.apache.flex.compiler.tree.as.IDynamicAccessNode;
import org.apache.flex.compiler.tree.as.IExpressionNode;
import org.apache.flex.compiler.tree.as.IForLoopNode;
import org.apache.flex.compiler.tree.as.IFunctionCallNode;
import org.apache.flex.compiler.tree.as.IFunctionNode;
import org.apache.flex.compiler.tree.as.IFunctionObjectNode;
import org.apache.flex.compiler.tree.as.IIdentifierNode;
import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
import org.apache.flex.compiler.tree.as.ILiteralNode;
import org.apache.flex.compiler.tree.as.ILiteralNode.LiteralType;
import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
import org.apache.flex.compiler.tree.as.IPackageNode;
import org.apache.flex.compiler.tree.as.IParameterNode;
import org.apache.flex.compiler.tree.as.ITypeNode;
import org.apache.flex.compiler.tree.as.IVariableNode;

import randori.compiler.codegen.js.IRandoriEmitter;
import randori.compiler.codegen.js.ISessionModel;
import randori.compiler.internal.codegen.js.emitter.BinaryOperatorEmitter;
import randori.compiler.internal.codegen.js.emitter.DynamicAccessEmitter;
import randori.compiler.internal.codegen.js.emitter.FieldEmitter;
import randori.compiler.internal.codegen.js.emitter.FooterEmitter;
import randori.compiler.internal.codegen.js.emitter.FunctionCallEmitter;
import randori.compiler.internal.codegen.js.emitter.HeaderEmitter;
import randori.compiler.internal.codegen.js.emitter.IdentifierEmitter;
import randori.compiler.internal.codegen.js.emitter.MemberAccessExpressionEmitter;
import randori.compiler.internal.codegen.js.emitter.MethodEmitter;
import randori.compiler.internal.utils.DefinitionUtils;
import randori.compiler.internal.utils.MetaDataUtils;

/**
 * The base ship...
 * 
 * @author Michael Schmalle
 */
public class RandoriEmitter extends JSEmitter implements IRandoriEmitter {
    @Override
    public List<ICompilerProblem> getProblems() {
        return super.getProblems();
    }

    //--------------------------------------------------------------------------
    // Properties
    //--------------------------------------------------------------------------

    //----------------------------------
    // model
    //----------------------------------

    private final ISessionModel model;

    @Override
    public final ISessionModel getModel() {
        return model;
    }

    //--------------------------------------------------------------------------
    // Emitters
    //--------------------------------------------------------------------------

    private IdentifierEmitter identifier;

    private MemberAccessExpressionEmitter memberAccessExpression;

    private DynamicAccessEmitter dynamicAccessEmitter;

    private BinaryOperatorEmitter binaryOperator;

    private MethodEmitter method;

    private FieldEmitter field;

    private FunctionCallEmitter functionCall;

    private HeaderEmitter header;

    private FooterEmitter footer;

    //--------------------------------------------------------------------------
    // Constructor
    //--------------------------------------------------------------------------

    public RandoriEmitter(FilterWriter out) {
        super(out);

        model = new SessionModel();

        createEmitters();
    }

    //--------------------------------------------------------------------------
    // Protected :: Methods
    //--------------------------------------------------------------------------

    /**
     * Creates the sub emitters.
     */
    protected void createEmitters() {
        method = new MethodEmitter(this);
        field = new FieldEmitter(this);

        identifier = new IdentifierEmitter(this);
        memberAccessExpression = new MemberAccessExpressionEmitter(this);
        dynamicAccessEmitter = new DynamicAccessEmitter(this);
        binaryOperator = new BinaryOperatorEmitter(this);
        functionCall = new FunctionCallEmitter(this);

        header = new HeaderEmitter(this);
        footer = new FooterEmitter(this);
    }

    //--------------------------------------------------------------------------
    // Overridden Public :: Methods
    //--------------------------------------------------------------------------

    @Override
    public void emitPackageHeader(IPackageDefinition definition) {
        // TODO (mschmalle) emit package render comments
    }

    @Override
    public void emitPackageHeaderContents(IPackageDefinition definition) {
        IPackageNode node = definition.getNode();
        ITypeNode tnode = findTypeNode(node);
        if (!MetaDataUtils.isGlobal((IClassNode) tnode)) {
            header.emit(definition);
        }
    }

    @Override
    public void emitPackageContents(IPackageDefinition definition) {
        IPackageNode node = definition.getNode();
        ITypeNode tnode = findTypeNode(node);
        if (tnode != null) {
            writeNewline();
            getWalker().walk(tnode); // IClassNode | IInterfaceNode
        }
    }

    @Override
    public void emitPackageFooter(IPackageDefinition definition) {
        IClassNode node = (IClassNode) findTypeNode(definition.getNode());
        if (node == null)
            return; // temp because of unit tests

        if (!MetaDataUtils.isGlobal(node)) {
            footer.emit(node);
        }
    }

    @Override
    public void emitClass(IClassNode node) {
        // fields, methods
        final IDefinitionNode[] members = node.getAllMemberNodes();
        if (members.length > 0) {
            if (!MetaDataUtils.isGlobal(node)) {
                IFunctionDefinition constructor = node.getDefinition().getConstructor();
                IFunctionNode cnode = (IFunctionNode) constructor.getNode();
                if (cnode != null) {
                    method.emit(cnode);
                } else {
                    method.emitConstructor(constructor);
                }

                writeNewline(";");
            }
        }

        if (members.length > 0) {
            writeNewline();

            final int len = members.length;
            int i = 0;
            for (IDefinitionNode member : members) {
                IDefinition definition = member.getDefinition();

                if (member.getNodeID() == ASTNodeID.FunctionID) {
                    if (((IFunctionDefinition) definition).isConstructor())
                        continue;
                }

                if (member.getNodeID() == ASTNodeID.VariableID) {
                    model.addInjection(definition);
                    model.addViewInjection(definition);

                    if (definition.isStatic()) {
                        getWalker().walk(member);

                        write(";");
                        writeNewline();
                        writeNewline();
                    }
                } else if (member.getNodeID() == ASTNodeID.FunctionID) {
                    model.addInjection(definition);

                    getWalker().walk(member);

                    write(";");
                    writeNewline();
                    writeNewline();
                } else if (member.getNodeID() == ASTNodeID.GetterID || member.getNodeID() == ASTNodeID.SetterID) {
                    model.addInjection(definition);
                    model.addViewInjection(definition);

                    getWalker().walk(member);

                    write(";");
                    if (i < len - 1) {
                        writeNewline();
                        writeNewline();
                    }
                }
                i++;
            }
        }
    }

    @Override
    public void emitField(IVariableNode node) {
        field.emit(node);
    }

    @Override
    public void emitFunctionBlockHeader(IFunctionNode node) {
        method.emitHeader(node);
    }

    @Override
    public void emitMethod(IFunctionNode node) {
        method.emit(node);
    }

    @Override
    public void emitFunctionObject(IFunctionObjectNode node) {
        FunctionObjectNode f = (FunctionObjectNode) node;
        FunctionNode fnode = f.getFunctionNode();
        //write(IRandoriEmitter.ANON_DELEGATE_NAME);
        //write("(");
        //write("this, ");
        write("function");
        emitParamters(fnode.getParameterNodes());
        emitType(fnode.getTypeNode());
        emitFunctionScope(fnode.getScopedNode());
        //write(")");
    }

    @Override
    public void emitFunctionCall(IFunctionCallNode node) {
        functionCall.emit(node);
    }

    @Override
    public void emitParameter(IParameterNode node) {
        getWalker().walk(node.getNameExpressionNode());
    }

    @Override
    protected void walkArguments(IExpressionNode[] nodes) {
    }

    @Override
    public void emitForEachLoop(IForLoopNode node) {
        IContainerNode containerNode = (IContainerNode) node.getChild(1);
        writeToken("for");
        write("(");

        IContainerNode conditionalNode = node.getConditionalsContainerNode();
        getWalker().walk(conditionalNode.getChild(0));

        write(")");
        if (!isImplicit(containerNode))
            write(" ");

        getWalker().walk(node.getStatementContentsNode());
    }

    @Override
    public void emitAsOperator(IBinaryOperatorNode node) {
        getWalker().walk(node.getLeftOperandNode());
    }

    @Override
    public void emitIsOperator(IBinaryOperatorNode node) {
        getWalker().walk(node.getLeftOperandNode());
        write(" instanceof ");
        getWalker().walk(node.getRightOperandNode());
    }

    @Override
    public void emitBinaryOperator(IBinaryOperatorNode node) {
        binaryOperator.emit(node);
    }

    @Override
    public void emitMemberAccessExpression(IMemberAccessExpressionNode node) {
        memberAccessExpression.emit(node);
    }

    @Override
    public void emitDynamicAccess(IDynamicAccessNode node) {
        dynamicAccessEmitter.emit(node);
    }

    @Override
    public void emitIdentifier(IIdentifierNode node) {
        identifier.emit(node);
    }

    @Override
    protected void emitType(IExpressionNode node) {
    }

    @Override
    public void emitLanguageIdentifier(ILanguageIdentifierNode node) {
        if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.ANY_TYPE) {
        } else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.REST) {
        } else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.SUPER) {
            IIdentifierNode inode = (IIdentifierNode) node;
            if (inode.getParent() instanceof IMemberAccessExpressionNode) {
                // emitFunctionCall() takes care of super.foo()
            } else {
                IClassNode typeNode = (IClassNode) DefinitionUtils.findTypeNode(inode.getParent());
                String qualifiedName = DefinitionUtils.toBaseClassQualifiedName(typeNode.getDefinition(),
                        getWalker().getProject());
                write(qualifiedName + ".call");
            }
        } else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS) {
            IIdentifierNode inode = (IIdentifierNode) node;
            if (!(inode.getParent() instanceof IMemberAccessExpressionNode))
                write("this");
        } else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.VOID) {
        }
    }

    @Override
    public void emitLiteral(ILiteralNode node) {
        String value = node.getValue(false);
        if (node.getLiteralType() == LiteralType.STRING) {
            value = "\"" + StringEscapeUtils.escapeEcmaScript(value) + "\"";
        }
        write(value);
    }

    @Override
    public String toNodeString(IExpressionNode node) {
        return stringifyNode(node);
    }

    @Override
    public void emitParamters(IFunctionNode node) {
        emitParamters(node.getParameterNodes());
    }

    @Override
    public void emitMethodScope(IFunctionNode node) {
        emitMethodScope(node.getScopedNode());
    }
}