compiler: Static equivalence planning

This re-introduces the unit tests from the reducer and implements static
equivalence planning for constant values. This is more powerful than the
reducer because we can infer non-constant values are not (eqv?) when
their types are disjoint.

This also fixes a typo that was causing (equal?) to not be planned at
all.
compiler: Static (length) planning

This re-adds the (length) unit tests from the reducer. This was mostly
working already except the empty list wasn't handled.
compiler: Extend DisposeValues to dispose steps

This replaces the old MergeableStep trait with a new "DisposableStep"
trait. "Disposable" in this case refers to both dropping the step
completely or merging it with other instances of itself. It also adds a
new NullipotentStep trait for steps that are completely nullipotent.

If DisposeValues encounters a nullipotent step with an unused result it
will drop it from the plan completely. I'm guessing LLVM is smart enough
to remove the code itself in the vast majority of cases but this cleans
up our emitted IR and makes the static plan tests easier to write.
compiler: Support inlining with empty rest args

Until immutable pairs materialize it's problematic to inline procedures
taking rest argument lists. This is because it's difficult to track
modifications to mutable lists which means we can't statically reason
about their contents at compile tiVme.

However, empty lists are completely immutable. This means we can safely
plan applications of procedures taking rest args as long as the rest arg
list is empty.
compiler: Add unit test for lambda with captures

Generalised captures aren't supported by the inliner. However, some
cases such as capturing a variable that's also live at the application
site should work.