My compiler for PLI, the "programming language implementations" course.
compli is a functional-style programming language based on the language we implemented in the first six homeworks.
On a high level, the compiler pipeline consists of:
- Parsing (source code to AST)
- Type checking (provide type information in AST)
- Lowering (typed AST to compli's IR)
- Code generation (compli's IR to LLVM IR)
The main differences compared to the language we developed in the course are:
- My custom language design (with major additions, see next paragraph)
- Implementation specifics (used programming language & libraries)
- Much higher-level intermediate representation (thanks to the
inkwellbuilder)
The highlights of my compiler project are:
- Capable front-end
- Inspectable AST and IR (with pretty tree view)
- Powerful type checker (allows for type-dependent lowering)
- Nice error reports
- Floating-point numbers
- Records (product types)
- Runtime with useful builtins
In the language-tour.compli all language features are shown.
There are also some more examples.
You need to have installed:
- Rust toolchain (1.74.1 or newer)
- LLVM 18 (see llvm-sys documentation for more information)
- Additional libraries for linking
- I needed to install:
libz,libzstd,libffi
- I needed to install:
This project is Linux-only.
apt install build-essential libzstd-dev zlib1g-dev libffi-dev
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key > /etc/apt/trusted.gpg.d/llvm.asc
echo 'deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-18 main' > /etc/apt/sources.list.d/llvm-18.list
apt update
apt install llvm-18-dev libpolly-18-dev
cargo build- For other Debian/Ubuntu versions: see https://apt.llvm.org/
- For Arch Linux:
pacman -S llvm18
The compiler has multiple execution modes:
compli build main.compliwill compile the source code and automatically calls to the system C compiler to link the module with the runtime. This produces amainELF executable.compli generate main.compliwill only generate the compiled object (or assembly) file but won't link anything. This produces amain.oobject file.compli inspect-ast main.compliwill print the program's AST. With the--typedflag, it includes type information.compli inspect-ir main.compliwill print the intermediate representation of the program.
See compli --help for all options.
compli build main.compli
./main
# with manual linking
compli generate main.compli
gcc runtime.c main.o -o main
./mainThere are syntax and filetype detection files for Vim provided
(which can be copied/symlinked to the $VIMHOME/syntax/ and $VIMHOME/ftdetect/ directories).
Also, there is a very basic Emacs major mode. To use it, open compli-mode.el,
M-x eval-buffer, open a compli file and then M-x compli-mode.
I used some awesome libraries for this compiler. The most interesting ones are:
- inkwell, a LLVM wrapper and building library
- chumsky, a text parsing library that uses parser combinators
Also: