compiler: Consistent handling of (eqv?) NaN

R7RS states (eqv?) on NaN is undefined. However, if we hit our planner
value eq or pointer compare fast paths we can return #t for two
identical NaN values. For consistency we should always treat NaN as
(eqv?) with itself. To accomplish this we:

- Have the runtime and planner (eqv?) logic explicitly check for NaN
  values and consider them eqv?

- Change the constant cache to only produce one constant for +nan.0
compiler: Support (cond-expand) in library decls

This is required by R7RS and will be needed to conditionally hide
(set-car!) and (set-cdr!) when immutable pairs are enabled.
Scheme dialect and immutable pair support

- Add a concept of Scheme dialects to the compiler. A Scheme dialect
  currently just has a set of feature identifiers, a (currently unused)
  "immutablePairs" flag and a name.

- Add the "r7rs" and "llambda" dialects. "r7rs" works as the compiler
  did before this commit and "llambda" removes the "r7rs" feature
  identifier and adds "immutable-pairs"

- Add a --scheme-dialect command line option that defaults to "llambda"

- Support (cond-expand) inside functional tests. This allows tests to be
  conditionally executed based on the current dialect

- Run every available functional test in every dialect at -O 2. To save
  time only run the default dialect (llamba) at -O 0

- Remove (set-car!) and (set-cdr!) if the immutable-pair feature
  identifier exists. Update any tests that broke as a result
compiler: List planning refactor

- Introduce iv.KnownPair trait for pairs with statically known contents.
  This includes constant pairs in all Scheme dialects. Additionally, if
  the dialect uses immutable pairs it can construct a new
  KnownPairCellValue instance with the known immutable car and cdr
  values

- Instead of manually tracking proper list metrics at intermediate value
  construction time calculate them dynamically using the KnownPair
  trait. This ensures the list metrics and actual list structure cannot
  become desynchronised

- Introduce ValuesToPair and ValuesToProperList that will use
  ConstantPairValue/KnownPairCellValue instances whenever possible on
  dialects that use immutable pairs. ValuesToProperList will even
  construct mixed lists with a runtime allocated head and a constant
  tail if possible.

- Remove ps.BuildProperList now that ValuesToProperList will dynamically
  construct the appropriate steps to build a list
compiler: Fix (-) with constant and dynamic args

Unlike (+) and (*) subtraction is non-commutative. That means we can't
re-order our operands arbitrarily. For now just disable constant (-)
strength reduction when there is a mixture of contant and non-constant
args.
compiler: Support for inlining with rest args

This uses the new ValuesToProperList functionality to inject a rest arg
value in to the inline function's body. This is most effective with
immutable pairs as the rest arg's structure and members will be known at
compile time. This allows static planning to occur in many cases.

However, with mutable pairs static planning can occur as long as the
rest arg is treated like an opaque value (passed to another procedure,
returned directly, etc).
compiler: Static planning for (apply)

- Introduce KnownListElement to generalise KnownPair and EmptyListValue.
  This gains a new method to pull the IntermediateValues out of a known
  proper list

- Add a special case in PlanApplication that tries to detect an (apply)
  with a constant list. We are careful to not immediately plan our
  applied procedure expression. This is so we can trigger the
  self-executing lambda code path if the applied procedure is an inline
  lamda. This is important because (case-lambda) generates (apply) with
  inline lambda expressions.
compiler: Support inlining lambdas with captures

If a lambda is capturing a variable that the inline site state has
access to we can just use that value directly.

This catches a common pattern where helper produres are defined inside
the body of a larger procedure and then invoked from within that larger
procedure. Previously we would refuse to inline the helper procedures
even if they were capturing values clearly available to the outer
procedure.

This reduces the amount of generated IR for the R7RS life example
program by over 40% and increases its performance by approximately the
same amount.
compiler: Speed up boolean value checks

Because our boolean values are preconstructed we don't need to test if
they're a boolean cell first. We can directly compare the passed cell to
the preconstructed boolean value we're interested in

To accomplish this the derived type infrastructure in PlanTypeCheck has
changed from always testing parent types to allowing individual types to
opt-in. This will become more important as our type hierarchy gets
deeper and many intermediate types won't need to be checked.
stdlib: Fix weird indentation in typed.scm
Support for typed pairs

This adds a vt.SpecificPairType representing a pair with type
constraints. Normal pairs are still represented using the pair cell type
atom which has been renamed to vt.AnyPairType. There is a helper
PairCell object which ensures the right type is constructed for the
given car/cdr types.

Pair types are only exposed to Scheme code if immutable pairs are
enabled. They cannot be easily supported with R7RS-style mutable pairs.
The internal mechanism for pair types is still active, however, and can
influence optimisations related to constant pairs.
compiler: Introduce vt.SatisfiesType

This replaces the vt.SchemeType.satisfiesType method. The logic was
fairly convoluted and spread throughout the various data types in
ValueType.scala.

This moves all the logic in to a separate SatisfiesType function that
takes the two types as arguments. This is easier to follow and will
allow more complicated (and possibly stateful) type checking in the
future.