Post-Modern Compiler Design V1
Preface
1
Introduction
1.1
Compilers and Interpreters
1.2
Programs as Data
1.3
Program Evaluation and Program Equivalence
1.4
History of Compilers
2
Integer Arithmetic
2.1
Representing Programs as Data
2.1.1
Abstract Syntax
2.1.2
Programs as Data
2.1.3
Writing an Interpreter
2.1.4
Our First Compiler
2.1.5
Correctness of our Compiler
2.2
Compiling to Machine Code
2.2.1
Architecture Refresher
2.2.2
Notional Machine
2.2.3
Figuring out Assembly Language
2.2.4
Assembly Language Primer
2.2.5
Compiling to x86-64 Assembly
2.2.6
Compiling and Running x86-64
2.3
Parsing
2.3.1
Utilities
2.3.2
Source Code as Stream of Characters
2.3.3
Parsing Expressions
2.3.4
End-Of-File
2.4
Error Handling
2.4.1
Parser: Literal Out of Bounds
2.4.2
Runtime: Divide by Zero
2.5
Where are we?
3
Nested Expressions
3.1
Language Definition
3.2
Direct Interpreter and Compiler
3.3
Compiling to Machine Code
3.3.1
Architecture Refresher
3.3.2
Notional Machine
3.3.3
Stack-Based Interpreter and Compiler
3.3.4
Targeting x86
3.3.5
Stack-Based Evaluation with Register Allocation
3.4
Parsing
3.4.1
Parenthesized Expressions
3.4.2
Operator Sequences
3.4.3
Operator Precedence
3.5
Generalize
3.6
Pretty-Printing
3.7
Where are we?
4
Variables
4.1
Language Definition
4.1.1
Syntax
4.1.2
Direct Interpreter and Compiler
4.2
Code Generation
4.2.1
Stack-Based Interpreter and Compiler
4.2.2
Stack-Based Compiler Targeting x86-64 Registers
4.3
Parsing
4.3.1
Tokenization
4.4
Error Cases
4.5
Where are we?
5
Lowering
5.1
Single vs. Multi-Pass
5.2
Revised Implementation
6
Error Handling
6.1
Improving the Parser
6.1.1
Integer Literals Out of Bounds
6.1.2
Source Position Information
6.1.3
Semicolon inference
6.1.4
Comments
6.1.5
Better Error Messages
6.1.6
Error Recovery
6.1.7
Indentation-Sensitive Syntax
6.2
Semantic Analysis
6.2.1
Analysis Phase in Code
6.2.2
Soundness Property
6.2.3
Example
6.3
Lecture Material
6.3.1
Current Grammar (extended from last lecture)
6.3.2
Quiz
6.3.3
Error Handling
6.3.4
Syntax Error Handling
6.3.5
Syntax Error Repair
6.4
Where Are We?
7
Control Flow: If/Else
7.1
Language Definition
7.1.1
Syntax
7.1.2
AST
7.1.3
Semantics
7.2
Code Generation
7.2.1
Machine model
7.2.2
Stack-Based Interpreter
7.2.3
Stack-Based Compiler
7.2.4
Stack-Based Compiler with Labels and Jumps
7.2.5
x86 Flags And Jumps
7.2.6
Compiling Ifs
7.3
Parsing
7.4
Where Are We?
8
Mutable Variables and Loops
8.1
Recap
8.1.1
Current Grammar
8.1.2
Quiz
8.2
Mutable Variables
8.2.1
Syntax
8.2.2
AST
8.2.3
Semantics
8.3
Loops
8.3.1
Syntax
8.3.2
AST
8.3.3
Semantics
8.3.4
x86 Flags And Jump - Compile Loops
8.4
Parsing and Desugaring
8.4.1
We Can Write, Parse, and Compile Nice Code!!
8.4.2
Grammar - Syntactic Sugar
8.4.3
One-Sided Ifs
8.4.4
AST Of Sugared Expressions
8.5
Where Are We?
9
Type Checking/Inference
9.1
Types
9.1.1
About Types
9.1.2
Our Grammar, Typed
9.1.3
Type Checking
9.2
Formal Type System
9.2.1
Inference Rules
9.2.2
Example
9.2.3
Inference Rules (cont’d)
9.3
Type Checking and Type Inference
9.3.1
Syntax of Types
9.3.2
A First Typer
9.3.3
Separating Checking and Inference
9.3.4
Type-Annotating Trees
9.3.5
Type-Driven Transformation
9.3.6
The Unknown Type as Sentinel
9.4
Wrap-Up
9.4.1
Interpretation With Types
9.4.2
New Error Cases
9.4.3
Type Soundness
9.4.4
Compilation With Types
9.5
Where Are We?
10
Functions
10.1
Example
10.2
Syntax
10.3
AST
10.4
Semantics
10.5
Type Checking
10.6
Interpreter
10.7
Compilation: Calling Conventions
10.8
Where Are We?
11
Dynamic Memory: Arrays
11.1
Let’s Add Arrays
11.2
Syntax
11.3
AST
11.4
Semantic Analysis
11.5
Semantic Analysis
11.6
Interpreter
11.7
Compiler
11.8
Where Are We?
12
Outlook
12.1
A Taste Of MiniScala
12.2
More Functions
12.2.1
Nested Functions
12.2.2
Closures
12.3
Intermediate Representations
12.4
Optimization
References
Post-Modern Compiler Design Volume 1: Basics
References