public void emit()

in compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java [51:297]


    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()).isXMLish((IdentifierNode)obj))
        	{
        		write(".elementNames()");
        		isXML = true;
        	}
            if (((JSRoyaleEmitter)getEmitter()).isProxy((IdentifierNode)obj))
            {
                emitNullSafeProxyTarget(targetName);
                isProxy = true;
            }
        }
        else if (obj.getNodeID() == ASTNodeID.Op_DescendantsID)
        {
            //it should always be XMLList... but check anyway
            if (((JSRoyaleEmitter)getEmitter()).isXMLList((IMemberAccessExpressionNode)obj))
            {
                write(".elementNames()");
                isXML = true;
            }
        }
        else if (obj.getNodeID() == ASTNodeID.MemberAccessExpressionID)
        {
            if (((JSRoyaleEmitter)getEmitter()).isXMLList((IMemberAccessExpressionNode)obj))
            {
                write(".elementNames()");
                isXML = true;
            }
            if (((JSRoyaleEmitter)getEmitter()).isProxy((IMemberAccessExpressionNode)obj))
            {
                emitNullSafeProxyTarget(targetName);
                isProxy = 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 {
                    IClassDefinition asTarget = (IClassDefinition) ((IdentifierNode) asChild).resolve(getProject());
                    if (asTarget != null) {
                        //check ancestry for proxy
                        RoyaleProject project = (RoyaleProject) getProject();
                        if (asTarget.isInstanceOf(project.getProxyBaseClass(), project)){
                            emitNullSafeProxyTarget(targetName);
                            isProxy = 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;
        		} else {
        		    IDefinition funcNameDef = funcName.resolve(getProject());
                    //if it is IClassDefinition, then it is a type cast, otherwise...
        		    if (funcNameDef instanceof IFunctionDefinition) {
                        //then it is a regular function call, so check the return type, and use that for the IClassDefinition type check:
                        funcNameDef = ((IFunctionDefinition)funcNameDef).resolveReturnType(getProject());
                    }
        		    if (funcNameDef instanceof IClassDefinition) {
        		        //this is a a hard cast
                        //check ancestry for proxy
                        RoyaleProject project = (RoyaleProject) getProject();
                        if (((IClassDefinition) funcNameDef).isInstanceOf(project.getProxyBaseClass(), project)){
                            emitNullSafeProxyTarget(targetName);
                            isProxy = true;
                        }
                    }
                }
        	} else if (funcName instanceof IMemberAccessExpressionNode) {
                IFunctionDefinition funcDef = (IFunctionDefinition) ((IMemberAccessExpressionNode) funcName).getRightOperandNode().resolve(getProject());
                if (funcDef == null) {
                    //we need to check the LHS for XMLishness, and then resolve the method name against the determined XMLish definition (XML or XMLList),
                    // and then check its return type once we find the public FunctionDefinition for the method name
                    // (because although it is a member of something XMLish, it may not return something that is also XMLish, such as a QName, a String, a uint, or a Namespace etc)
                    IDefinitionSet matchingDefinitions = null;
                    if (EmitterUtils.isLeftNodeXML(((IMemberAccessExpressionNode) funcName).getLeftOperandNode(), getProject())) {
                        if (((IMemberAccessExpressionNode) funcName).getRightOperandNode().getNodeID() == ASTNodeID.IdentifierID) {
                            matchingDefinitions = getProject().getBuiltinType(IASLanguageConstants.BuiltinType.XML).getContainedScope().getLocalDefinitionSetByName(((IIdentifierNode)((IMemberAccessExpressionNode) funcName).getRightOperandNode()).getName());
                        }
                    } else if (EmitterUtils.isLeftNodeXMLList(((IMemberAccessExpressionNode) funcName).getLeftOperandNode(), getProject())) {
                        if (((IMemberAccessExpressionNode) funcName).getRightOperandNode().getNodeID() == ASTNodeID.IdentifierID) {
                            matchingDefinitions = getProject().getBuiltinType(IASLanguageConstants.BuiltinType.XMLLIST).getContainedScope().getLocalDefinitionSetByName(((IIdentifierNode)((IMemberAccessExpressionNode) funcName).getRightOperandNode()).getName());
                        }
                    }
                    if (matchingDefinitions != null) {
                        for (int i = 0; i< matchingDefinitions.getSize(); i++) {
                            IDefinition functionDefinition = matchingDefinitions.getDefinition(i);
                            if (functionDefinition instanceof IFunctionDefinition) {
                                if (functionDefinition.isPublic()) {
                                    isXML = SemanticUtils.isXMLish((((IFunctionDefinition) functionDefinition).resolveReturnType(getProject())), getProject());
                                    break;
                                }
                            }
                        }
                    }

                    //@todo should we emit a warning here if wasXMLish (from either of the first 2 checks) && !isXML (from the matchingDefinitions check)?
                    // results will not be consistent in this case.
                    // e.g. looping over a QName or Namespace instance
                    // It is probably rare and ill-advised, but it definitely won't work well in javascript currently for those classes, for example.

                } else {
                    IClassDefinition returnType = (IClassDefinition) funcDef.resolveReturnType(getProject());
                    isXML = SemanticUtils.isXMLish(returnType, getProject());
                    if (!isXML) {
                        //check for Proxy
                        RoyaleProject project = (RoyaleProject) getProject();
                        if (returnType.isInstanceOf(project.getProxyBaseClass(), project)){
                            emitNullSafeProxyTarget(targetName);
                            isProxy = true;
                        }
                    }
                }
                if (isXML) {
                    write(".elementNames()");
                }
            } //@todo what about dynamic access node for function call? e.g. myXML[string_Value_Here]() ... not so easy really, would likely need a runtime helper/wrapper.
        }
        endMapping(rnode);
        startMapping(node, cnode);
        writeToken(ASEmitterTokens.PAREN_CLOSE);
        endMapping(node);
        writeNewline();
        write(ASEmitterTokens.BLOCK_OPEN);
        writeNewline();
        
        if (childNode instanceof IVariableExpressionNode)
        {
            startMapping(childNode);
            write(ASEmitterTokens.VAR);
            write(ASEmitterTokens.SPACE);
            write(((IVariableNode) childNode.getChild(0)).getName()); //it's always a local var
            //putting this in here instead of common code following the 2 blocks to keep sourcemap tests passing
            write(ASEmitterTokens.SPACE);
            write(ASEmitterTokens.EQUAL);
            write(ASEmitterTokens.SPACE);
            endMapping(childNode);
        }
        else { //IdentifierNode
            getWalker().walk(childNode); //we need to walk here, to deal with non-local var identifiers
            startMapping(childNode);
            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();
    }