Hello, in this and the next few videos I'm going to be giving a overview of COOL the programming language in which you'll be writing a compiler. Cool is the Classroom Object Oriented Language and the acronym of course, is COOL. And the unique design requirement for COOL is that the compiler has to be able to be written in a relatively short period of time. We only have one quarter, or in some cases, a semester for students to write the compilers. And so COOL has to be implementable quickly. And actually since it's used primarily for teaching compilers, the number of COOL compilers in the world vastly exceeds, the number of COOL programs. So, there many, many more compilers have been written, thousands of compilers, maybe tens of thousands of compilers have been written for COOL, but probably only some dozens, or hundreds COOL programs. And so, it's probably the only language, in existence for which this is true, That, that, the number of compilers actually exceeds the number of programs, but it does Tell you about the main design requirement. It's much more important in COOL that the compiler be easy to write then that it be easy to write programs in. And so there are some quirks in the language, Things that have been done specifically to make it easier to implement where that wouldn't take away from the, the teaching value of the, of the language. But that would make it inconvenient to use the language on a day-to-day basis as a working programmer. So, what is in the language? Well it's, we've tried to design it so that it will give you a taste of modern notions of extraction static typing reuse through inheritance, automatic memory management. And there's actually a few more things that we'll talk about when we come to them. But many things are left out. We're not gonna be able to put everything in the language and have it be implementable quickly. We'll be able to cover some things in lectures, but unfortunately, there'll even be some interesting language ideas that we won't be able to get to in this class. So the course project is to build a complete compiler. And specifically you're going to compile COOL into MIPS assembly language. So MIPS is a real instruction set, It was for a machine that was designed in the 1980's. And there is a simulator for MIPS that runs on just about any kind of hardware. And so this makes the, the whole project very portable, We can run your compiler, or you can generate MIPS assembly language and then that MIPS assembly language can be simulated on just about whatever kind of machine you have access to. The project is broken up into five assignments. First you're gonna write a COOL program. And that program itself will be an interpreter to give you a little bit of experience with writing a simple interpreter. And then the compiler itself will consist of the four the phases that we discussed lexical analysis, parsing, semantic analysis and code generation. And all of these phases, I should emphasize are [inaudible] compatible. Meaning that we have separate implementations, separate reference implementations of each of these. And so for example, when you are working on semantic analysis, you will be able to take the lexical analysis, parsing, and code generation components from the reference compiler and plug your semantic analysis into that. Framework and, and test it against the reference components. And so this way if you have trouble with one component or aren't sure that your components is working very well you won't have a problem in working on a different component because you'll be able to test that independently. And finally there's no required optimization assignment, But we do have some suggestions for optimizations that you can do. And many people have written optimizations for COOL. And so this is an optional assignment if you're interested in learning something about program optimization. So, let's write the simplest possible COOL program. And the first thing to know is that COOL source files, and in the extension dot CL for COOL, and you can use whatever editor you like to write your programs. I happen to use Emacs, you can use some other editor if you like. And every COOL program has to have a class called main. And let's talk about that business in a second. So a class declaration in COOL begins with the key word, class, Followed by the name of the class, So in this case, main, Followed by a pair of curly braces And inside the curly braces is where all the stuff that belongs to the class goes, And every class declaration must be terminated by a semi-colon. So a program consists of a list of class declarations. Each class declaration terminated by a semi-colon. So that's the structure of a class. And now we need this class to actually do something so we're going to have a method in this class, and let's call the method main. In fact the main method of the main class must always exist. This is the method that's run to start the program and furthermore this method must take no arguments. So the empty argument list for the main method is always empty. And let's say the main method its body always goes in a pair of curly braces. So the main method always goes inside curly braces. And a class consists of a list of such declarations. And again, those declarations must all be separated by semicolons. So in, or terminated, excuse me, by semicolons. So in this case, we only have one method in the class. But still has to have its semi-colon and now we can say what we want the method actually do so this is the place for the code for the method goes and let's just have the simplest possible method the one that just event evaluates to the number one. Okay, so [inaudible] an expression language, which means that wherever a piece of code can go, you can put an arbitrary expression, any expression can go there there's no explicit return statement for a method. It's just a value of the method body is the value of the methods. So in this case we just put the number one in there, and that will be the value of this method when we run it. So let's save that. And now we can try compiling this simple program, so how do we compile the compiler is called a COOL c for the COOL compiler and you just give the COOL compiler a list of COOL source files. So in this case there's just one file 1.CL hit enter and ooh we got a syntax error so we have to come back and fix that and the error said at or near the open curly brace on line three there's a mistake. And I know what the mistake is, because I'm a competent COOL programmer, at least somewhat competent COOL programmer. Cool methods must declare their return type. So we need to put a type here. And the syntax for the declaration is to put a colon after the name of the method and the argument list, and then the name of a type. And since we're returning the number one for this program for sorry, for this method we might as well say that the main method is going to return an integer, So save that, Go back to our compilation window and let's compile the program again. And this time it compiles successfully. And now if we look in our directory we see that there is a new file called 1.s. That's the assembly code for the program one. And now we could try to run this code. And the, The, the Mitch simulator is called spin, and it just takes a, assembly file to, to simulate, And so we just give it one [inaudible] hit enter and it will run. A whole bunch of stuff is printed out. But as you can see, it says part way down that the COOL program successfully executed, so that's good, and then afterwards there are some statistics and things like number of instructions executed, a number of loads and stores, a number of branches, those things would be interesting if we're worried about performance if we were to say working on the optimization of the compiled code, but we're not doing that right now. We're just running programs. And we can see if this program works. So the program ran. It terminated successfully. But it didn't actually produce any output. And that's because we didn't ask it to produce any output, If we want to have output. We have to go back and modify the program again. So, so what this program does currently, is that it just returns its value but that, but nothing is done with that value. It's not printed out or anything like that. If you wanted to have something printed out in a COOL program, you have to do that explicitly. So there's a special class built in, a primitive class called IO. And we can declare, what's called a attribute of this class, it will be a IO attribute and it will be called I, okay and I will be a object that we use to do IO. So now in our, main method, Here we could add a call to out-string, I dot out-string is how we invoke a method. Okay so out-string is a method of the IO class so we use I to invoke that method and then we can pass it a string that we want printed out on the screen. So for example we could say hello world. Okay, And now, we have to decide what to do, with our, with our number one there. And let me show you one more feature of COOL. Let's leave the one there, and let's make it part of a statement block. So a statement block consists of a sequence of expressions separated by semicolons. And you can have any number of expressions, and the semantics of a statement block or an expression block is to just evaluate the expressions in order. And the value of the block is the value of the last expression. But now, a statement or an expression block has to be included in its own set of curly braces. Okay, so that now is a valid COOL program so let me just read this for you so the body of the program is a block of expressions. The first one, executes. A out string call to the object I, which is going to print hello world for us. And then the second one evaluates to one, which is the value of the entire of the entire method. Okay, actually I should say it's the value of the block, okay, and then because the block is the body of the method the value of the block becomes the value of the entire method, So one will be returned from this method call. So let's save this. Go back over here and let's compile this again. So, Looks like I failed to save it. Let's compile this and we see we have a syntax error. And so it says on line four, we have a syntax error at or near our closing curly brace. And the problem here is that a statement block, or expression block consists of a series or a sequence of expressions terminated by semi-colons, and we forgot to terminate the last expression in the sequence by its semi-colon, So we have to add that. And now we should be able to compile this, and lo and behold it compiles correctly, and then we can run it. And now we see, oh we got another mistake. So we have an, when the program ran it complained that we have a dispatched void. So that on line four, our dispatch was to an object that didn't exist. And, you can see the dispatch call right here to I, and it doesn't exist, because, in fact, we forgot to allocate an object for I. So here we declare I to be of type IO, but that doesn't actually create any objects. That just says that it creates a variable name I but I doesn't actually have a value. So if you want I to actually have a value, we have to initialize it to something. So we can initialize it to a new IO object. And new here, is the way you allocate new objects in COOL and new always take a type argument so in this case were creating a new object in type IO and were assigning it To this object i. And notice here that I is a, is a, is what would be called a field name in Java. It's what we call an attribute in COOL. So, so these are the data el, the data elements of the, of the class. And so the class can have both of names of things that are so, attributes or fields that hold values as well as methods that can perform computation. [sound] Let's save this and switch back. And now we'll compile this again. So and it still compiles. And now we can run it. And now it runs, and low and behold, as you can see down there third line from the, the top, it prints out hello world. And that looks a little bit ugly because the, the successful execution message is on the same line as our hello world message. So let's fix that. Let's come back over here. And in our string here we can add a new line. Okay at the end of the string, so backslash N is how you write a new line character in the string. Save that, come back over here let's compile. So if you don't know Unix bang will repeat the previous expression the previous command that began with the same prefix that you type after the bang. So I want to run the last command that began with C which is to compile and then I want to run the last command that began with S which is to run spin. And now we can see there it is all nice hello world is on a line by itself. Let's continue now, let's [sound] clear all this out [sound]. So let me just show you a few variations on the same program. What I'm going to do here is just rewrite it in a couple of different ways. So I just illustrate a couple of features of COOL and get you more familiar with the syntax, and also just show some alternative ways to do the same thing. So you know this, this. A block here of, of expressions is kind of a clumsy way to, to implement the Hello World program. So let's get rid of that. Let's get rid of the, the block. Let's get rid of the one here at the end. Okay, let's just make the statement body a single expression again, and, and now the problem we're going to have is that the types won't match. But just to illustrate that, let me show it to you so let's do COOL C of one dot CL, and you'll see here that in complains that the inferred return type of the IO of the method main does not conform to the declared return type INT. So coming back over here, the, to the program, The, the compiler figured out that this expression, I dot out string, yields an object of type IO. So it returns the i object as the results evaluating this expression. And that does not match the type it. And so naturally, the compiler says, hey, something's wrong with the types. Well, that's easily repaired. We can just change the return type or the main method to say it returns something of type IO. So let's go back over here and see if that now works. So, we compile the program. And then we run spin on the output, and yes, everything still works as expected. Now, We don't have to be so specific about the type over here, since we're not actually using the result of the method body for anything. I mean, the program just exits once it prints the string. We could have allowed ourselves more flexibility here. We could've just declared the result type of main to be of type Object. So Object is the root of the class hierarchy in COOL. Every other class is a subclass of Object. So let's come back over h, let's save this first. And then we can come back over to our compilation window. We can compile it. And we can run it and it still works. So now another thing we can do if we want, is we could observe. Here that this attribute that we declare, this field I isn't really necessary. Here we, we allocate, you know we have a special name I when the main object is constructed to run the program, a new [inaudible] object is allocated to I and then that gets used in the main method. We can actually just do all of that inside the main method itself by just allocating a new [inaudible] object right here and then calling out string on that object. Alright, So this should also work. And let's check it out. So it compiles. And lo and behold, it rots. Alright, So coming back over here let's illustrate one more, or a couple more things that we could do. So, we could also say that [inaudible] inherits From IO. So we have to have the IO functionality somewhere in order to call the out string method. So we have been doing that by creating a separate object of type IO. But now we can say well just the main object is itself. And something that has all the capabilities of IO by inheriting from IO. And if you've seen any [inaudible] language before this will be a familiar concept. So main here gets all the attributes and methods of IO, in addition to whatever attributes and methods of its own that it will have. And now Instead of, of having to allocate a new IO object in order to call out string, we can just invoke it on self, Which is the name of the current object when the main method runs In other languages self is called this. Okay, and so let's we saved it, so let's go over and compile this. So it compiles, it compiles and, and it runs, right? So last example here, we don't have to name self actually in this dispatch. There's a feature that allows us to call a method without explicitly naming the object on which it's dispatched and defaults to self, so if no object is named in a dispatch then it's just a dispatched self. So this should also work. [sound], And indeed it does. So that concludes our first example. In the next couple of videos we'll look at some more complex examples of COOL programming.