Compilation Phases for a Module ========================================
Haldean Brown                                      First draft: Jul 2016
                                                  Last updated: Jul 2016

------------------------------------------------------------------------

The following phases occur during module compilation

  1. source material loading
  2. parsing
  3. compile imported modules
  4. add splatted imports
  5. infer types
  6. compile patterns to boolean predicates
  7. convert ADT declarations to functions
  8. resolve names
  9. generate graphs
 10. compile interfaces and implementations to multimethods

These dependencies exist:
  - Parsing depends on source material loading (1 -> 2)
  - Compiling imported modules just depends on the parsed data (2 -> 3)
  - Splatted imports depends on both the AST and imported AST information
    (2 -> 4, 3 -> 4)
  - Interfaces and implementations depend on the AST and type inference,
    because this phase adds untypeable constructs that inference can't
    deal with. (2 -> 10, 5 -> 10)
  - Type inference depends on the AST, imported data, and (potentially)
    splatted names, and it depends on name resolution to be able to
    determine known types (2 -> 5, 3 -> 5, 4 -> 5, 8 -> 5).
  - Pattern compilation depends on type inference, imports and the AST as
    well. It introduces new names, which means it needs to happen before
    resolution (2 -> 6, 3 -> 6, 4 -> 6, 5 -> 6, 6 -> 8)
  - ADT compilation depends on the AST and imports, but it also
    introduces new names which need to be resolved (2 -> 7, 3 -> 7,
    4 -> 7, 7 -> 8)
  - Name resolution needs the AST and imports, as well as the names
    introduced by interface compilation (2 -> 8, 3 -> 8, 4 -> 8, 10 -> 8)
  - Graph generation depends on everything else

There's a dependency cycle in this graph:

    pattern -> resolve -> infer -> pattern

Pattern compilation introduces new names, so we need to re-resolve after
it. Inferrence depends on knowing where names come from. Patterns depend
on knowledge of the types of the things going into the patterns.

We solve this by running name resolution twice; once on the base AST
straight off the parser, and once after it's been subject to all of the
abuse. So the compilation flow becomes:

   1. load
   2. parse
   3. import
   4. splat
   5. resolve (the "pre-resolve")
   6. infer
   7. interface
   8. pattern
   9. adt
  10  resolve (the "post-resolve")
  11. graph