So we now begin a sequence of three units that discuss how the compiler generates code that is designed to handle objects. Now before we start to talk about this code proper, I would like to make a few comments about some low level aspects of data handling using VM commands. And to begin with, let's look at the big picture. The big picture is such that when you write a high level object oriented program, you can allow yourself the luxury to think in terms of all sorts of obstructions. You think in terms of, for example, two-dimensional points being objects that are implemented in a language like Jack or Java, which is very programmer friendly. And it allows you to think about these points and about the algebraic operations that you can apply on these points, almost like a mathematician that deals with these points in the context of some mathematics application. However, if you were forced to write the same code using the intermediate VM language you wouldn't have all this luxury of objects and methods that operate an object. Instead, you would be stuck, so to speak, with a much simplified world view of the virtual machine which consists of eight virtual memory segments. So, everything that you did in the high level, you had to do using these virtual memory segments and push and pop and other VM commands. And finally, if you were forced to do all this using machine language, then obviously you will be far more restricted, the whole notion of objects and arrays would completely lose its meaning and you would be reduced to operating directly on their end. So with that in mind, we are kind of fortunate that we have compilers, that save us all this trouble and write all the necessary low level and intermediate code automatically. And this is the purpose of the compiler, to closer these gaps and to give us the luxury of writing programs at the high level, and let the compiler worry about all the details of expressing the same semantics in simpler and more primitive languages. Now in this course, we've already dealt with the VM translator. You've written a VM translator in projects seven and eight, and so now we have to focus on the compilation stage only. So with that in mind, we have to write the VM code or more accurately, the compiler has to write the, or let me put it this way. We have to write the compiler that writes the VM code. And let me remind you that in VM programs, if we want to operate on these eight segments, we have to use push and pop commands. And we always have to say on which segment we operate and on which entry within the segment. For example, push local three or something like that. Pop static two and so on. All right and at the end of the game everything that we do at the VM level is going to be reduced to operations on the ram. And to remind you the re implementation deals with this mapping by looking at the RAM in a very specific way. First of all the first five words in the RAM are used as very important pointers that hold the current value of the stick pointer, the current value of the base address of the local segment, the base address of the argument segment, this and that. And all these segments we fail or belong to the VM function which is currently running. And in addition, the VM implementation also allocates a certain area on the RAM to hold the global stack. That is the stack that keeps the working stack of the currently running VM function, as well as all the working stacks and memory segments of the functions that wait for the current function to terminate. Namely the functions which are on the calling chain. So, let us say a few words about how this architecture is used in order to support the notion of local and argument variables. Well local and argument variables are stored on the stack and managed by the VM implementation. And as far as the VM code is concerned, we can access them using the local and argument segments respectively. And once again they are managed by the VM implementation on the stack. And the way the VM implementation recalls the location of these segments of the stack is by using the two pointers, LCL and ARG. The VM implementation puts for example, the local segment in a certain area in the stack and it records the base address of this segment in the LCL pointer and it does exactly the same thing with the argument segment. All right, moving along, how do we use the same architecture to represent object and array data? Well, here the situation is similar but slightly more complex. First of all, we use a different area altogether on the RAM, which is called heap. And on the heap we recall the data of all the objects and arrays that the current program seeks to manipulate. And I wish to remind you that in an object oriented application you may well have numerous objects and quite a few arrays that are necessary in order to implement the computer game, or the financial application, or whatever it is, that you are trying to implement. You may well have dozens, hundreds, thousands, maybe even millions of objects that you have to manage at the same time. One at a time, but overall, you may have numerous objects to worry about. So, as opposed to the local and the argument segment, which are singular so to speak. You have only one of each to worry about. Here, you may have many objects on the heap and before we access an object using this segment. We have to somehow tell the system what do we mean when we say this? I mean, to which object are we actually referring? So, the implementation of the, of this location first of all, is taken care of using the point as this and that. Just like we did with local and argument. However, before we use the two segments this and that, we first have to use the pointer segment to tell the system where we want to align this and that on the RAM. Now this should be handled using VM commands. You may ask yourself why did we, or why do we have to use the pointer segment in such a way? Well that's how Norm and I decided to design this architecture. We had to provide a mechanism to anchor this and that on the particular object and array the code has to operate on and we are using this virtual segment pointer for this purpose. Now, I bet that some of what I just said sounds a little bit obscure or isoteric I think that the following example will clarify everything. So suppose we wish to access RAM words 8,000, 8,001, 2 and so on because they stand for a particular object or a particular array or because they store the data of a particular object or an array. How do we do it? Well, I'd like to show you the sequence of commands that are needed to implement it and for each command, I will discuss the command as well as what the VM implementation does with this command. So, first of all, we have to anchor this, the this segment on the desired address and the desired address is 8,000, so we push 8,000 on to the stack and then we pop it off the stack and into pointer 0. In response to these two commands the VM implementation will set the this pointer to 8,000. So we'll get this effect. Now by the way you shouldn't be surprised from what we had right because if you did project seven and eight, he actually implemented this particular implementations or these particular realizations of the VM commands. Right? Moving along, once you set this pointer to a particular address, this segment can be used as if It mirrors, or as if it is anchored exactly on the 8,000th address in the RAM. So from now on, given that we have this desired mapping, I can happily use commands like pop this zero. Now what will pop this zero do? It will take the value which is currently. I'm sorry, let's do push this zero. It will take the value which is currently located in RAM 8,000 and it will push it onto the stack. And pop will take something off the stack and put it in RAM 8,000 and we do this using the this segment. We can do exactly the same with any other index of this. We can do, we can use this one, this two, this three, this i and in order to access the ith word we add up 8,000 then i and we can use this obstruction here to zero in on the exact word that we want in the RAM. So notice that the VM program doesn't know where all these segments are located on the RAM. It only works with the this segment and the via implementation takes care of all the other details in the background. So here's a specific example. Suppose we want to set RAM 8,000 to 17. How do we do it? Well, we push 8,000, pop point to 0. By doing this, we get the desired, the anchor, so to speak, or the desired alignment. And now that this is aligned on the proper area in the RAM, we go on to do push 17 and pop this 0. This will put the number 17 virtually in the segment this and practically if we put it in a RAM location, 8,000. So, this technique that I just showed you here is the general sort of generic way to access the RAM, a specific location on the RAM using VM commands. And that's how we're going to deal with object data when we get to it. And that's also how we're going to deal with array data in a very similar fashion that we'll discuss later on in the course. So to recap, object data is accessed by VM commands using the this segment, array data is accessed by via commands, using the that segment. And in both cases, we need to write some VM code that first anchors this and that, or any one of them, on the desired location in the RAM. And we do this using the virtual pointer segment. That has two entries only, zero and one. Zero for setting the this segment properly, and one for setting the that segment. But don't worry about the arrays because we'll deal with them later on in the course. So with that I gave you some information about low level data handling techniques using VM commands and we now have what we need in order to go on and discuss how to write VM code that handles object construction.