compiler: Add the reducer

The reducer is a replacement for the optimizer passes. In contrast to
the optimizer which sequentially ran unrelated passes over the same
expression tree the reducer will recursively try to reduce the
expression tree in to simpler expressions in one pass.

In addition to subsuming and extending the existing optimizer
functionality this is intended to provide a basis for future inlining
work. The current goal is to use (case-lambda) to provide for default
arguments to stdlib functions and have the reducer convert the
(case-lambda) in to direct (native-function) calls with the appropriate
arguments.

On top of flattening self-executing lambdas and improved (call/cc)
optimisation this implements:

- Removal of unused branches through partial evaluation. This works for
  trivial (if)s and for the expression trees produced by (and)/(or)

- Removal of unused pure values (i.e. pure values in the non-terminal
  position of a body). The planner would rarely generate code for these
  but if we learn which report procedure are pure this could become more
  useful.

- Removal of unused bindings of pure values

- Partial evaluation of certain report procedures. These are mostly
  type/equality predicates, basic arithmetic and simple queries such as
  (length). This is useful for simplifying code generated by macros and
  compile-time constants in conjunction with dead code removal. In the
  future this will also become key for procedure inlining.