private QilNode FoldComparison(QilNodeType opType, QilNode left, QilNode right) {
object litLeft, litRight;
int cmp;
Debug.Assert(left.XmlType == right.XmlType, "Comparison is not defined between " + left.XmlType + " and " + right.XmlType);
// Extract objects that represent each literal value
litLeft = ExtractLiteralValue(left);
litRight = ExtractLiteralValue(right);
if (left.NodeType == QilNodeType.LiteralDouble) {
// Equals and CompareTo do not handle NaN correctly
if (Double.IsNaN((double) litLeft) || Double.IsNaN((double) litRight))
return (opType == QilNodeType.Ne) ? f.True() : f.False();
}
if (opType == QilNodeType.Eq)
return litLeft.Equals(litRight) ? f.True() : f.False();
if (opType == QilNodeType.Ne)
return litLeft.Equals(litRight) ? f.False() : f.True();
if (left.NodeType == QilNodeType.LiteralString) {
// CompareTo does not use Ordinal comparison
cmp = string.CompareOrdinal((string) litLeft, (string) litRight);
}
else {
cmp = ((IComparable) litLeft).CompareTo(litRight);
}
switch (opType) {
case QilNodeType.Gt: return cmp > 0 ? f.True() : f.False();
case QilNodeType.Ge: return cmp >= 0 ? f.True() : f.False();
case QilNodeType.Lt: return cmp < 0 ? f.True() : f.False();
case QilNodeType.Le: return cmp <= 0 ? f.True() : f.False();
}
Debug.Assert(false, "Cannot fold this comparison operation: " + opType);
return null;
}