 Welcome to part 3 of the lectures on intermediate code generation. So, today we will continue to discuss the code generation strategies for various constructs. So, we briefly discussed short circuit evaluation of Boolean expressions in the last lecture. So, today let us consider in detail and see what difficulties it can actually give rise to. So, if there is an expression Boolean expression expression 1 and and expression 2 or expression 1 or expression 2, it is not necessary to evaluate the complete expression in all cases to know the value of the expression. For example, this is an AND operator if expression 1 is true then we must actually evaluate expression 2 in order to know the complete value of the expression. However, if expression 1 is false it is known that the entire value will be false it is not necessary to evaluate expression 2. So, similarly in this case if expression 1 is true it is not necessary to evaluate this complete expression at all it is necessary to evaluate expression 2 only if expression 1 is false. So, therefore, in the case of short circuit evaluation we try to evaluate only parts of the expression as necessary to infer the complete value you know the value of the complete expression. We do not really evaluate the entire expression in all cases and it is also possible to generate a control flow code for such short circuit evaluation as we will see very soon. And since such Boolean expressions are mostly used in conditional and loop statements we can always take advantage of the control flow representation of Boolean expressions. The advantage of this short circuit and control flow you know expression representation is that it is much faster than the normal evaluation. But the disadvantage is that if by chance the expression has some side effects for example, expression 2 has a function call or a print statement and this function call has alter some global variable. In such a case if expression 2 is never evaluated because the value of the entire expression was inferred using expression 1 then non deterministic behavior can arise. So, in some cases x 2 is not evaluated so the printing and other side effects should not take place. In some cases expression 2 will be evaluated and in these cases the printing will happen. So, such non deterministic behavior if it is not desirable then short circuit evaluation should not be performed. Here is a detailed example so we have an expression here and it is odd with another expression. So, in this case if the first expression is true we do not have to evaluate the second expression at all. So, the code here shows that so we do t 1 equal to a plus b t 2 equal to c plus d and if t 1 is less than t 2 we go directly to l 1 which is the code for a 1 that is the then part of the expression. So, we skip the evaluation of this entire expression but if t 1 less than t 2 is false then we have to go and evaluate the second expression so that is l 2 part. Again here we have and expression so if this is false we do not have to evaluate this part and if this is true we need to continue evaluation for this part as well. So, if e equal to f go to l 3 so that means we must evaluate h minus k otherwise we go to l 4 which is really the code for the l's part that is a 2 right here. So, this is how the short circuit evaluation and control for representation of Boolean expressions takes place. So, now let us understand how to generate such code so e going to even or e 2 so as usual we place a marker m here m really goes to epsilon and only remembers the quadruple number of the next quadruple to be generated. So, in this case it remembers the beginning of the code for e 2. So, if even is true then you know we do not have to evaluate e 2 at all. So, therefore, e dot true list which is very similar to the statement dot next in the case of statements. So, e dot true list becomes a merger of even dot true list and e 2 dot true list. So, there could be jumps out of this e 2 as well that is why we need to have two lists and merge them this is the exit part for the expression in case even is true. Then if even is false we must compulsorily evaluate e 2 therefore, it is logical to patch even dot false list to the beginning of e 2 which is m dot square and e dot false in this case will become e 2 dot false list because we come to e 2 only if even is really false. What about the AND operator very similar it is you know in some sense complementary to the R operator. So, if even is false the entire expression would be false. So, we have to take an exit. So, e dot false list is a merger of even dot false list and e 2 dot false list and if even is true we still continue and evaluate e 2. So, we back patch even dot true list to the beginning of e 2 which is nothing but m dot square and e dot true list would be obviously, e 2 dot true list because we come to e 2 only if even is true otherwise we do not even come to e 2. e going to not even we simply swap this true list becomes even dot false list and false list becomes even dot true list and we saw e m 2 epsilon already e going to even less than e 2. So, you must obviously, generate test here. So, generate even if even dot result less than e 2 dot result go to and then followed by a go to this is the false part and this is the true jump. So, that is why e dot true list takes on it this quadruple and e dot false list takes the next quadruple. So, these two lists contain these quadruples here e going to parenthize even parenthesis parenthesis expression. So, we just copy the list and nothing much happens and if e is the constant true just like numerics this is the Boolean constant true and this is the Boolean constant false. Then true list will take in itself this go to and in the case of false list e dot false list will take this particular go to statement. So, this is easy to see you know the use of this is very easy to see for example, you know if we have this if expression s 1. So, if e this is let us assume the constant true right. So, in that case e dot true list will be patched to next quad which is nothing but the beginning of the then statement and in this case e false e dot false list will be nil. So, nothing is patched here and similarly for e equal to false if this is false then you know we have to jump to the else part to the else part and that automatically is done later. So, let us go through this. So, s going to if x s 1 n else m s 2. So, if if x p is false if x dot false list is you know if the expression is false then it is patched to we need to jump to m dot pad which is the beginning of the else part. So, false list is patched to this and the exits from s would be the exits from s 1 and the exits from s 2 and also the jump here and the jump from n to epsilon generated during the reduction of n to epsilon. This we already saw if s going to if x s 1. So, the jumps out of s would be merger of s 1 dot next and if x dot false list these are the only ways to jump out of if then statement. So, now the while statement. So, here we must be you know we must observe in this case we must observe that for the r and and operators we really have not generated n any code. So, it is just that we direct the true list and false list appropriately. So, the actual code gets generated in a comparison all right and these quadruples will be patched appropriately in these productions. So, really speaking this is the comparison and go to are the only statements which we generated and that is why it is called as control flow representation or implementation of Boolean expressions. So, going to the while loop this is very similar to what we have seen already. So, while x do s 1. So, we need to jump we are here. So, we jump to the beginning of the while loop. So, we generate a go to to while x dot begin and all the jumps out of s 1 must go to while x dot begin. So, that is back patched here the only exit out of s would be when this expression is false. So, that is while x dot false list this is very simple. So, while x going to while m e. So, false list will become e dot false list that is the exit and true list will be patched to next quad which is nothing, but the beginning of s 1 because when the while when the expression is true we just fall through and execute the statement s 1 and while x dot begin would be the beginning of the expression m dot quad. So, m to epsilon of course, is the same as before. So, now let us proceed and look at the code generation mechanism for one of the most complicated programming language constructs the switch statement in C or a C like language. The syntax of the statement is switch and there is an expression. So, this expression must necessarily be producing integer types and then we have a list of values here l 1 l 2 1 l 2 2 etcetera etcetera and we also have a list of statements s l 1 s l 2 s l 3 etcetera. So, the way it goes if this expression is evaluated at run time and l 1 l 2 etcetera are all these l 2 1 etcetera are all constants either integer or character. So, if this expression is equal to this value at run time then the list of statements s l 1 is executed. If it is equal to l 2 1 or l 2 2 or any of these then s l 2 is executed etcetera and if none of them match then the default takes over and s l n will be executed. So, this code can be this switch statement can be compiled in many ways. One simple way would be an if then else like this you know an explicit if tests and so on and so forth. So, let us go through this and this is good for 10 to 15 cases. So, code for expression. So, the result is in temporary t. Now, we must why is this switch statement difficult for code generation. The problem is the expression is evaluated. So, code for generation code generation for expression is very simple straight forward. We really cannot generate a test for l 1 and then say let us go to s l 1 etcetera etcetera. We will have to generate the code for s l 1 s l 2 etcetera s l n minus 1 s l n and then you know make a test they you know. So, the reason for this is if all the tests are at the end after the statements are all generated code for statements is generated the compiler can possibly replace this entire set of if then statements by a more efficient implementation such as a table search or sometimes even you know maybe a hash table and things are with kind. So, after the code for expressions we have a go to. So, we directly go here and following that is the code for s l 1 s l 2 etcetera, but the control flow will bring us here. If we execute the test if t equal to l 1 then go to l 1. So, we execute the code for s l 1 if we wanted to execute only s l 1 and then jump to exit we should have had a break statement within s l 1 as a part of it. So, if there is no break statement in s l 1 automatically after s l 1 it will go to s l 2 and execute it this is known as fall through execution and the C language does not really prohibit this. So, a break statement must be compulsorily inserted here if we really want to get out of the switch statement after executing s l 1 the same is true for s l 2 etcetera up to s l n as well and after this we have the code for next which jumps to the exit. So, in the worst case if we start executing the code for s l 1 because t equal to l 1 is true and we have no breaks anywhere all these would be executed and then we go to the end of the switch. So, this is how the code generation must happen for the switch statement. So, let us see how it can be done. So, remember this order first the code for expression and then go to and then we have the code for s l 1 s l 2 etcetera, but in the meanwhile when we generate the code for s l 1 s l 2 etcetera we must remember the beginning addresses of these codes l 1 l 2 l n. So, that we can generate these if then statements at the end of this sequence of codes. So, if we do not know l 1 and if we have not remembered this then you know we will not be in a position to generate this statement at all. Our strategy would be generate the code for expression then as we as the parser scans this l 1 l 2 1 l 2 2 etcetera. It creates a list of these labels and along with it it also keeps track of the beginning of the corresponding statements. So, for l 1 it would keep the beginning of s l 1 as a pair and in the case of l 2 1 it will keep the beginning of s l 2 for l 2 2 again the beginning of s l 2 etcetera. And for the default it will remember separately the beginning of its block of statements s l n. So, this is our strategy for code generation. So, let us look at the grammar for the switch statement. So, here according to the C reference manual switch statement is one of the selection statements. So, selection statement can be switch followed by expression followed by statement. So, if this statement is not one of you know the case statements as we know then there is really no effect of the switch at all. So, there is nothing much you can do unless you have cases and the labels. So, that is why here is a more intuitive form of the switch statement which inherently has to be taken care of by any parser anyway. So, let us look at it statement is the switch statement I mean is a switch head followed by switch body. The switch head is the reserved word switch followed by the expression and E must be of the int type. The switch body has a pair of flower brackets followed by that is you know case list. So, the case list has a list of case statements and each case statement has a list of case labels followed by a statement list. The case labels can be empty or you know many case labels. So, each case label has the reserved word case followed by a constant integer expression. So, this must be either int or care type or it could be the reserved word default. One of the statements can be a break to ensure that the correct flow of statements happens. So, let us look at the productions and see how to generate code. So, switch head goes to switch followed by E. So, we have an attribute called switch head dot result and another attribute called switch head dot test. So, switch head dot result stores the address of the result of E. So, E dot result and switch head dot test stores the address of the next quadruple which is nothing but a go to statement. So, far if you observe our code template, we have generated the code for expression and we have generated a go to, but we still do not know the address test here. We will know that only at the end of the sequence of statements is you know at the end of the switch statement really speaking. So, that is why we need to retain it on switch head dot test and we will patch it at a later point. If the statement is a break statement, then it is like the exit of the statement. So, statement dot next would take this on and next statement generated would be a go to. So, nothing else is done really. So, we generate a go to here. The reason why it is so simple to take care of a break statement within a switch is that we do nothing but getting out of the switch statement. So, it can be put on statement dot next. We are going to see later that for loops the handling breaks is not so trivial it requires much more machinery. What is a case label? It has a case followed by an integer constant integer expression. So, we keep the value of the constant integer expression which is available in constant index to dot val, keep it in case label dot val and obviously, this is not a default case. So, default is set as false. If it is a default, then we say case label dot default equal to true. So, now we go on generating many case labels. So, if this goes to epsilon, then we simply set it at false and put a null list on case labels dot list. If we are generating many case labels well you know if case label dot default this one is not true. In other words this is not a default case, then case labels dot list is got by appending case labels dot 1 case labels 1 dot list followed by case label dot val. So, if it is default we have to maintain it separately that is why we are doing all this. So, if it is not a default then we add this case label value to this case labels dot list along with the other one case labels 1 dot list. So, this is the list of labels that we are maintaining. We still have not really placed the beginning of these statements I know paired them we have still not paired it with these values we will do that very soon. So, if case labels dot default or case labels 1 dot default or case label dot default is true, then there is a default among these. So, case label dot default is set to true. So, case statement goes to case labels m statement list. So, we have taken care of all the case labels here. Now we get the statement list and it is beginning is remembered in m dot quad. So, case statement dot next is statement list dot next. So, that is the exit out of the statement list case statement lot list is obtained by executing ad jump target to case labels dot list with m dot quad. So, what we are doing here is to take the address of the beginning of the statement list which is available in m dot quad attach it to all the values on this case labels dot list and make that the case s t dot you know list. So, now we have a list of labels and list of associated statement addresses as well. So, at the end of the switch statement we can generate the if then tests. So, if case labels this is a default statement then we set it as m dot if m dot quad because for this again we need to jump to the beginning of statement is otherwise we set it as minus 1. So, case list generates a list of case statements. So, this is nothing but transfer of all the attributes here there is nothing more to it than that. So, this is now for so far we have generated this expression you have generated this test go to and then we have generated all the code for s l 1 s l 2 s l n. We have in we remembered the beginnings of these codes and we have also remembered the values l 1 l 2 1 l 2 2 l n minus 1 paired it with l 1 l 2 l n. So far this is the work done. So, now again we have a transfer of attributes case list goes to case list 1 case list case statement. So, we merge the two next and put it on this merge the two lists and put it on case list and default is set appropriately depending on whether this is the default or this is the default. So, now the switch body is nothing but case list. So, we have generated code for all this. So, we must generate code for go to next and then the these tests this is what remains. So, switch body is completed. So, we generate a go to here switch body dot next would be merger of case list dot next and then the next quad which is nothing but the go to here and for the other two it is just a transfer of attributes. What remains is the generation of the if then statements at the end of the switch. So, now we come to statement going to switch head switch body. So, we have all the lists with switch you know the expression etcetera is all here. So, switch head dot result contains the you know address of the temporary which maintains the result and in switch body we have the entire list of values and pairs. So, back patch switch head dot test to next quad. So, this is the test go to we had generated at the end of switch head. So, that must that go to next quad which is nothing but the beginning of the series of tests. Now, we iterate through the switch body dot list. So, for each value jump pair in switch body dot list v comma j equal to you know the next value comma jump pair from switch body dot list. So, we take the next value pair value jump pair assign it to v comma j. Now, generate if switch head dot result equal to v go to j. So, for each value jump pair we generate this. So, automatically we would have generated something like this. So, all these tests would have been generated at the end if there is a if there was a default you know within the list then we generate go to switch body dot default. If there is not any we simply add the switch statement dot next equal to you know we do not generate any of this and simply says a statement dot next equal to switch body dot next nothing else is done. So, the list of tests and the last you know default are both taken care of in this set of in this particular production. So, that completes the switch statement. Now, the next very important statement is the for loop in C. The for loop in C is a very general for loop. So, here is a the for then we have 3 expressions expression 1 expression 2 and expression 3 followed by a statement. So, here the all or any one or all of the 3 expressions can be missing the manual says. So, you know so you could simply have for semicolon semicolon statement. So, in that case the statement keeps running forever. Otherwise the this for statement is equivalent to these 2 together expression 1 is the initialization. So, it is executed first and then the expression 2 part is the test part. So, there is a while loop expression 2 then we execute the statement followed by expression 3 which corresponds to the increment in general. So, statement followed by expression 3. So, this while loop is repeatedly executed until expression 2 becomes 0. So, the code generation becomes a bit difficult why if you look at this equivalence we have expression 2 expression 1 no problem we can generate the code for that followed by that is the expression 2 we can generate the code for expression 2 also no problem at all. But then we have statement and then expression 3. So, whereas in the source we have expression 3 followed by statement. So, because of this the code generation becomes little more difficult we need to introduce extra jump statements. And all this happens because we want to generate code in one pass during L R parsing. Suppose we did not have to do that we had the parse tree already and this intermediate code was being generated by a a walk over the parse tree. Then you know we would have had the for statement to node having expression 1 expression 2 expression 3 and expression 4 as children. So, we could have visited them in the order expression 1 expression 2 statement and then expression 3 and generated code appropriately, but in one pass bottom up parsing we really cannot do that. So, here is the code template for the c for loop for even semicolon e 2 semicolon e 3 s. So, code for even and then the code for e 2 let us say the result is in the temporary t. And then we need to have a go to go to l 4 why we need to actually generate a test if t equal to 0 then something that is where the go to takes you. Then we have the code for e 3 right. So, but when you actually and then we have the go to for l 1 code for s and then the go to l 2 then the test go to l 3 and exit. So, let us look at the flow of control. So, this is executed first this is executed next then we go to l 4 execute the test if t equal to 0 go to l 5 l 5 would be the exit part. Otherwise we go to l 3 that means we execute the code for s then go to l 2 that means we execute the code for e 3 and then go to l 1 which is the beginning of code for e 2. So, because of the order in which we need to generate code and the order that we need to generate code is exactly the order in which the source code appears. We interspers the code with go to statements in order to get the appropriate flow of control. So, here is our production statement going to for even semicolon m e 2 semicolon n e 3 followed by p s t m t 1. We have a couple of markers m n and p. So, as usual m does not generate code it simply remembers the beginning of the expression e 2. Obviously, that is necessary because we need to jump to the beginning of e 2 and evaluate it after the entire statement sequences executed. So, n generates a go to and p also generates a go to let us see how what kind of code is generated. So, in bottom up parsing we would have parsed this entire thing and generated code for even e 2 e 3 then m n p and statement 1 and we have we will be here just before reduction we need to execute this action. So, what does that action do? So, we have executed statement 1 now it generate there is a code go to n dot quad plus 1. So, n dot quad is the you know go to statement here. So, plus 1 would be the beginning of e 3 so that is correct right. So, we have you know we go to so this after the statement 1 is completed we are here right code for s is over. So, we go to the beginning of e 3 so right go to l 2 that is the beginning of e 3 that is where we are going. So, n dot quad plus 1 is the beginning of e 3 that is where we jump. Next q 1 remembers this quadruple so what is this quadruple? We have a test if e 2 dot result equal to 0 go to something. So, automatically we would have jump to this place and we will see from where we jump to just assume that q 1 remembers this go to statement and that is also according to what we wanted. So, here is this go to that we generated just now and here is the comparison that we have generated. Now, we need to generate another go to so now go to p dot quad plus 1. So, if e dot result is not equal to 0 then we go to p dot quad plus 1 p dot quad is nothing but this go to statement and the beginning of statement 1 is p dot quad plus 1. So, if the result is greater than or 0 or less than 0 whatever what it is definitely not equal to 0 then we jump to the beginning of the statement that is what we wanted here. So, go to l 3 so beginning of core for s. So, far we have justified the generation of these 3 codes, but we have still not filled up this. Now, we back patch n dot quad with q 1. So, what is n dot quad? n dot quad is this go to statement and so that would be filled with q 1. So, we have evaluated e 2 now this go to takes you to the beginning of q 1 is nothing but this quad. So, this n the go to in n takes you here so which is correct again. So, we can see that after this e 2 we have jump to l 4 which is nothing but the test for t. Then we back patch statement 1 dot next with n dot quad plus 1. So, statement 1 dot next is all the jumps out all the jumps out of statement 1. So, that is patch to the beginning of e 3 n dot quad plus 1 is the beginning of e 3. So, we must execute e 3. So, this jump this back patch is also correct. Then we have back patch p dot quad and m dot quad. So, p dot quad is this go to which is generated here and that is to the beginning of e 2 again. So, at the end of e 3 we have go to to l 1 so the code for e 2 is executed all over again. So, then of course, statement dot next is nothing but the jump out of this when e dot result equal to 0. So, let us make list q So, this is the justification for this code generation for the for loop in c. So, there are other varieties of for loop in other programming languages. So, let us take one variant which is very popular this is the algal for loop this is also available in part of it partially it is available in Pascal as well. So, let us also look at this now that the syntax is statement going to for i d equal to expression 1 to expression 2 by expression 3 do statement 1. So, expression 1 2 and 3 are all arithmetic statements. So, what we really do is this we assume that this is the beginning value of i d this is the name i d this is the ending value of the name and this is the increment. So, we start with this value run the loop and every time we check whether we have reached expression 2 and we increment or decrement based on the value of x 3 and then execute the statement 1 if necessary. So, x 3 can have either positive or negative value. So, if the value of x 3 is positive then you know the expression will be lower than expression 2 usually we rise from expression 1 to expression 2 in a monotonically increasing order and if expression 3 has a negative value then usually expression 1 is higher and expression 2 is lower. So, we go down from expression 1 to expression 2 in monotonically decreasing order and then enduring this course we execute this statement. Another important thing is expression 1 2 and 3 are all evaluated only once whereas, in the case of C loop the expression 2 and expression 3 were evaluated every time in every iteration of the loop. So, this does not happen in the all go loop they are executed only once and the values are stored. Finally, all the three expressions are mandatory it is not that you can skip any one or more of them. So, what is the code template? So, you have a for i d equal to expression 1 to expression 2 by expression 3 do statement 1. So, we have the code for expression 1 result in T 2 code for expression 3 result in T 3. So, that is in the same order no problem at all in that now we have the statement 1. So, before that we have a jump. So, and then we have the code for statement 1 then the increment i d equal to i d plus T 3 and then finally, go to L 2 which checks whether the value of T 3 is less than or equal to 0. So, or it is greater than 0. So, the reason is T 3 could be positive or negative and based on that value the termination condition will also be different. So, let us then there are two tests one for a positive increment and other for the negative increment and finally, we go back to go to L 0 execute the statement and repeat. So, let us look at the flow of control here first of all the control executes and evaluates all the three expressions. Then we go to L 1 this is an initialization for the name i d then we check whether the increment is negative. So, if so we go to L 3 if the increment is negative then we check whether i d is less than T 2 that means, if it is less than then we need to jump out of the loop we have finished the loop. Otherwise, go to L 0 code for statement 1 is executed then the increment is added and we go back to the test again. Similarly, if the increment was positive we check whether i d greater than T 2 and jump out if it is greater otherwise we go back to L 0 execute the statement 1 etcetera. So, how does the code get generated in syntax redacted translation. So, we have statement then for i d equal to expression 1 to expression 2 by expression 3 we do not need markers among these simply because there is no need to jump to the beginning or end of any of these expressions they are evaluated only once. But, we definitely require a marker to remember the beginning of the statement and also to generate go to at the end of expression 3. So, remember there is a go to at the end of expression 3. So, m remembers the quadruple which is nothing but a go to here. Now, the name i d is searched for in the symbol table and we generate the increment. So, we are here we have finished statement code generation for statement 1 also. Now, we generate the increment statement and also a jump. So, we generate the increment statement then we remember this q 1 which is the next quad generate a jump here. Then since we had generated a go to here in the marker m and now we know where to patch that. So, for example, here this is the go to generated by the marker and that is to go to the initialization statement i d equal to t 1. So far we have generated all these codes we are yet to generate this. So, we generate i d p t r equal to expression 1 dot result and this is the quad to which m dot quad was backpatched. So, the go to has been now patched that go to has been patched properly. Next we patch backpatch q 1 with next quad and remember next q 2 as next quad as well. So, what is the next quadruple this is the test if expression 3 dot result less than or equal to 0 go to. So, for example, we have generated this. So, we are generating t 3 less than or equal to 0 go to. So, that is what we are generating and we have patched q 1 which is nothing, but this go to to come here. So, remember after the increment statement the go to supposed to go to the test. So, that is what we had done here. So, increment and then go to l 2 that is the test part. Now, if it is not less than or equal to 0 then it means it is a positive increment. So, we check whether i d p t r greater than expression dot result go to and then this is yet to this is the exit part this will go on to the statement dot next. So, you can see that. So, q 2 this is q 2 this is q 2 plus 1. So, we have put q 2 plus 1 also on statement dot next then after this if the exit is not going to take this we generate a go to to the beginning of m you know the statement which is nothing, but m dot quad plus 1. So, m dot quad is this. So, m dot quad plus 1 is statement 1. So, we generate that go to here and we back patch q 2 which is nothing, but again this quadruple right and with the next quad. So, next quad is again the check whether the i d p t r x has gone beyond its limit in the case of the negative increment. So, that is what we have done here you know. So, we back patch that into this and finally, generate a go to to the beginning of the statement if we have not cross the limit. So, statement dot next contains q 2 plus 1 then q 3 which is this this is also an exit this is one exit this is the other exit statement 1 dot next would be the third possible exit. So, all these 3 exits are put on statement dot next. So, this is the code generation strategy for the algal for loop it is also possible to generate code for the algal for loop in a slightly different way, but this requires a little extra work. So, for example, generation of code for expression 1 expression 2 and expression 3 straight forward. So, that will not even worry about now we try to do the initialization of i d straight away here before we check whether the t 3 is less than equal to 0 or greater than equal to 0. Now, we check whether it is less than 0 or if go to l 2 if it is greater than t 2 then go to l 4 etcetera. So, the order in which we have generated this code slightly different from the order in which we have generated code for the other one. So, this would be left as an exercise for students to do. So, the hint is we may have to break the production appropriately and insert more markers in order to generate this code properly. So, now it is also time to look at you know important aspects of checking the range overflow in arrays. So, let us look at an example. So, here is int b 10 20. So, 2 dimensional array and here is an assignment a equal to b of x 1 x 2. What we want to do is make sure that expression 1 is always less than 10 remember c arrays run from 0 to 9 and this part runs from 0 to 19. So, we want to make sure that x 1 is less than 10 strictly and x 2 is less than 20 strictly. If it is not we want to issue errors. So, the code generation generated code template would be something like this code for expression 1 resultant even no problem. Now, before generating the code for expression 2 we check whether t 1 is less than 10 if. So, go to l 1. So, this is normal course of action. If t 1 is equal to 10 or greater than 10 an error message error array overflow in dimension 1 is issued. T 1 is reset to the maximum value of dimension 1 which is 9 0 to 9 is the array index range. So, we set it to 9 something very similar happens for expression 2 code for expression 2 result in t 2. If t 2 is less than 20 it is normal course of action otherwise we issue the error array overflow in dimension 2 set maximum value of t 2 as 19 that is the maximum for the dimension 2 part and then we proceed. So, since we have set it to 9 and 19 there are no more errors, but the results that we obtain by the computation may be wrong, but at least the program will try to execute to completion even though it may not produce the right value. So, t 3 is equal to t 1 another option possible here is to just exit the program, but if we had exited here we would not have caught this error that is the reason why we have set it to maximum and then try to continue. So, then the it is normal code t 3 equal to t 1 star 20 and then t 4 equal to t 3 plus t 2 and. So, we multiplied by the number of elements in the second dimension then add the second dimension value the subscript value that is t 2 then multiplied by the element size. So, t 4 into int size finally, a equal to t 6 of t 5. So, this is the code that is generated. So, here is the you know syntax directed translation for it. So, these two are the same as before they have been reproduced here to just to set the context properly s going to l colon equal to e. So, this is the assignment. So, if l dot offset is null we generate simple id. So, it is a simple id. So, we generate l dot plus equal to e dot result otherwise we set generate an indexed assignment. So, the right hand side could be an array again. So, again we check whether it is an array or simple id if it is an array then we generate an indexed assignment once more. So, this is necessary as I already mentioned both left and right sides cannot be array assignments at the array expressions at the same time. Now, this part e list going to id bracket e. So, we search for the name id dot name and get its pointer then that pointer is transferred to e list dot array pointer the result of e is stored in e list dot result. The dimension number is set to 1 because this is the first expression in the subscript list we get the number of elements from the for the dimension 1 using this array pointer. Now, we generate the required quadruples if e dot result less than num go to q 1 plus 3. So, this is q 1 this is q 1 plus 1 this is q 1 plus 2 following that is the normal course of action. So, that is q 1 plus 3 otherwise generate the error and then set it to num element minus 1. So, this is the maximum for the dimension 1 the same thing happens for other dimensions as well. So, here is the list of subscripts that is being processed. So, e list going to e list 1 comma e. So, the same thing happens here we get the number of elements in the appropriate dimension e list 1 dot 1 generate the three codes check whether it is this then num element if. So, jump to the third expression otherwise generate an error message and set the maximum to num element minus 1 at the end of it we do the normal processing temp 1 is equal to e list 1 dot result star num element. So, that is the number of elements in this dimension e add the e dot result to it. So, now we are ready to go to the next level. So, this is how we process the expressions. So, now this is the ending production e list bracket. So, here we just multiplied by the element size and that is finally, the offset that we have generated for e list. So, we will stop the lecture here and continue with break and continuous statements in the next part of the lecture. Thank you.