MethodGenerator methodGen) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
int iteratorIndex = 0;
BranchHandle ifBlock = null;
LocalVariableGen iter, node, node2;
final String iteratorName = getNextFieldName();
// Store node on the stack into a local variable
node = methodGen.addLocalVariable("step_pattern_tmp1",
Util.getJCRefType(NODE_SIG),
null, null);
node.setStart(il.append(new ISTORE(node.getIndex())));
// Create a new local to store the iterator
iter = methodGen.addLocalVariable("step_pattern_tmp2",
Util.getJCRefType(NODE_ITERATOR_SIG),
null, null);
// Add a new private field if this is the main class
if (!classGen.isExternal()) {
final Field iterator =
new Field(ACC_PRIVATE,
cpg.addUtf8(iteratorName),
cpg.addUtf8(NODE_ITERATOR_SIG),
null, cpg.getConstantPool());
classGen.addField(iterator);
iteratorIndex = cpg.addFieldref(classGen.getClassName(),
iteratorName,
NODE_ITERATOR_SIG);
il.append(classGen.loadTranslet());
il.append(new GETFIELD(iteratorIndex));
il.append(DUP);
iter.setStart(il.append(new ASTORE(iter.getIndex())));
ifBlock = il.append(new IFNONNULL(null));
il.append(classGen.loadTranslet());
}
// Compile the step created at type checking time
_step.translate(classGen, methodGen);
InstructionHandle iterStore = il.append(new ASTORE(iter.getIndex()));
// If in the main class update the field too
if (!classGen.isExternal()) {
il.append(new ALOAD(iter.getIndex()));
il.append(new PUTFIELD(iteratorIndex));
ifBlock.setTarget(il.append(NOP));
} else {
// If class is not external, start of range for iter variable was
// set above
iter.setStart(iterStore);
}
// Get the parent of the node on the stack
il.append(methodGen.loadDOM());
il.append(new ILOAD(node.getIndex()));
int index = cpg.addInterfaceMethodref(DOM_INTF,
GET_PARENT, GET_PARENT_SIG);
il.append(new INVOKEINTERFACE(index, 2));
// Initialize the iterator with the parent
il.append(new ALOAD(iter.getIndex()));
il.append(SWAP);
il.append(methodGen.setStartNode());
/*
* Inline loop:
*
* int node2;
* while ((node2 = iter.next()) != NodeIterator.END
* && node2 < node);
* return node2 == node;
*/
BranchHandle skipNext;
InstructionHandle begin, next;
node2 = methodGen.addLocalVariable("step_pattern_tmp3",
Util.getJCRefType(NODE_SIG),
null, null);
skipNext = il.append(new GOTO(null));
next = il.append(new ALOAD(iter.getIndex()));
node2.setStart(next);
begin = il.append(methodGen.nextNode());
il.append(DUP);
il.append(new ISTORE(node2.getIndex()));
_falseList.add(il.append(new IFLT(null))); // NodeIterator.END
il.append(new ILOAD(node2.getIndex()));
il.append(new ILOAD(node.getIndex()));
iter.setEnd(il.append(new IF_ICMPLT(next)));
node2.setEnd(il.append(new ILOAD(node2.getIndex())));
node.setEnd(il.append(new ILOAD(node.getIndex())));
_falseList.add(il.append(new IF_ICMPNE(null)));
skipNext.setTarget(begin);
}