Cover image for 5 Lessons from Writing a Compiler

5 Lessons from Writing a Compiler

hunter profile image Hunter Henrichsen ・5 min read


I'm still a student, but I'm seeing the light at the end of the tunnel. Normally I do pretty well in classes, but this class had me questioning whether that light was the end of the tunnel, or an oncoming train. The goal of this class was to take a language that the professor had written the specification for, and to write code to convert it to MIPS Assembly that we could run, while learning about the different parts that go into writing that code.

I learned a lot over the course of this project. Not all of it was about algorithms or compilers. Here's what went down, and here's what I learned from it.

Classes, Trees, and Experiences

Notes on automata, with lots of epsilon edges
Notes on automata and graphs, with lots of epsilon edges.

This class and its attached project were scary starting off. Rumors went around from past students about how hard the subject matter was. The professor himself even talked about how this class would be extremely difficult for the first few class periods, and I started to notice empty seats around me in the class as time went on.

Nevertheless, I persisted. Pridefully.

The class was broken up into pieces. The first piece discussed the algorithms and structures that are used to convert text in a file into something that we can use to simulate how want the program to work, the Abstract Syntax Tree. This was some of the most tedious and frustrating work that I've had to do in my six years working in code, and thus took me a long while to get through. I still held my head high, thinking that I would be able to do it.

The next piece we spent some time working with that tree, squishing nodes together where we could so that we could more efficiently use resources available, and getting things out of that tree where we couldn't. The main meat of this piece was making simple math expressions and some basic functions work. This code is the foundation for the project, and mistakes here have far-reaching consequences. At this point, I was really behind.

The third piece was about using those primitive types from the previous piece to build up custom types and arrays. These are dramatically more complex than the simple pieces above, and are expected to work in the same situations. This portion required me to make sweeping adjustments to my entire code, and I was thoroughly humbled. I got worried enough about it that I dropped the class, and focused on other work that needed to be done.

I wouldn't be writing this if I hadn't made it all the way through. I was extremely lucky, and given a unique opportunity to join back into the course. The last piece was about writing logic with these, the important pieces that make up what we use to program. Things like if statements, for loops, and while loops all fall under here.

We had planned to do some on functions, but we didn't get around to it with many adjustments to how class was delivered. After all of this, I'm glad that those adjustments were made.


I learned a bunch of lessons about compilers and some code in general, but after having a few weeks to reflect, I've decided that those lessons weren't the most important things. Here's what I learned.

Lesson 1: Be Humble

Assembly code to print "Be Humble."
Assembly code to print "Be Humble."

I came into this class with a bad attitude, and I ended up burning myself in the process. I approached this class with confidence because I spent some time preparing before this class on what I thought would be important. It wasn't.

I ended up facing (and eventually overcoming) problems that I didn't know how to solve, and because of my attitude, I ended up nearly failing. This was an experience that showed me that despite what I think, I have a long way to go, and a lot more to learn.

Lesson 2: Don't Be Afraid To Ask For Help

I was about halfway through writing the basic handling for expressions with less than a month left. I was behind, very behind. I sat for hours, moving text between files and going nowhere. It was close to 1AM one late night when I finally broke and started talking to some of my classmates about what they were doing, and shared my own ideas. Ironically, they were awake and working on the same portion of the project.

They really helped me out, and walked me through some of the decisions that they had made while designing their solutions to the problems. Later on in the project, I was given the opportunity to give back to some other individuals who had fallen behind, and I was grateful that I was able to be one of those individuals for someone else.

Lesson 3: Push through frustration

I spent a lot of time on the beginning of the project, because the first steps of writing a compiler are setting up recognition for the parts that make up the language. Every character, every symbol, and every keyword needs to be recognized and grouped. Writing that code manually is awful, but it's the only way to do it.

As awful as writing all of that code upfront was, having that code available in the end saved me a lot of headache. Not to mention that the gratification from having all of that finally finished was amazing, and then I got onto the next section and ran into the same thing, then seeing my computer print 2 from write(1+1) was amazing.

Lesson 4: Not Everything Comes Out Neat

Messy debugging comments within some assembly.
Messy debugging comments within some assembly.

I came in with the idea that I could write this cleanly, as I always try to do. Keep things neatly contained in their own boxes and files, piece them together with bigger boxes, etc. That was not the case.

My code used 9 globals, had numerous cases of static-abuse, didn't manage memory, broke completely when it encountered anything it didn't expect, had files strewn all over the place, and many, many more things that I would consider to be dangerous or "unclean."

And that's fine.

This code doesn't run anything critical. No one else is going to use it. Not everything fit into the boxes that I wanted them to fit into. Sometimes I didn't have time to refactor everything the way I wanted to. But it still works, and fulfills the needs that it's expected to, and I'm okay with that.

Lesson 5: Test and Automate

This is the most concrete, but one of the most important. For the first few months of the class, I had no idea if my code was working. If I changed something, I had no idea if it had just undone a week's worth of work. Halfway through I decided that I didn't want to do this anymore, so I wrote some scripts. They were simple little things that saved me some typing, and gave me the ability to be confident that when I made a change, I wasn't hurting the work I already did.

Then I wrote scripts that ran through that, and told me how well I was doing. Seeing the script spit out successes where it had previously failed was motivating, extremely so, and doing this has motivated further testing efforts in some of my other endeavors.

All in all, I'm glad I had the opportunity to take this class, and I'm looking forward for new ways that I can use what I've taken from it in some of my other projects.

Posted on by:

hunter profile

Hunter Henrichsen


He/Him. CodingCoach mentor. Computer Science, Math, and English student. I like to write, whether that's code, fiction, or somewhere in between.


markdown guide