private void Compare(QilBinary ndComp) {
QilNodeType relOp = ndComp.NodeType;
XmlTypeCode code;
Debug.Assert(ndComp.Left.XmlType.IsAtomicValue && ndComp.Right.XmlType.IsAtomicValue, "Operands to compare must be atomic values.");
Debug.Assert(ndComp.Left.XmlType.IsSingleton && ndComp.Right.XmlType.IsSingleton, "Operands to compare must be cardinality one.");
Debug.Assert(ndComp.Left.XmlType == ndComp.Right.XmlType, "Operands to compare may not be heterogenous.");
if (relOp == QilNodeType.Eq || relOp == QilNodeType.Ne) {
// Generate better code for certain special cases
if (TryZeroCompare(relOp, ndComp.Left, ndComp.Right))
return;
if (TryZeroCompare(relOp, ndComp.Right, ndComp.Left))
return;
if (TryNameCompare(relOp, ndComp.Left, ndComp.Right))
return;
if (TryNameCompare(relOp, ndComp.Right, ndComp.Left))
return;
}
// Push two operands onto the stack
NestedVisitEnsureStack(ndComp.Left, ndComp.Right);
// Perform comparison
code = ndComp.Left.XmlType.TypeCode;
switch (code) {
case XmlTypeCode.String:
case XmlTypeCode.Decimal:
case XmlTypeCode.QName:
if (relOp == QilNodeType.Eq || relOp == QilNodeType.Ne) {
this.helper.CallCompareEquals(code);
// If relOp is Eq, then branch to true label or push "true" if Equals function returns true (non-zero)
// If relOp is Ne, then branch to true label or push "true" if Equals function returns false (zero)
ZeroCompare((relOp == QilNodeType.Eq) ? QilNodeType.Ne : QilNodeType.Eq, true);
}
else {
Debug.Assert(code != XmlTypeCode.QName, "QName values do not support the " + relOp + " operation");
// Push -1, 0, or 1 onto the stack depending upon the result of the comparison
this.helper.CallCompare(code);
// Compare result to 0 (e.g. Ge is >= 0)
this.helper.Emit(OpCodes.Ldc_I4_0);
ClrCompare(relOp, code);
}
break;
case XmlTypeCode.Integer:
case XmlTypeCode.Int:
case XmlTypeCode.Boolean:
case XmlTypeCode.Double:
ClrCompare(relOp, code);
break;
default:
Debug.Fail("Comparisons for datatype " + code + " are invalid.");
break;
}
}