|
13 | 13 |
|
14 | 14 | Midterm 2 will be released at least 72 hours prior to its due date. |
15 | 15 |
|
16 | | -@;{ |
| 16 | +@section{Instructions} |
17 | 17 |
|
18 | | -Midterm repository: |
19 | | -@centered{@link[repo repo]} |
| 18 | +The midterm will be released as a zip file @tt{m2.zip} on ELMS. |
20 | 19 |
|
21 | | -The exam consists of two parts: a written portion and a programmatic |
22 | | -portion. Both will be handled through gradescope. You will see two |
23 | | -gradescope assignments marked accordingly. |
| 20 | +There are FIVE parts to this midterm. Each part has its own directory |
| 21 | +with a README and supplementary files. Read the README in each part |
| 22 | +for instructions on how to complete that part of the midterm. |
24 | 23 |
|
25 | | -During the exam period, you may only ask private questions to |
26 | | -the staff (via email, discord, etc.) if you need clarification. |
27 | | -You may not communicate or collaborate with any one else about the |
28 | | -content of this exam. |
| 24 | +@section{Communications} |
29 | 25 |
|
30 | | -Questions that are deemed applicable to the entire class will be shared, along |
31 | | -with their responses, with the rest of the class. |
| 26 | +If you have questions about the exam, send a DM to ModMail on Discord. |
| 27 | +This will go to the entire course staff. |
32 | 28 |
|
33 | | -The repository contains two things. |
34 | | -@itemlist[ |
35 | | -@item{A folder @tt{BoxIncr} which contains the base code to build upon for Question 4.} |
36 | | -@item{A folder @tt{CallByName} which contains the base code to build upon for Question 5.} |
37 | | -] |
| 29 | +Answers to common clarifying questions will be posted to the |
| 30 | +@tt{#midterm-2} channel on Discord. |
38 | 31 |
|
39 | | -Your submission must be submitted by 11:59 EDT on Tuesday, April |
40 | | -13th. For the programmatic fragment, you should submit a zip file |
41 | | -containing two files: the @tt{BoxIncr/compile.rkt} for |
42 | | -Question 4, and @tt{CallByName/interp.rkt} for Question 5. |
| 32 | +If you have trouble reaching the course staff via Discord, email |
| 33 | +@tt|{dvanhorn@cs.umd.edu}|. |
43 | 34 |
|
44 | | -@section[#:tag-prefix "m2"]{Short answer} |
| 35 | +You may not communicate with anyone outside of the course staff about |
| 36 | +the midterm. |
45 | 37 |
|
46 | | -@bold{Question 1} |
| 38 | +@section{Submissions} |
47 | 39 |
|
48 | | -[10 points] |
49 | | - |
50 | | -@itemlist[ |
51 | | - |
52 | | -@item{On the random generation lecture on Tuesday (a recording can be |
53 | | -found on ELMS!), we wrote random generators for testing the @tt{Con} |
54 | | -and @tt{Dupe} languages. When going from @tt{Con} to @tt{Dupe}, |
55 | | -we modified the generators to take an additional argument representing |
56 | | -the type of the expression we want to generate. Why?} |
57 | | - |
58 | | -@item{Why did we need to introduce the @tt{Lea} assembly |
59 | | -instruction when implementing @tt{Knock}?} |
60 | | -] |
61 | | - |
62 | | -@bold{Question 2} |
63 | | - |
64 | | -[10 points] |
65 | | - |
66 | | -Is it possible for @tt{fib1} to run out of memory? Justify your |
67 | | -answer. |
68 | | - |
69 | | -@#reader scribble/comment-reader |
70 | | -(racketblock |
71 | | -(define (fib1 i) |
72 | | - (match i |
73 | | - [0 1] |
74 | | - [1 1] |
75 | | - [_ (+ (fib1 (- i 1)) (fib1 (- i 2)))])) |
76 | | -) |
77 | | - |
78 | | - |
79 | | -How about @tt{fib2}? Again, justify your answer. |
80 | | - |
81 | | -@#reader scribble/comment-reader |
82 | | -(racketblock |
83 | | -(define (fib2-aux i fib-1 fib-2) |
84 | | - (if (zero? i) fib-1 |
85 | | - (fib2-aux (sub1 i) (+ fib-1 fib-2) fib-1))) |
86 | | - |
87 | | -(define (fib2 i) |
88 | | - (match i |
89 | | - [0 1] |
90 | | - [1 1] |
91 | | - [_ (fib2-aux (sub1 i) 1 1)])) |
92 | | -) |
93 | | - |
94 | | -Hint: consider Jig. |
95 | | - |
96 | | -@bold{Question 3} |
97 | | - |
98 | | -[10 points] |
99 | | - |
100 | | -For each of the following expressions, which subexpressions are in tail |
101 | | -position? Assume that the top-level expression is in tail position. |
102 | | - |
103 | | -@itemlist[ |
104 | | - |
105 | | -@item{@verbatim{(sub1 e0)}} |
106 | | - |
107 | | -@item{@verbatim{(begin e0 e1)}} |
108 | | - |
109 | | -@item{@verbatim{(let ((x a)) e)}} |
110 | | - |
111 | | -@item{@verbatim{(if b (box e1) e2)}} |
112 | | - |
113 | | -@item{@verbatim{(match e [p1 e1] [_ e2])}} |
114 | | - |
115 | | -] |
116 | | - |
117 | | -@section[#:tag-prefix "m2"]{Code generation} |
118 | | - |
119 | | -@bold{Question 4} |
120 | | - |
121 | | -[25 points] |
122 | | - |
123 | | -In the repo (@link[repo repo]), you will find a directory named |
124 | | -"BoxIncr". That contains the @tt{Hustle} language from the lectures, |
125 | | -partially extended with two additional primitives: @racket[incr-box!] |
126 | | -and an @racket[decr-box!]. |
127 | | - |
128 | | -An @racket[(incr-box! _e)] expression evaluates @racket[_e]. The |
129 | | -result of @racket[_e] should be a boxed integer (otherwise an error is |
130 | | -signalled). The box is updated (mutated) to increment its value by 1. |
131 | | -Similarly, @racket[(decr-box! _e)] should decrement the boxed integer |
132 | | -by 1. The result of the operation should be @racket[void]. |
133 | | - |
134 | | -Here's an example that returns 42 (note: @racket[let] is used for |
135 | | -sequencing here): |
136 | | - |
137 | | -@#reader scribble/comment-reader |
138 | | -(racketblock |
139 | | -(let ((b (box 41))) |
140 | | - (let ((v (incr-box! b))) |
141 | | - (unbox b))) |
142 | | -) |
143 | | - |
144 | | -The ast, parser, and interpreter have already been updated for you to |
145 | | -implement this functionality. Your job is to implement the compiler. |
146 | | - |
147 | | -@section[#:tag-prefix "m2"]{Call by Name} |
148 | | - |
149 | | -@bold{Question 5} |
150 | | - |
151 | | -[45 points] |
152 | | - |
153 | | -In the @link[repo repo], you will find a stripped down version of the |
154 | | -@secref["Iniquity"] language: just the interpreter. Iniquity |
155 | | -introduces the notion of function definitions and function calls. The |
156 | | -way we evaluate function calls (as in racket) is known as |
157 | | -"call-by-value": the arguments to a function call are evaluated |
158 | | -before the body of the function is evaluated. |
159 | | - |
160 | | -An alternative evaluation strategy is "call-by-name". In call-by-name, |
161 | | -the arguments to a function call are substituted in the function body, |
162 | | -left to be evaluated as they appear: if an argument is unused, it will |
163 | | -never be evaluated; if an argument is used multiple times, it will be |
164 | | -evaluated multiple times. |
165 | | - |
166 | | -Consider the following example: |
167 | | - |
168 | | -@#reader scribble/comment-reader |
169 | | -(racketblock |
170 | | -(begin |
171 | | - (define (f x) 42) |
172 | | - (f (read-byte))) |
173 | | -) |
174 | | - |
175 | | -In standard call-by-value, this will read a byte from standard input, |
176 | | -and proceed to call @tt{f} with that read value, ignore it, and return |
177 | | -42. In call-by-name, this program will not read any value from the |
178 | | -standard input - the @tt{read-byte} will never be evaluated, as the body |
179 | | -of @tt{f} does not make use of @tt{x}. |
180 | | - |
181 | | -On the other hand, consider the following program: |
182 | | - |
183 | | -@#reader scribble/comment-reader |
184 | | -(racketblock |
185 | | -(begin |
186 | | - (define (f x) (+ x x)) |
187 | | - (f (read-byte))) |
188 | | -) |
189 | | - |
190 | | -Again, in standard call-by-value, this will read a byte from standard |
191 | | -input, and proceed to call @tt{f} with that read value, doubling it. |
192 | | -In call-by-name, this program will result to two different calls to |
193 | | -@tt{read-byte}, whose results will then be added together: when |
194 | | -calling @tt{(f (read-byte))}, the argument will be substituted into |
195 | | -the body of @tt{f}, yielding @tt{(+ (read-byte) (read-byte))}. |
196 | | - |
197 | | -An interesting point is how call-by-value interacts with |
198 | | -let-bindings. For this assignment, we will keep let-bindings strict, |
199 | | -just like in the current interpreter, that is the argument to the let |
200 | | -will be evaluated before the body is executed. |
201 | | - |
202 | | -To fully understand the interactions between let and function calls, consider the following examples: |
203 | | - |
204 | | -@#reader scribble/comment-reader |
205 | | -(racketblock |
206 | | -(begin |
207 | | - (define (f x y) (+ (+ x x) (+ y y))) |
208 | | - (let ((z (read-byte))) (f z (read-byte)))) |
209 | | -) |
210 | | - |
211 | | -This program has the effect of first evaluating @tt{read-byte} (for |
212 | | -example, say 42), and then substituting its value for @tt{z} in the |
213 | | -body of the let. Then it will evaluate the call @tt{(f z |
214 | | -(read-byte))}. This will have the effect of substituting the value of |
215 | | -@tt{z} (which has already been evaluated), and the expression |
216 | | -@tt{(read-byte)} for @tt{x} and @tt{y} in the body of @tt{f}. In turn, |
217 | | -that means that there will be two new calls to @tt{read-byte}, for |
218 | | -each occurence of @tt{y} in the body of f. |
219 | | - |
220 | | -@#reader scribble/comment-reader |
221 | | -(racketblock |
222 | | -(begin |
223 | | - (define (f x) (+ x y)) |
224 | | - (let ((y 42)) (f y))) |
225 | | -) |
226 | | - |
227 | | -This program should yield an error - we're still using static scoping! |
228 | | - |
229 | | -@#reader scribble/comment-reader |
230 | | -(racketblock |
231 | | -(begin |
232 | | - (define (f x) (let ((y 42)) x)) |
233 | | - (let ((y 17)) (f y))) |
234 | | -) |
235 | | - |
236 | | -This program should yield 17, in both evaluation methods. |
237 | | - |
238 | | -@#reader scribble/comment-reader |
239 | | -(racketblock |
240 | | -(begin |
241 | | - (define (f x) (let ((x 42)) x)) |
242 | | - (f 17)) |
243 | | -) |
244 | | - |
245 | | -This example should yield 42, the let in the body of f shadows the |
246 | | -argument. |
247 | | - |
248 | | -@#reader scribble/comment-reader |
249 | | -(racketblock |
250 | | -(begin |
251 | | - (define (loop x) (loop x)) |
252 | | - (define (f x) 42) |
253 | | - (f (loop 0))) |
254 | | -) |
255 | | - |
256 | | -In call-by-name, this program terminates as the argument |
257 | | -@tt{(loop 0)} is never evaluated! |
258 | | - |
259 | | -@#reader scribble/comment-reader |
260 | | -(racketblock |
261 | | -(begin |
262 | | - (define (f x) 42) |
263 | | - (f (+ #t #f))) |
264 | | -) |
265 | | - |
266 | | -In call-by-name, this program also terminates: the error-producing |
267 | | -argument @tt{(+ #t #f)} is again never evaluated! |
268 | | - |
269 | | -Your task is to modify the interpreter to implement this style of |
270 | | -evaluation. The easiest way to do that is to re-implement |
271 | | -let-bindings and function calls using substitution instead of the |
272 | | -environment to pass arguments. While an implementation using |
273 | | -environments is possible, it can be very tricky to get right; you have |
274 | | -been warned! |
275 | | - |
276 | | - |
277 | | -@bold{Question Call-by-need: Extra Credit} |
278 | | - |
279 | | -[20 points] |
280 | | - |
281 | | -An alternative to call-by-name is call-by-need. In call-by-need, the |
282 | | -arguments to a function are not evaluated at call time (just like in |
283 | | -call-by-name), but the evaluation of the argument is memoized - it's |
284 | | -going to only be evaluated the first time it's needed and future |
285 | | -occurences will reuse that evaluation's result. |
286 | | - |
287 | | -You're on your own on this one and there will be no autograder, so |
288 | | -reach out to set out a time to talk about your solution if you try to |
289 | | -tackle this! |
290 | | - |
291 | | -@subsection{Submission and Grading} |
292 | | - |
293 | | -We will only use two files for grading: @tt{BoxIncr/compile.rkt} and |
294 | | -@tt{CallByName/interp.rkt}. You should be able to submit a zip from |
295 | | -inside the cloned repo to Gradescope, but we will only be using these |
296 | | -two files for grading, so restrict your work in those. |
297 | | -} |
| 40 | +You should submit your work as a single zip file of this directory on |
| 41 | +Gradescope. Unlike past assignments, Gradescope will not provide |
| 42 | +feedback on the correctness of your solutions so you are encouraged to |
| 43 | +check your own work. |
0 commit comments