private QilNode FoldArithmetic(QilNodeType opType, QilLiteral left, QilLiteral right) {
Debug.Assert(left.NodeType == right.NodeType);
// Catch any overflow or divide by zero exceptions
try {
checked {
switch (left.NodeType) {
case QilNodeType.LiteralInt32: {
int intLeft = left;
int intRight = right;
switch (opType) {
case QilNodeType.Add: return f.LiteralInt32(intLeft + intRight);
case QilNodeType.Subtract: return f.LiteralInt32(intLeft - intRight);
case QilNodeType.Multiply: return f.LiteralInt32(intLeft * intRight);
case QilNodeType.Divide: return f.LiteralInt32(intLeft / intRight);
case QilNodeType.Modulo: return f.LiteralInt32(intLeft % intRight);
}
break;
}
case QilNodeType.LiteralInt64: {
long lngLeft = left;
long lngRight = right;
switch (opType) {
case QilNodeType.Add: return f.LiteralInt64(lngLeft + lngRight);
case QilNodeType.Subtract: return f.LiteralInt64(lngLeft - lngRight);
case QilNodeType.Multiply: return f.LiteralInt64(lngLeft * lngRight);
case QilNodeType.Divide: return f.LiteralInt64(lngLeft / lngRight);
case QilNodeType.Modulo: return f.LiteralInt64(lngLeft % lngRight);
}
break;
}
case QilNodeType.LiteralDecimal: {
decimal lngLeft = left;
decimal lngRight = right;
switch (opType) {
case QilNodeType.Add: return f.LiteralDecimal(lngLeft + lngRight);
case QilNodeType.Subtract: return f.LiteralDecimal(lngLeft - lngRight);
case QilNodeType.Multiply: return f.LiteralDecimal(lngLeft * lngRight);
case QilNodeType.Divide: return f.LiteralDecimal(lngLeft / lngRight);
case QilNodeType.Modulo: return f.LiteralDecimal(lngLeft % lngRight);
}
break;
}
case QilNodeType.LiteralDouble: {
double lngLeft = left;
double lngRight = right;
switch (opType) {
case QilNodeType.Add: return f.LiteralDouble(lngLeft + lngRight);
case QilNodeType.Subtract: return f.LiteralDouble(lngLeft - lngRight);
case QilNodeType.Multiply: return f.LiteralDouble(lngLeft * lngRight);
case QilNodeType.Divide: return f.LiteralDouble(lngLeft / lngRight);
case QilNodeType.Modulo: return f.LiteralDouble(lngLeft % lngRight);
}
break;
}
}
}
}
catch (OverflowException) {
}
catch (DivideByZeroException) {
}
// An error occurred, so don't fold operationo
switch (opType) {
case QilNodeType.Add: return f.Add(left, right);
case QilNodeType.Subtract: return f.Subtract(left, right);
case QilNodeType.Multiply: return f.Multiply(left, right);
case QilNodeType.Divide: return f.Divide(left, right);
case QilNodeType.Modulo: return f.Modulo(left, right);
}
Debug.Assert(false, "Cannot fold this arithmetic operation: " + opType);
return null;
}