This is a compiler for the C0 language written in Haskell. It was my semester project for the partner-based Compiler Design course (15-411) at CMU, where every 2 weeks we had to support new specs added to the language, starting from arithmetic to control sequence, function calls, and finally structs and pointers, each of which required refactoring of entire data pipeline.
Our compiler follows a data pipeline that converts the C0 language into multiple representations before finally outputting assembly. It starts off by parsing the C0 code into an AST, then elaborating it into a functional structure. Next, it performs type checking, and then proceeds to generate abstract assembly, on which we run register allocation. Finally, with all that data, our compiler produces actual assembly.
I established the base pipeline, and then spend the remainder of the time mainly on elaboration and typechecking. I also initially worked on abstract assembly generation and implemented register allocation and optimizations. My partner implemented parsing, the rest of abstract assembly generation, and conversion to actual assembly.
Obviously, I learned about the inner workings of a compiler. However, my most important takeaway was how to design scalable software which requires features being added on iteratively. Every change to the language could require large amounts of code refactoring, so I learned the importance of making good design decisions early on and how it percolated well into the future. This required a lot of communications and agreements between me and my partner, which we were successful at.