Welcome to module five, in which we are going to talk about the code generation component of our compiler. Now, I think that you will agree with me that most high-level programmers tend to take compilers for granted. They write the programs, they apply the programs to the source code, and they happily sit back and observe how the code is being translated into machine language. They don't see the actual process, they just see the result. Actually, they don't even see the result, they just execute it and then they go on to debug their source code. Now, this bliss of ignorance is just fine, however, I think that you will also agree with me that translating a program from high-level to machine code is nothing short of magic. And if you don't want to understand this magic, then I think that you're going to deny yourself from two important benefits. First of all, you will not appreciate the beauty and the wisdom that goes into the algorithms and the technique that come to play in writing a compiler. And second of all, you will lose the opportunity to become a much more competent high level programmer. Because in the process of writing a compiler, you're going to gain lots of very important capabilities that go far beyond the narrow context of writing a compiler for high level language. So, with that, let us go back to the overall roadmap. That's what we want to do. We want to write a compiler that translates programs from the Jack language into machine language. And, in this course, we decided to write a two-tier compiler just like the compilers of Java and C#. So, instead of going all the way to machine code, the compiler will translate from Jack into VM code. And then there will be a VM translator that will translate further into machine language. Now the good news is that the VM translator has already been taken care of. We wrote in the previous two models. So now all we have to do, quote, unquote, all we have to do, is write a compiler that translates from the high level to the VM code only. Now, we decided to split the construction of this compiler into two well defined modules, syntax analyzer and a code generator. Now, the syntax analyzer is something that we already developed in the previous modules. And in order to test it, we decided that the syntax analyzer will emit, not VM code, but rather, XML code. And the purpose of this exercise was just to verify that the parser understands the source code. That it understands the syntactic structure of the commands. And is capable of demonstrating this understanding by producing legible XML code. In this project, the XML code is no longer relevant, right? Because in this module, we're going to focus on a code generator which is going to translate into VM code. So, what we're going to do is, we're going to focus on the parser and the code generator modules. We will rewrite certain elements from the parser that are responsible for generating code. We'll write some more code generation capabilities. And the result will be a compiler that goes all the way from Jack programs to VM code. So the objective, once again, is to develop a full-scale compiler, or more accurately, to extend the compiler that we've written before into a full-scale compiler. So instead of generating passive XML code, we will morph the compilation engine that we had before into something that generates executable VM code. So this is the objective and that's how we're going to do it. Now, when we say program compilation, in this course, we talk about a language which is high-level and object oriented. The Jack language. And here's an example of some code segment that you've seen before, that is designed to manipulate some points on a two dimensional space. If you compile and execute this code, you'll end up seeing some nice results on the screen. And as we discussed before, in order for this code to work properly, it has to interact with yet another class file that delivers the point functionality, so to speak, the point class file. Now, when you set out to develop something complicated like a compiler, it always helps to try to simplify matters as much as possible. So I'm going to make some simplification observations. And the first one is the following, each class file is compiled separately. Each Jack class file, just like each Java class file, is a separate and standalone compilation unit. So, the overall task of compiling a multi-class program has been reduced to the more sort of limited task of compiling one class at a time. So that's my first observation. And the second one is based on going into the class itself. So here's an example of the class point. And what I've listed here is some class-level declaration statements, and then all the methods, or all the subroutines, of the point class. And for lack of space I didn't list the code of all the subroutines. I just listed their signatures, except for one subroutine, distance, in which I took the trouble to show the entire code. So here is my second simplifying assumption. First of all, let us observe that the class consists of two main modules. First of all, we have some preamble code that defines the class in some class level variables. And then we have zero or more subroutine called declarations, right? And in the case of this class, here's the code which is at the class level. And here's an example of the code of one particular subroutine. Now, the simplifying assumption is such that compilation can once again be viewed as two separate processes when you go down to the class level. First, you compile the class level code that we see here on the top. And then you compile each subroutine one at a time. So, to a great extent, these two compilation tasks are relatively separate and standalone. And, therefore, once again, the overall and rather formidable past of writing a compiler for multi-class program has been reduced to compiling one subroutine at a time. So, once again, things are localized and we're going to use a very modular strategy. And as usual, we're going to do things one step at a time. All right, now, what do you see when you compile a subroutine? You see variables, expressions, if, while, statements like those, you can see objects and obviously you can see arrays. So, the compilation challenges that we're going to handle are what you see here on the screen. And these challenges are also sort of the table of contents of the next units in this module. In every unit, we'll deal with one of these challenges one at a time. Now, the challenge when I say to deal with them is to generate VM code that captures the semantics or variables, expressions and so on, using VM commands. Now this is not a trivial task because high-level languages today, including Jack, are very sophisticated. They give you all these fancy control structures and objects and arrays. And yet, the target language, the VM language is very simple and limited. It has only push, pop commands and a few more commands, and that's it. So, we are facing the challenge of bridging the gap between the high-level and the VM code. And we have to somehow express this very rich semantics that you see here in front of you using the very limited VM language. But as you will see, we will do it in a surprisingly elegant and relatively simple fashion. All right, before we wrap up this module, I'd like to list some of the lessons that you're going to take from it. So, first of all you will learn how programming languages work. You will learn how to implement a simple procedural language like C, because you will know how to handle variables, expressions, flow of control. You will also learn to handle arrays and objects in the low level. And by doing this, once again, you will gain a very deep understanding of the tools of the trade. And secondly, you will learn some general purpose techniques which can be applicable to numerous other problems and applications. You will strengthen your understanding of parsing, something that we've dealt with extensively in the previous module. You will understand how recursive compilation works. You will learn how to generate code, how to create in the user symbol tables. And you will begin to learn how to manage memory cleverly. Something that we will take up also when we discuss the operating system in the last module of this course. So all these goodies are coming up in the current module. So, in closing, these are the challenges that we have to deal with starting with variables. So that's what we'll do in the next unit.