The Philomath interpreter is organized as a re-entrant multi-pass compiler; that is, it may process different parts of the source, tokens, or other intermediaries out of order with each part moving through a pass independently. Additionally, it should be possible to introduce a new code section to an earlier pass while processing code sections in a later pass.
In general, parts are partially processed until they run into a missing dependency and then the compiler continues on with the next part until can fulfill the dependency.
- Lexical Analysis - Transform source characters to tokens
- Syntax Analysis - Transform tokens into an AST and dependency graph
- Semantic Analysis - Transform an AST into metadata and control flow graphs
- Declaration uniqueness - Verify each declaration name is unique in its scope
- Declaration ordering - Verify that variables are declared before use
- Type inference - Infer the type of each untyped declaration
- Type checking - Check that expressions evaluate into the correct type
- ... - There are probably some sub-passses missing here
- Bytecode Generation - Transform a control flow graph into bytecode
- (Optional) CFG optimizations - Data-flow, recursion, loop, and etc optimizations
- SSA conversion - Convert to single static assignment form
- (Optional) SSA optimizations - Optimiztions which benefit strongly from SSA
- Intermediate bytecode - Generate a platform-agnostic bytecode representation
- (Optional) Interpretation - Run bytecode, and possible re-enter an earlier pass
- (Optional) Code generation - Transform bytecode to platform-specific assembly