gt: 	final ConstantPoolGen cpg = classGen.getConstantPool();
context: /*
   * 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.
   */
  /*
   * $Id$
   */
  
  package org.apache.xalan.xsltc.compiler;
  
  import org.apache.bcel.generic.BranchHandle;
  import org.apache.bcel.generic.BranchInstruction;
  import org.apache.bcel.generic.ConstantPoolGen;
  import org.apache.bcel.generic.GOTO;
  import org.apache.bcel.generic.IFEQ;
  import org.apache.bcel.generic.IFNE;
  import org.apache.bcel.generic.IF_ICMPEQ;
  import org.apache.bcel.generic.IF_ICMPNE;
  import org.apache.bcel.generic.INVOKESTATIC;
  import org.apache.bcel.generic.INVOKEVIRTUAL;
  import org.apache.bcel.generic.InstructionList;
  import org.apache.bcel.generic.PUSH;
  import org.apache.xalan.xsltc.compiler.util.BooleanType;
  import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
  import org.apache.xalan.xsltc.compiler.util.IntType;
  import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
  import org.apache.xalan.xsltc.compiler.util.NodeSetType;
  import org.apache.xalan.xsltc.compiler.util.NodeType;
  import org.apache.xalan.xsltc.compiler.util.NumberType;
  import org.apache.xalan.xsltc.compiler.util.RealType;
  import org.apache.xalan.xsltc.compiler.util.ReferenceType;
  import org.apache.xalan.xsltc.compiler.util.ResultTreeType;
  import org.apache.xalan.xsltc.compiler.util.StringType;
  import org.apache.xalan.xsltc.compiler.util.Type;
  import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
  import org.apache.xalan.xsltc.runtime.Operators;
  
  /**
   * @author Jacek Ambroziak
   * @author Santiago Pericas-Geertsen
   * @author Morten Jorgensen
   * @author Erwin Bolwidt <ejb@klomp.org>
   */
  final class EqualityExpr extends Expression {
  
      private final int _op;
      private Expression _left;
      private Expression _right;
  		
      public EqualityExpr(int op, Expression left, Expression right) {
  	_op = op;
  	(_left = left).setParent(this);
  	(_right = right).setParent(this);
      }
  
      public void setParser(Parser parser) {
  	super.setParser(parser);
  	_left.setParser(parser);
  	_right.setParser(parser);
      }
      
      public String toString() {
          return Operators.getOpNames(_op) + '(' + _left + ", " + _right + ')';
      }
  
      public Expression getLeft() {
  	return _left;
      }
  
      public Expression getRight() {
  	return _right;
      }
  
      public boolean getOp() {
          return (_op != Operators.NE);
      }
  
      /**
       * Returns true if this expressions contains a call to position(). This is
       * needed for context changes in node steps containing multiple predicates.
       */
      public boolean hasPositionCall() {
  	if (_left.hasPositionCall()) return true;
  	if (_right.hasPositionCall()) return true;
  	return false;
      }
  
      public boolean hasLastCall() {
  	if (_left.hasLastCall()) return true;
  	if (_right.hasLastCall()) return true;
  	return false;
      }
  
      private void swapArguments() {
  	final Expression temp = _left;
  	_left = _right;
  	_right = temp;
      }
  
      /**
       * Typing rules: see XSLT Reference by M. Kay page 345.
       */
      public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  	final Type tleft = _left.typeCheck(stable); 
  	final Type tright = _right.typeCheck(stable);
  
  	if (tleft.isSimple() && tright.isSimple()) {
  	    if (tleft != tright) {
  		if (tleft instanceof BooleanType) {
  		    _right = new CastExpr(_right, Type.Boolean);
  		}
  		else if (tright instanceof BooleanType) {
  		    _left = new CastExpr(_left, Type.Boolean);
  		}
  		else if (tleft instanceof NumberType || 
  			 tright instanceof NumberType) {
  		    _left = new CastExpr(_left, Type.Real);
  		    _right = new CastExpr(_right, Type.Real);
  		}
  		else {		// both compared as strings
  		    _left = new CastExpr(_left,   Type.String);
  		    _right = new CastExpr(_right, Type.String);
  		}
  	    }
  	}
  	else if (tleft instanceof ReferenceType) {
  	    _right = new CastExpr(_right, Type.Reference);
  	}
  	else if (tright instanceof ReferenceType) {
  	    _left = new CastExpr(_left, Type.Reference);
  	}
  	// the following 2 cases optimize @attr|.|.. = 'string'
  	else if (tleft instanceof NodeType && tright == Type.String) {
  	    _left = new CastExpr(_left, Type.String);
  	}
  	else if (tleft == Type.String && tright instanceof NodeType) {
  	    _right = new CastExpr(_right, Type.String);
  	}
  	// optimize node/node
  	else if (tleft instanceof NodeType && tright instanceof NodeType) {
  	    _left = new CastExpr(_left, Type.String);
  	    _right = new CastExpr(_right, Type.String);
  	}
  	else if (tleft instanceof NodeType && tright instanceof NodeSetType) {
  	    // compare(Node, NodeSet) will be invoked
  	}
  	else if (tleft instanceof NodeSetType && tright instanceof NodeType) {
  	    swapArguments();	// for compare(Node, NodeSet)
  	}
  	else {	
  	    // At least one argument is of type node, node-set or result-tree
  
  	    // Promote an expression of type node to node-set
  	    if (tleft instanceof NodeType) {
  		_left = new CastExpr(_left, Type.NodeSet);
  	    }
  	    if (tright instanceof NodeType) {
  		_right = new CastExpr(_right, Type.NodeSet);
  	    }
  
  	    // If one arg is a node-set then make it the left one
  	    if (tleft.isSimple() ||
  		tleft instanceof ResultTreeType &&
  		tright instanceof NodeSetType) {
  		swapArguments();
  	    }
  
  	    // Promote integers to doubles to have fewer compares
  	    if (_right.getType() instanceof IntType) {
  		_right = new CastExpr(_right, Type.Real);
  	    }
  	}
  	return _type = Type.Boolean;
      }
  
      public void translateDesynthesized(ClassGenerator classGen,
  				       MethodGenerator methodGen) {
  	final Type tleft = _left.getType();
  	final InstructionList il = methodGen.getInstructionList();
  
  	if (tleft instanceof BooleanType) {
  	    _left.translate(classGen, methodGen);
  	    _right.translate(classGen, methodGen);
          _falseList.add(il.append(_op == Operators.EQ ? 
  				     (BranchInstruction)new IF_ICMPNE(null) :
  				     (BranchInstruction)new IF_ICMPEQ(null)));
  	}
  	else if (tleft instanceof NumberType) {
  	    _left.translate(classGen, methodGen);
  	    _right.translate(classGen, methodGen);
  
  	    if (tleft instanceof RealType) {
  		il.append(DCMPG);
          _falseList.add(il.append(_op == Operators.EQ ? 
  					 (BranchInstruction)new IFNE(null) : 
  					 (BranchInstruction)new IFEQ(null)));
  	    }
  	    else {
              _falseList.add(il.append(_op == Operators.EQ ? 
  					 (BranchInstruction)new IF_ICMPNE(null) :
  					 (BranchInstruction)new IF_ICMPEQ(null)));
  	    }
  	}
  	else {
  	    translate(classGen, methodGen);
  	    desynthesize(classGen, methodGen);
  	}
      }
  
      public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  