[CommonML] Support arbitrary preprocessors and file extensions.
[CommonML] Support arbitrary preprocessors and file extensions.

Summary:

You may supply a custom preprocessor program that should be executed on
each file in order to parse the source into a canonical AST. The
preprocessor must be available in your `PATH` and be able to accept an
arbitrary file, and either invoke a custom parser, or invoke the
standard parser. (It must do this because `ocamldep` requires one
preprocessor program for the collection of source files). That means it
must somehow determine which of the two to perform. Your preprocessor
likely would use file extensions as "hints" as to which to do.

Because of that, CommonML also allows you to indicate that particular
"pairs" of extensions should be treated as interfaces/implementations
respectively - otherwise the file extension "hints" that are used by
your preprocessor will confuse the rest of the compilation toolchain.

You will often want to supply both a preprocessor *and* extensions.
Below is an example of doing both, by populating the `preprocessor` and
`extensions` fields in a `package.json`'s `CommonML` field:

  "CommonML": {
    "exports": ["MyProjectMod"],
    "preprocessor": "myCustomPreprocessor",
    "extensions": [{
      "interface": ".heyoi",
      "implementation": ".heyo"
    }],

The `preprocessor` and `extensions` fields are separate concepts that
are often used in simultaneously.

Test Plan:

Reviewers:

CC:

frantic/CommonML,frantic/CommonML,jordwalke/CommonML,jordwalke/CommonML