 All right, let's get started today, Wednesday. It is Wednesday, right? Good. Yes. Any questions on project three? Do you like two or three minutes? Project three questions? What would you suggest for... I've passed all of my local test cases, but only like 90% of the ones on the server. So I have no idea where to start. So what do you mean local test cases? Well, the ones that were given to us, the six or seven test cases. Yeah, the shell script one. Yeah, the shell script. I've passed all of those, but like 90% of the ones on the server. Okay. What about... Did you take any other... Did you create any other test cases? I'd say that's probably where to start. Create test cases. One way to do it is to take the example from the site itself. Take that, create test cases for that test case. You want to look at how... So I would do two things. A, create test cases. So try to look at the test cases that you have, look at other test cases, and try to think, okay, what types of grammars is this not testing? Is there... Say a grammar with maybe like an infinite loop or something, or what would be an infinite loop, right? Something like in the business of unplugging and plugging things in. Okay, there you go. Something like S goes to A, S goes to B, A goes to, I don't know, A. Little A, B, I don't know. A goes to S, A, B goes to B, something like this. S little B. There's something simple like that. Because the key is you want to do this and then write what you... Before you run your program, that's the key to make your own test cases. You create this test case, and of course if you're doing it, you would first have on the first line, S, A, B, a pound, this pound, that pound, pound, a pound, and then finally a double pound. So I would try something like this, right? But before you run it, you want to use this as the test case and then output what you expect for tasks zero, one, and two, right? That shows that you know what it should be doing, and then you run your program on it to compare it with your output. So that's the big thing is to make sure that your expected output matches what your program actually outputs, right? If you just use this as input, run it into your program, and just look at the output and be like, yeah, yeah, that's what it should be, right? Then you're just confirming the bias that's in your own program. I would do things like this. I'd also read through the description and say, okay, am I testing all of these things, right? Where, for instance, the description says, you know, in between any of these characters, there can be any white space, right? So are you testing with spaces, new lines, tabs, you know, all kinds of crazy things, or can the hash be on the separate line, multiple lines, active and hash, you know, all kinds of that kind of stuff? That's what I would do is go through the description, specifically look at every piece and be like, okay, does my test case actually test them? Like even just testing something like with, for instance, one of the requirements is that, you know, all the string matching and everything is case sensitive, right? So if I have like a non-terminal foo here, and then in my grammar, I have like foo, goes to capital foo, right? Does it properly know that those are two different symbols? All those kinds of things. So that's one thing to do. The other thing to do is I kind of wrote this, this morning on the man list, you want to look and see, and it's kind of difficult because unless your code is going to hit that, it's hard to tell, but you want to look through your code A and look for any, is it possible that I have any null point or D references, which are going to cause segmentation faults? Because you could miss the test case for three reasons. Well, yeah, three reasons. Mostly. One is it's just straight wrong. The thing that you output is not the thing that we're checking for, right? One is your program causes a segfault before it outputs, right? So segfault, dereferencing a null pointer, dereferencing either the star operator or the arrow operator. So is it possible in your program for there to be a null pointer dereference? So then even if you calculate first and follow correctly, right, you're hitting that condition and your program's crashing before it outputs anything, so it's the same as if it outputs nothing. Third option, yeah. Would it pass the local test cases? It depends. I mean, it depends on if your local test cases are exercising all possible paths through your program, which I'd say probably not, right? It could be a case of you're checking if something's null and you're doing something, but that test, that code is never executed on your local test cases. So that's important to write a varied set of test cases for yourself. And I'm totally okay. Well, that was the ground rule. Okay, let's go back to the third one. The third one would be an infinite loop, right? If your code gets into some infinite loop, for instance, if you're trying to calculate this first set recursively, right, it's going to get an infinite loop. It's going to crash, but if you think about even an infinite loop, right, we're only running your code for so long. I think it's only three minutes, or I actually don't know what it is, probably 30 seconds. So if that's the way it's running forever, we kill it, and we say, okay, that's the same thing as doing no output. So those are the three main possibilities. So here's what I will say. I'm fine if you want to share on the mailing list test cases, but not... because I don't want it to be like, oh, this test case passed... like, once I solved this, then I solved the thing on the server, right? I don't think that's fair for everyone, right? But if you just say, hey, here's a test case that I made, I think that's totally cool. And like, here's what I think the expected output is, and then other people can compare and decide what the expected output of that should be. I think that's totally fine. If you want to do that, I'm fine with that. But if you want to do this, it's not like, oh, I passed test case X, or I was missing the last two test cases, and then I came up with this test case, and it caused a bug, so I fixed it, and now, any other questions? Oh, that's been 10 minutes. Back to server. Okay. So pointer operations. So we've talked about pointers a bit. So what does the address operator do for pointers? What's the semantics here? Think about the semantics, does it? Almost. Close. Very close. Let's start from the beginning. How many parameters does it take in? One parameter. So it's a unary operator. What can it be applied to? L values, R values. Think about types like that. Only L values. Why only L values? Because it returns an R value. Let's think about that for a second. Because it only returns an R value. I don't know that I can get on board with that. I'm trying to think of a counter example. So what does it return? An R value, right? Yeah, perfect. So what else has something? Yeah, so the return value is the address of the box, right? So yeah, it takes in a box, and it returns the address of that box. Yeah, so the return value is the address of the box. And it returns the address of that box as an R value. So what about with types? So we think about the types. So if the type of the input parameter is T, some abstract type T, what's the return type going to be? The type of the... So let's say it's a T. Let's call it an int to make it a little more concrete. Right? So we do the address of an operator on an int. What's that resulting return values? It's always an address, no matter the type, but in the type system. So it is an address, and the addresses are usually shown in hexadecimal. But what's... So if we were to use that variable, what's the type of that variable? So first, why is it returned on an R value and not an L value? Yeah, another way to put it right, there's no location associated with it, right? It's just returning the address of some other location. With a memory address of some other location. So if we take the address of an int, and address of an int, then what do we get back in the type system? A pointer to an int. Yeah, it's an int star. Good, good, good. So it's an R value, right? But this R value has the type, just like normal R values, like the immediate value 5 in your program has, I assume the type int, actually, but it could be any number of types, but let's call them int. So the key point is the location. So we kind of have to change a little bit how we're doing Boxer. Not change, we're just going to add. So we have x, right? It has some location with something in it. And if we take the address of x, right? So here we have the variable name. So this is the, what do we call this? The binding, yeah. So we're binding x to this location. This is going to be the value in x. We'll call it 10. And then on the right-hand side here, we're going to have some address where this memory location lives. It could be, you know, a hex value, like the fff 4042, or we could call it something abstract because we don't really care what the actual value is, like alpha. I'm going to say this is alpha. So then when we take the address of x, we know that this returns. Alpha, yeah, either alpha or whatever this value is, right? Yeah. Is alpha pointing to the value of x or the location? Alpha pointing to the value of x or the location. Okay, so the first way to think about it, so this return value of the address of operator, is it an L value or an order value? So does it have a location associated with it or no? It's an R value, right? So this is just the mechanical value, so this is actually why we're doing this and going through this, because pointers and pointing and dereferencing and multiple pointers, they actually are nothing but values inside of them, right? So if we had, let's say, we had some variable y, and we said y is equal to the address of x. I have my box circle diagram here for y. So what are the exact semantics of this operation? So we went over assignment semantics. What are the exact semantics here? What does this mean? Y is equal to the address of x. The address? Yeah, so we got to break it down a little bit, right? So on the left-hand side, is this an L value or an R value? Yeah, better be an L value, right, because we can't have it any other way. And on the right, address of x is what kind of value? R value, right? So the address of x returns an R value, so this is just the same thing as saying except that instead of 5, now it's computed based on the address of x. So we look at, okay, whatever this value is here, let's actually use this concrete value because I kind of like that, except now I'm going to run out of it. So what's the result? So then, what does this semantics mean here? Yeah, so take the address of x, right, which is some R value, which we can easily look up. Every location has some address. Take that value and copy it into the location associated with y, right? So this would be 0x, Bf, Ff, 4042. So what's the difference between y and x here? The only difference is the value of the store. Yeah, right, inside that location there's no difference. It's just a value. It'd be the same thing, you know, is this some special value? No, it's just some decimal, yeah. So you're saying if you printed y, it would actually print 10 or would it print that? Hmm, tricky question. Ah, okay. So we print out y. We'll do something like this. We're kind of in the right types right now. So what is this axis saying? Y, the value in y. It says print out as a, what does the D mean here in the print out? It's an integer. Yeah, print it out as an integer, whatever's in y. And you know what this is as an integer? Which is a calculator. Bf, Ff, 4042. I wish I'd done this beforehand so I could have tricked you all into thinking. I know this really well. No. So it actually depends, I guess, on how we're interpreting this number. Because of the 1 here, this could be a 2's complement number, but let's say it's not. We're printing out a normal integer. So this would be 3,221,176 Wait, 221,176,363 That's what it's going to output. Is this any different than saying can we do this? Can we say int z is equal to maybe this is, we're calculating how much money I want to make. Maybe in pennies, but still. I'm going to add commas even though you can't really do that. So what does this mean? What are the semantics here? Exactly the same. Exactly the same, right? Whatever this value is here then copy it into the location associated with z. So we need to have z, we need to have some binding to some location. And then inside that we put 322, I wish I'd used a different address. 176, 386 Right, inside there? And what's the address of z? Now beta, we don't actually care at this point, right? It doesn't matter. So if we were to say is y equal to z this x is just a different way of representing the same integer. This is why the calculator is nice because it shows us the exact 32 bits, 1s and 0s of this number. But yeah, this and this are exactly the same. So if we ask the computer to compare these two if they say it's identical. So to the computer it doesn't matter that this is the address of x and that this is an integer all it is is these are values in the locations associated with y and z. But when does it matter actually to address them there or not? Yeah, when we try to dereference it, right? When we try to do the dereference So what are the semantics here? So how many parameters does it take in? So can the input so the input can I guess this is kind of two questions. So the input can be either an L value or an R value. If it's an L value it takes the value within there and it's the R value. What does it return? An L value or an R value? Where can you use the dereference operator on the hand side? So let's try to think about this Can I do this? Is this valid c code? So because I can do this, what does this mean that the result of star y must be? Yeah, it's got to be an L value. Right, so the question I guess is is it always an L value or is it sometimes an L value or is it sometimes an R value? So it's always an L value right, it doesn't matter what you do star y is going to return a location so an R no one claims you're here a box and the type here right, we have so as far as types go let's say the input to y let's say y is a t star, we have t star y then what's the type of star y? That's how we get rid of those pointer dereferences. So then what are the actual semantics here? So here we have let's see I'm going to go back up here I'm going to erase all this let's do star y is equal to what number do you guys want? number less than 100 1? and it's easily going to step for an L so we have star y is equal to 1 so what are the semantics so on the right-hand side we have what R value L value yeah it's an R value right, there's no location this is just the value 1 right so then star y is going to return an L value a location so what is it going to return? what are the semantics here? so intuitively what's going to happen to this diagram? after the end after this the 10 at x the 10 at x is going to be a 1 yeah but how does that actually happen? so star y what does star y do? we're defining dereference you can't use dereference it goes to the location of the value at y yeah so it uses the value in the location associated with y this value here it takes this value and it looks up what location is associated with that and it returns that location and it returns the box so that star y this expression returns this box do we care that this box is also bound to the name x? no, we don't care at all and then once we have this location so now we just have an L value is equal to an R value can we know what to do here? yeah we just take this 1 we copy it into the value in the location associated with the L value it's right in here we're going to change this from 10 to 1 and that's all pointers are they actually are absolutely nothing special or scary until we get to the dereference operator and then it's just take whatever value is in y look at that value and return that L value so what's the difference between that and this? yeah the important thing to keep in mind especially when you're programming when you're looking for no pointer dereferences so this is equivalent to it's actually usually something like y plus offset so what type is y usually if you use this? what type is the pointer of y? a struct so you're trying to access so structs are just fixed chunks of memory let's say group these fields together all at once so that every time you refer to some structure let's call this bar and so if we have a struct called bar it has let's say an integer foo let's call it something else first we'll go baz and then an integer bar foo so this means okay every bar is two integers together continuously in memory and so I know when I'm accessing foo so bar the pointer to a structure points here is the address here and so I know at that address is going to be baz the first four bytes is baz the next four bytes are foo and so the compiler automatically translates this y arrow foo into y plus that here it's going to be four so it'll be y plus four and then dereference that so that's how it's able to index into the structure the point is when you're programming so let's look at an example so what if I said this y is equal to null and star y is equal to 100 so what's this going to do so first what does this do so let's draw this picture so after this first line it's going to say what the value which value why is this the name the value at y the value in the location associated with y yes semantics this is so fun right so y is equal to null but what is null yeah it's a preprocessor macro what is it usually zero yeah so the preprocessor goes through and replaces all nulls with zero so this is equivalent to writing y is equal to zero so then after this executes what's the value that's going to be in the location associated with y zero so I want to do star y is equal to 100 what's it going to do what's it going to try to do it'll try to change the value of the location zero before it changes though what is it going to do when it does the last tan side here star y is equal to 100 yeah so it's going to try to find a location with do we know anything about the value there what do we know about this location the address is zero yeah I'm going to do like a weird not a null set but like a weird zero there so it's clear that this isn't the value right so it's going to try to look up this location most times in your program this location is not going to exist and that's when the program throws a segmentation fault it said oh I tried to access some memory that you are not using and so this is an error in your program this is where a segmentation fault comes from so pretty much this whole thing it goes eh can't do this therefore I can't set that to be 100 if you had something at zero if you had some location at zero then it works it just will change whatever is there as we saw to 100 so you can completely control that actually kind of a funny story well this is actually a big security vulnerability or it used to be more so because it used to be that you could trick some programs to allocate something at memory address zero and so no pointer to your references you could get it to like write certain bytes into the program at memory zero and you could use that to completely mess with the program but now most most systems trying to access zero completely fails there if you did one y equals 100 that would set 100 right? if you did this exactly so what's going to be inside this location let's see if it's y 100 and then now if you did star y is equal to do another number 42 so what's this going to try and do yeah it's going to try to find some location that has the address 42 and then sorry the address 100 right? going to try to return that L value if you can find it then it will return it and everything will work if it doesn't then it won't work this is why the star accepts either an L value or an R value because you can do pointer arithmetic and you can change where pointers point to when you're dealing with an array right and see iterating through that pointer simply incrementing that pointer or offsetting from that pointer cool so we've seen this we have some T it actually doesn't matter whether it's a T star or a T or whatever the type of that variable is every variable is going to have a box circle diagram with some name associated with that a bound to that and it should if everything is going correctly it's going to have some value inside of that and for everything to be type checked correctly xv has to be has to be some address of a location that exists some box that actually exists and the type of that value that's inside there should be type T x is a T star this means I dereferencing that that thing should be a type T so this may when you have if x is an int star star when you dereference that it should be an int it should be an int star because dereference only removes one of the pointers from there and so another way we'll draw this is that this xv takes star x points to this memory location so that's kind of what we're doing as we do that but we can draw it actually on the diagram and so as xv the value that's inside the location associated with x changes then what happens to star x it's also going to change and point to some other location, some other value okay so we have our L value right and L value if there's a location associated with it and our values have no location those are just values so is star x an L value yeah so how do we know well x has yep x definitely has locations associated with it in this box so what about star x star x returns a location those are locations associated with star x yeah it depends on what side it's on does it right so what's the the criteria for an L value is the location associated with it right so star x returns a location then is there a location associated with star x it's definitely an L value right doesn't matter where it appears and so what's going to happen here if we do star x is equal to 100 how's this diagram going to change these going to turn to 100 right so we're going to take the value in the location associated with x which is xv we're going to look up are there any locations with that address there's this one here's this location and so we're going to set the value in that location to be 100 so it's going to copy the value 100 to the location associated with star x right and we know that star x has a location associated with it we just saw that so we're going to end up writing 100 and changing that value questions so let's look at an example okay so we have int x and int z so how many circle box diagrams are you going to have here 2 x and z and then we say z is the address of x and okay we'll say the address of x is y right so it's y a variable it's just some abstract address right it doesn't matter what we put there it could be pretty much anything so in the semantics of this right we're going to take that address y and we're going to copy it into the value associated with z so what happens when we do this address of x star is equal to 10 or star address x equals 10 how do we figure out what's going to happen here yeah so first so address of x what is it going to return y and what type of value is that l value r value right there's no location associated with that y does not have any location associated with it it's just an address of a location so we take y and can we do star y so what would star y do yeah so it's going to what does star y go into return in the diagram why is it yeah but why is it value it's just like 10 or 100 right oh so it would return the value yeah so it's going to look up okay I know the address I'm looking for is y are there any locations with the address y and it's going to return that location that box exactly and so then where is 10 going to go yes into the location 10 is going to be copied into the location associated with x so what's this the same thing as doing just saying x equals 10 x equals 10 so in theory they undo each other so if we stack them like this yes can you stack them the other way could you stack them the other way or that just be garbage you mean in this so if we stack them the other way switch it so if we work outside in let's uh let's see here we had x and we had let's say the value in there is 10 and we have the address of x is y so is this valid we want to say now depends what's stored in x or in the location associated okay let's write it down so first how am I going to read which happens first on the left-hand side here the top reading exactly so it's kind of like this I mean if we were to parenthesize this start x first and then take the address of that so what's start x going to do look at the location yes return the location associated with 10 it's going to try to find some location 10 try to return that let's say for argument's sake that it works okay then what's the address of this going to return what's the address of this location 10 10 that was inside of 10 but then how does so then what do we do change this to 100 because that's an r value now yeah so remember what is the r value of the address of anything what does that return this is just a value so the address of star x we can take that that would give us 10 assuming we can actually dereference 10 that's kind of the trick but it's an r value so in essence we're saying can we do r value is equal to 100 no and hopefully it shows that look there's no where to put where do we put this 100 address of star x is 10 can you write a program as 10 is equal to 100 as an assignment statement no no it doesn't make any sense there's no place to put 100 right you do a weird like type death or maybe like a pound to five to say that 10 is 100 if you really want to ask people that's actually one of the fun things you can do to people's code if you do like a pound you can do like a pound to find zero as one not to completely mess them up but it'll usually still compile if you do this so you do this like at the sneak it into their code there you go don't do that one your students in this class or your fellow students in this class when they're trying to do their assignment cool so we saw this so what happens when we do this we say x is equal to star address of x so what's going to happen here with star address of x x is equal to x so what's address of x going to return y y and star of y what is star return but the earth is operating what is at the address 10 not the address 10 which address here y and what is it going to return specifically the location the box yes remember the location is not the value that's inside that location right so it's going to return the box and then we say x is equal to some l values we have l values equal to l value do we know what to do there yeah we take the value in the location associated with star address of x which is this box we take that value 10 we add where into the location associated with the name x which happens to be the same thing so we copy 10 to the 10 we say that star returns location without the address yes star always returns star takes in the address and returns a location and the other way is the address of operator takes in location and returns the address okay let's make a convocated example but first we need to cover something new locations we're going to malloc and new malloc and new so let's we'll just focus on c for now because new actually I think under the cover just uses malloc right so we have malloc but how else do we create space for variables we declare the variables right when we declare so we're actually going to go super in depth into the differences here between malloc and essentially we'll call it the stack for now right so we have these two ways that we can create a name for variables so if we do something like if I have some code in x here let's call it an in pointer x so where is x living is malloc or the stack stack right so after this declaration I know that the computer is going to create something with the name x and bound to some location right what's the value inside x at garbage we don't know what it is it's undefined right do we know the address of x we don't know it but the at runtime the computer is definitely going to know we'll call it alpha for now then if I say x is equal to malloc so what are the parameters to malloc it's just size right so how many bytes do you want to store things in so how many bytes do I want in here size yeah why do I want so I could do this or I could do so what's the difference between the two one is portable one is not one is portable the other is not how big are integers on 64 bits systems 64 bits yeah and not 4 bytes right so this is the number of bytes so it would be 8 bytes right for an int so if you try to write this code it's going to fail on it can fail in unsurprising ways on 64 bit operating systems and the cool thing is at compile time the compiler translates size of int the compiler knows when it's compiling exactly what architecture it's compiling for and it knows how many bytes an int takes so it actually on 32 bits it creates this call and on 64 bit it knows and it's going to create the equivalent malloc 8 so when you actually look at the binary code it's actually using a number and it's not looking it up at runtime but it's this is why you use the compiler to do that job okay so let's say we've done this correctly and for our purposes right now it doesn't really matter what we pass in here because we're talking about locations as we don't really care at this point how the size of the values that can possibly fit inside this location right but that's clearly determined by the number of bytes so what does this do what does malloc add to our picture without doing this what does malloc do you know it space that x will point to on the heap so that we can maintain that memory so what does it create then in our circle box diagrams places the garbage value of the value of memory location for too much what if we just did this what does malloc do if does it return returns a memory location that we can put things in how do we represent things that we can put things in places the box locations right it's all it is a location a location just have memory addresses associated with them right so this is going to create some new location do we know what the value is inside that location we have no idea it has some address we'll call it beta because we don't know it at runtime either right it could be anything and every time we call malloc so this is what malloc does is it creates a new a new location and so what does the call to malloc return the address of that location exactly so here in this case it would be beta right and so if I said x is equal to malloc this is the exact same thing so if I had x is equal to beta where beta is is this a variable not just a value right some value so if I said x is equal to some value what do you do what what are the semantics here take the value beta copy it into the location associated with x so put x put beta here so if beta happens to be the address that malloc creates so malloc returns beta then what are the semantics here yeah so malloc is just a function call right and the return value is I gotta look I think it's like a void pointer technically but the return value is just an address right which is a value and so we say okay take that value and put it in the location associated with x so we put it in here right so now after I do this where does star x point to the location at beta exactly say again x is an address x well x is a name so what's in the location associated with x an address but it's just a value it's just a number that number just happens to be the return value of malloc that actually created some space so okay when we come back super cool examples like what does this do and then you're gonna be able to do all this in your sleep pointer ninjas