Ever wondered how programming languages work under the hood? What sets apart a compiler from an interpreter? What exactly are a virtual machine and a JIT-compiler? And how do functional and imperative programming differ?
Understanding Programming Languages and Compilers
The journey of implementing a programming language is filled with numerous questions and challenges. Unfortunately, traditional "compiler classes" in educational settings often present these concepts as "hardcore rocket science", targeted only at advanced engineers.
Many classic compiler books dive into the technicalities like Lexical analysis and formal grammars right from the start. As a result, students often lose interest before they even begin implementing a programming language, spending whole semesters on tokenizers and BNF grammars without truly grasping the semantics of programming languages.
I believe we can understand and build a full programming language's semantics, end-to-end, within 4-6 hours. This course offers focused content, using live coding sessions in pair-programming, all described in an easy-to-understand manner.
Course Focus: Programming Language with LLVM
In this Programming Language with LLVM class, the focus is on compiling languages into LLVM IR, creating a lower-level programming language. By working directly with the LLVM compiler infrastructure, you'll gain an understanding of how modern languages like C++ and Rust operate at a lower-level.
Building a programming language will elevate your proficiency in numerous other programming languages, making your skills more professional.
Prerequisites
There are three prerequisites for this class.
The Programming Language with LLVM course is an extension of previous classes including Building an Interpreter from Scratch (also known as Essentials of Interpretation) and Building a Virtual Machine. If you're not already familiar with how programming languages function at this level—in terms of eval, closure, scope chain, environments, and other constructs—you should take the interpreters class first.
Furthermore, to delve into the lower (bitcode/IR) level where production languages reside, basic C++ experience is necessary. However, this class is not about C++ itself; we utilize fundamental C++ constructs that are easily transferable to other languages.
Target Audience
This class is designed for curious engineers eager to acquire skills in building complex systems, such as programming languages, which is an advanced engineering task. The knowledge acquired is transferable to other complex system builds as well.
If you are particularly interested in LLVM, its compiler infrastructure, and the process of creating your own language, this course is also suitable for you.
Implementation Tools
Low-level compilers often focus on performance, so they're typically implemented in languages like C or C++. In this course, we utilize basic C++ features to ensure the code is easily convertible and portable to other languages like Rust or even higher-level ones like Python. Using C++ simplifies the implementation of further JIT-compilers.
Note: Our objective is for students to understand and implement every detail of the LLVM compiler independently, rather than copying from solutions. While full source code is shared in video lectures, the project repository contains /* Implement here */ assignments that students need to complete.