Start a personal dev blog on your domain for free with Hashnode and grow your readership.
Get Started

How Compiling Code Works

When you run a program, you know that somehow, somewhere the code is getting compiled. You might be able to see a few outputs during the compilation, but for the most part all of it happens behind the scenes. It's like the little black box that we all accept and not many people question it which is ok. But for those of you who want to know a little more about the inside of that black box, here's something for you.

What happens when you compile code

The short version is that the code you wrote gets translated to machine code. That's why we typically write code in an IDE (integrated development environment). They have built in compilers that take your code and perform that translation. There are a few different steps the compiler takes to correctly compile the code.

First it takes your code and turns it into a sequences of tokens. This is a process called lexing which is a fancy term for turning your code into tokens. Each token contains symbols, numbers, and letters that make sense to the compiler.

Once your code has been lexed, the compiler will parse that sequence of tokens to make sure that your code meets all of the rules of the programming language. When the compiler parses your code that just means it's checking everything to make sure it's right. Here is where any syntax errors will likely be found.

After the parsing is finished, the compiler makes a syntax tree. The syntax tree is just a representation of the semantical meaning of the code you wrote. Using this tree, the compiler then creates some output that is the translated code. The output could be in machine code or some other language.

How compilers work

Now that you know exactly what happens when you compile your code, it might help to understand how your IDE does the work. Again, a compiler is just there to translate your code into another type of code. The catch is that there are different layers in a compiler.

There are single-pass compilers and multi-pass compilers. Here's a little history lesson I learned. Back in the early days of computers and programming, compilation was limited by computing resources. Can you imaging trying to compile your code on a computer that only has a 1GB hard drive? That's why single-pass compilers were created.

Since the computers didn't have many resources, a lot of the older languages, like Pascal, were designed to compile in a single pass. Now that we have computers capable of taking over the world, we can use multi-pass compilers. Multi-pass compilers can be broken down into three main parts: front end, middle end, and back end. These aren't like the front and back end in web development.

The front end is where your code gets verified. All of the checks for syntax errors are made here. This is where your code first gets transformed into something the computer can understand. Next is the middle end which is a little interesting. This is where your code gets optimized.

The middle end takes the output from the front end and makes it faster. It might do some loop transformation or get rid of useless code. It's just taking the translation from the front end and making it better for the computer to run it. The last part is the back end and it's pretty straightforward.

The back end takes the optimized code from the middle end and finishes the translation into machine code. This is how the computer can decide how to use its resources to execute your code in the most efficient way. This is where your compiler stops and your program starts to run.

Why we compile code

Do you really want to write machine code? Have you tried writing with the Assembly language? I made the terrible mistake of trying to learn Assembly and it broke my brain in ways I'm still not quite sure I've recovered from. If you think you're up for the challenge, try writing a simple if-else statement in Assembly. I'll be here for emotional support.

Compilers are the reason we are able to use so many different programming languages without worrying about the machine code. That's how we are able to build these complex websites and systems without dealing with 1s and 0s. They are able to take any programming language and translate it into what the computer understands.

Next time you're writing code for the website you're working on, take a minute to look at the output after the code has compiled. I never really thought about how much work they do for us until I got behind the scenes of some compiler code. That stuff is gnarly and I'm so thankful that there are other people out there that can do it.

Have you ever tried writing the code for a compiler? I'm really curious about any personal experiences because I don't see how you do it.

You can stay in the loop with what's happening in the web development world when you sign up for my emails. You can click here to do that. There's hundreds of people who already get the updates, so why not you too?

Start a personal dev blog on your domain for free and grow your readership.

3.4K+ developers have started their personal blogs on Hashnode in the last one month.

Write in Markdown · Publish articles on custom domain · Gain readership on day zero · Automatic GitHub backup and more

Comments (1)

Paul Watts's photo

A very interesting article on Compiling.

Although you were generous with a 1Gb hard drive in “the early days” :-)

My first hard drive was 5Mb and coming from Mag Tape this was luxury.

In our computer room (the size of a modern entire office floor) we eventually had 67Mb drives that were the size of a washing machine and had to be locked down hard to the floor so they didn’t vibrate across the room when in operation.

The fundamental nature of all computing is abstraction. There are literally thousands of layers of abstraction which separates us humans from increasingly levels of complexity as we delve deeper into what makes a computer tick.

Having been a machine code and assembler programmer in my early career I can attest to the fact that it can warp your brain as I still remember the instructions for pushing and popping stacks and dealing with registers all these years later :-)

It did however help my layman’s knowledge of digital electronics at the chip level which is another whole level of abstraction.

Fortunately these days we are far far removed from these complexities and can focus on programming computers to do ever increasing sophisticated tasks without having to get down into the weeds of how it all works.