Welcome to module six, the last module in Nand to Tetris part two. In fact we're going to have one more module following this one but it's going to be mostly ceremonial. And the real module is the last module, is this one. And we're going to have a handful of many different things that we're going to discuss about operating systems. And this module reminds me of a generous dinner that you might get in some Indian restaurant out there. We're going to have numerous little dishes with many different colors and tastes and I think that you're going to enjoy it tremendously. So to remind you, this is our big picture that's the plan of our course, and we are now right here in the operating system module. And you see, there's no way to write high-level programs without having some operating system support in the background. And the goal of the operating system is to close many gaps that exist between your high-level programming and the bare-bone hardware on which your programs are supposed to execute. And closing these gaps and describing this operating system is what this module is all about. Now, there are numerous operating systems out there, and here are the icons of those that are better known. And here is another operating system, which is less known, yet, and that's the operating system that we are going to develop in this module, the Jack operating system. Now, why do we need operating systems to begin with? Well, take a look at this piece of high-level code, written in Jack. And if you will do so, you will see that there are many calls in this code to methods that don't exist in this class. And presumably they exist in some other classes like keyboard, output, math. And these classes are in fact, they belong to the standard class library that accompanies the Jack language. Now this is not something that we invented, every modern high language comes equipped with a standard library that supports it. This is true for Java, for C#, for Python, for C++, of course. And so when you develop a high-level language, the users of this language will expect to get along with it a standard library that supports it. And so one way think about operating systems is to take the perspective of a high-level programmer and to view this system as a set of classes that belong to some standard library. And the high-level programmer will expect to get all sorts of the mathematical calculations implemented in all things like square root. He or she will expect to get support in terms of data structures, like strings and stacks and arrays, and whatnot. The programmer will expect to be able to interact with the input devices like keyboard and mouse, and perhaps microphone in some high-level and abstract and convenient way. Likewise, programmers would expected be able to write on the screen, whether it's texts or graphics using some convenient APIs and interfaces. So as developers of operating systems, we have the obligation to support all these necessary abstractions. Now in addition, the operating system is supposed to deliver all sorts of system-oriented services which are presumably more kind of low-level than what we discussed here. First of all we have to be able to manage the host's memory and I'm talking about the RAM. Otherwise we won't be able to help the compiler create new objects and new arrays whenever the high-level programmer wants to do that. And if we have mass storage, disks, either hard disks or flash memory, or whatnot, well, we have to manage this storage also. And in order to do this, we also need some file system obstruction. We'll have to support at least files, and hopefully also folders and subfolders and so on and all the stuff that people typically take for granted, which is obviously just an obstruction that someone has to realize. We'll need to develop all sorts of drivers which are programs that serve to mitigate between the high-level programs and the low-level peripheral devices that include things like the keyboard, and the screen, and the mouse and all sorts of other devices, plotter or printer. Everything that you want to connect to your printer has to be managed somehow. Obviously, you will need to be able to talk to this computer. And so someone has to realize things like shells and a windowing system. And a lot people want to be able to do many things at the same time, right. I mean, every one of you probably is used to write emails and chat and blog and write talkbacks and post various messages. And people today are fond of doing all these things at the same time. I don't understand how. But in order to do this we need to equip our computer with the ability to multitask and run several programs at the same time. And no man and woman today is an island. And we expect our computers to interact with all the other computers in the world through some network. And for this we have to have some software that mitigates and controls these communications. Once we have communications, we also have to worry about security. So we have to support all these services. Someone has to support it. And this mighty someone is the operating system. And so as you can see, writing an operating system is a gigantic undertaking. And in this course, in Nand to Tetris which is just one humble little course, we're not going to develop a full-blown operating system. But we'll develop a sufficiently interesting and challenging system that will include first of all, all the stuff that you see here on the left hand side. So all the language extensions will be developed. We'll also develop the memory management part of the system services. And to some extent, we'll develop some I/O device drivers and everything else is left for our future work as optional projects that can follow up our Nand to Tetris courses. All right, so here is our Jack operating system in all its glory. It consists of eight classes, and let me go through every one of them briefly. The Math class provides all sorts of mathematical operations. So Java's Math class, I think, features something like 60 or 70 mathematical functions. Although many of these functions, they are overloaded, so actually it's less. Well we offer this selection and obviously we can add more if we want. Then we'll have a Memory class, this class is actually classical because it contains some fundamental operations which exist in any operating system are out there, peek, poke, alloc, deAlloc. And presumably these words mean nothing and that's perfectly okay. They will mean a lot in a short while. We're going to provide a class that's allows you to draw graphics on the screen, lines, circles, some polygons. And we'll use this extensively, actually we used it already in some of our projects before. And we'll have another class that we used extensively, Output, in order to write text on the screen. Then we'll have a Keyboard class with which we can interact with the user, who uses his or her keyboard out there. We'll have a String processing class, very similar to Java's String class, and to one which is used in C#. So we'll have to develop all these capabilities. Then we'll have an Array class which is somewhat unique to Jack. Because in Jack, arrays are not a primitive part of the language, as they are in some other languages. Rather, we decided to implement arrays using our operating system. And by doing this the arrays becomes very similar to objects and in fact that's also what happens in Java and in C# but, [LAUGH] we don't have time to get into it. It is hidden from the high-level programmer. And finally we will have a Sys class that includes some useful services and that's it. This is our operating system. As you may know, there are people who make a living from developing operating systems and these people basically falling into two categories. First of all there are theoreticians, people who are experts in algorithms and data structures. And they take requirements like those that we have here. And they come up with all sort of ingenious algorithms and data structures which are designed to deliver these requirements and deliver them efficiently. And then there's another class of people who take these great ideas and actually implement them. They implement it by writing programs in languages like C++ and C. And they implement these data structures and algorithms and make them actually happen. And in this course, in Nand to Tetris, we'll take both perspectives. And in the subsequent unit of this module, we'll talk, actually every one of these units will begin with some theoretical discussion on what is needed in the way of algorithms and data structures. And then the second half of the unit will actually implement these ideas using the Jack language. And so you see, the Jack operating system is written in Jack. Just like the Unix operating system is written in C. So we'll also need some boot strapping capabilities and this will be part of this module as well. So there are many take home lessons in this module. I've written only a few of them. We are going to learn quite a bit about every one of these super important areas of interest in applied computer science that you see here. And we are going to learn it both at the high-level, at the low-level. And then at the end of this module you'll understand all this stuff in the marrow of your bones. And how are we going to do it? Well this module is a great opportunity for Norm and myself to introduce you to some beautiful algorithms. That are designed to manage our resources and draw graphics on the screen and so on. And in order to implement these algorithms, we'll also introduce you to the art of ingenious hacking. And we'll give you some ideas on what can be done in order to control the whole platform that surrounds your software. And of course we're going to give you numerous implementation tips on how to actually build it using all the tools that are available to us. So that's the plan and before we end this unit, I'd like to say just a few words about efficiency. So far in this course, we allowed ourself to be kind of blase, I think, is the right word, and slack about efficiency. We didn't worry too much about efficiency. We just wanted to things to work and we didn't care if they were quick or slow or whatnot. When it comes to developing operating systems, efficiency is critically important because the algorithms that we develop are going to serve everything that we do on top of these algorithms. So if someone doesn't work sufficiently fast, then all the application programs that they're going to run on top of this service are going to become sluggish and vice versa. If you managed to optimize something at the low level then everyone on top of it is going to treat you like a big hero. And so when it comes to OS, we can no longer for this bliss of ignorance in terms of efficiency. And we have to be very clever about how the programs are going to operate. So that's what we're going to pick up beginning with the next unit.