 Hey class, my name is Andrew Dudley. I am one of your undergraduate TAs and today I'll be going over the CSC340 final exam that I took last semester. This exam goes over regular expressions, first and follow sets, static and dynamic scoping, box circle diagrams, and Hindley-Millner type inference. There are two other problems at the end of this exam that will be covered by a different undergraduate TA and that's on pass-by-value reference and name as well as lambda calculus. Let's go ahead and get started. First we are given a set of regular expressions as well as a set of strings and we are asked if the string occurs inside of the language of that regular expression. So for the language of alpha we see that little a can be matched by letter star. And digit or capital letter can match the capital D and then we have letter star afterwards and unfortunately letter star will not match the next zero in the string so this string is not an element in this language. Next we look at the language of row. Row can accept zero or more digits so we know that can match 3300 followed by zero or more capital letters so if letter star matches the empty string then we see that row is in fact or that this string is in fact in the language of row. Next we have the same string but for the language of phi. Phi takes in a digit followed by another digit followed by zero or more lowercase letters. Well it'll match the first two digits 33 however letter star will not match the zeros that follow so this string is not in the language of phi and finally we have the language of omega and omega accepts zero or more capital letters so we know a will match to letter star then we need either a letter or zero or more digits so digit star will match the zero zero here however then we are at the end of the regular expression so it won't match this entire string indicating that this string is also not an element in the language of omega. Next we're asked to find the sequence of tokens that will be returned if we call get token on this string here. Now there's a quick way to do this for small examples like this but for the sake of this demonstration I'm going to show you the long way so you understand what happens at each step. So we're going to start out by making a table and in the first column I'm going to put the longest match that we've found so far and in the second column I'm going to put the potential regular expressions or languages and we know that when we start out all of these tokens could potentially be a match so I'm going to skip that row and just imagine that we have a row here that says all instead I'm going to start out by moving the cursor over to the first character in the string and now we're going to go through each one of these regular expressions and find out which one matches or could potentially match this string. We know lowercase letter will not match zero and capital letter will not match zero. However digit does match so we will put digit here with a length of one. Now we know that if any of these other regular expressions do match the string zero digits going to take precedence because it comes first so we'll only put them in potential and we'll only put them in potential if that's the end of the regular expression. So moving on we'll take a look at alpha we see that letter star can match the empty string then for digit or letter we can have this digit match zero and then capital letter star can also match the empty string indicating that alpha is a match and it's also a potential match because we know that if we were to get a capital letter later on alpha may still match the string so we're going to put alpha in this row. Next we'll take a look at row. Row takes zero or more digits followed by zero or more capital letters so digit star can match zero and then letter star can match the empty string indicating that row is also a potential match. Next up we have phi. Phi matches a digit followed by another digit followed by letter star so this first digit indicates that we could have a potential match with phi and finally we have omega which matches capital letter star followed by either a letter or zero or more digits so if letter star matches the empty string and we use digit star here to match the zero we see that omega is also a potential match and again several of these are also current matches for just the string zero but digit will take precedence over them because it comes earlier in the list however because these we weren't at the ends of these regular expressions or they use a clean star we know that as we go further down the string they may still in fact be longer matches so let's go ahead and copy our string down again zero zero a capital D a3d and we'll move the cursor over one so now we're looking at the string zero zero and instead of looking through all of the regular expressions we're just going to look at the ones that could be the tokens in the potential column so we'll take a look at alpha alpha matches zero or more letters followed by a single digit that we have here followed by zero or more capital letters unfortunately this will not match the second zero in our string so alpha is no longer a potential match then row can match zero or more digits so this can match both zeros followed by zero or more capital letters so this can match just the empty string and we see that row is now the longest match with a length of two moving on to phi we phi will match a digit followed by another digit so that'll match the first zero and then the second zero followed by zero or more letters so phi is still a potential match and then for omega we have zero or more letters followed by letter and then zero or more digits well if letter star matches the empty string then digit star here will match the two zeros and omega is still a potential match next we'll move the cursor over one now we're looking at the string zero zero a if we take a look at phi we see that phi will match a digit followed by another digit followed by zero or more lowercase letters which is in fact exactly what we have a digit another digit and then a lowercase letter so now phi is our longest match of length three and looking at omega if letter star matches the empty string then we can take digit star here to match the first two zeros however that will not match the lowercase a so omega is no longer a potential match next we'd want to run this one more time because omega here is actually still a potential match as well we haven't necessarily reached the end of the regular expression so we'll copy the string down we'll move the cursor over one and then when we look at phi we'll see that it matches digit digit followed by zero or more letters well that will not match this capital D that we have here and we no longer have anything left in our potential column so we'll move the cursor back one and we'll write down that phi was our longest match of length three make sure you don't forget to move the cursor back so now we are left with this string d a 3d and we'll start the process over moving the cursor over to the first letter we have capital D which lowercase letter will not match but capital letter matches so we have our longest match so far digit will not match alpha has zero or more lowercase letters followed by a digit or a letter so alpha is a potential match row matches zero or more digits followed by zero or more capital letters so if digit star matches the empty string then letter capital letters star will match the capital D for phi phi requires a digit followed by another digit followed by zero or more letters and unfortunately this first digit will not match the capital D so phi is not a potential match and omega starts out by matching zero or more capital letters so omega is a potential match next we'll move the cursor over one and we'll look at the regular expressions that we have in our potential list starting with alpha if letter star matches the empty string and then we take the or to mean this letter followed by zero or more capital letters we see that the lowercase a will not be matched by this string alpha so alpha is no longer a potential match next up we have row which matches zero or more digits followed by zero or more capital letters so row will not match either and finally we have omega which matches zero or more capital letters so this can match the capital D followed by a letter or zero or more digits so this letter will match the lowercase a and we are left with a new longest here with omega of length two and because we took letter here we are in fact at the end of the regular expression so we can stop here and we know that omega is the longest token that we can get so we will start over once more we'll copy the rest of our string down here as 3d and first looking at just the three we see that digit will match that so digit is our longest match of length one for alpha star or I'm sorry for alpha if letter star is the empty string then the digit three can be matched by this so alpha is a potential match and then we have row which matches zero or more digits at the start so row is a potential match and finally we have omega which is letter star followed by a letter or zero or more digits so if letter star matches the empty string and we take the digit star option then the three will be matched by digit star and therefore omega is also a potential match finally we'll move the cursor over again and now we'll take a look at alpha alpha matches the empty string with letter star it matches the three with digit and then it matches the capital D with capital letter star so we see that alpha is in fact a match of length two and because we're at the end of our string and we have a match we don't have to continue any further we know that alpha will match this token and for our final answer the sequence of tokens that is returned if we call get token on this string will be phi omega alpha moving on to the next problem we have first and follow sets so for this I'll show you guys the rules on the side here and as you know when we're calculating first sets we're going to want to create a table for every non-terminal and for each of those non-terminals we are going to initialize an empty set so we'll have the first of s equals the empty set etc now that we have the start of our table we will calculate the first set for each of our non-terminals and as stated on the side here in the rules we have initialized the first sets as empty so starting with s we'll see that in rule three we'll take the first symbol of our non-terminal s and we will add the first set of that symbol minus epsilon to the first of s so s has s goes to ac as the rule so we will add the first of a minus epsilon to the first of s and when we look for the first of a we aren't trying to calculate up here we're using our initialized sets down here so the first of a minus epsilon is currently just the empty set for our next rule for s we see s goes to bd so we will add the first of b minus epsilon to the first of s and the first of b is also currently the empty set and that's the last rule that we have for the non-terminal s so we'll close this off and move on to a so for the first rule of a we see that a goes to bbc so we will add the first of b to the first of a and the first of b is currently the empty set next we see the rule a goes to epsilon so using rule three we'll add the first of i'm sorry well we'll actually use rule two and say that the first of epsilon equals the set containing epsilon so we will add epsilon to the first of a and then for the first of b we see that in the first rule for b we have little bc and using rule one we see that the first of x equals the set containing x if x is a terminal so in this case little b is a terminal so we will add the set containing b to the first of b and then for the next rule of b we see that b goes to b and you'll notice this rule doesn't actually do anything it's a circular loop it doesn't add any characters to the string being generated so what we can actually do to help simplify this for us is simply scratch this rule out and that is the last rule that we have for the non-terminal b now i'm going to put an asterisk next to this and the reason for that is if we take a look at now the one rule that we have for b it starts out with a terminal so anytime we go through this rule we're going to hit this terminal we're going to add it to our set and then we're going to be done so b can never have any more characters added to the set for the first of b doing this will help prevent us from recalculating first sets that we've already completed next up we have the non-terminal c so we see that c goes to c little c so first we will use rule 3 and we will add the first of c minus epsilon to the first of c and the first of c is currently the empty set next we'll look at the second rule for c which says that c goes to epsilon so using i believe rule 3 and then rule 2 will end up with the first of epsilon is the set containing epsilon so we will add that to our first of c finally we have the non-terminal d so to calculate the first of d we'll look at its first rule we see that d goes to capital a so we will add the first of a minus epsilon to d and the first of a is currently the set containing epsilon so that minus epsilon is just the empty set and then if we take a look over here at rule 4 we'll see that if a rule contains epsilon then we'll move on to the next symbol in that rule and calculate that as well so now we'll take a look at the we'll add the first of little a minus epsilon to d and the first of little a as per rule 1 says that the first of little a is the set containing little a so we will add that here and then for our second rule for d here we see that d goes to little d so again using rule 1 we will add d to our first set now that we've gone through all of the first sets for the non-terminals we are going to continue this process and we will keep continuing this process until these first sets don't change through an entire iteration so starting again with the first of s we'll say that we'll add the first of a minus epsilon to the first of s the first of a is currently the set containing epsilon so that matches the empty set and using rule 4 because the first of a contained epsilon we'll move on to the next symbol and we that next symbol here is c so we'll add the first of c minus epsilon to the first of s the first of c is currently just the set containing epsilon so if we subtract epsilon from that set we are returned an empty set again once again we'll use rule 4 and because the first of c contained epsilon we'll move on to the next character however there is no next symbol so if we take a look down here at rule 5 it says that if all of the symbols following our current rule or if the first sets of all of those symbols contain the element epsilon then we will add epsilon to the first of our current non-terminal so we are currently looking at the non-terminal s so we will add epsilon to the first of s for the next rule of s we see that s goes to bd so if we're using rule 3 we will add the first of b minus epsilon to the first of s the first of b is the set containing b so we will add b to the first of s moving on to a we see a goes to bbc so using rule 3 we will add the first of b minus epsilon to the first of a the first of b is currently the set containing little b so we will add b to the first of a for the next rule of a we see that a of course goes to epsilon and using rule 2 we will add epsilon to the first of a b we see has an asterisk over it which means that this set is already complete and won't change again so we can simply copy this set containing b over now for the first of c we see that c goes to c little c so we'll add the first of c minus epsilon to the first of c the first of c is currently just the set containing epsilon so we will move on using rule 4 to the next symbol and using rule 1 we will add the first of little c to the first of c for the second rule for c we see again that c goes to epsilon so we will add epsilon to our first set now again you'll notice that c goes to c little c and this c can only possibly match either this epsilon or this terminal c here which means that we now know that just like with the first of b set here the first of c will no longer change we won't have any other characters added to this set so I will put an asterisk next to it moving on to the first of d we see that d goes to a so we will add the first of a minus epsilon to the first of d the first of a is the set containing b into epsilon so we will add b and using rule 4 because the first of a contains epsilon we'll move on to the next symbol and the next symbol is the terminal a so using rule 1 we will add that little a to our first of d and then we'll move on to the next rule for d which just says that d goes to little d and we will add that little d to our set now because the first sets of our non-terminals or at least one of them has changed from the first set of our previous iteration we will iterate through again so for s s goes to a we will add the first of a minus epsilon to s first of a is currently the set containing b epsilon so we will add b using rule 4 because the first of a contains epsilon we'll move on to the symbol c and we will add the first of c minus epsilon to the first of s the first of c is currently the set containing c and epsilon so we will add c and because the first of c contained epsilon we will use rule 4 and actually in this case rule 5 because c was the last symbol of that rule for s we know that both the a and the c contained the symbol epsilon so by rule 5 we will again add epsilon to the first of s next for a we see a goes to bbc so we add the first of b minus epsilon to a to the first of a the first of b is the set containing b then we'll move on to the second rule for a which is that a goes to epsilon and we will add epsilon again first of b we know is already complete and first of c we also know is already complete so moving on to the first of d we see d goes to a so we will add the first of a minus epsilon first of a is b epsilon so we will add b by rule 4 because the first of a contains epsilon we'll move on to the next symbol which is little a using rule 1 we will add the first of a to the first of d or i'm sorry the first of little a and for the second rule of d we see d goes to little d so we will add little d to our sets notice here that's the set for the first of s changed from our prior iteration to this one so we have to run the iteration again going to run through it quickly this time we see that s goes to big a so we will add the first of a minus epsilon to the first of s which is b because the first of a contains epsilon we will then add the first of c minus epsilon to the first of s first of c is c epsilon so we add c and because both a and c contained the first of both a and the first of c contained epsilon will add epsilon to s for the first of a we see that a goes to b so we will add the first of b minus epsilon the first of b is the set containing b and for the second rule of a we see a goes to epsilon so using rule 2 we will add epsilon to our set we know that the first of b is already complete and we know that the first of c is already complete and now for the first of d we see that d goes to a so we add the first of a minus epsilon which will give us b using rule 4 we move on to little a the first of little a is the set containing a little a so we add that and for the last rule of d we see d goes to little d using rule one we will add d to our set now you'll notice that our prior iteration and our current iteration didn't change the set or our current iteration didn't change the set from our prior iteration so we know that we are done and these are our first sets are you having fun yet i hope so because that's not the end of the problem now that we have our first sets we have to find the follow sets and the rule for follow sets is also here on the right side so once again we will initialize our follow sets as being empty now we know that the first set of a non-terminal is a set of all of the characters that can occur as the first symbol when we use that non-terminal similarly the follow sets for a non-terminal will be all the possible characters that could follow that non-terminal but the way that we calculate these is going to be a bit different from how we calculated the first sets first notice in our first rule over here that for follow sets we're going to take the non-terminal that is our starting symbol and we are going to add end of to the follow of that starting symbol right off the bat and i don't know if this is how you guys were taught it but when i took the course we represented end of with the dollar sign so i'm going to do the same here now when calculating follow sets instead of looking for the left hand side that contains the current symbol we're going to look for our current symbol on the right hand side of any of our rules so we'll notice that for s s doesn't occur on the right hand side anywhere however if it did even though it is our starting symbol we would still have to go through and use the rules from the rest of our steps because it doesn't occur on the right hand side we can simply close off our follow set and because it's not going to magically appear on the right hand side while we're calculating this i'll put an asterisk next to this indicating that the follow of s will not change now we'll move on to a and i should warn you guys that the rules for the follow sets are kind of inverted from the order that i would think they would intuitively be in so i might mix them up as i run through this but we'll go ahead and start so for the follow of a we're going to find all of the places that a occurs on the right hand side of a rule so we see a occurs in the first rule of s so following rule four here where in this case this b represents our a we are going to add the first of a one which in our case is c minus epsilon to the follow of our current symbol a so we are going to add the first of c minus epsilon to the follow of a let's take a look here we have our firsts calculated in amazing handwriting i know so the first of c is the set containing c epsilon so we will add that set minus epsilon to the follow of a similar to when calculating the first sets because the first of c contained epsilon we're going to use rule five here to say that we'll then add the first of the next symbol to the minus epsilon to the follow of a however c is the last symbol in the list and rule three says that if all of these if the first sets of all of the symbols following our current symbol contain epsilon then we are going to add the follow of the rule that we're looking at to the follow of our current symbol in our case because both because c contained epsilon we are going to add the follow of s to the follow of a and the follow of s is the end of symbol now remember that we have to do this for every instance that a occurs on the right hand side so we'll find another a down here in the first rule for d and using this a and rule four we are going to add the first of little a minus epsilon to the follow of a using rule one from the firsts rules the first of little a is little a and so we will add that to the follow of a and that is the last occurrence of a on the right hand side so we will move on to b we see that b occurs in the second rule of s here so using rule four we will add the first of d minus epsilon to the follow of b the first of d is b ad so we will add that to the follow of b and then we will move on to the next occurrence of b on the right hand side which is in the first rule of a using rule four we are going to add the first of b minus epsilon to the follow of b and we calculated the first of b to be the set containing little b so we will add a little b to the follow of b and it's already there so of course when we union two sets and they contain the same symbol that symbol just stays the same next we have another occurrence of b in the same rule here so for this one we will use rule four to add the first of c minus epsilon to the follow of b the first of c is c epsilon so we will add little c to the follow of b and for the b that we are looking at here we see that by rule let's see which rule is it here for rule three because every symbol that follows our current non-terminal b the first of that symbol contains epsilon we are going to add the follow of a to the follow of b and the follow of a is c dollar sign a so c and a are already in the set we will add the end of symbol for the follow of d we'll find the only occurrence of d here on the right hand side and we see that d is the last symbol in the rule and we have a specific follow set rule for this we see that if our symbol is the last symbol in the rule then we will add the follow of that rule to the follow of our current non-terminal again in our case that means that we are adding the follow of s to the follow of d and the follow of s and actually i'm sorry it looks like i skipped over one thing here something important i jumped down to d we need to go back and do this for c so let's do that really quick we see that c also occurs as the last symbol of rule a so using that rule two we will add the follow of a to the follow of c next we also see that c occurs as the last symbol of rule s so we will add the follow of s to the follow of c and we already have that dollar sign in there c is also the last symbol of rule b again with rule two we add the follow of b to the follow of c now you'll notice that every non-terminal symbol plus the dollar sign symbol that we have here every possible one that we could add to this set is already there so technically we can stop here but we'll just go ahead and look for the last occurrence of c in the rule of c we'll notice that it's here on the right hand side so we will add the first of little c minus epsilon to the follow of c and of course c is already in the follow of c so for rule d we've already said that rule d occurs in this rule for s and it's the last symbol so using rule two we will add the follow of s to the follow of d and that is the only place that d occurs on the right hand side so we know that we are done and because that rule that it occurs in is also already complete as noted by this asterisk here we can also technically put an asterisk next to this as well indicating that that set will not change going forward now at least one of our first sets has changed from the prior iteration so we will run through this again we know that the follow of s is already a complete set so we'll find a in this rule and we will add the follow of c minus epsilon or i'm sorry the first of c minus epsilon to the follow of a the first of c minus epsilon is c and because c was the last symbol and the first of c contained epsilon we will use our rule down here to add the follow of s to the follow of a a also occurs on the right hand side in this rule of d so we will add the first of little a minus epsilon to the follow of a and that will give us a for the follow of b we see that b occurs in this rule by s so we will add the first of d minus epsilon to the follow of b first of d is b a d and you'll notice here actually that because the first of b the follow of b already contains every possible symbol that no other symbols could all could possibly be added to this so instead of running through this for every occurrence of b we're just going to copy those symbols down and mark it with an asterisk if we were to continue this for the follow of b and locate all of the b's and go through our follow sets it should be apparent that nothing will change the same thing here for the follow of c the the set for the follow of c already contains every possible symbol that we can add to it so we are just going to copy that over and we've indicated that the follow of d is also complete so we will put that asterisk there notice that on this iteration none of our sets have changed from the prior iteration so we know that we are done and we are left with our final set now this isn't part of the problem but it's important to know one of the main reasons that we calculate first and follow sets is to determine what type of recursive descent parser we can use with them and you guys probably learned the predictive recursive descent parser and in order for a predictive recursive descent parser to work for a specific grammar it has to follow some rules and those rules are based on the first and follow sets of that grammar there were two rules one of which I believe is if you have a first set of some non-terminal contains epsilon so I guess we'll say if epsilon is an element in the first of one of your sets then the first of a intersected with the follow of a must equal the empty set and that means that for any of these occurrences here where our first set contains epsilon then the first of that set intersected with the first of its follow set they can't have any of the same symbols and we can actually see right away here that that isn't the case if we look at the first of c it contains c epsilon and the follow of c contains c dollar sign etc which means that the intersection of those two sets is going to equal the set containing c instead of the empty set so we know right away that this specific grammar will not work for a recursive descent parser or a predictive recursive descent parser there is one other rule which says that if you have a non-terminal that has more than one rule so say we have the non-terminal a and a goes to some alpha and a goes to some beta then the first of alpha intersected with the first of beta also must equal the empty set and both of these rules must hold for the grammar to work with a predictive recursive descent parser moving on to problem three we're looking at static and dynamic scoping so we're given this set of code in c syntax and we're asked what the output will be if we run it with static scoping and then what the output would be if we were running it with dynamic scoping now dynamic scoping is kind of an odd concept to a lot of us because it's not really used in many modern programming languages however static scoping you should be very familiar with and we'll do that one first so we of course starts in the main function we have i equals zero now notice that we aren't declaring i here we're simply setting our current i to zero and that means that this i is referring to the global i that we declared outside of the function so we now know that this i equals zero and then we call the function foo now in static scoping foo doesn't contain or a function doesn't look at the variables the local variables that were declared in the same scope in static scoping if you don't pass a local variable into that function then the function doesn't have access to that variable so here when foo says when foo says print i it's printing the global i that it has access to not a local i that we could have declared before it so it will print out zero from the global i and then we will leave that function and enter this block here we do declare a local int i and we set the value to 42 and then we enter another block and in this block we declare yet another int i and we set that value to two so everywhere inside of this block when we refer to the value of i we are referring to this two and then we call the function foo when we call that function and foo tries to print i because we didn't pass it this variable this local variable the i that it has access to is the one in the global scope so it will still print zero and then we'll leave that function we'll set i equals 100 which because we are inside of this local scope is referring to this i and it changes this value to 100 but that doesn't matter because then we instantly leave that scope and when we leave that scope we the value of i is now once again referring to this local i so we enter another block and we say i equals i plus 21 so here we are referring to this one and we will add 21 to 42 which will give us 63 and then we call foo again because we are still doing static scoping foo is going to again print out the global i which is zero and then it'll work and then it will return we then leave this block and we leave this block and we once again say i equals i plus 11 now even though we've had two local i's declared before this point they were declared within blocks and we have now left those blocks so this i is now once again referring to the global i so the global i now equals zero plus 11 which is 11 and we call foo once more and we see that foo now again prints out the global i which is 11 and that is the answer for the static scope now dynamic scoping is a little less straightforward but we will give it a shot again we start at the main function and we set the value of i to zero so the global i becomes zero and then we call foo and foo is going to print out the value of the global i which is zero we'll leave that function and we'll enter a local block here and we will declare i equal to int i equals 42 as a local variable we then enter another block and declare another local variable of i equal of int i equals two so notice now that because we're doing dynamic scoping we have three possible values of i depending on which block we're in so we have our global i which equals zero and then we have our i equals to 42 from this block then we enter another block and we declare another int i equal to two so on the stack over here we say i equals two and that refers to this block so when we call foo here foo instead of pulling from the global i well this global i actually now has a stack uh where at the bottom of the stack we have i equals zero but on the top of the stack we have i equals two so when foo prints i it's now referring to this two then we leave that function we say i equals 100 which changes this value to 100 and then we leave the scope we leave this block and when that happens we deallocate that memory and this i that we added to this stack gets popped off we then enter another stack and here we say that i equals i plus 21 note again it doesn't say int i we aren't declaring a new local variable here so the i that we are referring to is this one it was initialized as 42 so now we are going to say that 42 plus 21 equals 63 and that changes this value to 63 so we call foo again and when foo prints i it prints i from the top of the stack which is this one so foo prints out 63 and then our function returns and we leave this scope and then we leave this scope and we say and when we leave uh that last scope we are also popping this declaration of i off of the stack so we say i equals i plus 11 and when we do that the last the only value of i on the stack now is i equals zero it's the global i so now this becomes zero plus 11 equals 11 and we call foo and foo prints off the value of i on the top of the stack which is 11 and finally our program returns and that's it so we are left with the output using dynamic scoping next we'll move on to my favorite type of problem and also what i think is the most important problem to take out of this class which is using pointers and all for all of the ways that i was taught to learn pointers box circle diagrams to me were the best they made everything clear and to the point that you could solve complicated problems like this um simply by following a step of commands so for this problem we're going to end up having to find garbage memory locations uh or garbage memory at certain locations in the code as well as dangling references at those locations and lastly we'll say all of the memory locations that have been deallocated by location two so let's start before we reach the main function we declare a variable a here of type pointer to pointer to pointer to int at memory address alpha so using box circle diagrams we will write a and for that variable a we will give it a box the box represents space in memory and the memory location of that box the problem says is at alpha and for every box we will have a circle in it that represents the value stored there now if we have an empty box in this case it's going to represent uh a null value or or really just whatever value happens to be at that memory memory location at that time so entering the main function we declare another variable b of type pointer to pointer to int and that goes at memory location beta we then enter this block here represented by these curly braces and declare another variable c of type pointer to int which will go at memory location delta next we're going to set the value of c we do that by first calling malloc on size of int and what malloc is going to do is it's going to allocate memory on the heap and it says that this memory is at location one and malloc returns the value of the memory location that that uh memory address starts at or it returns the first memory address for that block so when we say c equals malloc here we're going to be setting the value of c to one which represents the memory location here next we allocate memory for b as well so we will create a new block here at memory address two and we are going to return that memory address and set it as the value of b directly after that we say that b equals ampersand c the ampersand represents the address so this say the value of b equals the address of c well we see that the address of c is delta so we are going to change the value of b to delta and then we set the value of a to a memory address by allocating memory so we will create another box circle diagram at memory location three and we are going to set a to the value of that memory location then we call free c now calling free c doesn't delete the value c it instead deallocates the memory that c that c points to so we see here that c points to the memory address one so we are going to go up and deallocate the memory at address one next we set the value of c to null so that i'll get rid of c there and we'll put null here and then we reach location one so problem one asks us to identify the memory locations that are garbage at location one and memory is garbage if it's not possible to reach that address in memory from any of your variables so the best way to visualize this is to go through each of your variables and show the boxes that they point to so we see that the value of a here is three so we know that this points here and the value of b is delta and delta and this b is also a pointer so we know that b points here the value of c is null so it doesn't point anywhere now all we have to do is find the boxes that haven't been deallocated that don't have any arrows pointing to them in this case that box will be the one here at memory address two so we will write in two then for problem three we're asked to find the dangling references at location one a dangling reference means that we have a pointer that points to a memory location that has been deallocated which means that we would have an arrow pointing to a box that was crossed out you'll notice that that doesn't occur anywhere in our problem so far so we'll say it's not applicable and then we'll move on just past location one and this is important to note we see a closing bracket here which means that we are leaving this scope and any variables declared within this local scope are deallocated automatically from memory in this case the one variable that we declared is int star c so we are going to cross that out and just to make things cleaner I'm going to remove these arrows for now so we've left that local scope and now we're entering a new scope and at this new scope we are declaring a new local variable of called x of type int star star so we will create a box circle diagram for x and it says that that is at memory location kappa next we have star a equals malloc so we have to determine what this star a means in this case or in really in any case where you see an asterisk it means to dereference that variable when you dereference a variable you go to the memory location that occurs at the value of that variable so here we're looking at the variable a which points to the memory address alpha so we're going to follow the value of a to the memory location of that value because the value of a is three we are going to go to memory location three and then it says that we allocate a new block of memory at memory address four so we'll create a new box circle diagram at address four and we are going to set the value at this dereferenced memory location at location three or i'm sorry we are going to set yeah we're going to set the value of this to the value that's returned by malloc and malloc is going to return the memory address four so we can see that a if we dereference a it points to memory address three and if we were to dereference this location or dereference a twice we would point here next we are going to set the value of x to the dereferenced value of a and dereferencing a will give us the value at the memory location pointed to by a so if we dereference a we go to memory location three and now we are setting x to the value at this memory location and the value is four so we will set x to four finally we set the dereferenced value of the dereferenced value of a to the address of a so in order to handle multiple asterisks you simply handle them one at a time going right to left i suppose so first we will dereference a which is going to take us to the memory location three and when we dereference that again it's going to take us to the memory location pointed out by that value which is four so now we're looking here and we are setting the value at this memory location to the address of a and we can see up here that the address of a is alpha so we will set the value at this memory location to alpha and that indicates that this pointer points here finally we leave the block that local scope and when we do that remember that any local variables declared in that block get deallocated so now this x variable is deallocated and we reach location two so problem two asks us to list the memory locations that are garbage at location two so we are looking for any boxes that we have here that do not have any arrows pointing to them and we can see that in fact we do not though here we see that b is a pointer and it contains the value delta so there should be an arrow from b pointing to that memory location but the only memory location here that hasn't been crossed out without any arrows is still two then for problem four we're asked to find the dangling references at location two so these will be boxes that have been crossed out that still have arrows pointing to them and we can see that the pointer b points to the memory location delta and the memory location delta has been deallocated so that is a hanging reference however the answer is not b as you might think because the value b has a value the value of b is delta rather it was when we deallocated b with the asterisk that brought us to the deallocate that brought us to the uh i'm sorry if we dereference b with the asterisk it brings us to the deallocated memory location delta so asterisk b is the dangling reference if you were to write b there here we already say that b equals delta right that's not how you draw delta delta and so this isn't a dangling reference delta is just some integer right some memory location for problem five we're asked for all the memory locations that have been deallocated at location two so that will be any box that we've drawn here that has a cross through it so we have delta and we have location one and we have location kappa and that's it for problem four finally we have the last problem that i'll be covering for you today which is very fun it's hindley millner type inference and while it is fun it does require a lot of writing so i'll try not to run out of room the first thing you want to do when you approach this problem is to number all of these instances uh i do it by using depth first traversal so we put one there two there three four five and those are now all magically numbered the second thing we want to do before we start is to write down all of the variables that we have here all the types including the function as well as all of the locations that we've numbered out here so we will have actually let's do this up top we have a b c d followed by one two etc now that we have those we're going to want to go through and write down the initial types for all of these locations and if we don't know the type then we're going to create a new one so we'll label a type one b type two it's an ugly two let's try that again a little better c is type three d is type four and then one here because it's uh this is a function declaration one here is a function and it's a function that takes in a b c and d which we know are of type t one t two t three and t four so we'll write those in and that function returns whatever the value of two is here so we could temporarily write two out as type four i'm sorry um as type five and then we would know that one this function returns type five t five okay now we are going to traverse this tree again i'm going to traverse it using uh depth first traversal uh in uh pre-order and i think that you can actually traverse it other ways but this is what i know works so we're going to do that and with pre-order we will start here at the plus sign at location two and if we have the plus operator it means that we have to add the left or the first input and the second input and they have to be of the same type for these examples they don't have to be numbers or integers as long as they're the same type the operator won't throw an error so we see that at location 15 we're given a string bar so we now know that location 15 is of type string and we can infer from that and the rule of the plus operator that both location three and location two must must be strings as well because as we said uh a the plus operator takes two values of the same type and returns a value of that same type so three is a string and two is a string now two already has a type it's of type t five so when we change t five to the type string we have to change all other instances of that type to be string as well so everywhere else that we see t five we will change it to string continuing our depth first traversal we are going to go to three and three is also a uh plus operator and we see that the plus operator is going to return a type string already which means that location four and location ten must also be of type string moving on down to four we see that location four has the array operator which means that it's going to return uh the type that we've already determined here which is a string and it's a if it's if it's an array operator then the left hand side is going to indicate the actual array of a certain type and the right hand side is going to indicate the index within that array that we're getting the value so if four returns something of type string then we know that five must be an array of type string which i'll mark here as a o s and because we know that arrays take in an integer value as their parameter we know that location six must be an integer so here we have location five which is d um and actually because of that here we've set up here that d is of type four so what we should have done is at all the location that's that d occurs we should have written in their type so here at five we had type four and now we've changed type four to be an array of strings so at all other locations where t four occurs we're going to change them to say array of string and let's actually go through and do that for all the other variables that this function takes in so in the places where a occurs like here at location seven we're going to write in the type of a which is t one b occurs at eight and thirteen and b is of type t two and c occurs at location nine and location eleven and c is of type t three so moving on we know here that at location six we are returning an integer right we've already marked that down here but we have to find out how we get that integer and we see the apply operator which means that we have a function as the first argument and all of the arguments that follow are all of the inputs that follow are the parameters of that function that means that at location seven we are going to change type t one to be a function that takes in whatever the type is at location eight and whatever the type is at location nine so it takes in t two and t three and it's going to return whatever the value is at the apply here so we see here that at location six it's an integer so this function returns an integer notice that we changed the type of t one to be the type being a function that takes in t two and t three and returns an int so at all of the places where we have type t one we need to replace it with that and instead of writing the whole thing out here I will scratch this out I guess we'll write it out this one the value is t two t three two int all right so now we have finished this branch we'll go back up here to the three and we will go down the right side we have an array operator and we know here from location ten that this array returns a string which means that the first input to the array or the first input to location ten is an array of type string so we change t three at location eleven to an array of strings and we know that the second argument for an array operator is an integer for the index so we know that location twelve is of type int and at eleven there because we changed t three to an array of strings we have to go through and change all other references to t three to be a reference to an array of strings next up we said that at location twelve we had an array operator so we know that the left hand side must be an array of whatever the type is at location twelve whatever twelve returns so thirteen location thirteen must be an array of integers so we will change type t two to be an array of int and we know that the second argument to the array operator must be an integer but in fact they've already written out just the contents constant zero here so we knew it was an integer already and because in thirteen we changed the type t two to an array of ints we now must go through and change all the references to t two to be of type array of int which means up here for a we have a function that takes in an array of ints and an array of strings and returns an int t two is an array of ints for location one i'll write this whole thing out now we said that it's a function that takes in t one and t one has changed to an array of a function that takes an array of ints array of strings and returns an integer so we'll write that in here the second argument for this function type was t two which is now an array of ints the third parameter is an array of strings and the fourth parameter is also an array of strings and that function type returns a value of type string and that's it so now we see that this function declaration is declaring a function that takes in another function that takes in an array of strings or an array of ints and an array of strings and returns an integer the function also takes in an array of integers and array of strings another array of strings and it returns a string so now we'll simply go down and fill in the blanks we saw that the type of a is an array of ints or a function that takes in an array of ints an array of strings and returns an int type b takes in an array of ints type c is an array of strings type d is also an array of strings and the type that f returns is a string and that is the end of the problem as i said at the start of the video there are two other problems on pass by type name and reference as well as on lambda calculus and that will be covered in a future video i hope that this helped and i wish you guys the best of luck on your finals