Refactor handling of `Expr` validity
Sadly Cmm is not a total language: there are many programs which one can write which do not have a defined result (e.g. signed division overflow). At the moment we handle this in the Arbitrary
generator, taking care to excluding undefined programs in the generator and shrinker. However, this is problematic as it is easy to forget handling UB in either the generator or the shrink (hence #8). Moreover, ideally we would want to have a canonical way to determine whether a Cmm program is well-behaved.
I suspect we should rather have a single function to check the definedness of a Cmm Expr
, used by both the generator and shrinker.