/// <summary>
/// Reduces this node to a simpler expression. If CanReduce returns
/// true, this should return a valid expression. This method is
/// allowed to return another node which itself must be reduced.
/// </summary>
/// <returns>The reduced expression.</returns>
/// <remarks >
/// Unlike Reduce, this method checks that the reduced node satisfies
/// certain invariants.
/// </remarks>
public Expression ReduceAndCheck()
{
if (!CanReduce)
{
throw Error.MustBeReducible();
}
var newNode = Reduce();
// 1. Reduction must return a new, non-null node
// 2. Reduction must return a new node whose result type can be assigned to the type of the original node
if (newNode == null || newNode == this)
{
throw Error.MustReduceToDifferent();
}
if (!TypeUtils.AreReferenceAssignable(Type, newNode.Type))
{
throw Error.ReducedNotCompatible();
}
return(newNode);
}