 And one example, we took us to the declaration drama and we were trying to see that all the rules which are just being used to lobby certain attitudes on different parts of the tree, whether they could be eliminated by using information on the stack and these two actions, these two actions which are initializing certain attitudes and these two actions which are making entries in the single table, these are the only ones which are important therefore, if I can eliminate the other rules then we will be able to enter the stack part. And we went through this example of finding out that whenever certain reductions are taking place that means I have a reduction which is either n goes to n from id or n goes to id, I was able to find value of the right information somewhere in the stack and using this then we found that actually this entry which was corresponding to n going to id could be replaced by finding out that the right information is on the stack just to the left and in this case when I was doing reduction, I was going to set l going to l, id and I had corresponding action here, I was able to find that value of the type was available at top minus 3 and once I identified the stack then I was able to eliminate all the copy rules and was straight away able to make these entries so these two initializations and these two entries or these two actions for the entries were the only things I required. That is what we were doing and now let us see what is the property I identified in replacing all those actions of copy by speculating that I could find value of the stack itself. So you notice something that is there some unique property which I should be looking for so that I can always use this scheme in the end of it because the trick is that if I cannot generalize it then this is not going to work. So I want to find the general solution so that it will work for all the dramas. So what is the characteristic you notice in this particular drama so that it becomes now a general scheme any ideas? So two things let me once again bring this into focus so what was the rules drama rules and I was able to replace all these information by stack information one was that when I had this reduction which said n goes to id and another was when I said n goes to l comma id. These are the two times I was able to do this replacement and in this case as I said the height was always at top minus 1 and in this case height information was always at top minus 3 so what is unique about this is that does not matter when I am doing this reduction if I do this reduction there is a predetermined place on the stack where this information is available. Similarly when I do reduction by the rules there is a predetermined place on the stack where this information is available. Now suppose I get into a situation where I do not know what this predetermined place is then this scheme is going to fail. So let us look at first an example of a grammar like this. So take this grammar we have two for us one says s goes to lower case a a c and this is s goes to b a b c and c goes to x and it happens that c inherited is a copy of a synthesizer. So inherited attitude of this c is a copy of a synthesizer and corresponding to this rule I have c is going to or c is going to assign a function of c inherited. Now what happens can I apply the scheme will the same scheme work that I say that I do not have to now worry about finding out because c inherited is nothing but a copy of a synthesizer and therefore if I need to use this rule then there is no need to really copy c inherited here I should be directly using this synthesizer. Is that possible here? Yes, no. Why you are saying no then why you are saying yes and again you have to justify both the things. So focus on this particular this is where I am saying that I am using c inherited which happens to be a copy of a synthesizer. So I am saying that instead of making the copy directly use a synthesizer and a synthesizer is already on the stack. Now when I am doing this reduction when I do reduction of x to c do I know where a synthesizer is? Why would I not know? So I know the question. So when it was terminal starting by a. So wait a minute, wait a minute, wait a minute then we have forgotten about parsing altogether. So if I am doing my parsing what will be the configuration of stack? So let me assume two configurations of the stack either my so these are only talking about the state stack and not the value stack. My stack configuration will either be a capital A x before this reduction or it will be B capital A in x. These are going to be my stack configuration before I do this reduction. Before I say that this c either goes this x either goes to c or this x either goes to c and this is the time I say that I want to compute c synthesizer which happens to be a function of c inherited which happens to be a copy of a synthesizer. That means either the value of a synthesizer is there in the corresponding value stack or corresponding value stack will contain value of a synthesizer. Problem is that I am doing this reduction I do not know which rule I am going to use next for either this reduction or this reduction. At that point of time I know I am talking in general about bottom of bottom. So when I do this particular reduction that it is not clear whether next reduction is going to be by the first rule or the second rule. And therefore position of A when this reduction happens is not known. It could be below that top minus one or it could be top minus and that is where the problem is. Now how do I carry this information so that I can always find the correct place. We talked about the general trick. What was the general trick? I moved my embedded actions to the end. What was the trick I used? Now somebody has to say something. Edition of extra non-dominus. Edition of extra non-dominus and I call these markers. Now suppose I make a similar trick here and change my rule to something like this. If I say S goes to A, C and then I say S goes to B, A, B, C. And then I say C goes to X. Now instead of this I am now making a small change and saying that let me put a marker M here and then I say M goes to that side. Now what I can do is that now you can see that if A synthesized is just below it and now in this I make a copy of A synthesized then it does not matter whenever I do reduction by this rule A synthesized is just going to be below this. Can I use this trick? So now of course my stack configuration in this case becomes when I am changing my second rule my stack configuration will be something like this B, A, B and X. And now this marker is used to keep a copy of A synthesized. Now suppose I make a copy of A synthesized here I make a copy of A synthesized here then is there a difference between this reduction and this reduction as far as reduction by this rule is concerned? It is always below it, it is always at top minus. So what I can do when I am leading you towards a general solution that in the first case why this scheme works because whenever I did a reduction I was always able to find a predetermined location for noise inside that. If I make similar transformation in my grammar and you can see that this transformation is not going to change the language I am trying to pass. And therefore if I now make this change, the problem is that it is either at top minus or top minus 2 which I do not know. So now if I make this change and say that I am introducing a marker and when I introduce a marker I will also have to introduce certain rules and the rules here are that M inherited is now a copy of A synthesized and then I say C synthesized is nothing but a copy of M synthesized and then when I do this particular reduction with that silence I am saying that synthesized will be nothing but a copy of inherited that you do and then I can always say that C synthesized is a function of C inherited. Now I know that when I am talking of C inherited which is a copy of A synthesized. This MS is also you can see is a copy of A synthesized through this rule. So A synthesized is copied into MI, MI is copied into MS and MS is used just here which is just below it and I am done. So in this case I either I will have AS here in this case I will have AS here. So I will not have to worry about which rule I am going to use for reduction next. I will always say that whenever you reduce by this rule which says C goes to X always find the attribute just below it that still has a limitation. So now whenever we apply this production I can always find that N synthesized is nothing but a copy of A synthesized and therefore value of C inherited which is nothing but a copy of N A synthesized is always a top minus one. I do not have to worry about that. But there is still a limitation and what is that limitation and how do I crack that problem. Perhaps they are not solved because as I said I am leading you towards the general solution but I have still not reached all the way. There is still a limitation I have. What is that? So when did this came here? So first problem I started with was I am saying that I will always have attribute at a predetermined location and the assumption I made was that most of the time attributes are nothing but copies of one another. Will this scheme fail if it is not a copy of it? Just another attribute. So what happens now? If I say that CI is, if you say CI is a copy of AS and MI is a copy of AS. Suppose CI is not a copy of AS. CI is a function of AS. It needs to be evaluated. Then there will be a function. So let us look at this one. Now when I say this is not a copy and this is a function then I need to evaluate and again I am going to use the same general trick and I will say that I am going to put another marker and this marker is the place where it will hold the value of the attribute but after evaluating it. Now this gives me the most general case where I say that does not matter whether you are attribute in the copy or attribute is a function of another attribute. I can always see where you can keep it on the stack in the predetermined position. Now with this I have all these tools. I have now enough machine range available to me where I can generalize my algorithm. So now let us move towards generalization of algorithm and at this point of time I am going to propose that let us say that I have in general rule which is A goes to X1, X2, Xn and I can have attributes which are copies I can have attributes which are not copies but which are functions and I want to generalize. So what I can do now is corresponding to every symbol on the right hand side I can blindly introduce a marker and if I introduce a marker then what will happen my grammar will become something like this this will be one change I do and then I will say that all these n's so n1 goes to epsilon and 2 goes to epsilon all nk is going to epsilon and what will these markers hold now what they can hold now is remember that now go back and I was talking about evaluation order and if you remember what was evaluation order we said that inherited attribute of a symbol must be evaluated in the position which is immediately that good and that means I can now say that n1 actually contains X1i and nk contains Xp i so all marker symbols are going to contain the inherited attribute and all the symbols themselves on the values that obviously and all the symbols grammar symbols on their values that they are going to contain the synthesized value so now I can say that corresponding to this location X1 synthesized corresponding to this location I have X2 synthesized and corresponding to this location I have Xk synthesized so now you can see on the values that all the inherited attributes can be there and all the synthesized attributes and depending upon whether this is a function I am going to have the appropriate rule on the right hand side so if it is just a copy then I copy it from the deep term in location and if it is function then I just put a function at the end now do I have a pre-determined location for everything so suppose now I am saying that a reduction happens to let's say mk now when I say reduction happens to mk I want to compute I am computing mk inherited attribute which basically is Xk inherited to compute Xk inherited and place here what do I need to know I need to know all these attributes and inherited attribute of A in my L attribute definitions now where will be the inherited attribute of A on the stack where will I find inherited attribute of A on the stack I have a pre-determined location for that so A will look at somewhere on the right hand side in the production corresponding to that there will be marker so inherited attribute of A will be that location so if I start now showing you the stack this is how the stack will look that I will have corresponding to let's say marker of A which will contain value of A inherited and then I will have m1 X1 up to mk and Xk now suppose I am doing reduction to this Xk has not yet come in I am doing this reduction and I am computing inherited attribute of Xk that is going to be computed here and I can now find everything it depends upon on the stack these are all pre-determined pre-computed attributes and if I want to if reduction is taking place to let's say Xk which is synthesized attribute then what does it depend upon when this reduction happens then all the attributes of the right hand side corresponding to this rule which said Xk is on the right hand side must have been on the stack so before I pushed Xk I am going to then compute the synthesized attribute for all those symbols and push Xk and push the synthesized attribute of Xk on the value stack that is my general set but this general scheme seems to be slightly flawed I am using this too much space right so how can I reduce space how can I optimize this markers are not required so if markers are not required then what do I do so if a grammar symbol does not have inherited attribute then I do not need a marker so I can throw away some of the markers I will only keep markers for the inherited attributes and for that still because I know which markers I am throwing away that only needs re-computation of the offsets but they will always be the predetermined locations so I can reduce number of markers by saying that for certain inherited attributes I will not require or for certain symbols I do not have inherited attributes and therefore I will not require and then I can throw it so in general what I can do is that if I am using the watermark a translation with inherited attributes my input are inherited attribute definitions and what I want is a bottom up parser so what I do is for every non terminal which has one inherited attribute and every grammar symbol has a synthesized attribute and for every production of this form which says a goes to x1 to xn I am going to introduce markers m1 to mn and I am going to replace this production by a production which has markers and then all m1 to mn and goes to xn and then synthesized attribute of x1 s is going to go into the entry values that corresponding to x1 and inherited attribute of x1 is going to go into the marker corresponding to x that gives me the predetermined location so a reduction is to a marker then marker belongs to this particular production then what do I do ai is in this position which is top minus 28 plus 2 this is I am computing from this particular stack and x1 i is in a position which is avoid and so on and if reduction is to non terminal a by this production then what do I do compute as and put it from the stack so this is the most general scheme I have for finding out all other attributed definitions on the stack itself of course I am assuming here that every grammar will have only one inherited attribute it has more inherited attributes you will have to put more markers basically what we are doing is we are creating space on the stack so this scheme can be easily generalized here any questions on this so let us continue our discussion on optimization worry about keeping all these attributes somewhere I need to allocate certain space for this so one space I have created all these are markers and I am saying that it is not good enough to say that keep a marker for every symbol and therefore use markers only for the symbols which require an inherited attribute and put them on the value limit can it be better than that so now we are really worried about the implementation we really want to have a compiler we want to have an algorithm can I put the attributes there is some idea just go and sleep in the class say something make a suggestion so how do I do that so proposal is that all markers which hold the same value they can be reduced to a single location good can I do better than that so let me give you a program instance now suppose I have a program so I have nothing else how many variables do I have so I have 1 2 3 4 5 6 and 7 so when I do memory allocation I am going to say that I am going to allocate 7 locations for this why really 7 locations so what happens here is I am saying that A is being assigned B plus C now there are some locations B and C but you can see that beyond this point I am not using B and C so can I just say that let me overwrite one of those locations and use that for A can I do that similarly when I say now that P is in a location so can I say that I can use for A location for B and then for P I can use location of C because that was not required and then I say that beyond this point that was not required so X takes one of those locations and then the location which was feed by use by Z and then X was already in that location and that was assigned to Y so do I need 7 or I can go with Q can we use just 2 or 3 so what is the trick I am using here so the trick I am using here is that I am looking at lifetime of each variable I am seeing that lifetime of a variable starts from the time this is initialized till the time it is last used and beyond this I do not have to block the space for this I can read this I am saying if I am going to be used here there is no reason that there are attributes which are copies of each other and these attributes beyond the point see attribute equations are something similar to this right so if I do not require this attribute beyond the point for computation why should I just keep it on the stack and keep blocking all this information on the stack I can as well use registers I can use some other locations which are not even related to the stack and say that my attributes are going to be there so if I say that I want to do lifetime computation so lifetime begins when it is first computed and lifetime of an attribute ends and all the attributes which depend upon it have been computed and as soon as that happens I just release that location so for example in this case lifetime of B C ends as soon as this statement is computed because beyond this point B and C have no use so I can use the same location so space can be conjured by assigning space for an attribute only during its lifetime and I do not keep blocking that space for whole of the program so if I just do this computation let us look at the grammar which is slightly similar to what we have done do not worry about this grammar that is not important part let me show you attribute computation for this grammar and I will first show you the dependence graph so what we want to do is here I am again initializing all my identifiers I have type information but I have also introduced now saying that I can have add it this is just to make little more complex nothing more complicated but important part is that if I now try to parse in X3, X5 Y5 and I look at first the abstract syntax tree for this and then I introduce all the dependencies this is how dependency is going to be that what is going to be used for computation of 2 and then 3 and 6 are going to use what was computed here and 7 is going to use 6 and so on so this is how the computation is going to happen now let's see what is the lifetime of these variables and how do I optimize my number of locations so let me just put these computations I am doing computations from 1 to 9 so I have this computation 1 2, 3 let me write vertically so that we have more space so these are the 9 computations I am doing and looking at the dependence graph here we say that 2 uses what was computed in 1 and then 6 and 3 use what was computed in 2 and 7 uses what was computed in 6 and then 9 uses what was computed in 7 and 8 and on the other side of the tree 5 uses what was computed in 3 and 4 I am just taking all these red arrows and flatten this graph this is how the computation is going to be now you can see that as far as this is concerned now let me start allocating resources to this so I say that the first I compute 1 and therefore I allocate the resource R1 to this and then I compute 2 but now beyond this point 1 has no use and therefore I can now use the same resources I am preserving immediately you can see that I am preserving one location that I want to now compute 3 3 depends upon 2 but 2 has a future use who is going to be used here and therefore I allocate a new resource to this and I say that this is R2 then I say that I want to compute now 4 but I can see that before 4 can be given a space I cannot free this space and I cannot free this space they have a future use and R3 here and now when I come to this node and say I want to do computation then I find that beyond this point both R2 and R3 have no use and therefore I can free both these locations and I can say that this goes into resource R2 and then I come to this node and now I find that this node depends only on this and now I can free even R1 and therefore I can allocate R1 to resource number 6 and when I come to 7 then I find that 7 depends on 6 which is bound to resource R1 so I can then just compute put this information in R1 and then I find that R2 beyond this point have no use finally computation was done so when it comes to R8 I can use R2 here and when it comes to 9 I can free both R1 and R2 and put that information in R1 so rather than having a large stack in all these grammar symbols I can actually do it just free resources that's an optimal idea now can I do better than this because remember that we are trying to extract every possible information look for everything in this the information is in this graph there is nothing like this so let's go back in this so what happens here when you say L inherited is T type T type is real T type is integer L inherited is L inherited I inherited is L inherited and so on if you see all these are nothing but copies only computation that is happening is either here or here rest I am just creating copies now if I just start creating copies now you can see that actually 2 is nothing but if I say this is my resource R1 2 is nothing but R1 the same problem this is what I did if you go back this is what I am saying I just created another copy if I am creating another copy then I don't even have to worry about like that so first find out what are the copies which I am creating so I created copies here then 3 and 6 also happen to be copies of R1 3 and 6 they are also copies of R1 and what about 7 7 also happens to be a copy of R1 so if I use this information only computation that is happening is at 5 and 9 and now how many additional resources do I need just one more 5 I first compute 5 put that information in the simple paper and corresponding to 9 I do this computation and I can actually work with just 2 resources sufficient so I don't have to maintain that large value stack I can use some other locations I just need to keep track of this information so using all possibilities like lifetime information finding out what are the copy rules what are the resources and remember that all this thing is going to be used for register allocation when I finally start generating machine code you will find that I have limited number of registers most machines will provide you 8 or 16 registers and I will try to see that whenever I do an expression evaluation or any evaluation I will try to use registers as far as possible so I will try to free registers as early as possible whenever there is no filter use and if it is keeping the same value I will try to reuse the register so I am going to use the same filter and say that if I look at resource requirement this is how my graph looks and if I allocate resources using lifetime information this is how the information is going to be bound and finally I am using only 3 locations and I am using allocate I am trying to not using information like copy information and suddenly I find that many of these are copies and if they are copies then I just need 2 resources so whatever information is available to you try to use that information to further optimize it so now you can see that not only we understand algorithm we understand where the attributes are available but we can also further optimize it and see that I can now work with just 2 resources which happens to be in this case but the techniques are general where you say that whatever are copies you choose to use it and then you use lifetime information and try to minimize all this all the number of resources so some rules are that you will just look at copies and you will look at lifetime and once you apply these some rules then you will be able to further optimize it of course number of resources will depend upon the kind of program you are trying to optimize so for different grammar rules you will have different number of resources so you see that if you go back to this grammar here so let me go back to this grammar or I can go back to this grammar this is suppose I bound a resource to t-type now you can see that when I am talking of alien heritage I am making a copy so I can say that look lifetime of t-type is not just ending here but it is going beyond this because I have a copy here and similarly if I look at alien heritage alien heritage is being copied here I can say this is basically the same resource I don't have to be allocated so by finding out copy information I am slightly extending my lifetime information so this is what happens here if you want to look at the graph we are saying that 2 is a copy of 1 and 6 and 3 are also copies of 2 and 7 is a copy of 6 and 5 happens to be a copy of 5 will depend upon this so you can see 1, 2, 3 and 4 these are nothing but copies and this is where I use this information that I say that 1 is and then 2, 3, 6 and 7 are nothing but just copies so they are same things, 1 so that means I can say that whatever was allocated here is being used here and therefore don't free R1 till this point once I recognize this fact then you will find that what I was doing here I was saying that I am going to use this resource and then use R2 but this is nothing but a copy I don't have to allocate a new resource for this because R1 is already there and then I say that as far as this node is concerned compute that in R2 but lifetime of R2 hence here because 5 is depending upon 3 and 4 and therefore it's not really a copy it requires so whenever you have 2 inputs you require a not copy you need a new resource whenever it's just copy of another then I can just use a copy so that means 5 will depend upon 3 and 4 and 3 has a further use which is R1 but 4 can be freed here and therefore 5 can go into R1 similarly now once this part is done then I say 8 is now a new resource required but 9 now both R1 and R2 can be freed because beyond this point even R1 has no use so I just use R1 so when you are constructing your compiler you need to worry about space so I will tell you I told you this story somewhere in the beginning where people were not careful while building a compiler so I mean we went through where we were trying to make a compiler and programs were written in a certain manner and we found suddenly that the compilation became so slow and to give a small program for compilation and just not coming out it's not coming out of compilation cycle and the reason was that single table became so large that all the time there was not sufficient space because when this was I mean we tried to put some single table in the memory and found there was not enough space those days I am talking about somewhere around KTK, KT9 so machines did not have this kind of memory where you said my virtual space is 4GT I have 32 bit of disability and therefore I have physical memory of 4GT now I am going to have 16GB, 32GB we were talking about 1MB kind of 1MB was even considered and suddenly you found you have a single table which is not put in written into memory and all the time space was being just written so on a program you want to compile a function which is like 5 line function and it takes 3 hours to compile because people were not careful in building their single table properly and once you go through this optimization then you found that it was a matter of milliseconds because remember that when it comes to a very big and instead of a linear single table start using caching and so on you still have to reduce the size because if it does not fit into memory then you are going to operating system is going to raise a lot of time in stack you have to be aware of this stack that effectively compiler is going to run or any system software is going to run in the control of operating system and if you are not careful in space optimization so this many of the people have this notion of memory availability there is never enough memory on the system you can always write programs which can flash your system so one has to be very very careful and one has to learn all possible techniques to reduce amount of memory memory is and resources are always there to be so this is one optimization but I want to further optimize so what are the optimizations I can think of so let me go back to one of the examples we dealt with earlier so we had this example we said S goes to block and then we had this block going to B1 or B2 and then we had another block going to B1 subscript B2 and so on remember this grammar what was this equation type now when I start looking at information here what happens is that attribute will be held on a single stack so what is it that we were doing that when this reduction was taking place basically what was happening was that I had this B1 on the stack and then I had B2 on the stack and now suppose I have to put markers on the stack then I also need space for inherited attributes now when I say space for inherited attributes that means immediately my stack changed to something like this I must have had a marker for B1 then I had B1 then I had a marker for B2 and then I had B2 my actually stack was of size source and these markers were keeping the inherited attributes so this is where what was the inherited attribute in this example point size and what was the synthesized attribute height so I was keeping now size there and I was keeping of B1 height there now you can see that actually these are nothing but copies right so one way I just showed you that I am going to use registers I am going to use certain resources I don't want to use stacks but sometimes you will not be able to avoid stacks but can I split this now so when I say that I am going to do a reduction by this rule of this form what is the maximum size of the stack possible potentially what height can be improved so when I say that I am doing reduction by this rule let's say forget about any other symbol what can be the maximum height of the stack here 4 right so in general if you have k symbols on the right hand side you can height of the stack can be up to 2k right but you find that within this 2k you have these copies now suppose I separate my inherited attribute stack and synthesized attribute stack then what will happen I will have 2 stacks of height but as soon as I do this separation I will say oh but this stack the top and top minus one have the same value so I can keep it in the same location and keep it height 1 so I will say one space there in general so in general what we can do is that whenever I have a rule which is of this form it says A goes to BC stack goes up to height of 5 so how is stack of height of 5 because I have inherited attribute of A then I have inherited and synthesized of B and C on the stack so probably can become 5 before top 4 symbols are pushed out and their synthesize comes on the stack and that will reduce to 2 once again so just before reduction this is how my stack will look inherited attribute of A then inherited attribute of B inherited of C and synthesized of C and immediately after reduction my stack will have inherited attribute of A and synthesized of C and if I show you pictorially the example which I just picked up this is how your tree will be constructed and how will my stack look so when I am saying that I am at this node I am only left inside will be synthesized attribute so I will say that B point size is on this stack then I will say B point size B point size will be on the stack and in this I will compute synthesized attribute which is going to be here and then I will put B point size and as soon as I evaluate B2 I will also have B2 height on the stack so it grows to height 5 and then it again reduces to a height of 2 right this is how you have to see that stack started here then kept on growing till it came back to 1 stack to grow to this height and you will find that many times B point size, B1 point size, B2 point size these are nothing but the same values so what I do is I separate the stacks I say that instead of having two stacks one for inherited attribute another for synthesized attribute I have only not one for two stacks one for inherited another for synthesized and if I do that then what will happen is that I will say B point size is here synthesized is still at me and now I say now this is where the things start coming using the copy rules I say oh I know for sure that B1 point size is nothing but B point size so I don't have to push that value that is already on the top of stack and then I am going to say that I only need to compute B1 height here B1 point size is already on the top of stack and again I find B2 point size is nothing but a copy rule that is on the top of stack and only my synthesized attribute goes to a height 2 which will have both synthesized attribute of B1 and synthesized attribute of B2 and then finally this reduction happens and my synthesized attribute again comes to height 1 so now you can see that my inherited attribute stack did not grow beyond 1 remain only a height 1 because of all these copies and my synthesized attribute starting from empty it grew to a height 2 and finally reduced to height 1 ok so you can see that if I separate it my total number of again spaces are going to go down now I mean this in percentage wise this may look I mean attribute numbers may not look very large percentage wise you can do this computation but real benefit will come when you find that suddenly on the right hand side you have a large production you have to get the synthesized and inherited inherited and synthesized how did you take you have already answered your question because these are our free term locations look at it this way so suppose I say that this attribute does not exist and I want to find out where is now I am saying that I want to find out to compute mk I need all these attributes then what will happen to these heights only offset will change by 1 but I know that at the time of construction of the grammar so I can compute all these offset so it is not that I am doing something later I am constructing my grammar I am saying certain grammar symbol certain markers do not exist so I can find out all the locations same thing I will do here I say these are copy rules now you can see that actually this is one of the resources because I am saying that synthesized attribute is just one resource I am just binding one to it one resource to it and therefore I can always say that not really does not matter whether I use some other resource or if I use a stack because here I have bound the stack which is of pipeline I could have said that point size is bound to a certain resource so take away from all these exercises that if you just want to see the principles there remember two things one that there are going to be certain attributes which are just copies of each other and therefore you should preserve that information what is copy of each other and second that each attribute is going to have certain lifetime and allocate resources only for the duration of lifetime and not others if you just remember these two rules then suddenly you will find that the total space requirement is going to go down drastically and these are really the tricks which are used in the resource allocation and we are doing the same thing in resource allocation so I mean I do not want to distinguish between the discuss and resources because these are nothing but as far as we are concerned these are just resources and we want to optimize all your resources and this optimization is the one which is going to make your programs much faster because suddenly you find you have some additional things to be done because now you want to manipulate all the stack conditions that you must remember where the pieces of locations are but once you have done that that is one time exercise once you have done that then suddenly you find that your compiler is going to be much faster and don't think that and you don't have to worry about combined time it is only one time activity and only the execution time is important this has an impact on my execution time also because if you use too many resources suppose I do not optimize my code I just use large number of registers what will happen? I will have to do register spelling somewhere register spelling means extra machine cycles and if you have more instructions that means extra pet size so a good compiler is going to make sure that we get it optimized but at the same time remember compiler is also a program so compiler itself needs to be optimized any questions? so let's break here today and tomorrow we are going to start our discussion on type systems and see that how to compute all the type expressions and build up a type system for the life so let's break here and continue our discussion tomorrow