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