 So, if you recall from the previous class and the discussion towards end of the previous class, we started looking at how do we, now we type back in in the presence of the explicit type casting. Explicit type casting will be more of an issue at the time of 4th generation, but the implicit has to be done in 5th generation. So, we have got some kind of code where we have an expression of this form and type of x in i added. Now, the two issues here, one that I need to change the representation of. So, what I need to change the representation of y, because finally I want type expression to have some kind of type which is consistent for both these variables and for the expression I want is that I should be able to find out what is the type expression which is associated with this. So, it becomes very clear at least from whatever we know of programming languages that when I try to mix types of 20 points and integers, both will be converted into 20 points. So, that means basically internally you look at type what will happen is something like this. This kind of conversion will implicitly happen and once this conversion happens then I know that this type is floating point, this type is floating point and therefore type expression that is associated with both type expression which is of x plus i becomes floating point and this is the information I need to carry because finally if I say that I am going to say do an assignment of this form. So, before I do an assignment I should be able to find out what is type of x plus i and what is type of i d and whether this is consistent assignment or not. Remember that we had a rule like this when we said s is i d being assigned an expression and there I wrote the rule saying if i d type is e type then expression is valid otherwise it is a type. So, with this background let us look at what kind of would be that of generating and what are the things we need to worry about. So, if we take an expression like x plus i where x is of type real and i is of type real then I need to internally change the presentation of i making sure that it is compatible with real and because the operations which are going to be on the machines are really different and compiler has to convert both the same type. So, this operand is now being converted to this particular type and who defines it obviously the language is telling us that what kind of convergence are possible and what kind of convergence are not possible. So, type conversion normally the inversion when I have a situation like this conversion usually happens from this type to this type but there is a small category and that is that if I am trying to do this conversion which is possible that in certain conversions I am going to lose information. So, for example if this is of type in and this is of type real or float then I know that it is going to lead to truncation which is equivalent to loss of information I do not want that. So, implicit type conversion also puts a rider saying that I will not do a conversion if there is loss of information. So, usually it is going to be to the left hand side provided there is no loss of information. Now, is it possible that I still want to typecast the rear into integer but in that case I will say that compiler will not do it let the programmer decide whether they really want to lose information. So, you may have functions like round you may have ceiling flow and so on right. So, those kind those are kind of explicit functions and where I will not let the compiler do any conversion but I will let the user do the conversion. So, type checker is used to insert conversion operations like what I have inserted here. So, when I say x plus i what it is converted into is x and plus then becomes real plus and i becomes into real. And type conversion is also called implicit or coercion this is going to be done by compiler like in this case and this is only one of the two situations where is there is no loss of information. So, this point is very important that compiler does not want to take sort of responsibility for what programmer may have in mind. So, compiler will say I will only do conversion if it is only a matter of changing the representation and no change of information. If you want to explicitly change certain information do an explicit type casting but do not depend upon the compiler for doing that. So, conversions are explicit if programmer has to write something to cause a conversion. So, for example if this conversion has to be done then we are leaving it to the programmer and that is going to be now an explicit conversion. Implicit conversion will happen only when it is a matter of change of representation and no loss of information. Is this point clear? This is a general principle which is followed. So, now let us get deeper into the code. So, suppose I am just worried about this kind of expressions. So, if I now have to capture basically now I have both integer and real types and id type I know will be available in the symbol table. So, for this I know that e type is int and for this e type is real and for this e type is nothing but just saying that look for the table and whatever is the type. Interesting thing that happens is here and for the time being let us assume that I only have tight mixing between integers and real. Of course, you can expand it to whatever is defined by the language but assuming that at this point of time language only permits mixing of integer and real type and if I know even type and e to type I want to find out what is the type expression for e. So, how will I do that? What kind of code I will end up writing? So, earlier when I wrote this and we were not worried about type conversion what is the kind of code I wrote? Do we have a time when you guys can come to the class? I mean just look at the what is the time now? I mean this is a 15 minute class of which 10 minutes are gone which is 20 percent I mean why do you have to come? Is it necessary to come to the class? If you cannot come on time then why do you come to the class at all? You just need to schedule your activities. What activity did you have in gone? Did you have a class before this? Then why can you get a 10 minutes earlier plan to come here 10 minutes earlier? So, what kind of code I will now write for this? So, earlier when I just had no type mixing allowed then what was the code I wrote? So, there was no type conversion allowed then we said if both are of type integer then it was it and if both were of type float then it was float. But now with implicit type conversion what will happen is I will permit mixing of types of intent float and how many combinations are possible? So, both can be in both can be real first and second can be these are the four possibilities I have. So, now I will say that if both are in then this type is going to be in. Now I can write a very short notation that assuming that only types which are possible of e 1 and e 2 are either integer or real. So, I just need to write else real but I am not going to do that and what I will do is rather than just saying else real I will now say let me enumerate all possibilities and it will become evident why I am enumerating all possibilities. So, now I will say that if the first is in the second is real then this becomes real and if first is real and the second is in I think these colors are not very I will change it sorry about this this is finding that on display is not coming out very clearly and then it is real and if both are real then this is real. Now you can see that in these three cases because outcome is real I could have just eliminated this and could have put else real and that would have worked right ok. Now why I am doing this why I am enumerating everything here any reason for particular reason does it give me any additional information no. So, let us just come in look at this ok I mean even if it is not primitive how does it matter I am not even worried about that I am standing always my input from left to right. So, at some point of time I am going to integrate my code generator with the type check ok and when I integrate my code generator with the type check then at this point I will say that the first operand needs to be converted into real and therefore I will insert a small piece of code here saying that convert whatever this variable is into a real number and here I will have to insert the code. So, really what will happen is that no type conversion here but type isn't no type conversion here but type is real and in this cases all the type changes are this or this will have to be implicitly coerced. And therefore I will have to insert code for saying that insert this function which says into real either for the first operand or the second operand and therefore I want to integrate all the code options because as I said at some point of time this will get expanded and the code generator will become part of it. Otherwise if I am just doing type checking then I don't need to do anything else then I did not need to do anything else. So, this is not giving me any additional information. Now next issue we need to deal with is overloading of functions. Now what is overloading of functions? So, let me go back and let me look at this. Can you notice here that I started with x plus i but then when I was doing type checking I said this plus is a real plus. Now it is possible that if I am just saying i plus j where both i and j happen to be integers then my code or type checker will say this is i integer plus j. So, it is the same plus operator in one case this is a real plus in another case this is an integer. So, what I have done is I have overloaded this particular function and depending upon the context I am going to find out which is the real operator. This operator which is integer addition and real addition they may map on to different outputs. So, I need to at time of type checking I need to find out what real operator is but actually situation is far worse than this. So, there are some operators which by definition by mathematical definitions they can take multiplication. I can multiply two integers I can multiply combination of integers and floating point numbers I can multiply two floating point numbers and outputs are going to be different so my type checker needs to tell you. So, those are by nature but what happens when I overload the function that is permissible in certain languages. So, let us take a situation where I say that I am not only an operator it is possible but overloading of functions is possible and the language is like data which will permit you to overload functions you can take a standard function. So, I can take a standard function like plus and overload it with something else I can define a function plus and have a different operator for this in addition to the built-in operation and the question that will now come is that if I now write an expression like this what is the definition of the function I associate with this how do I figure that out how will I figure that out . . . . . So, I can have a function like this I can have let us say I can overload so let us take this function now normal prototype of this function is let us say there is a normal prototype but I can also have let us say I can overload this and say that now if I give two integers should I use this function or this function. So, left hand side I do not know but let us say it depends on the context the left hand side is actually restricting the context. So, what we want to do here is we want to see that if I have overloaded functions how do I know what is the kind of method I have which is going to help me resolve these overloaded functions. So, suppose I have overloaded this function so let us now look at a situation that I have overloaded a function in let us say A dot which is function star and these are the two prototypes which are available I like more prototypes for this and now I want to find out that which is the so what it is doing is that suppose I take two integers here it is going to return a complex number to me of the form A plus I B or this is just going to give me a multiplication of A B. Now in this case clearly outcome is integer in this case clearly outcome is a complex number now I need to look at the context so suppose I say that I have so let us look at a situation like this that I have let us say 2 and 3 and I apply this function here question I want to ask you what will be the type of 2 star 3 now just by looking at this sub expression I will not be able to find out what is the type of 2 star 3. So, suppose now I say that I put it in a context which where I say that 2 star 3 multiplied by let us say 5 and 5 also happens to be integer then I clearly know that what will be the definition of this particular function which prototype will apply this one right because you know that there is no operation which is defined on integer complex and integer that is invariant but suppose I have something like this where that happens to be a complex number then which prototype will I apply then obviously because again there is no operation which is defined on integer and complex and for this to be valid this must be complex so I may have to have add another prototype so let us go through this example first and then see how we will resolve these issues so overloaded symbols they have different meanings depending upon the context and the context is the one so it is not just the left hand side so therefore I use a general term that it is the context which determines and if addition is overloaded this is used for integer real complex matrices in fact yeah this is another interesting thing so there are languages where you may have data types like matrices if you take language like ATL where data type would be integer, protein point number, a vector, a matrix and if I want to do multiplication of two matrices all I need to say is a multiplied by b I do not have to write unless I do if I want to take two vectors and I want to do addition of two vectors I do not have to write a loop saying do an element by element addition all I need to do is say add vector a and b and the semantics of this operator is defined right there okay so ADAP now permits overloading which is used for arrays functions called type conversion and so on okay so if you look at brackets here so brackets are overloaded they can be used in many of these contexts but overloading is resolved when you find them there is a unique mean okay now what you have to understand here is and this last point is very important that to begin with when I just look at this okay I do not know what is the function which is being applied here but then I start looking into context okay and when I start looking at context I try to resolve it okay I keep on resolving till I find that there is a unique meaning which is associated with this now if at any point of time I come to a conclusion that there is no unique meaning associated I say this is an error because such a program should not be written because if it cannot be interpreted then we have a problem right so if we cannot interpret it obviously compile a camera but if I find a unique meaning then I associate that meaning with it and that is the function that we are going to get okay so let us look at a situation where we say that in Ada the standard interpretation of star is multiplication but it can be overloaded by having multiple types multiple arguments and return types so I can now have this and this is the kind of syntax it says that function star takes two integers and returns a complex and it can also take two complex numbers and return a complex number two so basically this is saying that I can take two integers and return a complex number which is of this form a plus i b or I can take two complex numbers and do multiplication a complex number now if that happens then the possible type expressions or the prototypes for star are these I can take integer cross integers it gives me integer I can take integer cross integer which gives me complex and I take complex cross complex and now if I so overloading suppose I say two three and five these are integers and Z is a complex variable then what will happen three star five is either integer or complex depending upon the context I have to determine the context there so if I say my context is like saying two star three star five then what is the context here context is that I am taking an integer here and therefore since I don't have a prototype it will say that integer cross integer multiplied by complex such a prototype is just not there then I say that this is only going to be an integer but if I have something like this then I know that this has to be complex but because again complex and integer multiplication are not allowed at least I don't have a complex problem now issue that comes is how do I do that in terms of writing the code so let me go back and remind you what is the code we had for function resolution and then we will try to modify that so I wrote something of this form where I said e1 e2 remember this is the kind of syntax we had and what is the code I wrote for this for type checking I wanted to find out e type and what was e type here remember the code for this so we said that if e1 is equal to a mapping from s to t and e2 type is s then t else this is what we have now what may happen here is that when I start applying see so I don't distinguish between function and operator I mean it is just a matter basically semantically what is happening exactly the same now what may happen here is that when I say e type e type if I say that I am taking the first function which is 3 star 5 then what could be e type what would be e type here well it be this type error or it will be t and if it is t then what will be value of t so I just look at only this so let's just take 2 star 3 here or just take 3 star 5 I am applying the function here so what will be type of 3 star 5 just go by this rule so what are the changes I made here do I need to make any change or I will just use it in the same manner so only change I need to make here is rather than saying t it will be a set all I am saying is that e1 type remember that I know e2 type e2 type in both cases is int but even type will say that int cross int matches to int and int cross int also maps on to complex so all I need to say here is this t instead of a single value will be now a set that's the only change that will happen really nothing else will change so this is the kind of thing we will do and now once we start doing this at some point of time I need to have a unique value so remember that this will occur now in certain context so when I started by saying that I will have this 3 star 5 at some point of time this 3 star 5 when this reduction happens to e this will occur in certain context and that context is going to be 2 star 3 star 5 so again I will do this and say that when this resolution happens again I will have a set of types but at some point of time I will know the complete context and at that point of time I need to say that only one type is possible and rest of the types will have to be discarded so I discard all those types so one way to look at this is that if I am building my expression tree and in expression tree if I have an expression tree like this so let's say I have an expression tree of this form then I start finding out type so if I say what is type of tree this is int and this is int and what is the type of this star this could either be value here could either be either inferior or complex and then I will say this is int I know that c is not defined here so this can only be int so I can come down and discard this and I have resolved okay so actually it's a 2 pass process where I first say that I start bottom up and start building all the types and find out the sets here rather than a unique value which was possible when I did not have overloading and then once I have reached the top at that point of time I must know that it must have a unique type and if it does not have a unique type that's a type error but if it has a unique type then I use that information and start traversing down one again and say that certain types will be discarded and I need to find a unique type because that's the only way I can generate code that's the only way I can call a function so let's look at an example of this so type resolution is that try all possible types for each overloaded function in some cases it may be possible but it's absolutely a brute force method we are not interested in those kind of situations so keep track of all possible types and this is what I'm doing I'll keep track of using these kind of rules all possible types and then discard all invariant possible so when I start traversing down I'll start discarding this kind of information and then at the end check if there is a single unique type for every operator I have if it's a single unique type I'm done if it is not then I say this is a type error so how do I rank code for this so overloading can be resolved in two passes so first pass is the bottom up compute set of all possible types for each expression and pop down this when I start narrowing down the set of possible types based on what could be used in an expression and that comes from the context right makes sense so this is precisely what we do that now my code will look something like this that when I say E prime goes to E I'll say that so let we first write the full code and then show you so basically what is happening here is that if I say 3 and 5 these are integers and this is star and if I have a type expression like this which says E goes to E star E then I know that types of star are I cross I going to I I cross I going to C and C cross C going to C these are the three overloaded types but since these are two Is then I know that third type is not possible but these two types are possible and my outcome is going to be Is and then I'll traverse down once I have resolved what is the unique type of this I'll traverse down and discard one of those types so suppose I come down and say in this context in the context this E occurs C is not possible then I'll say this is I and therefore this I cross I going to C will be discarded and only the first type will be used so basically what happens here is that if I look at these types I look up ID and now I say what is E type here this is a set T can we say that there exists some as in E2 types and S2T even types so I'll not say this is just T but it could have multiple values so rather than having a single value of T what you end up with is a set so if each operator has a unique type then how do we resolve something like 2 into 3 into 5 into 10 don't worry about what compiler does you tell me suppose you were to write such an expression how will you resolve it how will you interpret right most the first unique representation then we have to so first I mean make an expression for this an expression we say that I am going to it has certain rules that I have start reading it from left to right and start evaluating it from left to right so suppose I want to write 2 star 3 star 5 star z right this is what you are saying 2 star 3 2 star 3 is 5 this right okay let's make an expression free for this how is expression free for this look this is expression free right okay now if this is I and this is I then you know that it can be either I or C what about 5 5 is I okay now what are the types of this C right okay so if this is because if I take I star I C C and I combination will not be permitted but I know that if this is I and this is I I can still get I can see here okay and this is C okay now what about type of this C okay but what is C what C means that I can take now 2 inputs in complex and multiply it okay so as soon as you say this is because I and C are not permissible only C and C are permissible you will discard this does it resolve I already said that we have multiple passes don't worry about now passing technique although it can be done still in a single pass okay but doesn't matter if you have to do multiple passes here you have a bottom of pass and you have to talk about pass so I am not even trying to do it in single pass I am talking with lot of jugglery and moving about the rules it is possible to go into a pass okay but let's at that point of time let's not worry about whether I am doing it in one pass okay let's say that even if I have to have multiple passes I can do it and I will show you that so in 2 inputs you are still not here that's what I have okay so look at it this way that I say that if this is C then is if I say I and I okay then isn't it clear that what I am trying to get here is that I am taking here an integer value okay because remember that C and I combination is not permitted I don't have such a prototype okay so this C anyway is not allowed okay then I know that what I am doing here is I am starting with integer giving an integer taking another integer now giving a complex and then taking two complex and doing a multiplication okay so what happens here is so look at it this way that I will keep going up okay till I reach the last operator at the root and the root I say that now do I know the unique type if I do that's a type error but if I do then I use that information to come down and for each node I try to determine the unique type so what happens here is so look at it this way I try to determine the unique type if I am able to do that then I am successful if I am not able to determine that I flag a type error so it is possible that you can overload a function in a manner that I will never be able to resolve it okay and then I will have to give a type error because I don't know which function to use and in any case if I can use more than one function I am stuck so compiler is only implementing it look at it this way that if I cannot resolve it there is no way compiler can resolve it any more questions on this so this is what we do here that we keep on resolving these types so first thing that happens is rather than having a single value I will now have a set of values and how do I narrow down this set of values that this requires now programming language says that a complete expression must have a unique type anything else is not permitted anything else is a type error so what we do is given a unique type from the context we narrow down the type of choices for each of the expressions which are below in this and if this process does not present in a unique type for each of expression then we declare a type error okay so how do I write the rules now narrowing down the types so basically let me again okay let's have full code and see what happens here so what we have is when I say EID is so look at two kind of rules actually I could have color coded it but so okay so when I say that E goes to ID that time I just do a look so the assumption is that every variable has been declared as a type so if I say E goes to num then I know that E type is integer if E goes to num.num then E type is real and if E goes to ID then I just look at my single way okay and when I parse this particular rule which says that I have a function then I say that E types is so this is the rule we saw that E types is nothing but a set of types okay so forget about this part don't even read these four lines for the time this is what I mean okay now once I have constructed this then I say that now I say what is E prime type E prime type here when this is the start rule which says E prime goes to E prime types E prime types just takes the value of E types which is going to be a set now this is the start symbol and now I check whether this type is unique or not whether the ordinality of this set is one or not if it is not one then I have a problem but if it is one then we say that what is E unique that's a new variable I define and we say if E prime type is T then this is T otherwise type F so it must have only one type when I reach the start symbol by that it should have been resolved okay now if it gets resolved if it is not type error then we say now let's come down and that is where we start looking at last four lines okay and we say that here now I am trying to resolve type so here I will now define a new variable which says what is my E unique now E unique must be having a single member cannot have a set anymore okay because I have seen here because if E unique is not a single member then I give a type F now I say let me find out types of arguments okay so now I say that if S belongs to E2 type and S going to T belongs to E1 type then if E2 type is S then this is S otherwise type error and if E1 type is S then this is S going to T otherwise this is a type error okay so basically I mean just understand this code what I am doing here is that first I have reached here in fact I mean you pointed out example which you can just pass using this that when I reach here I check what is the type of this particular function okay this is unique so I am happy here this is not a type error but then I start coming down saying can I now narrow down earlier when I said I had I comma C here can I narrow down it by saying that only IC is not a valid combination only C and C is a valid combination and therefore this type is distorted and basically it becomes unique and I keep recursively coming down till I am able to narrow down type of each of the star signals and actually if you now see implementation of this okay you will again find I am using the same jugglery and which is that I am absorbing something which is an inherited attribute and something which is a synthesized attribute and the combination of this basically helps me in doing it in one pass but there is no guarantee that I will be able but basically okay the trick remains the same that have a two pass have multiple passes two passes keep on building types till you reach the root and at root if you find you do not have a unique type like a type error but if you find at root you have a unique type then keep coming down and keep resolving types of each of the descendant nodes and wherever you find that you are not able to resolve like a type error otherwise you are done clear questions anything so as I said right in the beginning we are not going to go for type resolution in functional languages or languages where types are not declared we are always assuming that I will always be able to find type of variable by looking at my symbol table okay now there are languages where such a declaration does not exist value of a type of an identifier could be determined only from the value of the sign so I can take a variable I can take something like basic I can take a variable start by assigning an integer value to this and subsequently I start a floating point value and then subsequently I assign a totally different type to this the functional languages operate in this manner and then lot of work actually goes on in type resolution but that is as I said is a separate course in fact you need to know more of lambda calculus in type resolution and type associations and so on just to do that and that becomes a very major issue for both functional languages as well as when we go into processing with languages like natural languages and so on but we keep out of that domain and we just have languages where you say everything is all variables are applied to declare the types are not and therefore this actually plays a major role which says that this lookup will always be able to give me a new type so this is where I want to close discussion on type checking and move on to code generation unless you have any question about what we have done in type checking is there till you move on to the next topic so let us move on to then the code generation so what we want to do is now we want to start generating code and if you recall once again what we did in our compiler structure we had a front end so let me just remind you of the structure we had we had a front end we had a back end and within back end I said that we are going to have at least two phases one which will give me the intermediate code and other which will give me finally the machine code and of course we had an optional optimization phase which we will introduce only towards the end after doing code generation because this part is optional at least we must know this box and this box to complete our compiler and if time permits we can see that how to improve code what are the techniques which are available to us for improving the quality of code so now what we want to do is we are here and we want to talk about this box and this box is saying that I have done type checking on the program now I know that this program is correct with respect to the specifications of the program language and once I have resolved that this is now correct I know the meaning of each and every symbol I have resolved all my operators I want to now convert that into some kind of code which is closer to the machine so I am not straight away generating machine code but I am saying I will do it in two steps and I want to move into two steps one where I will have some kind of notation which is not exactly the machine instruction it is not the concrete syntax but it is much closer to the machine resources so this is the final phase when I do machine code generation at that point of time I will convert this representation into a concrete syntax of the machine which will look exactly like what an SMG language language program is so exception at source level once again so this is again I have captured from the introduction and this point leads to the functional specifications of what we are trying to do that the exception we started with were identifier operator and at target level what I am having are again memory locations where you stress like op-votes addressing nodes and so on and code generation is going to be mapping from here and we want to take all the source level abstractions and we want to map them on to the target abstractions this is what my aim is and in this I am going to use first the intermediate code generation so front end translates source program into an intermediate presentation so normally what happens is logically we may say that I have a front end and I have this but actually what happens is that you can implementation wise fit all of this I am leaving the optimization out for the timing you can fit all of this actually into some kind of same physical code so you will see that when I talk about intermediate code generation I will still talk about syntax that will be translated that as I am passing time I will be able to not only type checking but I will be able to generate code straight away so back end generates target code target is now the target machine from the intermediate presentation so my back end really when I talk about my back end this generates code starting from the intermediate so you have to distinguish between the logical activities and the way I implement a compiler so logically I may have many activities but I am able to put them together into a single physical phase so what are the benefits of this model obviously re-targeting is possible and machine independent code optimization is also possible because remember that this phase is giving me some kind of intermediate representation which is independent of the machine but is closer to machine so I am not doing optimization at the machine level here and this is how my logical structure looks I have a front end I have intermediate code intermediate and I have machine code intermediate and what we have done so far is this part and this is where we are moving now and therefore first thing I must remember is that if I am talking about this box what is my input and what is my output so what is my input here logically I am not worried about all the implementation is done at this point of time what is my input to the intermediate code intermediate and extract syntax tree which has been completely resolved where I know the meaning of each of the operands and where I know the exact meaning of each of the operands and what is my output here output is going to be some intermediate representation which we do not know at this point of time so remember that we started talking about right in the beginning we started talking about some kind of universal intermediate representation which could then be targeted on to any machine so let us now start looking at what is the kind of intermediate representation that we are talking about so intermediate representation design becomes very important issue for us because this is really going to be the interface and it is not just interface between a machine code generator but it could be an interface to many machine code generators because I want to target different machines there and therefore this design has to be done very carefully now first thing that happens is unfortunately we are talking about science and principles and so on but science involved and what we are talking about is wizardry or artistry saying that how do I design intermediate representation it is almost like saying how do you write a good program do you have an ability for writing a good program you perhaps cannot even define what a good program is you may have certain guidelines but you cannot say that give me a program and I will be able to look at this program or I will have a tool which will look at this program and say there is a good program both the programs may achieve the same functionality but then I mean you look at a program and you say this program is very good very easy to understand fast to execute and so on and you look at some programs and then you say I do not want to test such programs I do not want to look at them similarly when you say IR design IR design basically comes from lot of experience lot of experience of the compiler I think so if you have been in the compiler project for 20 years when you have this talk of now inbuilt skill when you say this is a good IR because this is going to serve all kind of machines I am going to encounter this is going to help me in doing code generation this is going to help me in doing optimization and so on and I can design a very bad IR and you will suddenly find that you keep going back and forth here you are able to achieve all the functionality so first thing is that is an art really and each compiler uses multiple IRs multiple IRs so where are the multiple IRs if I look at this first IR what was the first IR we encountered stream of programs stream of programs and what was the next IR we encountered abstract syntax T which was not resolved we were also talking about parse T but as I said parse T is more of a notation which is really compiler does not worry about psychological notation and then we have another IR which was resolved syntax T so resolved syntax T is the one where all the operators have been resolved and then we look at other IRs now IR could be at multiple levels so we have one notation which is used this theory is what we know as HIR or high level intermediate representation where I say that I want to preserve all the loop structures and all the information now at this point of time it may not be clear so let us look at what are the other IRs we may have so another IR we may have is what we know as medium level intermediate representation or MIR you will find in short where which has a range of features which is basically close to the set of languages we have but still remains independent of the language and is also good for code generation for multiple machine and this is appropriate for large number of optimizations but what happens is then why I am talking about even this kind of IR there are certain optimizations you may want to do and therefore it becomes really an art where we say that I am designing an IR keeping overall compiler structure in mind keeping overall functionality I want to achieve in compiler so if you design an IR where lot of information is lost so let us take an example suppose I say that I have a loop in the program now how do you translate normally loops you will have a sequence of test results you have something like this for I let us say 1 2 n and i plus plus and then I have this set of statements now when I am doing this translation normally what will happen is that I am going to convert this into a sequence of test results so I will say that maybe I is stored in a variable which could be a register variable and then every time this loop has to be executed I will first check whether this is still within the bounds and then I will execute it I will come back I will implement it and I will keep on moving now many times suppose I want to do optimization right here I want to recognize that there is something a loop because remember that I can convert this into a sequence of test and jumps but not all sequences of test and jumps can be converted back so as I keep on moving from abstraction which is source level up to target level every time I do translation I am losing some information when I am losing information there is no point saying I will go back and start reconstructing that information because I have already put in effort and I have lost information which I may not be able to recover so many times when I want to do optimization at this level and suppose here I have now an array which is of this form so this is a very simple form where I say a is assigned b and for each element element of b is being assigned to a what is going to happen here is that once I convert this what is going to be the conversion here when I convert this into a language which is close to machine language what is the kind of conversion you can think of load and store load and store is a general technique when you load something from memory and then store it back no if you look at conversion that will happen is that I will say take the base address of b I know the base address of a and I will take the first element then I will increment i and if it takes 4 bytes to store an element then I will say that whatever is the base address I add 4 to that and keep on doing it for all the elements but suppose I want to do certain optimizations in analysis on i now take for example something like i plus 3 and I want to do this analysis on these index values then I lost that information out so what I will try to do therefore is I will try to preserve hir and once I have done this then I will be able to do this resolution for this optimization so depending upon the kind of things I want to do our other want to keep hir there or I want to go to mir depending upon the kind of optimization sample so this is we will stop our discussion today