Initial implementation of compacting GC

Remove free-list, allocate sequentially instead.

Now that garbage collection compacts the free cells (relocates them to
form a contiguous block), we no longer need to maintain a free list.
Instead, ff points to the next available cell.  We allocate cells
sequentially, incrementing ff as we go.  When ff gets to 64k less some
minimum number of free cells, we perform garbage collection.
Deduplicating garbage collector

Allocated cells in the SECD machine are immutable.  Therefore, it is valid
to restructure the cell graph so that:

  - no two cells contain the same atomic value, and furthermore that
  - whenever two cons cells, say A and B, are such that the subgraph reachable
    from A is identical to the subgraph reachable from B (in structure and in
    the atomic values reachable from A or B), that A and B are in fact the
    same cell.

This can lead to a significant reduction in cell usage, as a typical running
SECD machine will have many cells containing common values (e.g., small
numbers, common symbols, common code fragments, etc.).

This algorithm is much more expensive than the basic garbage collection, so we
only do this as a last resort when the basic garbage collection fails to yield
sufficient space.

Working Array
-------------

To accomplish this task, we must be able to rearrange cells in a potentially
very full cell array.  We will need a second working area for this task.  In
this working area, we store the permutation that transforms the original
arrangement of the cells into the new arrangement.  Each DWORD value in the
working array contains:

    [31.....FWD....16|15.....REF.....0]

    FWD = The index into the cell array of the location where the cell that
          was originally here has moved.
    REF = The index into the original cell array of the cell that should be
          moved to this location.

We sort, swap, and collapse cells by rearranging cells in this working array,
and only at the end do we update the actual cell array.

Algorithm
---------

We determine if two cells contain identical values simply by looking at the
type and value stored in the cell array.  For atomic values, this is
sufficient.  However, two cons cells may be identical but not share the same
numerical values if their CARs and CDRs have not been collapsed.

Example:

    Index:   0     1   2   3              4
    Value: [ NIL | A | A | CAR=1, CDR=0 | CAR=2, CDR=0 ]

  In this example, cells 3 and 4 are identical, but because cells 1 and 2
  have not yet been collapsed to a single cell, a comparison of the numerical
  values stored in 3 and 4 is insufficient to detect that they are identical.

We therefore collapse the cell array in phases:

  - Phase 0: Find and collapse the atoms.
  - Phase 1: Find and collapse the 'Level 1' cons cells (those whose CAR and
             CDR are both atoms).
  - Phase 2: Find the collapse the 'Level 2' cons cells (those whose CAR and
             CDR are both atomic or 'Level 1' cons).
  ...
  - Phase N: Find and collapse the 'Level N' cons cells (those whose CAR and
             CDR are both atomic or 'Level K' cons with K < N).

Each phase proceeds by:

  - Partitioning the remaining cells (those on the right side of a 'mark'
    value, those cells to the left 'mark' have already been collapsed) so that
    atomic (Phase 0) or 'Level N' (Phase N, N > 0) cells are on the left,
    sorted by their numerical value, and all other cells (Level K cells,
    K > N) are on the right.
  - Collapse the cells in the partition on the left.
  - Update the 'mark' to point at the start of the partition on the right.

Each phase must result in no more collapsed cells than the prior phase, since
we cannot have a common 'Level N' graph without also having a common
'Level N-1' graph.  Therefore, if a phase fails to find any cons cells to be
collapsed, the algorithm terminates.  The algorithm also terminates if the
'mark' reaches the end of the cell array.
Support some string escape seqs in Scheme lexer.

Interpret the following escape sequences in string literals:

\a - alarm (ascii 7)
\b - backspace (ascii 8)
\t - tab (ascii 9)
\n - linefeed (ascii 10)
\v - vertical tab (ascii 11)
\f - formfeed (ascii 12)
\r - return (ascii 13)
\e - escape (ascii 27)
\' - quote
\<newline> - empty string (allows single-line strings to span multiple
  lines.
Add function STARTSWITH to Util
Add support for (LIST ...)

LIST takes variable arguments and constructs a list.  It is a more
convenient way of writing

  (CONS A (CONS B (CONS C ... (CONS Z (QUOTE NIL)) ... )))

Instead, we can now write:

  (LIST A B C ... Z)

Since the whole list is not quoted, as in:

  (QUOTE (A B C ... Z))

A through Z may be expressions themselves, not just numbers and symbols.
Add parser combinators
Add calculator to exercise parser combinators
Add support for nested S-exprs to calc
Add support for comparisons to simple calc
Add pseudo-instruction for reserved opcodes
Add instructions for DELAY/FORCE

Add the LDE, AP0, and UPD instructions from Chapter 8 of
Henderson (1980) -- with the following alterations:  we will not
distinguish between an unevaluated receipe and an evaluated recipe.
A recipe is always unevaluated.  An "evaluated recipe" is just a
value.  The implications of this are:

  - AP0 doesn't necessarily expect a recipe on the top of the stack.  If
    the item on the top of the stack is not a recipe, AP0 acts like NOP.
    If it is a recipe, it behaves as described in the book.
  - UPD replaces (recipe:(c.e)) with the result of the evaluation, not
    with an "evaluated recipe" that refers to the result of the
    evaluation.
Add support for DELAY/FORCE to LispKit
Print recipes as '?'
Add RCP instruction for isrecipe predicate
Add RECIPE predicate to lisp compiler