FileDocCategorySizeDatePackage
ForEach.javaAPI DocJava SE 5 API6735Fri Aug 26 14:55:34 BST 2005com.sun.org.apache.xalan.internal.xsltc.compiler

ForEach

public final class ForEach extends Instruction
author
Jacek Ambroziak
author
Santiago Pericas-Geertsen
author
Morten Jorgensen

Fields Summary
private Expression
_select
private Type
_type
Constructors Summary
Methods Summary
public voiddisplay(int indent)

	indent(indent);
	Util.println("ForEach");
	indent(indent + IndentIncrement);
	Util.println("select " + _select.toString());
	displayContents(indent + IndentIncrement);
    
public voidinitializeVariables(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
The code that is generated by nested for-each loops can appear to some JVMs as if it is accessing un-initialized variables. We must add some code that pushes the default variable value on the stack and pops it into the variable slot. This is done by the Variable.initialize() method. The code that we compile for this loop looks like this: initialize iterator initialize variables <-- HERE!!! goto Iterate Loop: : : (code for contents) : Iterate: node = iterator.next(); if (node != END) goto Loop

	final int n = elementCount();
	for (int i = 0; i < n; i++) {
	    final Object child = getContents().elementAt(i);
	    if (child instanceof Variable) {
		Variable var = (Variable)child;
		var.initialize(classGen, methodGen);
	    }
	}
    
public voidparseContents(com.sun.org.apache.xalan.internal.xsltc.compiler.Parser parser)

	_select = parser.parseExpression(this, "select", null);

	parseChildren(parser);

        // make sure required attribute(s) have been set
        if (_select.isDummy()) {
	    reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
        }
    
public voidtranslate(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)

	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = methodGen.getInstructionList();

	// Save current node and current iterator on the stack
	il.append(methodGen.loadCurrentNode());
	il.append(methodGen.loadIterator());
		
	// Collect sort objects associated with this instruction
	final Vector sortObjects = new Vector();
	Enumeration children = elements();
	while (children.hasMoreElements()) {
	    final Object child = children.nextElement();
	    if (child instanceof Sort) {
		sortObjects.addElement(child);
	    }
	}

	if ((_type != null) && (_type instanceof ResultTreeType)) {
	    // Store existing DOM on stack - must be restored when loop is done
	    il.append(methodGen.loadDOM());

	    // <xsl:sort> cannot be applied to a result tree - issue warning
	    if (sortObjects.size() > 0) {
		ErrorMsg msg = new ErrorMsg(ErrorMsg.RESULT_TREE_SORT_ERR,this);
		getParser().reportError(WARNING, msg);
	    }

	    // Put the result tree on the stack (DOM)
	    _select.translate(classGen, methodGen);
	    // Get an iterator for the whole DOM - excluding the root node
	    _type.translateTo(classGen, methodGen, Type.NodeSet);
	    // Store the result tree as the default DOM
	    il.append(SWAP);
	    il.append(methodGen.storeDOM());
	}
	else {
	    // Compile node iterator
	    if (sortObjects.size() > 0) {
		Sort.translateSortIterator(classGen, methodGen,
					   _select, sortObjects);
	    }
	    else {
		_select.translate(classGen, methodGen);
	    }

	    if (_type instanceof ReferenceType == false) {
                il.append(methodGen.loadContextNode());
                il.append(methodGen.setStartNode());
	    }
	}


	// Overwrite current iterator
	il.append(methodGen.storeIterator());

	// Give local variables (if any) default values before starting loop
	initializeVariables(classGen, methodGen);

	final BranchHandle nextNode = il.append(new GOTO(null));
	final InstructionHandle loop = il.append(NOP);

	translateContents(classGen, methodGen);
		    
	nextNode.setTarget(il.append(methodGen.loadIterator()));
	il.append(methodGen.nextNode());
	il.append(DUP);
	il.append(methodGen.storeCurrentNode());
	il.append(new IFGT(loop));

	// Restore current DOM (if result tree was used instead for this loop)
	if ((_type != null) && (_type instanceof ResultTreeType)) {
	    il.append(methodGen.storeDOM());	    
	}

	// Restore current node and current iterator from the stack
	il.append(methodGen.storeIterator());
	il.append(methodGen.storeCurrentNode());
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypetypeCheck(com.sun.org.apache.xalan.internal.xsltc.compiler.SymbolTable stable)

	_type = _select.typeCheck(stable);

	if (_type instanceof ReferenceType || _type instanceof NodeType) {
	    _select = new CastExpr(_select, Type.NodeSet);
	    typeCheckContents(stable);
	    return Type.Void;
	}
	if (_type instanceof NodeSetType||_type instanceof ResultTreeType) {
	    typeCheckContents(stable);
	    return Type.Void;
	}
	throw new TypeCheckError(this);