blob: 86e62275e98f82e666edf69e084d08fd81ee9323 [file] [log] [blame]
/*
*
* 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.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
import org.apache.royale.compiler.internal.tree.as.LabeledStatementNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
import org.apache.royale.compiler.tree.as.IContainerNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IForLoopNode;
import org.apache.royale.compiler.tree.as.IIdentifierNode;
import org.apache.royale.compiler.tree.as.IVariableExpressionNode;
import org.apache.royale.compiler.tree.as.IVariableNode;
public class ForEachEmitter extends JSSubEmitter implements
ISubEmitter<IForLoopNode>
{
public ForEachEmitter(IJSEmitter emitter)
{
super(emitter);
}
@Override
public void emit(IForLoopNode node)
{
IContainerNode cnode = node.getConditionalsContainerNode();
IBinaryOperatorNode bnode = (IBinaryOperatorNode) cnode.getChild(0);
IExpressionNode childNode = bnode.getLeftOperandNode();
IExpressionNode rnode = bnode.getRightOperandNode();
final String iterName = getModel().getCurrentForeachName();
getModel().incForeachLoopCount();
final String targetName = iterName + "_target";
startMapping(rnode);
write(ASEmitterTokens.VAR);
write(ASEmitterTokens.SPACE);
write(targetName);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.EQUAL);
write(ASEmitterTokens.SPACE);
endMapping(rnode);
IASNode obj = bnode.getChild(1);
getWalker().walk(obj);
startMapping(rnode);
write(ASEmitterTokens.SEMICOLON);
endMapping(rnode);
writeNewline();
if (node.getParent().getNodeID() == ASTNodeID.BlockID &&
node.getParent().getParent().getNodeID() == ASTNodeID.LabledStatementID)
{
// emit label here
LabeledStatementNode labelNode = (LabeledStatementNode)node.getParent().getParent();
writeToken(labelNode.getLabel());
writeToken(ASEmitterTokens.COLON);
}
startMapping(node);
write(ASEmitterTokens.FOR);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.PAREN_OPEN);
endMapping(node);
startMapping(rnode);
write(ASEmitterTokens.VAR);
write(ASEmitterTokens.SPACE);
write(iterName);
endMapping(rnode);
startMapping(bnode, childNode);
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.IN);
write(ASEmitterTokens.SPACE);
endMapping(bnode);
startMapping(rnode);
write(targetName);
boolean isXML = false;
boolean isProxy = false;
if (obj.getNodeID() == ASTNodeID.IdentifierID)
{
if (((JSRoyaleEmitter)getEmitter()).isXML((IdentifierNode)obj))
{
write(".elementNames()");
isXML = true;
}
if (((JSRoyaleEmitter)getEmitter()).isProxy((IdentifierNode)obj))
{
write(".propertyNames()");
isProxy = true;
}
}
else if (obj.getNodeID() == ASTNodeID.MemberAccessExpressionID)
{
if (((JSRoyaleEmitter)getEmitter()).isXMLList((MemberAccessExpressionNode)obj))
{
write(".elementNames()");
isXML = true;
}
if (((JSRoyaleEmitter)getEmitter()).isProxy((MemberAccessExpressionNode)obj))
{
write(".propertyNames()");
isXML = true;
}
}
else if (obj.getNodeID() == ASTNodeID.Op_AsID)
{
IASNode asChild = obj.getChild(1);
if (asChild.getNodeID() == ASTNodeID.IdentifierID)
{
String asName = ((IdentifierNode)asChild).getName();
if (asName.equals(IASLanguageConstants.XML) || asName.equals(IASLanguageConstants.XMLList))
{
write(".elementNames()");
isXML = true;
}
}
}
else if (obj.getNodeID() == ASTNodeID.FunctionCallID)
{
FunctionCallNode func = (FunctionCallNode)obj;
IExpressionNode funcName = func.getNameNode();
if (funcName.getNodeID() == ASTNodeID.IdentifierID)
{
String asName = ((IdentifierNode)funcName).getName();
if (asName.equals(IASLanguageConstants.XML) || asName.equals(IASLanguageConstants.XMLList))
{
write(".elementNames()");
isXML = true;
}
}
}
endMapping(rnode);
startMapping(node, cnode);
writeToken(ASEmitterTokens.PAREN_CLOSE);
endMapping(node);
writeNewline();
write(ASEmitterTokens.BLOCK_OPEN);
writeNewline();
startMapping(childNode);
if (childNode instanceof IVariableExpressionNode)
{
write(ASEmitterTokens.VAR);
write(ASEmitterTokens.SPACE);
write(((IVariableNode) childNode.getChild(0)).getName());
}
else
write(((IIdentifierNode) childNode).getName());
write(ASEmitterTokens.SPACE);
write(ASEmitterTokens.EQUAL);
write(ASEmitterTokens.SPACE);
endMapping(childNode);
startMapping(rnode);
write(targetName);
if (isXML)
{
write("[");
write(iterName);
write("]");
}
else if (isProxy)
{
write(".getProperty(");
write(iterName);
write(")");
}
else
{
write(ASEmitterTokens.SQUARE_OPEN);
write(iterName);
write(ASEmitterTokens.SQUARE_CLOSE);
}
write(ASEmitterTokens.SEMICOLON);
endMapping(rnode);
writeNewline();
getWalker().walk(node.getStatementContentsNode());
write(ASEmitterTokens.BLOCK_CLOSE);
writeNewline();
}
}