pax-compiler 0.14.3

Compiler APIs for parsing and building Pax projects into application executables
Documentation
# Pax-Compiler

This document describes the high-level archiecture of pax-compiler.

For more information refer to our [docs](https://docs.pax.dev/reference-compilation-model.html).

## Bird's Eye View

Roughly it can be broken down into three steps: 
1) Analyze the user Pax project (Pax Template + Rust) and generate a Pax Manifest (data structure summarizing the Pax project)
2) Code-gen a Pax Manifest into a Pax Cartridge (Rust target agnostic library).
3) Build a target platform executable (chassis) with this rust cartridge included. 

The main entry-point for all of this is `perform_build` found in `lib.rs`.

### Step 1: Pax Project -> Pax Manifest 

Pax projects decorate their associated Rust with a special macro `#[derive(Pax)]`. These macros generate code to dynamically analyze their tagged structs. They each add a `parse_to_manifest` function for every `#[derive(Pax)]` tagged struct. This `parse_to_manifest` function (template found [here](https://github.com/paxproject/pax/blob/master/pax-macro/templates/derive_pax.stpl)) stores its associated structs information in a ParsingContext object and calls `parse_to_manifest` on its Pax Template dependencies. It utilizes logic in `parsing.rs` and relies on our pest grammar (`pax.pest`) to understand the template dependencies. For the root struct (tagged `#[main]` e.g. [here](https://github.com/paxproject/pax/blob/aabc8978085a65a5369b7b5a61c00d620d5b5c81/examples/src/camera/src/lib.rs#L7)), we generate a binary target as well that starts the process and writes the accumulated information into a Pax Manifest and serializes it to stdout. This binary (named `parser`) is kicked off (`run_parser_binary`) as our first step of the compilation process to generate the Manifest in the `lib.rs/perform_build` function. 

### Step 2: Pax Manifest -> Pax Cartridge

Next we generate the Pax Cartridge. This work is roughly two steps: compiling [expressions](https://docs.pax.dev/start-key-concepts-expressions.html) and generating the cartridge code. The former involves parsing Paxel (Pax's expression language) and generating the equivalent rust code. This work lives in `expressions.rs`. Once expressions are compiled, the second step is generating the cartridge code. This lives in the `code_generation` module. We utilize [Tera](https://keats.github.io/tera/) templates for the code-gen and the bulk of this work is translating a Pax Manifest into a Tera context. The main entry point is `generate_and_overwrite_cartridge` in `code_generation/mod.rs`.


### Step 3: Building a Chassis with our Pax Cartridge

The last step of this process involves building our target platform (e.g. Web/MacOS/..) scaffolding (see [chassis](https://docs.pax.dev/reference-compilation-model.html#3-chassis-compilation)) with our cartridge included. This work lives in the `building` module. This mainly involves building the generated cartridge, loading it into our specific chassis and then building that chassis. Currently we support 3 targets (Web/MacOS/iOS). We load our cartridge as [WASM](https://webassembly.org/) for Web and as `.dylib`s for our Apple targets.

## Consumers

The main consumers of `pax-compiler` are `pax-cli` and `pax-macro`. `pax-cli` is the CLI that Pax user's invoke to build Pax projects. `pax-macro` is the crate the defines the `#[derive(Pax)]` macro that we use for dynamic analysis of the Pax Project (see Step 1).