1 00:00:15,840 --> 00:00:20,260 PROFESSOR: Well, I hope you appreciate that we have 2 00:00:20,260 --> 00:00:26,690 inducted you into some real magic, the magic of building 3 00:00:26,690 --> 00:00:29,730 languages, really building new languages. 4 00:00:29,730 --> 00:00:30,430 What have we looked at? 5 00:00:30,430 --> 00:00:39,390 We've looked at an Escher picture language: this 6 00:00:39,390 --> 00:00:42,360 language invented by Peter Henderson. 7 00:00:42,360 --> 00:00:46,260 We looked at digital logic language. 8 00:00:53,260 --> 00:00:53,570 Let's see. 9 00:00:53,570 --> 00:00:55,360 We've looked at the query language. 10 00:00:59,700 --> 00:01:01,570 And the thing you should realize is, even though these 11 00:01:01,570 --> 00:01:06,760 were toy examples, they really are the kernels of really 12 00:01:06,760 --> 00:01:08,250 useful things. 13 00:01:08,250 --> 00:01:12,520 So, for instance, the Escher picture language was taken by 14 00:01:12,520 --> 00:01:17,320 Henry Wu, who's a student at MIT, and developed into a real 15 00:01:17,320 --> 00:01:21,840 language for laying out PC boards based just on extending 16 00:01:21,840 --> 00:01:23,300 those structures. 17 00:01:23,300 --> 00:01:25,320 And the digital logic language, Jerry mentioned when 18 00:01:25,320 --> 00:01:28,550 he showed it to you, was really extended to be used as 19 00:01:28,550 --> 00:01:32,050 the basis for a simulator that was used to 20 00:01:32,050 --> 00:01:33,460 design a real computer. 21 00:01:33,460 --> 00:01:34,900 And the query language, of course, is kind 22 00:01:34,900 --> 00:01:37,510 of the germ of prologue. 23 00:01:37,510 --> 00:01:39,830 So we built all of these languages, they're 24 00:01:39,830 --> 00:01:41,080 all based on LISP. 25 00:01:43,630 --> 00:01:48,010 A lot of people ask what particular problems is LISP 26 00:01:48,010 --> 00:01:48,820 good for solving for? 27 00:01:48,820 --> 00:01:52,150 The answer is LISP is not good for solving any particular 28 00:01:52,150 --> 00:01:56,340 problems. What LISP is good for is constructing within it 29 00:01:56,340 --> 00:01:58,140 the right language to solve the problems you want to 30 00:01:58,140 --> 00:02:01,470 solve, and that's how you should think about it. 31 00:02:01,470 --> 00:02:04,326 So all of these languages were based on LISP. 32 00:02:04,326 --> 00:02:07,270 Now, what's LISP based on? 33 00:02:07,270 --> 00:02:07,920 Where's that come from? 34 00:02:07,920 --> 00:02:09,400 Well, we looked at that too. 35 00:02:12,740 --> 00:02:23,760 We looked at the meta-circular evaluator and said well, LISP 36 00:02:23,760 --> 00:02:25,810 is based on LISP. 37 00:02:25,810 --> 00:02:28,910 And when we start looking at that, we've got to do some 38 00:02:28,910 --> 00:02:29,950 real magic, right? 39 00:02:29,950 --> 00:02:31,660 So what does that mean, right? 40 00:02:31,660 --> 00:02:37,730 Why operators, and fixed points, and the idea that what 41 00:02:37,730 --> 00:02:40,460 this means is that LISP is somehow the fixed-point 42 00:02:40,460 --> 00:02:44,600 equation for this funny set of things which are defined in 43 00:02:44,600 --> 00:02:47,470 terms of themselves. 44 00:02:47,470 --> 00:02:49,070 Now, it's real magic. 45 00:02:49,070 --> 00:02:53,000 Well, today, for a final piece of magic, we're going to make 46 00:02:53,000 --> 00:02:54,250 all the magic go away. 47 00:03:06,430 --> 00:03:09,770 We already know how to do that. 48 00:03:09,770 --> 00:03:11,970 The idea is, we're going to take the register machine 49 00:03:11,970 --> 00:03:14,380 architecture and show how to implement 50 00:03:14,380 --> 00:03:15,500 LISP on terms of that. 51 00:03:15,500 --> 00:03:22,640 And, remember, the idea of the register machine is that 52 00:03:22,640 --> 00:03:24,800 there's a fixed and finite part of the machine. 53 00:03:24,800 --> 00:03:27,050 There's a finite-state controller, which does some 54 00:03:27,050 --> 00:03:30,510 particular thing with a particular amount of hardware. 55 00:03:30,510 --> 00:03:32,470 There are particular data paths: the operation the 56 00:03:32,470 --> 00:03:33,550 machine does. 57 00:03:33,550 --> 00:03:35,780 And then, in order to implement recursion and 58 00:03:35,780 --> 00:03:38,460 sustain the illusion of infinity, there's some large 59 00:03:38,460 --> 00:03:42,060 amount of memory, which is the stack. 60 00:03:42,060 --> 00:03:47,280 So, if we implement LISP in terms of a register machine, 61 00:03:47,280 --> 00:03:48,900 then everything ought to become, at this point, 62 00:03:48,900 --> 00:03:49,850 completely concrete. 63 00:03:49,850 --> 00:03:51,650 All the magic should go away. 64 00:03:51,650 --> 00:03:55,140 And, by the end of this talk, I want you get the feeling 65 00:03:55,140 --> 00:03:58,400 that, as opposed to this very mysterious meta-circular 66 00:03:58,400 --> 00:04:01,630 evaluator, that a LISP evaluator really is something 67 00:04:01,630 --> 00:04:03,740 that's concrete enough that you can hold in the 68 00:04:03,740 --> 00:04:04,720 palm of your hand. 69 00:04:04,720 --> 00:04:06,950 You should be able to imagine holding a 70 00:04:06,950 --> 00:04:09,546 LISP interpreter there. 71 00:04:09,546 --> 00:04:10,950 All right, how are we going to do this? 72 00:04:10,950 --> 00:04:13,960 We already have all the ingredients. 73 00:04:13,960 --> 00:04:18,300 See, what you learned last time from Jerry is how to take 74 00:04:18,300 --> 00:04:23,980 any particular couple of LISP procedures and hand-translate 75 00:04:23,980 --> 00:04:28,210 them into something that runs on a register machine. 76 00:04:28,210 --> 00:04:30,900 So, to implement all of LISP on a register machine, all we 77 00:04:30,900 --> 00:04:34,010 have to do is take the particular procedures that are 78 00:04:34,010 --> 00:04:37,450 the meta-circular evaluator and hand-translate them for a 79 00:04:37,450 --> 00:04:39,120 register machine. 80 00:04:39,120 --> 00:04:42,320 And that does all of LISP, right? 81 00:04:42,320 --> 00:04:45,380 So, in principle, we already know how to do this. 82 00:04:45,380 --> 00:04:51,640 And, indeed, it's going to be no different, in kind, from 83 00:04:51,640 --> 00:04:53,430 translating, say, recursive factorial 84 00:04:53,430 --> 00:04:54,670 or recursive Fibonacci. 85 00:04:54,670 --> 00:04:56,840 It's just bigger and there's more of it. 86 00:04:56,840 --> 00:04:58,760 So it'd just be more details, but nothing really 87 00:04:58,760 --> 00:05:01,730 conceptually new. 88 00:05:01,730 --> 00:05:03,600 All right, also, when we've done that, and the thing is 89 00:05:03,600 --> 00:05:06,990 completely explicit, and we see how to implement LISP in 90 00:05:06,990 --> 00:05:10,510 terms of the actual sequential register operations, that's 91 00:05:10,510 --> 00:05:13,230 going to be our final most explicit model of 92 00:05:13,230 --> 00:05:14,810 LISP in this course. 93 00:05:14,810 --> 00:05:16,410 And, remember, that's a progression 94 00:05:16,410 --> 00:05:16,950 through this course. 95 00:05:16,950 --> 00:05:18,790 We started out with substitution, which is sort of 96 00:05:18,790 --> 00:05:20,370 like algebra. 97 00:05:20,370 --> 00:05:22,070 And then we went to the environment model, which 98 00:05:22,070 --> 00:05:24,230 talked about the actual frames and how 99 00:05:24,230 --> 00:05:26,390 they got linked together. 100 00:05:26,390 --> 00:05:28,100 And then we made that more concrete in the 101 00:05:28,100 --> 00:05:31,080 meta-circular evaluator. 102 00:05:31,080 --> 00:05:33,120 There are things the meta-circular evaluator 103 00:05:33,120 --> 00:05:34,360 doesn't tell us. 104 00:05:34,360 --> 00:05:36,090 You should realize that. 105 00:05:36,090 --> 00:05:40,420 For instance, it left unanswered the question of how 106 00:05:40,420 --> 00:05:46,100 a procedure, like recursive factorial here , somehow takes 107 00:05:46,100 --> 00:05:47,210 space that grows. 108 00:05:47,210 --> 00:05:51,160 On the other hand, a procedure which also looks syntactically 109 00:05:51,160 --> 00:05:56,760 recursive, called fact-iter, somehow doesn't take space. 110 00:05:56,760 --> 00:06:01,040 We justify that it doesn't need to take space by showing 111 00:06:01,040 --> 00:06:01,960 the substitution model. 112 00:06:01,960 --> 00:06:05,550 But we didn't really say how it happens that the machine 113 00:06:05,550 --> 00:06:09,210 manages to do that, that that has to do with the details of 114 00:06:09,210 --> 00:06:12,520 how arguments are passed to procedures. 115 00:06:12,520 --> 00:06:14,710 And that's the thing we didn't see in the meta-circular 116 00:06:14,710 --> 00:06:17,930 evaluator precisely because the way arguments got passed 117 00:06:17,930 --> 00:06:21,840 to procedures in this LISP depended on the way arguments 118 00:06:21,840 --> 00:06:23,510 got passed to procedures in this LISP. 119 00:06:26,070 --> 00:06:30,740 But, now, that's going to become extremely explicit. 120 00:06:30,740 --> 00:06:31,230 OK. 121 00:06:31,230 --> 00:06:35,000 Well, before going on to the evaluator, let me just give 122 00:06:35,000 --> 00:06:37,940 you a sense of what a whole LISP system looks like so you 123 00:06:37,940 --> 00:06:39,730 can see the parts we're going to talk about and the parts 124 00:06:39,730 --> 00:06:43,250 we're not going to talk about. 125 00:06:43,250 --> 00:06:49,240 Let's see, over here is a happy LISP user, and the LISP 126 00:06:49,240 --> 00:06:52,525 user is talking to something called the reader. 127 00:07:00,360 --> 00:07:14,170 The reader's job in life is to take characters from the user 128 00:07:14,170 --> 00:07:17,960 and turn them into data structures in something called 129 00:07:17,960 --> 00:07:19,210 a list structure memory. 130 00:07:29,783 --> 00:07:33,110 All right, so the reader is going to take symbols, 131 00:07:33,110 --> 00:07:36,600 parentheses, and A's and B's, and ones and threes that you 132 00:07:36,600 --> 00:07:39,460 type in, and turn these into actual list structure: pairs, 133 00:07:39,460 --> 00:07:42,340 and pointers, and things. 134 00:07:42,340 --> 00:07:44,180 And so, by the time evaluator is going, there are no 135 00:07:44,180 --> 00:07:45,850 characters in the world. 136 00:07:45,850 --> 00:07:49,480 And, of course, in more modern list systems, there's sort of 137 00:07:49,480 --> 00:07:51,770 a big morass here that might sit between the user and the 138 00:07:51,770 --> 00:07:55,390 reader: Windows systems, and top levels, and mice, and all 139 00:07:55,390 --> 00:07:56,280 kinds of things. 140 00:07:56,280 --> 00:07:59,590 But conceptually, characters are coming in. 141 00:07:59,590 --> 00:08:06,240 All right, the reader transforms these into pointers 142 00:08:06,240 --> 00:08:09,940 to stuff in this memory, and that's what the 143 00:08:09,940 --> 00:08:17,090 evaluator sees, OK? 144 00:08:17,090 --> 00:08:19,780 The evaluator has a bunch of helpers. 145 00:08:19,780 --> 00:08:23,080 It has all possible primitive operators you might want. 146 00:08:23,080 --> 00:08:29,610 So there's a completely separate box, a floating point 147 00:08:29,610 --> 00:08:33,340 unit, or all sorts of things, which do 148 00:08:33,340 --> 00:08:35,960 the primitive operators. 149 00:08:35,960 --> 00:08:38,240 And, if you want more special primitives, you build more 150 00:08:38,240 --> 00:08:39,309 primitive operators, but they're 151 00:08:39,309 --> 00:08:42,080 separate from the evaluator. 152 00:08:42,080 --> 00:08:46,150 The evaluator finally gets an answer and communicates that 153 00:08:46,150 --> 00:08:47,400 to the printer. 154 00:08:50,780 --> 00:08:52,980 And now, the printer's job in life is to take this list 155 00:08:52,980 --> 00:08:56,150 structure coming from the evaluator, and turn it back 156 00:08:56,150 --> 00:09:03,630 into characters, and communicate them to the user 157 00:09:03,630 --> 00:09:05,540 through whatever interface there is. 158 00:09:08,050 --> 00:09:08,810 OK. 159 00:09:08,810 --> 00:09:10,100 Well, today, what we're going to talk 160 00:09:10,100 --> 00:09:12,670 about is this evaluator. 161 00:09:12,670 --> 00:09:14,900 The primitive operators have nothing particular to do with 162 00:09:14,900 --> 00:09:17,430 LISP, they're however you like to implement primitive 163 00:09:17,430 --> 00:09:19,440 operations. 164 00:09:19,440 --> 00:09:22,370 The reader and printer are actually complicated, but 165 00:09:22,370 --> 00:09:24,420 we're not going to talk about them. 166 00:09:24,420 --> 00:09:27,410 They sort of have to do with details of how you might build 167 00:09:27,410 --> 00:09:29,900 up list structure from characters. 168 00:09:29,900 --> 00:09:31,650 So that is a long story, but we're not going 169 00:09:31,650 --> 00:09:32,490 to talk about it. 170 00:09:32,490 --> 00:09:36,930 The list structure memory, we'll talk about next time. 171 00:09:36,930 --> 00:09:39,170 So, pretty much, except for the details of reading and 172 00:09:39,170 --> 00:09:41,860 printing, the only mystery that's going to be left after 173 00:09:41,860 --> 00:09:44,950 you see the evaluator is how you build list structure on 174 00:09:44,950 --> 00:09:46,295 conventional memories. 175 00:09:46,295 --> 00:09:50,580 But we'll worry about that next time too. 176 00:09:50,580 --> 00:09:51,830 OK. 177 00:09:53,350 --> 00:09:56,110 Well, let's start talking about the evaluator. 178 00:09:56,110 --> 00:09:59,970 The one that we're going to show you, of course, is not, I 179 00:09:59,970 --> 00:10:01,120 think, nothing special about it. 180 00:10:01,120 --> 00:10:03,040 It's just a particular register 181 00:10:03,040 --> 00:10:04,810 machine that runs LISP. 182 00:10:04,810 --> 00:10:08,280 And it has seven registers, and here 183 00:10:08,280 --> 00:10:09,890 are the seven registers. 184 00:10:09,890 --> 00:10:16,430 There's a register, called EXP, and its job is to hold 185 00:10:16,430 --> 00:10:18,370 the expression to be evaluated. 186 00:10:18,370 --> 00:10:22,660 And by that, I mean it's going to hold a pointer to someplace 187 00:10:22,660 --> 00:10:24,040 in list structure memory that holds the 188 00:10:24,040 --> 00:10:26,550 expression to be evaluated. 189 00:10:26,550 --> 00:10:29,490 There's a register, called ENV, which holds the 190 00:10:29,490 --> 00:10:34,070 environment in which this expression is to be evaluated. 191 00:10:34,070 --> 00:10:34,940 And, again, I made a pointer. 192 00:10:34,940 --> 00:10:38,240 The environment is some data structure. 193 00:10:38,240 --> 00:10:41,390 There's a register, called FUN, which will hold the 194 00:10:41,390 --> 00:10:44,630 procedure to be applied when you go to apply a procedure. 195 00:10:44,630 --> 00:10:48,210 A register, called ARGL, which wants the list 196 00:10:48,210 --> 00:10:50,630 of evaluated arguments. 197 00:10:50,630 --> 00:10:52,060 What you can start seeing here is the basic 198 00:10:52,060 --> 00:10:53,140 structure of the evaluator. 199 00:10:53,140 --> 00:10:54,490 Remember how evaluators work. 200 00:10:54,490 --> 00:10:57,670 There's a piece that takes expressions and environments, 201 00:10:57,670 --> 00:10:59,880 and there's a piece that takes functions, or 202 00:10:59,880 --> 00:11:03,480 procedures and arguments. 203 00:11:03,480 --> 00:11:05,360 And going back and forth around here is 204 00:11:05,360 --> 00:11:07,740 the eval/apply loop. 205 00:11:07,740 --> 00:11:10,270 So those are the basic pieces of the eval and apply. 206 00:11:10,270 --> 00:11:11,610 Then there's some other things, there's continue. 207 00:11:11,610 --> 00:11:15,340 You just saw before how the continue register is used to 208 00:11:15,340 --> 00:11:19,000 implement recursion and stack discipline. 209 00:11:19,000 --> 00:11:21,510 There's a register that's going to hold the result of 210 00:11:21,510 --> 00:11:24,190 some evaluation. 211 00:11:24,190 --> 00:11:25,890 And then, besides that, there's one temporary 212 00:11:25,890 --> 00:11:29,280 register, called UNEV, which typically, in the evaluator, 213 00:11:29,280 --> 00:11:32,980 is going to be used to hold temporary pieces of the 214 00:11:32,980 --> 00:11:34,690 expression you're working on, which you haven't gotten 215 00:11:34,690 --> 00:11:37,150 around to evaluate yet, right? 216 00:11:37,150 --> 00:11:40,646 So there's my machine: a seven-register machine. 217 00:11:40,646 --> 00:11:43,300 And, of course, you might want to make a machine with a lot 218 00:11:43,300 --> 00:11:46,040 more registers to get better performance, but this is just 219 00:11:46,040 --> 00:11:48,480 a tiny, minimal one. 220 00:11:48,480 --> 00:11:49,780 Well, how about the data paths? 221 00:11:49,780 --> 00:11:55,100 This machine has a lot of special operations for LISP. 222 00:11:55,100 --> 00:12:00,120 So, here are some typical data paths. 223 00:12:00,120 --> 00:12:03,410 A typical one might be, oh, assign to the VAL register the 224 00:12:03,410 --> 00:12:06,710 contents of the EXP register. 225 00:12:06,710 --> 00:12:10,190 In terms of those diagrams you saw, that's a little button on 226 00:12:10,190 --> 00:12:11,900 some arrow. 227 00:12:11,900 --> 00:12:14,040 Here's a more complicated one. 228 00:12:14,040 --> 00:12:18,810 It says branch, if the thing in the expression register is 229 00:12:18,810 --> 00:12:21,820 a conditional to some label here, called the 230 00:12:21,820 --> 00:12:23,850 ev-conditional. 231 00:12:23,850 --> 00:12:25,680 And you can imagine this implemented in a lot of 232 00:12:25,680 --> 00:12:26,230 different ways. 233 00:12:26,230 --> 00:12:28,950 You might imagine this conditional test as a special 234 00:12:28,950 --> 00:12:32,180 purpose sub-routine, and conditional might be 235 00:12:32,180 --> 00:12:34,400 represented as some data abstraction that you don't 236 00:12:34,400 --> 00:12:36,610 care about at this level of detail. 237 00:12:36,610 --> 00:12:37,980 So that might be done as a sub-routine. 238 00:12:37,980 --> 00:12:41,200 This might be a machine with hardware-types, and 239 00:12:41,200 --> 00:12:42,910 conditional might be testing some bits for 240 00:12:42,910 --> 00:12:45,350 a particular code. 241 00:12:45,350 --> 00:12:47,280 There are all sorts of ways that's beneath the level of 242 00:12:47,280 --> 00:12:50,190 abstraction we're looking at. 243 00:12:50,190 --> 00:12:52,610 Another kind of operation, and there are a lot of different 244 00:12:52,610 --> 00:12:55,880 operations assigned to EXP, the first clause 245 00:12:55,880 --> 00:12:56,840 of what's in EXP. 246 00:12:56,840 --> 00:12:59,260 This might be part of processing a conditional. 247 00:12:59,260 --> 00:13:03,810 And, again, first clause is some selector whose details we 248 00:13:03,810 --> 00:13:04,470 don't care about. 249 00:13:04,470 --> 00:13:06,670 And you can, again, imagine that as a sub-routine which'll 250 00:13:06,670 --> 00:13:09,180 do some list operations, or you can imagine that as 251 00:13:09,180 --> 00:13:12,170 something that's built directly into hardware. 252 00:13:12,170 --> 00:13:14,580 The reason I keep saying you can imagine it built directly 253 00:13:14,580 --> 00:13:18,360 into hardware is even though there are a lot of operations, 254 00:13:18,360 --> 00:13:19,740 there are still a fixed number of them. 255 00:13:19,740 --> 00:13:22,370 I forget how many, maybe 150. 256 00:13:22,370 --> 00:13:24,360 So, it's plausible to think of building these 257 00:13:24,360 --> 00:13:26,400 directly into hardware. 258 00:13:26,400 --> 00:13:28,500 Here's a more complicated one. 259 00:13:28,500 --> 00:13:29,940 You can see this has to do with looking up 260 00:13:29,940 --> 00:13:31,710 the values of variables. 261 00:13:31,710 --> 00:13:34,370 It says assign to the VAL register the result of looking 262 00:13:34,370 --> 00:13:39,310 up the variable value of some particular expression, which, 263 00:13:39,310 --> 00:13:41,330 in this case, is supposed to be a variable in some 264 00:13:41,330 --> 00:13:42,850 environment. 265 00:13:42,850 --> 00:13:46,650 And this'll be some operation that searches through the 266 00:13:46,650 --> 00:13:49,860 environment structure, however it is represented, and goes 267 00:13:49,860 --> 00:13:52,240 and looks up that variable. 268 00:13:52,240 --> 00:13:54,360 And, again, that's below the level of detail that we're 269 00:13:54,360 --> 00:13:55,790 thinking about. 270 00:13:55,790 --> 00:13:58,350 This has to do with the details of the data structures 271 00:13:58,350 --> 00:14:00,380 for representing environments. 272 00:14:00,380 --> 00:14:04,410 But, anyway, there is this fixed and finite number of 273 00:14:04,410 --> 00:14:05,940 operations in the register machine. 274 00:14:08,500 --> 00:14:11,720 Well, what's its overall structure? 275 00:14:11,720 --> 00:14:14,930 Those are some typical operations. 276 00:14:14,930 --> 00:14:17,060 Remember what we have to do, we have to take the 277 00:14:17,060 --> 00:14:20,172 meta-circular evaluator-- 278 00:14:20,172 --> 00:14:22,890 and here's a piece of the meta-circular evaluator. 279 00:14:22,890 --> 00:14:28,310 This is the one using abstract syntax that's in the book. 280 00:14:28,310 --> 00:14:30,500 It's a little bit different from the one 281 00:14:30,500 --> 00:14:33,500 that Jerry shows you. 282 00:14:33,500 --> 00:14:37,950 And the main thing to remember about the evaluator is that 283 00:14:37,950 --> 00:14:40,310 it's doing some sort of case analysis on the kinds of 284 00:14:40,310 --> 00:14:46,120 expressions: so if it's either self-evaluated, or quoted, or 285 00:14:46,120 --> 00:14:48,560 whatever else. 286 00:14:48,560 --> 00:14:51,620 And then, in the general case where the expression it's 287 00:14:51,620 --> 00:14:54,280 looking at is an application, there's some tricky 288 00:14:54,280 --> 00:14:55,750 recursions going on. 289 00:14:55,750 --> 00:15:00,730 First of all, eval has to call itself both to evaluate the 290 00:15:00,730 --> 00:15:05,880 operator and to evaluate all the operands. 291 00:15:05,880 --> 00:15:08,470 So there's this sort of red recursion of values walking 292 00:15:08,470 --> 00:15:12,270 down the tree that's really the easy recursion. 293 00:15:12,270 --> 00:15:14,750 That's just a val walking down this tree of expressions. 294 00:15:14,750 --> 00:15:16,600 Then, in the evaluator, there's a hard recursion. 295 00:15:16,600 --> 00:15:18,200 There's the red to green. 296 00:15:18,200 --> 00:15:19,450 Eval calls apply. 297 00:15:22,470 --> 00:15:26,132 That's the case where evaluating a procedure or 298 00:15:26,132 --> 00:15:28,920 argument reduces to applying the procedure 299 00:15:28,920 --> 00:15:30,370 to the list of arguments. 300 00:15:30,370 --> 00:15:31,700 And then, apply comes over here. 301 00:15:34,770 --> 00:15:39,270 Apply takes a procedure and arguments and, in the general 302 00:15:39,270 --> 00:15:41,950 case where there's a compound procedure, apply goes around 303 00:15:41,950 --> 00:15:44,560 and green calls red. 304 00:15:44,560 --> 00:15:48,170 Apply comes around and calls eval again. 305 00:15:48,170 --> 00:15:51,330 Eval's the body of the procedure in the result of 306 00:15:51,330 --> 00:15:54,600 extending the environment with the parameters of the 307 00:15:54,600 --> 00:15:56,605 procedure by binding the arguments. 308 00:15:59,620 --> 00:16:01,560 Except in the primitive case, where it just calls something 309 00:16:01,560 --> 00:16:03,550 else primitive-apply, which is not really the 310 00:16:03,550 --> 00:16:05,980 business of the evaluator. 311 00:16:05,980 --> 00:16:11,630 So this sort of red to green, to red to green, that's the 312 00:16:11,630 --> 00:16:15,130 eval/apply loop, and that's the thing that we're going to 313 00:16:15,130 --> 00:16:17,186 want to see in the evaluator. 314 00:16:19,840 --> 00:16:19,970 All right. 315 00:16:19,970 --> 00:16:22,570 Well, it won't surprise you at all that the two big pieces of 316 00:16:22,570 --> 00:16:27,470 this evaluator correspond to eval and apply. 317 00:16:27,470 --> 00:16:30,070 There's a piece called eval-dispatch, and a piece 318 00:16:30,070 --> 00:16:32,110 called apply-dispatch. 319 00:16:32,110 --> 00:16:34,520 And, before we get into the details of the code, the way 320 00:16:34,520 --> 00:16:37,760 to understand this is to think, again, in terms of 321 00:16:37,760 --> 00:16:40,430 these pieces of the evaluator having contracts with the rest 322 00:16:40,430 --> 00:16:41,870 of the world. 323 00:16:41,870 --> 00:16:44,320 What do they do from the outside before getting into 324 00:16:44,320 --> 00:16:45,780 the grungy details? 325 00:16:45,780 --> 00:16:50,080 Well, the contract for eval-dispatch-- 326 00:16:50,080 --> 00:16:51,300 remember, it corresponds to eval. 327 00:16:51,300 --> 00:16:54,100 It's got to evaluate an expression in an environment. 328 00:16:54,100 --> 00:16:56,840 So, in particular, what this one is going to do, 329 00:16:56,840 --> 00:16:59,920 eval-dispatch will assume that, when you call it, that 330 00:16:59,920 --> 00:17:01,460 the expression you want to evaluate 331 00:17:01,460 --> 00:17:03,640 is in the EXP register. 332 00:17:03,640 --> 00:17:07,680 The environment in which you want the evaluation to take 333 00:17:07,680 --> 00:17:09,569 place is in the ENV register. 334 00:17:09,569 --> 00:17:12,040 And continue tells you the place where the machine should 335 00:17:12,040 --> 00:17:13,880 go next when the evaluation is done. 336 00:17:17,440 --> 00:17:20,210 Eval-dispatch's contract is that it'll actually perform 337 00:17:20,210 --> 00:17:23,930 that evaluation, and, at the end of which, it'll end up at 338 00:17:23,930 --> 00:17:26,619 the place specified by continue. 339 00:17:26,619 --> 00:17:29,950 The result of the evaluation will be in the VAL register. 340 00:17:29,950 --> 00:17:33,100 And it just warns you, it makes no promises about what 341 00:17:33,100 --> 00:17:35,230 happens to the registers. 342 00:17:35,230 --> 00:17:37,490 All other registers might be destroyed. 343 00:17:37,490 --> 00:17:41,790 So, there's one piece, OK? 344 00:17:41,790 --> 00:17:43,640 Together, the pieces, apply-dispatch that 345 00:17:43,640 --> 00:17:47,650 corresponds to apply, it's got to apply a procedure to some 346 00:17:47,650 --> 00:17:52,060 arguments, so it assumes that this register, ARGL, contains 347 00:17:52,060 --> 00:17:54,540 a list of the evaluated arguments. 348 00:17:54,540 --> 00:17:57,220 FUN contains the procedure. 349 00:17:57,220 --> 00:17:59,500 Those correspond to the arguments to the apply 350 00:17:59,500 --> 00:18:01,055 procedure in the meta-circular evaluator. 351 00:18:03,970 --> 00:18:06,520 And apply, in this particular evaluator, we're going to use 352 00:18:06,520 --> 00:18:10,790 a discipline which says the place the machine should go to 353 00:18:10,790 --> 00:18:14,480 next when apply is done is, at the moment apply-dispatch is 354 00:18:14,480 --> 00:18:18,850 called at the top of the stack, that's just discipline 355 00:18:18,850 --> 00:18:21,840 for the way this particular machine's organized. 356 00:18:21,840 --> 00:18:23,950 And now apply's contract is given all that. 357 00:18:23,950 --> 00:18:25,540 It'll perform the application. 358 00:18:25,540 --> 00:18:28,890 The result of that application will end up in VAL. 359 00:18:28,890 --> 00:18:31,120 The stack will be popped. 360 00:18:31,120 --> 00:18:33,460 And, again, the contents of all the other registers may be 361 00:18:33,460 --> 00:18:35,110 destroyed, all right? 362 00:18:35,110 --> 00:18:39,760 So that's the basic organization of this machine. 363 00:18:39,760 --> 00:18:41,110 Let's break for a little bit and see if there are any 364 00:18:41,110 --> 00:18:42,700 questions, and then we'll do a real example. 365 00:19:47,850 --> 00:19:51,300 Well, let's take the register machine now, and actually step 366 00:19:51,300 --> 00:19:57,950 through, and really, in real detail, so you see completely 367 00:19:57,950 --> 00:20:03,400 concrete how some expressions are evaluated, all right? 368 00:20:03,400 --> 00:20:06,435 So, let's start with a very simple expression. 369 00:20:09,620 --> 00:20:13,320 Let's evaluate the expression 1. 370 00:20:18,880 --> 00:20:21,620 And we need an environment, so let's imagine that somewhere 371 00:20:21,620 --> 00:20:23,085 there's an environment, we'll call it E,0. 372 00:20:30,260 --> 00:20:36,230 And just, since we'll use these later, we obviously 373 00:20:36,230 --> 00:20:38,360 don't really need anything to evaluate 1. 374 00:20:38,360 --> 00:20:40,810 But, just for reference later, let's assume that E,0 has in 375 00:20:40,810 --> 00:20:49,140 it an X that's bound to 3 and a Y that's bound to 4, OK? 376 00:20:49,140 --> 00:20:53,700 And now what we're going to do is we're going to evaluate 1 377 00:20:53,700 --> 00:20:59,650 in this environment, and so the ENV register has a pointer 378 00:20:59,650 --> 00:21:03,560 to this environment, E,0, all right? 379 00:21:03,560 --> 00:21:05,650 So let's watch that thing go. 380 00:21:05,650 --> 00:21:08,260 What I'm going to do is step through the code. 381 00:21:08,260 --> 00:21:10,080 And, let's see, I'll be the controller. 382 00:21:10,080 --> 00:21:12,980 And now what I need, since this gets rather complicated, 383 00:21:12,980 --> 00:21:16,830 is a very little execution unit. 384 00:21:16,830 --> 00:21:22,624 So here's the execution unit, OK? 385 00:21:22,624 --> 00:21:23,874 OK. 386 00:21:27,088 --> 00:21:28,590 OK. 387 00:21:28,590 --> 00:21:30,690 All right, now we're going to start. 388 00:21:30,690 --> 00:21:31,710 We're going to start the machine at 389 00:21:31,710 --> 00:21:33,660 eval-dispatch, right? 390 00:21:33,660 --> 00:21:36,120 That's the beginning of this. 391 00:21:36,120 --> 00:21:39,320 Eval-dispatch is going to look at the expression in dispatch, 392 00:21:39,320 --> 00:21:42,010 just like eval where we look at the very first thing. 393 00:21:42,010 --> 00:21:46,990 We branch on whether or not this expression is 394 00:21:46,990 --> 00:21:47,950 self-evaluating. 395 00:21:47,950 --> 00:21:50,170 Self-evaluating is some abstraction we 396 00:21:50,170 --> 00:21:52,550 put into the machine-- 397 00:21:52,550 --> 00:21:53,690 it's going to be true for numbers-- 398 00:21:53,690 --> 00:21:57,040 to a place called ev-self-eval, right? 399 00:21:57,040 --> 00:22:00,260 So me, being the controller, looks at ev-self-eval, so 400 00:22:00,260 --> 00:22:02,780 we'll go over to there. 401 00:22:02,780 --> 00:22:09,050 Ev-self-eval says fine, assign to val whatever is in the 402 00:22:09,050 --> 00:22:15,220 expression unit, OK? 403 00:22:15,220 --> 00:22:19,930 And I have a bug because what I didn't do when I initialized 404 00:22:19,930 --> 00:22:23,610 this machine is also say what's supposed to happen when 405 00:22:23,610 --> 00:22:27,640 it's done, so I should have started out the machine with 406 00:22:27,640 --> 00:22:32,050 done being in the continue register, OK? 407 00:22:32,050 --> 00:22:33,640 So we assign to VAL. 408 00:22:33,640 --> 00:22:35,790 And now go to fetch of continue, and 409 00:22:35,790 --> 00:22:38,000 [? the value changed. ?] 410 00:22:38,000 --> 00:22:40,000 OK. 411 00:22:40,000 --> 00:22:42,160 OK, let's try something harder. 412 00:22:42,160 --> 00:22:47,900 Let's reset the machine here, and we'll put in the 413 00:22:47,900 --> 00:22:56,710 expression register, X, OK? 414 00:22:56,710 --> 00:22:59,610 Start again at eval-dispatch. 415 00:22:59,610 --> 00:23:01,690 Check, is it self-evaluating? 416 00:23:01,690 --> 00:23:02,650 No. 417 00:23:02,650 --> 00:23:04,630 Is it a variable? 418 00:23:04,630 --> 00:23:05,560 Yes. 419 00:23:05,560 --> 00:23:08,380 We go off to ev-variable. 420 00:23:08,380 --> 00:23:14,700 It says assign to VAL, look up the variable value in the 421 00:23:14,700 --> 00:23:21,620 expression register, OK? 422 00:23:21,620 --> 00:23:23,625 Go to fetch of continue. 423 00:23:23,625 --> 00:23:24,875 PROFESSOR: Done. 424 00:23:27,252 --> 00:23:28,950 PROFESSOR: OK. 425 00:23:28,950 --> 00:23:29,430 All right. 426 00:23:29,430 --> 00:23:31,330 Well, that's the basic idea. 427 00:23:31,330 --> 00:23:32,920 That's a simple operation of the machine. 428 00:23:32,920 --> 00:23:34,600 Now, let's actually do something a little bit more 429 00:23:34,600 --> 00:23:36,070 interesting. 430 00:23:36,070 --> 00:23:49,678 Let's look at the expression the sum of x and y. 431 00:23:49,678 --> 00:23:50,130 OK. 432 00:23:50,130 --> 00:23:53,240 And now we'll see how you start unrolling these 433 00:23:53,240 --> 00:23:57,100 expression trees, OK? 434 00:23:57,100 --> 00:24:00,645 Well, start again at eval-dispatch, all right? 435 00:24:04,610 --> 00:24:06,060 Self-evaluating? 436 00:24:06,060 --> 00:24:06,810 No. 437 00:24:06,810 --> 00:24:07,280 Variable? 438 00:24:07,280 --> 00:24:07,850 No. 439 00:24:07,850 --> 00:24:10,270 All the other special forms which I didn't write down, 440 00:24:10,270 --> 00:24:12,480 like quote, and lambda, and set, and whatever, 441 00:24:12,480 --> 00:24:13,260 it's none of those. 442 00:24:13,260 --> 00:24:16,520 It turns out to be an application, so we go off to 443 00:24:16,520 --> 00:24:19,970 ev-application, OK? 444 00:24:19,970 --> 00:24:25,580 Ev-application, remember what it's going to do overall. 445 00:24:25,580 --> 00:24:28,310 It is going to evaluate the operator. 446 00:24:28,310 --> 00:24:32,950 It's going to evaluate the arguments, and then it's going 447 00:24:32,950 --> 00:24:35,060 to go apply them. 448 00:24:35,060 --> 00:24:38,140 So, before we start, since we're being very literal, we'd 449 00:24:38,140 --> 00:24:40,610 better remember that, somewhere in this environment, 450 00:24:40,610 --> 00:24:46,010 it's linked to another environment in which plus is 451 00:24:46,010 --> 00:24:52,380 bound to the primitive procedure plus before we get 452 00:24:52,380 --> 00:24:55,340 an unknown variable in our machine. 453 00:24:55,340 --> 00:24:56,590 OK, so we're at ev-application. 454 00:24:59,850 --> 00:25:05,920 OK, assign to UNEV the operands of what's in the 455 00:25:05,920 --> 00:25:07,920 expression register, OK? 456 00:25:07,920 --> 00:25:09,230 Those are the operands. 457 00:25:09,230 --> 00:25:11,920 UNEV's a temporary register where we're 458 00:25:11,920 --> 00:25:12,916 going to save them. 459 00:25:12,916 --> 00:25:13,860 PROFESSOR: I'm assigning. 460 00:25:13,860 --> 00:25:18,070 PROFESSOR: Assign to x the operator. 461 00:25:18,070 --> 00:25:22,140 Now, notice we've destroyed that expression in x, but the 462 00:25:22,140 --> 00:25:25,820 piece that we need is now in UNEV. OK. 463 00:25:25,820 --> 00:25:27,490 Now, we're going to get set up to recursively 464 00:25:27,490 --> 00:25:28,750 evaluate the operator. 465 00:25:28,750 --> 00:25:31,565 Save the continue register on the stack. 466 00:25:34,870 --> 00:25:36,120 Save the environment. 467 00:25:40,520 --> 00:25:53,210 Save UNEV. OK, assign to continue a 468 00:25:53,210 --> 00:25:54,460 label called eval-args. 469 00:26:01,400 --> 00:26:01,980 Now, what have we done? 470 00:26:01,980 --> 00:26:04,380 We've set up for a recursive call. 471 00:26:04,380 --> 00:26:06,280 We're about to go to eval-dispatch. 472 00:26:06,280 --> 00:26:10,230 We've set up for a recursive call to eval-dispatch. 473 00:26:10,230 --> 00:26:11,020 What did we do? 474 00:26:11,020 --> 00:26:15,240 We took the things we're going to need later, those operands 475 00:26:15,240 --> 00:26:17,860 that were in UNEV; the environment in which we're 476 00:26:17,860 --> 00:26:20,100 going to eventually have to, maybe, evaluate those 477 00:26:20,100 --> 00:26:23,910 operands; the place we eventually want to go to, 478 00:26:23,910 --> 00:26:27,120 which, in this case, was done; we've saved them on the stack. 479 00:26:27,120 --> 00:26:29,120 The reason we saved them on the stack is because 480 00:26:29,120 --> 00:26:31,860 eval-dispatch makes no promises about what registers 481 00:26:31,860 --> 00:26:33,550 it may destroy. 482 00:26:33,550 --> 00:26:35,020 So all that stuff is saved on the stack. 483 00:26:35,020 --> 00:26:37,380 Now, we've set up eval-dispatch's contract. 484 00:26:37,380 --> 00:26:41,220 There's a new expression, which is the operator plus; a 485 00:26:41,220 --> 00:26:44,250 new environment, although, in this case, it's the same one; 486 00:26:44,250 --> 00:26:45,670 and a new place to go to when you're 487 00:26:45,670 --> 00:26:47,600 done, which is eval-args. 488 00:26:47,600 --> 00:26:48,130 So that's set up. 489 00:26:48,130 --> 00:26:50,890 Now, we're going to go off to eval-dispatch. 490 00:26:50,890 --> 00:26:53,090 Here we are back at eval-dispatch. 491 00:26:53,090 --> 00:26:54,490 It's not self-evaluating. 492 00:26:54,490 --> 00:26:57,270 Oh, it's a variable, so we'd better go off to 493 00:26:57,270 --> 00:27:00,260 ev-variable, right? 494 00:27:00,260 --> 00:27:02,880 Ev-variable is assigned to VAL. 495 00:27:02,880 --> 00:27:08,770 Look up the variable value of the expression, OK? 496 00:27:08,770 --> 00:27:13,000 So VAL is the primitive procedure plus, OK? 497 00:27:13,000 --> 00:27:15,020 And go to fetch of continue. 498 00:27:15,020 --> 00:27:15,660 PROFESSOR: Eval-args. 499 00:27:15,660 --> 00:27:19,340 PROFESSOR: Right, which is now eval-args not done. 500 00:27:19,340 --> 00:27:23,210 So we come back here at eval-args, and what do we do? 501 00:27:23,210 --> 00:27:25,620 We're going to restore the stuff that we saved, so we 502 00:27:25,620 --> 00:27:31,710 restore UNEV. And notice, there, it wasn't necessary, 503 00:27:31,710 --> 00:27:32,900 although, in general, it would be. 504 00:27:32,900 --> 00:27:35,430 It might be some arbitrary evaluation that happened. 505 00:27:35,430 --> 00:27:51,900 We restore ENV. OK, we assign to FUN fetch of VAL. 506 00:27:58,620 --> 00:28:01,650 OK, now, we're going to go off and start 507 00:28:01,650 --> 00:28:04,340 evaluating some arguments. 508 00:28:04,340 --> 00:28:08,330 Well, first thing we'd better do is save FUN because some 509 00:28:08,330 --> 00:28:10,165 arbitrary stuff might happen in that evaluation. 510 00:28:15,330 --> 00:28:18,590 We initialize the argument list. Assign to argl an empty 511 00:28:18,590 --> 00:28:25,460 argument list, and go to eval-arg-loop, OK? 512 00:28:25,460 --> 00:28:29,580 At eval-arg-loop, the idea of this is we're going to 513 00:28:29,580 --> 00:28:32,620 evaluate the pieces of the expressions that are in UNEV, 514 00:28:32,620 --> 00:28:36,110 one by one, and move them from unevaluated in UNEV to 515 00:28:36,110 --> 00:28:38,090 evaluated in the arg list, OK? 516 00:28:38,090 --> 00:28:39,340 So we save argl. 517 00:28:43,950 --> 00:28:53,960 We assign to x the first operand of the stuff in UNEV. 518 00:28:53,960 --> 00:28:55,890 Now, we check and see if that was the last operand. 519 00:28:55,890 --> 00:28:59,190 In this case, it is not, all right? 520 00:28:59,190 --> 00:29:01,235 So we save the environment. 521 00:29:09,170 --> 00:29:12,620 We save UNEV because those are all things 522 00:29:12,620 --> 00:29:13,500 we might need later. 523 00:29:13,500 --> 00:29:14,860 We're going to need the environment to do some more 524 00:29:14,860 --> 00:29:15,800 evaluations. 525 00:29:15,800 --> 00:29:18,420 We're going to need UNEV to look at what the rest of those 526 00:29:18,420 --> 00:29:20,340 arguments were. 527 00:29:20,340 --> 00:29:22,170 We're going to assign continue a place called 528 00:29:22,170 --> 00:29:24,040 accumulate-args, or accumulate-arg. 529 00:29:30,898 --> 00:29:33,300 OK, now, we've set up for another call to 530 00:29:33,300 --> 00:29:36,810 eval-dispatch, OK? 531 00:29:36,810 --> 00:29:39,510 All right, now, let me short-circuit this so we don't 532 00:29:39,510 --> 00:29:41,090 go through the details of eval-dispatch. 533 00:29:41,090 --> 00:29:45,550 Eval-dispatch's contract says I'm going to end up, the world 534 00:29:45,550 --> 00:29:48,480 will end up, with the value of evaluating this expression in 535 00:29:48,480 --> 00:29:50,270 this environment in the VAL register, 536 00:29:50,270 --> 00:29:51,320 and I'll end up there. 537 00:29:51,320 --> 00:29:58,010 So we short-circuit all of this, and a 3 ends up in VAL. 538 00:29:58,010 --> 00:30:00,050 And, when we return from eval-dispatch, we're going to 539 00:30:00,050 --> 00:30:02,110 return to accumulate-arg. 540 00:30:02,110 --> 00:30:03,555 PROFESSOR: Accumulate-arg. 541 00:30:03,555 --> 00:30:08,720 PROFESSOR: With 3 in the VAL register, OK? 542 00:30:08,720 --> 00:30:10,650 So that short-circuited that evaluation. 543 00:30:10,650 --> 00:30:11,320 Now, what do we do? 544 00:30:11,320 --> 00:30:13,230 We're going to go back and look at the rest of the 545 00:30:13,230 --> 00:30:18,580 arguments, so we restore UNEV. We restore 546 00:30:18,580 --> 00:30:28,650 ENV. We restore argl. 547 00:30:28,650 --> 00:30:29,170 One thing. 548 00:30:29,170 --> 00:30:30,750 PROFESSOR: Oops! 549 00:30:30,750 --> 00:30:31,290 Parity error. 550 00:30:31,290 --> 00:30:33,465 [LAUGHTER] 551 00:30:33,465 --> 00:30:34,905 PROFESSOR: Restore argl. 552 00:30:41,650 --> 00:30:42,900 PROFESSOR: OK. 553 00:30:45,570 --> 00:30:51,880 OK, we assign to argl consing on fetch of the value register 554 00:30:51,880 --> 00:30:53,130 to what's in argl. 555 00:30:58,985 --> 00:31:04,050 OK, we assign to UNEV the rest of the operands in fetch of 556 00:31:04,050 --> 00:31:11,516 UNEV, and we go back to eval-arg-loop. 557 00:31:11,516 --> 00:31:12,280 PROFESSOR: Eval-arg-loop. 558 00:31:12,280 --> 00:31:13,530 PROFESSOR: OK. 559 00:31:15,880 --> 00:31:18,090 Now, we're about to do the next argument, so the first 560 00:31:18,090 --> 00:31:19,340 thing we do is save argl. 561 00:31:25,400 --> 00:31:35,060 OK, we assign to x the first operand of fetch of UNEV. OK, 562 00:31:35,060 --> 00:31:37,140 we test and see if that's the last operand. 563 00:31:37,140 --> 00:31:40,320 In this case, it is, so we're going to go to a special place 564 00:31:40,320 --> 00:31:43,930 that says evaluate the last argument because, notice, 565 00:31:43,930 --> 00:31:45,600 after evaluating the argument, we don't need the 566 00:31:45,600 --> 00:31:47,446 environment any more. 567 00:31:47,446 --> 00:31:50,250 That's going to be the difference. 568 00:31:50,250 --> 00:31:53,090 So here, at eval-last-arg, which is assigned to 569 00:31:53,090 --> 00:32:06,220 accumulate-last-arg, now, we're set up again for 570 00:32:06,220 --> 00:32:06,900 eval-dispatch. 571 00:32:06,900 --> 00:32:08,620 We've got a place to go to when we're done. 572 00:32:08,620 --> 00:32:09,840 We've got an expression. 573 00:32:09,840 --> 00:32:11,330 We've got an environment. 574 00:32:11,330 --> 00:32:14,370 OK, so we'll short-circuit the call to eval-dispatch. 575 00:32:14,370 --> 00:32:18,090 And what'll happen is there's a y there, it's 4 in that 576 00:32:18,090 --> 00:32:21,060 environment, so VAL will end up with 4 in it. 577 00:32:21,060 --> 00:32:25,450 And, then, we're going to end up at accumulate-last-arg, OK? 578 00:32:25,450 --> 00:32:30,150 So, at accumulate-last-arg, we restore argl. 579 00:32:41,490 --> 00:32:45,460 We assign to argl cons of fetch of the new value onto 580 00:32:45,460 --> 00:32:49,850 it, so we cons a 4 onto that. 581 00:32:49,850 --> 00:32:53,446 We restore what was saved in the function register. 582 00:32:53,446 --> 00:32:56,590 And notice, in this case, it had not been destroyed, but, 583 00:32:56,590 --> 00:32:59,420 in general, it will be. 584 00:32:59,420 --> 00:33:02,850 And now, we're ready to go off to apply-dispatch, all right? 585 00:33:02,850 --> 00:33:04,510 So we've just gone through the eval. 586 00:33:04,510 --> 00:33:07,980 We evaluated the argument, the operator, and the arguments, 587 00:33:07,980 --> 00:33:09,580 and now, we're about to apply them. 588 00:33:09,580 --> 00:33:17,481 So we come off to apply-dispatch here, OK? 589 00:33:17,481 --> 00:33:21,670 We come off to apply-dispatch, and we're going to check 590 00:33:21,670 --> 00:33:23,450 whether it's a primitive or a compound procedure. 591 00:33:23,450 --> 00:33:24,116 PROFESSOR: Yes. 592 00:33:24,116 --> 00:33:24,830 PROFESSOR: All right. 593 00:33:24,830 --> 00:33:27,870 So, in this case, it's a primitive procedure, and we go 594 00:33:27,870 --> 00:33:29,790 off to primitive-apply. 595 00:33:29,790 --> 00:33:34,130 So we go off to primitive-apply, and it says 596 00:33:34,130 --> 00:33:38,360 assign to VAL the result of applying primitive procedure 597 00:33:38,360 --> 00:33:40,940 of the function to the argument list. 598 00:33:40,940 --> 00:33:42,540 PROFESSOR: I don't know how to add. 599 00:33:42,540 --> 00:33:43,995 I'm just an execution unit. 600 00:33:43,995 --> 00:33:45,350 PROFESSOR: Well, I don't know how to add either. 601 00:33:45,350 --> 00:33:48,360 I'm just the evaluator, so we need a primitive operator. 602 00:33:48,360 --> 00:33:51,290 Let's see, so the primitive operator, what's the 603 00:33:51,290 --> 00:33:52,605 sum of 3 and 4? 604 00:33:52,605 --> 00:33:53,205 AUDIENCE: 7. 605 00:33:53,205 --> 00:33:54,580 PROFESSOR: OK, 7. 606 00:33:54,580 --> 00:33:55,999 PROFESSOR: Thank you. 607 00:33:58,837 --> 00:34:12,330 PROFESSOR: Now, we restore continue, and we go to fetch 608 00:34:12,330 --> 00:34:12,900 of continue. 609 00:34:12,900 --> 00:34:13,880 PROFESSOR: Done. 610 00:34:13,880 --> 00:34:14,929 PROFESSOR: OK. 611 00:34:14,929 --> 00:34:18,659 Well, that was in as much detail as you will ever see. 612 00:34:18,659 --> 00:34:21,590 We'll never do it in as much detail again. 613 00:34:21,590 --> 00:34:25,780 One very important thing to notice is that we just 614 00:34:25,780 --> 00:34:29,780 executed a recursive procedure, right? 615 00:34:29,780 --> 00:34:31,500 This whole thing, we used a stack and the 616 00:34:31,500 --> 00:34:33,070 evaluator was recursive. 617 00:34:33,070 --> 00:34:36,480 A lot of people think the reason that you need a stack 618 00:34:36,480 --> 00:34:39,090 and recursion in an evaluator is because you might be 619 00:34:39,090 --> 00:34:40,810 evaluating recursive procedures like 620 00:34:40,810 --> 00:34:42,150 factorial or Fibonacci. 621 00:34:42,150 --> 00:34:43,670 It's not true. 622 00:34:43,670 --> 00:34:46,110 So you notice we did recursion here, and all we evaluated was 623 00:34:46,110 --> 00:34:48,010 plus X, Y, all right? 624 00:34:48,010 --> 00:34:51,219 The reason that you need recursion in the evaluator is 625 00:34:51,219 --> 00:34:53,550 because the evaluation process, itself, is 626 00:34:53,550 --> 00:34:54,780 recursive, all right? 627 00:34:54,780 --> 00:34:57,760 It's not because the procedure that you might be evaluating 628 00:34:57,760 --> 00:34:59,270 in LISP is a recursive procedure. 629 00:34:59,270 --> 00:35:01,130 So that's an important thing that people get 630 00:35:01,130 --> 00:35:03,010 confused about a lot. 631 00:35:03,010 --> 00:35:06,280 The other thing to notice is that, when we're done here, 632 00:35:06,280 --> 00:35:07,120 we're really done. 633 00:35:07,120 --> 00:35:12,600 Not only are we at done, but there's no accumulated stuff 634 00:35:12,600 --> 00:35:13,810 on the stack, right? 635 00:35:13,810 --> 00:35:17,170 The machine is back to its initial state, all right? 636 00:35:17,170 --> 00:35:19,830 So that's part of what it means to be done. 637 00:35:19,830 --> 00:35:26,410 Another way to say that is the evaluation process has reduced 638 00:35:26,410 --> 00:35:33,460 the expression, plus X, Y, to the value here, 7. 639 00:35:33,460 --> 00:35:36,010 And by reduced, I mean a very particular thing. 640 00:35:36,010 --> 00:35:38,180 It means that there's nothing left on the stack. 641 00:35:38,180 --> 00:35:41,480 The machine is now in the same state, except there's 642 00:35:41,480 --> 00:35:42,760 something in the value register. 643 00:35:42,760 --> 00:35:44,520 It's not part of a sub-problem of anything. 644 00:35:44,520 --> 00:35:46,210 There's nothing to go back to. 645 00:35:46,210 --> 00:35:46,440 OK. 646 00:35:46,440 --> 00:35:47,690 Let's break. 647 00:35:49,712 --> 00:35:50,159 Question? 648 00:35:50,159 --> 00:35:54,800 AUDIENCE: The question here, in the stack, is because the 649 00:35:54,800 --> 00:35:55,820 data may be recursive. 650 00:35:55,820 --> 00:35:59,312 You may have embedded expressions, for instance. 651 00:35:59,312 --> 00:36:01,490 PROFESSOR: Yes, because you might have embedded 652 00:36:01,490 --> 00:36:02,080 expressions. 653 00:36:02,080 --> 00:36:06,400 But, again, don't confuse that with what people sometimes 654 00:36:06,400 --> 00:36:08,660 mean by the data may be recursive, which is to say you 655 00:36:08,660 --> 00:36:12,270 have these list-structured, recursive data list 656 00:36:12,270 --> 00:36:12,930 operations. 657 00:36:12,930 --> 00:36:13,980 That has nothing to do with it. 658 00:36:13,980 --> 00:36:15,360 It's simply that the expressions contain 659 00:36:15,360 --> 00:36:17,363 sub-expressions. 660 00:36:17,363 --> 00:36:19,618 Yeah? 661 00:36:19,618 --> 00:36:22,260 AUDIENCE: Why is it that the order of the arguments in the 662 00:36:22,260 --> 00:36:23,225 arg list got reversed? 663 00:36:23,225 --> 00:36:23,860 PROFESSOR: Ah! 664 00:36:23,860 --> 00:36:27,260 Yes, I should've mentioned that. 665 00:36:27,260 --> 00:36:28,755 Here, the reason the order is reversed-- 666 00:36:32,507 --> 00:36:36,050 it's a question of what you mean by reversed. 667 00:36:36,050 --> 00:36:40,624 I believe it was Newton. 668 00:36:40,624 --> 00:36:43,800 In the very early part of optics, people realized that, 669 00:36:43,800 --> 00:36:46,100 when you look through the lens of your eye, the image was 670 00:36:46,100 --> 00:36:46,840 up-side down. 671 00:36:46,840 --> 00:36:48,650 And there was a lot of argument about why that didn't 672 00:36:48,650 --> 00:36:51,280 mean you saw things up-side down. 673 00:36:51,280 --> 00:36:52,860 So it's sort of the same issue. 674 00:36:52,860 --> 00:36:54,810 Reversed from what? 675 00:36:54,810 --> 00:36:57,940 So we just need some convention. 676 00:36:57,940 --> 00:37:01,730 The reason that they're coming at 4, 3 is because we're 677 00:37:01,730 --> 00:37:04,520 taking UNEV and consing the result onto argl. 678 00:37:04,520 --> 00:37:06,900 So you have to realize you've made that convention. 679 00:37:06,900 --> 00:37:10,100 The place that you have to realize that-- 680 00:37:10,100 --> 00:37:11,230 well, there's actually two places. 681 00:37:11,230 --> 00:37:12,910 One is in apply-primitive-operator, 682 00:37:12,910 --> 00:37:16,610 which has to realize that the arguments to primitives go in, 683 00:37:16,610 --> 00:37:19,490 in the opposite order from the way you're writing them down. 684 00:37:19,490 --> 00:37:21,760 And the other one is, we'll see later when you actually go 685 00:37:21,760 --> 00:37:24,720 to bind a function's parameters, you should realize 686 00:37:24,720 --> 00:37:26,410 the arguments are going to come in from the opposite 687 00:37:26,410 --> 00:37:28,870 order of the variables to which you're binding them. 688 00:37:28,870 --> 00:37:31,830 So, if you just keep track of that, there's no problem. 689 00:37:31,830 --> 00:37:34,560 Also, this is completely arbitrary because, if we'd 690 00:37:34,560 --> 00:37:36,890 done, say, an iteration through a vector assigning 691 00:37:36,890 --> 00:37:40,730 them, they might come out in the other order, OK? 692 00:37:40,730 --> 00:37:42,700 So it's just a convention of the way this particular 693 00:37:42,700 --> 00:37:45,085 evaluator works. 694 00:37:45,085 --> 00:37:46,335 All right, let's take a break. 695 00:38:41,840 --> 00:38:46,050 We just saw evaluating an expression and, of course, 696 00:38:46,050 --> 00:38:46,950 that was very simple one. 697 00:38:46,950 --> 00:38:51,020 But, in essence, it would be no different if it was some 698 00:38:51,020 --> 00:38:53,370 big nested expression, so there would just be deeper 699 00:38:53,370 --> 00:38:55,130 recursion on the stack. 700 00:38:55,130 --> 00:38:56,920 But what I want to do now is show you the last piece. 701 00:38:56,920 --> 00:39:01,300 I want to walk you around this eval and apply loop, right? 702 00:39:01,300 --> 00:39:03,000 That's the thing we haven't seen, really. 703 00:39:03,000 --> 00:39:09,070 We haven't seen any compound procedures where applying a 704 00:39:09,070 --> 00:39:11,110 procedure reduces to evaluating the body of the 705 00:39:11,110 --> 00:39:15,810 procedure, so let's just suppose we had this. 706 00:39:15,810 --> 00:39:29,340 Suppose we were looking at the procedure define F of A and B 707 00:39:29,340 --> 00:39:36,520 to be the sum of A and B. So, as we typed in that procedure 708 00:39:36,520 --> 00:39:41,120 previously, and now we're going to evaluate F of X and 709 00:39:41,120 --> 00:39:46,030 Y, again, in this environment, E,0, where X is bound to 3 and 710 00:39:46,030 --> 00:39:47,280 Y is bound to 4. 711 00:39:50,830 --> 00:39:53,120 When the defined is executed, remember, there's a lambda 712 00:39:53,120 --> 00:39:55,950 here, and lambdas create procedures. 713 00:39:55,950 --> 00:40:01,430 And, basically, what will happen is, in E,0, we'll end 714 00:40:01,430 --> 00:40:07,440 up with a binding for F, which will say F is a procedure, and 715 00:40:07,440 --> 00:40:18,180 its args are A and B, and its body is plus a,b. 716 00:40:18,180 --> 00:40:21,460 So that's what the environment would have looked like had we 717 00:40:21,460 --> 00:40:24,400 made that definition. 718 00:40:24,400 --> 00:40:29,180 Then, when we go to evaluate F of X and Y, we'll go through 719 00:40:29,180 --> 00:40:31,810 exactly the same process that we did before. 720 00:40:31,810 --> 00:40:33,360 It's even the same expression. 721 00:40:33,360 --> 00:40:36,030 The only difference is that F, instead of having primitive 722 00:40:36,030 --> 00:40:41,040 plus in it, will have this thing. 723 00:40:41,040 --> 00:40:43,600 And so we'll go through exactly the same process, 724 00:40:43,600 --> 00:40:48,130 except this time, when we end up at apply-dispatch, the 725 00:40:48,130 --> 00:40:50,590 function register, instead of having primitive plus, will 726 00:40:50,590 --> 00:40:54,300 have a thing that will represent it saying procedure, 727 00:40:54,300 --> 00:41:08,040 where the args are A and B, and the body is plus A, B. 728 00:41:08,040 --> 00:41:10,420 And, again, what I mean, by its ENV, I mean there's a 729 00:41:10,420 --> 00:41:12,530 pointer to it, so don't worry that I'm writing a lot of 730 00:41:12,530 --> 00:41:13,280 stuff there. 731 00:41:13,280 --> 00:41:17,170 There's a pointer to this procedure data structure. 732 00:41:17,170 --> 00:41:20,960 OK, so, we're in exactly the same situation. 733 00:41:20,960 --> 00:41:25,720 We get to apply-dispatch, so, here, we come to 734 00:41:25,720 --> 00:41:26,480 apply-dispatch. 735 00:41:26,480 --> 00:41:30,010 Last time, we branched off to a primitive procedure. 736 00:41:30,010 --> 00:41:34,900 Here, it says oh, we now have a compound procedure, so we're 737 00:41:34,900 --> 00:41:36,150 going to go off to compound-apply. 738 00:41:38,660 --> 00:41:39,910 Now, what's compound-apply? 739 00:41:42,100 --> 00:41:45,090 Well, remember what the meta-circular evaluator did? 740 00:41:45,090 --> 00:41:50,790 Compound-apply said we're going to evaluate the body of 741 00:41:50,790 --> 00:41:54,120 the procedure in some new environment. 742 00:41:54,120 --> 00:41:56,730 Where does that new environment come from? 743 00:41:56,730 --> 00:42:00,620 We take the environment that was packaged with the 744 00:42:00,620 --> 00:42:06,080 procedure, we bind the parameters of the procedure to 745 00:42:06,080 --> 00:42:10,760 the arguments that we're passing in, and use that as a 746 00:42:10,760 --> 00:42:14,990 new frame to extend the procedure environment. 747 00:42:14,990 --> 00:42:18,100 And that's the environment in which we evaluate the 748 00:42:18,100 --> 00:42:21,630 procedure body, right? 749 00:42:21,630 --> 00:42:24,470 That's going around the apply/eval loop. 750 00:42:24,470 --> 00:42:27,988 That's apply coming back to call eval, all right? 751 00:42:30,910 --> 00:42:32,860 OK. 752 00:42:32,860 --> 00:42:36,950 So, now, that's all we have to do in compound-apply. 753 00:42:36,950 --> 00:42:37,720 What are we going to do? 754 00:42:37,720 --> 00:42:40,730 We're going to manufacture a new environment. 755 00:42:43,720 --> 00:42:47,060 And we're going to manufacture a new environment, let's see, 756 00:42:47,060 --> 00:42:48,310 that we'll call E,1. 757 00:42:53,100 --> 00:42:57,830 E,1 is going to be some environment where the 758 00:42:57,830 --> 00:43:02,460 parameters of the procedure, where A is bound to 3 and B is 759 00:43:02,460 --> 00:43:06,220 bound to 4, and it's linked to E,0 because 760 00:43:06,220 --> 00:43:09,270 that's where f is defined. 761 00:43:09,270 --> 00:43:11,090 And, in this environment, we're going to evaluate the 762 00:43:11,090 --> 00:43:12,050 body of the procedure. 763 00:43:12,050 --> 00:43:13,870 So let's look at that, all right? 764 00:43:16,730 --> 00:43:20,690 All right, here we are at compound-apply, which says 765 00:43:20,690 --> 00:43:25,560 assign to the expression register the body of the 766 00:43:25,560 --> 00:43:28,300 procedure that's in the function register. 767 00:43:28,300 --> 00:43:31,470 So I assign to the expression register the 768 00:43:31,470 --> 00:43:42,710 procedure body, OK? 769 00:43:42,710 --> 00:43:46,300 That's going to be evaluated in an environment which is 770 00:43:46,300 --> 00:43:53,040 formed by making some bindings using information determined 771 00:43:53,040 --> 00:43:53,860 by the procedure-- 772 00:43:53,860 --> 00:43:55,320 that's what's in FUN-- 773 00:43:55,320 --> 00:43:57,800 and the argument list. 774 00:43:57,800 --> 00:44:00,230 And let's not worry about exactly what that does, but 775 00:44:00,230 --> 00:44:01,930 you can see the information's there. 776 00:44:01,930 --> 00:44:06,420 So make bindings will say oh, the procedure, itself, had an 777 00:44:06,420 --> 00:44:08,200 environment attached to it. 778 00:44:08,200 --> 00:44:09,320 I didn't write that quite here. 779 00:44:09,320 --> 00:44:11,810 I should've said in environment because every 780 00:44:11,810 --> 00:44:13,660 procedure gets built with an environment. 781 00:44:13,660 --> 00:44:17,400 So, from that environment, it knows what the procedure's 782 00:44:17,400 --> 00:44:19,290 definition environment is. 783 00:44:19,290 --> 00:44:21,830 It knows what the arguments are. 784 00:44:21,830 --> 00:44:23,060 It looks at argl, and then you see a 785 00:44:23,060 --> 00:44:24,280 reversal convention here. 786 00:44:24,280 --> 00:44:27,830 It just has to know that argl is reversed, and it builds 787 00:44:27,830 --> 00:44:29,990 this frame, E,1. 788 00:44:29,990 --> 00:44:32,400 All right, so, let's assume that that's what make bindings 789 00:44:32,400 --> 00:44:35,780 returns, so it assigns to ENV this thing, E,1. 790 00:44:41,490 --> 00:44:46,890 All right, the next thing it says is restore continue. 791 00:44:46,890 --> 00:44:48,760 Remember what continue was here? 792 00:44:48,760 --> 00:44:52,240 It got put up in the last segment. 793 00:44:52,240 --> 00:44:54,020 Continue got stored. 794 00:44:54,020 --> 00:44:56,180 That was the original done, which said what are you going 795 00:44:56,180 --> 00:44:59,920 to do after you're done with this particular application? 796 00:44:59,920 --> 00:45:01,980 It was one of the very first things that happened when we 797 00:45:01,980 --> 00:45:03,920 evaluated the application. 798 00:45:03,920 --> 00:45:06,860 And now, finally, we're going to restore continue. 799 00:45:06,860 --> 00:45:09,290 Remember apply-dispatch's contract. 800 00:45:09,290 --> 00:45:11,570 It assumes that where it should go to next was on the 801 00:45:11,570 --> 00:45:13,590 stack, and there it was on the stack. 802 00:45:13,590 --> 00:45:19,310 Continue has done, and now we're going to go back to 803 00:45:19,310 --> 00:45:19,940 eval-dispatch. 804 00:45:19,940 --> 00:45:20,970 We're set up again. 805 00:45:20,970 --> 00:45:23,470 We have an expression, an environment, and 806 00:45:23,470 --> 00:45:25,511 a place to go to. 807 00:45:25,511 --> 00:45:28,690 We're not going to go through that because it's sort of the 808 00:45:28,690 --> 00:45:29,940 same expression. 809 00:45:35,167 --> 00:45:39,590 OK, but the thing, again, to notice is, at this point, we 810 00:45:39,590 --> 00:45:44,830 have reduced the original expression, F,X,Y, right? 811 00:45:44,830 --> 00:45:50,150 We've reduced evaluating F,X,Y in environment E,0 to evaluate 812 00:45:50,150 --> 00:45:52,670 plus A, B in E,1. 813 00:45:52,670 --> 00:45:55,720 And notice, nothing's on the stack, right? 814 00:45:55,720 --> 00:45:56,830 It's a reduction. 815 00:45:56,830 --> 00:46:00,530 At this point, the machine does not contain, as part of 816 00:46:00,530 --> 00:46:03,790 its state, the fact that it's in the middle of evaluating 817 00:46:03,790 --> 00:46:08,090 some procedure called f, that's gone, right? 818 00:46:08,090 --> 00:46:13,072 There's no accumulated state, OK? 819 00:46:13,072 --> 00:46:14,370 Again, that's a very important idea. 820 00:46:14,370 --> 00:46:17,590 That's the meaning of, when we used to write in the 821 00:46:17,590 --> 00:46:20,430 substitution model, this expression reduces to that 822 00:46:20,430 --> 00:46:21,350 expression. 823 00:46:21,350 --> 00:46:22,660 And you don't have to remember anything. 824 00:46:22,660 --> 00:46:24,500 And here, you see the meaning of reduction. 825 00:46:24,500 --> 00:46:26,160 At this point, there is nothing on the stack. 826 00:46:31,590 --> 00:46:35,240 See, that has very important consequences. 827 00:46:35,240 --> 00:46:37,180 Let's go back and look at iterative 828 00:46:37,180 --> 00:46:40,590 factorial, all right? 829 00:46:40,590 --> 00:46:45,130 Remember, this was some sort of loop and doing iter. 830 00:46:45,130 --> 00:46:49,430 And we kept saying that's an iterative procedure, right? 831 00:46:52,570 --> 00:47:04,660 And what we wrote, remember, are things like, we said, 832 00:47:04,660 --> 00:47:12,360 fact-iter of 5. 833 00:47:12,360 --> 00:47:19,030 We wrote things like reduces to iter of 1, and 1, and 5, 834 00:47:19,030 --> 00:47:26,550 which reduces to iter of 1, and 2, and 5, and so on, and 835 00:47:26,550 --> 00:47:27,210 so on, and so on. 836 00:47:27,210 --> 00:47:29,360 And we kept saying well, look, you don't have to build up any 837 00:47:29,360 --> 00:47:31,720 storage to do that. 838 00:47:31,720 --> 00:47:33,730 And we waved our hands, and said in principle, there's no 839 00:47:33,730 --> 00:47:35,040 storage needed. 840 00:47:35,040 --> 00:47:36,170 Now, you see no storage needed. 841 00:47:36,170 --> 00:47:39,090 Each of these is a real reduction, right? 842 00:47:49,280 --> 00:47:51,370 As you walk through these expressions, what you'll see 843 00:47:51,370 --> 00:47:54,810 are these expressions on the stack in some particular 844 00:47:54,810 --> 00:48:00,045 environment, and then these expressions in the EXP 845 00:48:00,045 --> 00:48:01,650 register in some particular environment. 846 00:48:01,650 --> 00:48:03,570 And, at each point, there'll be no accumulated stuff on the 847 00:48:03,570 --> 00:48:09,135 stack because each one's a real reduction, OK? 848 00:48:09,135 --> 00:48:11,520 All right, so, for example, just to go through it in a 849 00:48:11,520 --> 00:48:15,510 little bit more care, if I start out with an expression 850 00:48:15,510 --> 00:48:33,520 that says something like, oh, say, fact-iter of 5 in some 851 00:48:33,520 --> 00:48:46,810 environment that will, at some point, create an environment 852 00:48:46,810 --> 00:48:48,120 in which n is down to 5. 853 00:48:51,340 --> 00:48:52,590 Let's call that-- 854 00:48:55,750 --> 00:49:02,120 And, at some point, the machine will reduce this whole 855 00:49:02,120 --> 00:49:08,780 thing to a thing that says that's really iter of 1, and 856 00:49:08,780 --> 00:49:16,550 1, and n, evaluated in this environment, E,1 with nothing 857 00:49:16,550 --> 00:49:17,160 on the stack. 858 00:49:17,160 --> 00:49:20,710 See, at this moment, the machine is not remembering 859 00:49:20,710 --> 00:49:22,500 that evaluating this expression, iter-- 860 00:49:25,000 --> 00:49:27,280 which is the loop-- is part of this thing 861 00:49:27,280 --> 00:49:29,366 called iterative factorial. 862 00:49:29,366 --> 00:49:30,590 It's not remembering that. 863 00:49:30,590 --> 00:49:33,170 It's just reducing the expression to that, right? 864 00:49:33,170 --> 00:49:38,390 If we look again at the body of iterative factorial, this 865 00:49:38,390 --> 00:49:42,810 expression has reduced to that expression. 866 00:49:42,810 --> 00:49:44,060 Oh, I shouldn't have the n there. 867 00:49:46,590 --> 00:49:48,495 It's a slightly different convention from the slide to 868 00:49:48,495 --> 00:49:53,340 the program, OK? 869 00:49:53,340 --> 00:49:56,310 And, then, what's the body of iter? 870 00:49:56,310 --> 00:49:59,460 Well, iter's going to be an it, and I won't go through the 871 00:49:59,460 --> 00:50:00,060 details of if. 872 00:50:00,060 --> 00:50:02,540 It'll evaluate the predicate. 873 00:50:02,540 --> 00:50:03,810 In this case, it'll be false. 874 00:50:03,810 --> 00:50:14,490 And this iter will now reduce to the expression iter of 875 00:50:14,490 --> 00:50:21,620 whatever it says, star, counter product, and-- 876 00:50:21,620 --> 00:50:22,650 what does it say-- 877 00:50:22,650 --> 00:50:30,820 plus counter 1 in some other environment, by this time, 878 00:50:30,820 --> 00:50:38,840 E,2, where E,2 will be set up having bindings for product 879 00:50:38,840 --> 00:50:43,200 and counter, right? 880 00:50:43,200 --> 00:50:45,140 And it'll reduce to that, right? 881 00:50:45,140 --> 00:50:47,925 It won't be remembering that it's part of something that it 882 00:50:47,925 --> 00:50:49,340 has to return to. 883 00:50:49,340 --> 00:50:51,500 And when iter calls iter again, it'll reduce to another 884 00:50:51,500 --> 00:50:55,050 thing that looks like this in some environment, E,3, which 885 00:50:55,050 --> 00:50:59,160 has new bindings for product and counter. 886 00:50:59,160 --> 00:51:08,450 So, if you're wondering, see, if you've always been queasy 887 00:51:08,450 --> 00:51:10,920 about how it is we've been saying those procedures, that 888 00:51:10,920 --> 00:51:16,095 look syntactically recursive, are, in fact, iterative, run 889 00:51:16,095 --> 00:51:19,230 in constant space, well, I don't know if this makes you 890 00:51:19,230 --> 00:51:21,230 less queasy, but at least it shows you what's happening. 891 00:51:21,230 --> 00:51:22,830 There really isn't any buildup there. 892 00:51:25,910 --> 00:51:28,830 Now, you might ask well, is there buildup in principle in 893 00:51:28,830 --> 00:51:31,710 these environment frames? 894 00:51:31,710 --> 00:51:33,240 And the answer is yeah, you have to make these new 895 00:51:33,240 --> 00:51:35,560 environment frames, but you don't have to hang onto them 896 00:51:35,560 --> 00:51:36,440 when you're done. 897 00:51:36,440 --> 00:51:39,020 They can be garbage collected, or the space can be reused 898 00:51:39,020 --> 00:51:40,720 automatically. 899 00:51:40,720 --> 00:51:43,520 But you see the control structure of the evaluator is 900 00:51:43,520 --> 00:51:47,020 really using this idea that you actually have a reduction, 901 00:51:47,020 --> 00:51:50,132 so these procedures really are iterative procedures. 902 00:51:50,132 --> 00:51:51,382 All right, let's stop for questions. 903 00:52:02,288 --> 00:52:03,538 All right, let's break. 904 00:52:48,770 --> 00:52:53,470 Let me contrast the iterative procedure just so you'll see 905 00:52:53,470 --> 00:52:56,480 where space does build up with a recursive procedure, so you 906 00:52:56,480 --> 00:52:58,030 can see the difference. 907 00:52:58,030 --> 00:53:00,470 Let's look at the evaluation of recursive 908 00:53:00,470 --> 00:53:02,880 factorial, all right? 909 00:53:02,880 --> 00:53:07,220 So, here's fact-recursive, or standard factorial definition. 910 00:53:07,220 --> 00:53:10,360 We said this one is still a recursive procedure, but this 911 00:53:10,360 --> 00:53:13,750 is actually a recursive process. 912 00:53:13,750 --> 00:53:17,210 And then, just to link it back to the way we started, we said 913 00:53:17,210 --> 00:53:20,530 oh, you can see that it's going to be recursive process 914 00:53:20,530 --> 00:53:24,520 by the substitution model because, if I say recursive 915 00:53:24,520 --> 00:53:36,000 factorial of 5, that turns into 5 times-- 916 00:53:36,000 --> 00:53:37,989 what is it, fact-rec, or record fact-- 917 00:53:42,620 --> 00:53:54,230 5 times recursive factorial of 4, which turns into 5 times 4 918 00:53:54,230 --> 00:54:08,090 times fact-rec of 3, which returns into 5 times 4 times 3 919 00:54:08,090 --> 00:54:15,240 times, and so on, right? 920 00:54:15,240 --> 00:54:18,100 The idea is there was this chain of stuff building up, 921 00:54:18,100 --> 00:54:20,540 which justified, in the substitution model, the fact 922 00:54:20,540 --> 00:54:21,520 that it's recursive. 923 00:54:21,520 --> 00:54:24,180 And now, let's actually see that chain of stuff build up 924 00:54:24,180 --> 00:54:27,465 and where it is in the machine, OK? 925 00:54:27,465 --> 00:54:28,970 All right, well, let's imagine we're going 926 00:54:28,970 --> 00:54:30,230 to start out again. 927 00:54:30,230 --> 00:54:41,690 We'll tell it to evaluate recursive factorial of 5 in 928 00:54:41,690 --> 00:54:46,360 some environment, again, E,0 where recursive factorial is 929 00:54:46,360 --> 00:54:49,580 defined, OK? 930 00:54:49,580 --> 00:54:52,490 Well, now we know what's eventually going to happen. 931 00:54:52,490 --> 00:54:55,670 This is going to come along, it'll evaluate those things, 932 00:54:55,670 --> 00:54:58,860 figure out it's a procedure, build somewhere over here an 933 00:54:58,860 --> 00:55:05,860 environment, E,1, which has n bound to 5, which hangs off of 934 00:55:05,860 --> 00:55:09,620 E,0, which would be, presumably, the definition 935 00:55:09,620 --> 00:55:14,610 environment of recursive factorial, OK? 936 00:55:14,610 --> 00:55:16,490 And, in this environment, it's going to go off and 937 00:55:16,490 --> 00:55:19,670 evaluate the body. 938 00:55:19,670 --> 00:55:27,860 So, again, the evaluation here will reduce to evaluating the 939 00:55:27,860 --> 00:55:30,240 body in E,1. 940 00:55:30,240 --> 00:55:32,880 That's going to look at an if, and I won't go through the 941 00:55:32,880 --> 00:55:33,530 details of if. 942 00:55:33,530 --> 00:55:34,880 It'll look at the predicate. 943 00:55:34,880 --> 00:55:37,840 It'll decide it eventually has to evaluate the alternative. 944 00:55:37,840 --> 00:55:43,122 So this whole thing, again, will reduce to the alternative 945 00:55:43,122 --> 00:55:47,870 of recursive factorial, the alternative clause, which says 946 00:55:47,870 --> 00:55:56,040 that this whole thing reduces to times n of recursive 947 00:55:56,040 --> 00:56:08,720 factorial of n minus 1 in the environment E,1, OK? 948 00:56:08,720 --> 00:56:11,200 So the original expression, now, is going to reduce to 949 00:56:11,200 --> 00:56:14,130 evaluating that expression, all right? 950 00:56:14,130 --> 00:56:16,280 Now we have an application. 951 00:56:16,280 --> 00:56:18,500 We did an application before. 952 00:56:18,500 --> 00:56:20,390 Remember what happens in an application? 953 00:56:20,390 --> 00:56:23,230 The first thing you do is you go off and you save the value 954 00:56:23,230 --> 00:56:25,350 of the continue register on the stack. 955 00:56:25,350 --> 00:56:27,365 So the stack here is going to have done in it. 956 00:56:29,980 --> 00:56:32,230 And then you're going to set up to evaluate 957 00:56:32,230 --> 00:56:35,130 the sub-parts, OK? 958 00:56:35,130 --> 00:56:36,710 So here we go off to evaluate the sub-parts. 959 00:56:39,520 --> 00:56:41,045 First thing we're going to do is evaluate the operator. 960 00:56:44,490 --> 00:56:47,250 What happens when we evaluate an operator? 961 00:56:47,250 --> 00:56:49,940 Well, we arrange things so that the operator ends up in 962 00:56:49,940 --> 00:56:51,480 the expression register. 963 00:56:51,480 --> 00:56:54,630 The environments in the ENV register continue someplace 964 00:56:54,630 --> 00:56:56,590 where we're going to go evaluate the arguments. 965 00:56:56,590 --> 00:56:59,520 And, on the stack, we've saved the original continue, which 966 00:56:59,520 --> 00:57:01,720 is where we wanted to be when we're all done. 967 00:57:01,720 --> 00:57:04,510 And then the things we needed when we're going to get done 968 00:57:04,510 --> 00:57:07,190 evaluating the operator, the things we'll need to evaluate 969 00:57:07,190 --> 00:57:11,710 the arguments, namely, the environment and those 970 00:57:11,710 --> 00:57:14,790 arguments, those unevaluated arguments, so there they are 971 00:57:14,790 --> 00:57:15,620 sitting on the stack. 972 00:57:15,620 --> 00:57:18,370 And we're about to go off to evaluate the operator. 973 00:57:23,130 --> 00:57:26,920 Well, when we return from this particular call-- 974 00:57:26,920 --> 00:57:29,380 so we're about to call eval-dispatch here-- 975 00:57:29,380 --> 00:57:32,730 when we return from this call, the value of that operator, 976 00:57:32,730 --> 00:57:34,890 which, in this case, is going to be the primitive multiplier 977 00:57:34,890 --> 00:57:43,080 procedure, will end up in the FUN register, all right? 978 00:57:43,080 --> 00:57:44,530 We're going to evaluate some arguments. 979 00:57:44,530 --> 00:57:47,730 They will evaluate in here. 980 00:57:47,730 --> 00:57:50,250 That'll give us 5, in this case. 981 00:57:50,250 --> 00:57:53,480 We're going to put that in the argl register, and then we'll 982 00:57:53,480 --> 00:57:57,460 go off to evaluate the second operand. 983 00:57:57,460 --> 00:58:00,050 So, at the point where we go off to evaluate the second 984 00:58:00,050 --> 00:58:02,390 operand-- and I'll skip details like computing, and 985 00:58:02,390 --> 00:58:04,510 minus 1, and all of that-- but, when we go off to 986 00:58:04,510 --> 00:58:08,210 evaluate the second operand, that will eventually reduce to 987 00:58:08,210 --> 00:58:09,460 another call to fact-recursive. 988 00:58:12,060 --> 00:58:17,520 And, what we've got on the stack here is the operator 989 00:58:17,520 --> 00:58:20,290 from that combination that we're going to use it in and 990 00:58:20,290 --> 00:58:23,790 the other argument, OK? 991 00:58:23,790 --> 00:58:28,490 So, now, we're set up for another call 992 00:58:28,490 --> 00:58:30,200 to recursive factorial. 993 00:58:30,200 --> 00:58:32,300 And, when we're done with this one, we're going to go to 994 00:58:32,300 --> 00:58:33,935 accumulate the last arg. 995 00:58:33,935 --> 00:58:35,200 And remember what that'll do? 996 00:58:35,200 --> 00:58:38,290 That'll say oh, whatever the result of this has to get 997 00:58:38,290 --> 00:58:41,690 combined with that, and we're going to multiply them. 998 00:58:41,690 --> 00:58:45,720 But, notice now, we're at another recursive factorial. 999 00:58:45,720 --> 00:58:49,710 We're about to call eval-dispatch again, except we 1000 00:58:49,710 --> 00:58:51,250 haven't really reduced it because there's stuff 1001 00:58:51,250 --> 00:58:53,700 on the stack now. 1002 00:58:53,700 --> 00:58:55,490 The stuff on the stack says oh, when you get back, you'd 1003 00:58:55,490 --> 00:58:58,430 better multiply it by the 5 you had hanging there. 1004 00:58:58,430 --> 00:59:07,430 So, when we go off to make another call, we 1005 00:59:07,430 --> 00:59:09,300 evaluate the n minus 1. 1006 00:59:09,300 --> 00:59:12,050 That gives us another environment in which the new 1007 00:59:12,050 --> 00:59:14,600 n's going to be down to 4. 1008 00:59:14,600 --> 00:59:18,930 And we're about to call eval-dispatch again, right? 1009 00:59:18,930 --> 00:59:21,350 We get another call. 1010 00:59:21,350 --> 00:59:26,040 That 4 is going to end up in the same situation. 1011 00:59:26,040 --> 00:59:30,020 We'll end up with another call to fact-recursive n. 1012 00:59:30,020 --> 00:59:32,330 And sitting on the stack will be the stuff from the original 1013 00:59:32,330 --> 00:59:35,360 one and, now, the subsidiary one we're doing. 1014 00:59:35,360 --> 00:59:36,910 And both of them are waiting for the same thing. 1015 00:59:36,910 --> 00:59:40,600 They're going to go to accumulate a last argument. 1016 00:59:40,600 --> 00:59:43,480 And then, of course, when we go to the fourth call, the 1017 00:59:43,480 --> 00:59:45,640 same thing happens, right? 1018 00:59:45,640 --> 00:59:47,300 And this goes on, and on, and on. 1019 00:59:47,300 --> 00:59:51,430 And what you see here on the stack, exactly what's sitting 1020 00:59:51,430 --> 00:59:54,960 here on the stack, the thing that says times and 5. 1021 00:59:54,960 --> 00:59:57,490 And what you're going to do with that is accumulate that 1022 00:59:57,490 --> 01:00:00,470 into a last argument. 1023 01:00:00,470 --> 01:00:02,760 That's exactly this, right? 1024 01:00:02,760 --> 01:00:05,650 This is exactly where that stuff is hanging. 1025 01:00:05,650 --> 01:00:12,650 Effectively, the operator you're going to apply, the 1026 01:00:12,650 --> 01:00:15,300 other argument that it's got to be multiplied by when you 1027 01:00:15,300 --> 01:00:17,620 get back and the parentheses, which says yeah, what you 1028 01:00:17,620 --> 01:00:19,620 wanted to do was accumulate them. 1029 01:00:19,620 --> 01:00:22,560 So, you see, the substitution model is not such a lie. 1030 01:00:22,560 --> 01:00:24,460 That really is, in some sense, what's sitting 1031 01:00:24,460 --> 01:00:27,198 right on the stack. 1032 01:00:27,198 --> 01:00:29,046 OK. 1033 01:00:29,046 --> 01:00:33,260 All right, so that, in some sense, should explain for you, 1034 01:00:33,260 --> 01:00:37,850 or at least convince you, that, somehow, this evaluator 1035 01:00:37,850 --> 01:00:41,870 is managing to take these procedures and execute some of 1036 01:00:41,870 --> 01:00:46,410 them iteratively and some of them recursively, even though, 1037 01:00:46,410 --> 01:00:49,430 as syntactically, they look like recursive procedures. 1038 01:00:49,430 --> 01:00:50,660 How's it managing to do that? 1039 01:00:50,660 --> 01:00:54,090 Well, the basic reason it's managing to do that is the 1040 01:00:54,090 --> 01:01:01,090 evaluator is set up to save only what it needs later. 1041 01:01:01,090 --> 01:01:04,670 So, for example, at the point where you've reduced 1042 01:01:04,670 --> 01:01:08,580 evaluating an expression and an environment to applying a 1043 01:01:08,580 --> 01:01:11,700 procedure to some arguments, it doesn't need that original 1044 01:01:11,700 --> 01:01:15,110 environment anymore because any environment stuff will be 1045 01:01:15,110 --> 01:01:18,160 packaged inside the procedures where the 1046 01:01:18,160 --> 01:01:20,160 application's going to happen. 1047 01:01:20,160 --> 01:01:23,120 All right, similarly, when you're going along evaluating 1048 01:01:23,120 --> 01:01:25,910 an argument list, when you've finished evaluating the list, 1049 01:01:25,910 --> 01:01:28,200 when you're finished evaluating the last argument, 1050 01:01:28,200 --> 01:01:31,500 you don't need that argument list any more, right? 1051 01:01:31,500 --> 01:01:33,330 And you don't need the environment where those 1052 01:01:33,330 --> 01:01:36,690 arguments would be evaluated, OK? 1053 01:01:36,690 --> 01:01:40,890 So the basic reason that this interpreter is being so smart 1054 01:01:40,890 --> 01:01:43,050 is that it's not being smart at all, it's being stupid. 1055 01:01:43,050 --> 01:01:44,760 It's just saying I'm only going to save 1056 01:01:44,760 --> 01:01:46,010 what I really need. 1057 01:01:48,700 --> 01:01:51,000 Well, let me show you here. 1058 01:01:54,880 --> 01:01:58,310 Here's the actual thing that's making a tail recursive. 1059 01:01:58,310 --> 01:02:00,135 Remember, it's the restore of continue. 1060 01:02:00,135 --> 01:02:09,090 It's saying when I go off to evaluate the procedure body, I 1061 01:02:09,090 --> 01:02:12,090 should tell eval to come back to the place where that 1062 01:02:12,090 --> 01:02:15,170 original evaluation was supposed to come back to. 1063 01:02:15,170 --> 01:02:17,700 So, in some sense, you want to say what's the actual line 1064 01:02:17,700 --> 01:02:18,770 that makes a tail recursive? 1065 01:02:18,770 --> 01:02:19,920 It's that one. 1066 01:02:19,920 --> 01:02:23,680 If I wanted to build a non-tail recursive evaluator, 1067 01:02:23,680 --> 01:02:27,650 for some strange reason, all I would need to do is, instead 1068 01:02:27,650 --> 01:02:31,300 of restoring continue at this point, I'd set up a label down 1069 01:02:31,300 --> 01:02:35,340 here called, "Where to come back after you've finished 1070 01:02:35,340 --> 01:02:38,560 applying the procedure." Instead, I'd 1071 01:02:38,560 --> 01:02:39,920 set continue to that. 1072 01:02:39,920 --> 01:02:42,240 I'd go to eval-dispatch, and then eval-dispatch 1073 01:02:42,240 --> 01:02:43,790 would come back here. 1074 01:02:43,790 --> 01:02:45,920 At that point, I would restore continue and go to the 1075 01:02:45,920 --> 01:02:47,920 original one. 1076 01:02:47,920 --> 01:02:51,790 So here, the only consequence of that would be to make it 1077 01:02:51,790 --> 01:02:52,840 non-tail recursive. 1078 01:02:52,840 --> 01:02:55,340 It would give you exactly the same answers, except, if you 1079 01:02:55,340 --> 01:02:57,800 did that iterative factorial and all those iterative 1080 01:02:57,800 --> 01:02:59,500 procedures, it would execute recursively. 1081 01:03:03,080 --> 01:03:05,760 Well, I lied to you a little bit, but just a little bit, 1082 01:03:05,760 --> 01:03:07,670 because I showed you a slightly over-simplified 1083 01:03:07,670 --> 01:03:12,510 evaluator where it assumes that each procedure body has 1084 01:03:12,510 --> 01:03:13,890 only one expression. 1085 01:03:13,890 --> 01:03:15,790 Remember, in general, a procedure has a sequence of 1086 01:03:15,790 --> 01:03:17,870 expressions in it. 1087 01:03:17,870 --> 01:03:20,490 So there's nothing really conceptually new. 1088 01:03:20,490 --> 01:03:23,480 Let me just show you the actual evaluator that handles 1089 01:03:23,480 --> 01:03:24,730 sequences of expressions. 1090 01:03:28,470 --> 01:03:30,650 This is compound-apply now, and the only difference from 1091 01:03:30,650 --> 01:03:35,980 the old one is that, instead of going off to eval directly, 1092 01:03:35,980 --> 01:03:38,510 it takes the whole body of the procedure, which, in this 1093 01:03:38,510 --> 01:03:40,920 case, is a sequence of expressions, and goes off to 1094 01:03:40,920 --> 01:03:42,670 eval-sequence. 1095 01:03:42,670 --> 01:03:48,380 And eval-sequence is a little loop that, basically, does 1096 01:03:48,380 --> 01:03:49,980 these evaluations one at a time. 1097 01:03:52,630 --> 01:03:53,900 So it does an evaluation. 1098 01:03:53,900 --> 01:03:56,110 Says oh, when I come back, I'd better come back here to do 1099 01:03:56,110 --> 01:03:58,440 the next one. 1100 01:03:58,440 --> 01:04:00,410 And, when I'm all done, when I want to get the last 1101 01:04:00,410 --> 01:04:04,800 expression, I just restore my continue and go off to 1102 01:04:04,800 --> 01:04:06,410 eval-dispatch. 1103 01:04:06,410 --> 01:04:08,880 And, again, if you wanted for some reason to break tail 1104 01:04:08,880 --> 01:04:11,690 recursion in this evaluator, all you need to do is not 1105 01:04:11,690 --> 01:04:14,900 handle the last expression, especially. 1106 01:04:14,900 --> 01:04:17,820 Just say, after you've done the last expression, come back 1107 01:04:17,820 --> 01:04:21,900 to some other place after which you restore continue. 1108 01:04:21,900 --> 01:04:24,920 And, for some reason, a lot of LISP evaluators tended 1109 01:04:24,920 --> 01:04:26,550 to work that way. 1110 01:04:26,550 --> 01:04:29,300 And the only consequence of that is that iterative 1111 01:04:29,300 --> 01:04:31,614 procedures built up stack. 1112 01:04:31,614 --> 01:04:35,670 And it's not clear why that happened. 1113 01:04:35,670 --> 01:04:36,210 All right. 1114 01:04:36,210 --> 01:04:38,990 Well, let me just sort of summarize, since this is a lot 1115 01:04:38,990 --> 01:04:41,120 of details in a big program. 1116 01:04:41,120 --> 01:04:44,040 But the main point is that it's no different, 1117 01:04:44,040 --> 01:04:47,060 conceptually, from translating any other program. 1118 01:04:47,060 --> 01:04:49,760 And the main idea is that we have this universal evaluator 1119 01:04:49,760 --> 01:04:51,870 program, the meta-circular evaluator. 1120 01:04:51,870 --> 01:04:53,250 If we translate that into LISP, then 1121 01:04:53,250 --> 01:04:54,560 we have all of LISP. 1122 01:04:54,560 --> 01:04:57,980 And that's all we did, OK? 1123 01:04:57,980 --> 01:04:59,680 The second point is that the magic's gone away. 1124 01:04:59,680 --> 01:05:01,970 There should be no more magic in this whole system, right? 1125 01:05:04,820 --> 01:05:08,720 In principle, it should all be very clear except, maybe, for 1126 01:05:08,720 --> 01:05:10,940 how list structured memory works, and 1127 01:05:10,940 --> 01:05:12,640 we'll see that later. 1128 01:05:12,640 --> 01:05:15,450 But that's not very hard. 1129 01:05:15,450 --> 01:05:18,720 The third point is that all this tail recursion came from 1130 01:05:18,720 --> 01:05:23,580 the discipline of eval being very careful to save only what 1131 01:05:23,580 --> 01:05:25,870 it needs next time. 1132 01:05:25,870 --> 01:05:28,180 It's not some arbitrary thing where we're saying well, 1133 01:05:28,180 --> 01:05:30,440 whenever we call a sub-routine, we'll save all 1134 01:05:30,440 --> 01:05:33,940 the registers in the world and come back, right? 1135 01:05:33,940 --> 01:05:37,150 See, sometimes it pays to really worry about efficiency. 1136 01:05:37,150 --> 01:05:39,400 And, when you're down in the guts of your evaluator 1137 01:05:39,400 --> 01:05:42,560 machine, it really pays to think about things like that 1138 01:05:42,560 --> 01:05:45,230 because it makes big consequences. 1139 01:05:45,230 --> 01:05:49,680 Well, I hope what this has done is really made the 1140 01:05:49,680 --> 01:05:52,560 evaluator seem concrete, right? 1141 01:05:52,560 --> 01:05:57,120 I hope you really believe that somebody could hold a LISP 1142 01:05:57,120 --> 01:05:59,390 evaluator in the palm of their hand. 1143 01:05:59,390 --> 01:06:02,540 Maybe to help you believe that, here's a LISP evaluator 1144 01:06:02,540 --> 01:06:06,160 that I'm holding the palm of my hand, right? 1145 01:06:06,160 --> 01:06:11,750 And this is a chip which is actually quite a bit more 1146 01:06:11,750 --> 01:06:13,700 complicated than the evaluator I showed you. 1147 01:06:17,815 --> 01:06:19,200 Maybe, here's a better picture of it. 1148 01:06:22,070 --> 01:06:24,730 What there is, is you can see the same overall structure. 1149 01:06:24,730 --> 01:06:26,940 This is a register array. 1150 01:06:26,940 --> 01:06:27,910 These are the data paths. 1151 01:06:27,910 --> 01:06:29,800 Here's a finite state controller. 1152 01:06:29,800 --> 01:06:32,810 And again, finite state, that's all there is. 1153 01:06:32,810 --> 01:06:34,160 And somewhere there's external memory 1154 01:06:34,160 --> 01:06:35,750 that'll worry about things. 1155 01:06:35,750 --> 01:06:38,090 And this particular one is very complicated because it's 1156 01:06:38,090 --> 01:06:41,450 trying to run LISP fast. And it has some very, very fast 1157 01:06:41,450 --> 01:06:45,570 parallel operations in there like, if you want to index 1158 01:06:45,570 --> 01:06:50,040 into an array, simultaneously check that the index is an 1159 01:06:50,040 --> 01:06:53,750 integer, check that it doesn't exceed the array bands, and go 1160 01:06:53,750 --> 01:06:55,810 off and do the memory access, and do all those things 1161 01:06:55,810 --> 01:06:57,120 simultaneously. 1162 01:06:57,120 --> 01:06:58,970 And then, later, if they're all OK, actually 1163 01:06:58,970 --> 01:07:00,420 get the value there. 1164 01:07:00,420 --> 01:07:02,520 So there are a lot of complicated operations in 1165 01:07:02,520 --> 01:07:06,550 these data paths for making LISP run in parallel. 1166 01:07:06,550 --> 01:07:10,640 It's a completely non-risk philosophy of evaluating LISP. 1167 01:07:10,640 --> 01:07:13,740 And then, this microcode is pretty complicated. 1168 01:07:13,740 --> 01:07:17,740 Let's see, there's what? 1169 01:07:17,740 --> 01:07:23,600 There's about 389 instructions of 220-bit microcode sitting 1170 01:07:23,600 --> 01:07:27,940 here because these are very complicated data paths. 1171 01:07:27,940 --> 01:07:33,580 And the whole thing has about 89,000 transistors, OK? 1172 01:07:33,580 --> 01:07:33,840 OK. 1173 01:07:33,840 --> 01:07:37,970 Well, I hope that that takes away a lot of the mystery. 1174 01:07:37,970 --> 01:07:39,240 Maybe somebody wants to look at this. 1175 01:07:42,048 --> 01:07:43,298 Yeah. 1176 01:07:46,260 --> 01:07:46,480 OK. 1177 01:07:46,480 --> 01:07:47,730 Let's stop. 1178 01:07:55,890 --> 01:07:57,815 Questions? 1179 01:07:57,815 --> 01:08:00,130 AUDIENCE: OK, now, it sounds like what you're saying is 1180 01:08:00,130 --> 01:08:03,070 that, with the restore continue put in the proper 1181 01:08:03,070 --> 01:08:08,830 place, that procedures that would invoke a recursive 1182 01:08:08,830 --> 01:08:13,385 process now invoke an integer process just by the way that 1183 01:08:13,385 --> 01:08:15,165 the eval signature is? 1184 01:08:15,165 --> 01:08:17,850 PROFESSOR: I think the way I'd prefer to put it is that, with 1185 01:08:17,850 --> 01:08:22,540 restore continue put in the wrong place, you can cause any 1186 01:08:22,540 --> 01:08:25,880 syntactically-looking recursive procedure, in fact, 1187 01:08:25,880 --> 01:08:28,029 to build up stack as it runs. 1188 01:08:28,029 --> 01:08:34,350 But there's no reason for that, so you might want to 1189 01:08:34,350 --> 01:08:35,660 play around with it. 1190 01:08:35,660 --> 01:08:38,640 You can just switch around two or three instructions in the 1191 01:08:38,640 --> 01:08:42,260 way compound-apply comes back, and you'll get something which 1192 01:08:42,260 --> 01:08:45,060 isn't tail recursive. 1193 01:08:45,060 --> 01:08:47,670 But the thing I wanted to emphasize is there's no magic. 1194 01:08:47,670 --> 01:08:51,689 It's not as if there's some very clever pre-processing 1195 01:08:51,689 --> 01:08:55,540 program that's looking at this procedure, factorial iter, and 1196 01:08:55,540 --> 01:08:59,920 say oh, gee, I really notice that I don't have to push 1197 01:08:59,920 --> 01:09:01,060 stack in order to do this. 1198 01:09:01,060 --> 01:09:03,760 Some people think that that's what's going on. 1199 01:09:03,760 --> 01:09:05,840 It's something much, much more dumb than that, it's this one 1200 01:09:05,840 --> 01:09:08,880 place you're putting the restore instruction. 1201 01:09:08,880 --> 01:09:10,353 It's just automatic. 1202 01:09:10,353 --> 01:09:11,603 AUDIENCE: OK. 1203 01:09:14,217 --> 01:09:16,109 AUDIENCE: But that's not affecting the time 1204 01:09:16,109 --> 01:09:17,850 complexity is it? 1205 01:09:17,850 --> 01:09:18,275 PROFESSOR: No. 1206 01:09:18,275 --> 01:09:21,810 AUDIENCE: It's just that it's handling it recursively 1207 01:09:21,810 --> 01:09:23,020 instead of iteratively. 1208 01:09:23,020 --> 01:09:26,960 But, in terms of the order of time it takes to finish the 1209 01:09:26,960 --> 01:09:29,220 operation, it's the same one way or the other, right? 1210 01:09:29,220 --> 01:09:29,920 PROFESSOR: Yes. 1211 01:09:29,920 --> 01:09:32,609 Tail recursion is not going to change the time complexity of 1212 01:09:32,609 --> 01:09:34,420 anything because, in some sense, it's the same algorithm 1213 01:09:34,420 --> 01:09:36,029 that's going on. 1214 01:09:36,029 --> 01:09:38,790 What it's doing is really making this thing run as an 1215 01:09:38,790 --> 01:09:41,210 iteration, right? 1216 01:09:41,210 --> 01:09:44,750 Not going to run out of memory counting up to a giant number 1217 01:09:44,750 --> 01:09:47,683 simply because the stack would get pushed. 1218 01:09:47,683 --> 01:09:49,970 See, the thing you really have to believe is 1219 01:09:49,970 --> 01:09:51,640 that, when we write-- 1220 01:09:51,640 --> 01:09:53,040 see, we've been writing all these things called 1221 01:09:53,040 --> 01:09:57,990 iterations, infinite loops, define loop to be called loop. 1222 01:10:01,660 --> 01:10:05,390 That's is as much an iteration as if we wrote do forever 1223 01:10:05,390 --> 01:10:07,630 loop, right? 1224 01:10:07,630 --> 01:10:09,280 It's just syntactic sugar as the difference. 1225 01:10:09,280 --> 01:10:14,730 These things are real, honest to god, iterations, right? 1226 01:10:14,730 --> 01:10:17,285 They don't change the time complexity, but they turn them 1227 01:10:17,285 --> 01:10:18,535 into real iterations. 1228 01:10:21,686 --> 01:10:23,800 All right, thank you.