55
66@title{Midterm 2 }
77
8- @bold{Due: TBD }
8+ @bold{Due: Friday, November 13th 11:59PM }
99
1010@(define repo "TBD " )
1111
@@ -14,10 +14,10 @@ Midterm repository:
1414
1515The repository contains a single markdown file @tt{m2.md}, which you can edit
1616to submit your answers to the following questions. Your submission must be
17- pushed by 9pm on Saturday (unless you have already arranged otherwise).
17+ pushed by 11:59pm on Friday (unless you have already arranged otherwise).
1818
19- During the 60 hours of the exam period, you may only ask private
20- questions on Piazza if you need assistance for the course staff. You
19+ During the 72 hours of the exam period, you may only ask private
20+ questions on Discord if you need assistance for the course staff. You
2121may not communicate or collaborate with any one else about the content
2222of this exam.
2323
@@ -33,17 +33,17 @@ equivalent to each of the following:
3333
3434@itemlist[
3535
36- @item{@verbatim{'(( 10 ) y y z 2 )}}
36+ @item{@verbatim{'(y y z ( 5 ) 2 )}}
3737
38- @item{@verbatim{'((2 ) . 2 )}}
38+ @item{@verbatim{'((1 2 ) . 2 )}}
3939
4040@item{@verbatim{'(a . (b . (c)))}}
4141
42- @item{@verbatim{'(quote (x 2 ))}}
42+ @item{@verbatim{'(a . (b . c ))}}
4343
44- @item{@verbatim{`(1 . ,(add1 2 ) )}}
44+ @item{@verbatim{`(,(add1 1 ) . 2 )}}
4545
46- @item{@verbatim|{`(1 ,@'(2 3 ) ,@'(x))}|}
46+ @item{@verbatim|{`(,@'(1 2 ) ,@'(x) , 3 )}|}
4747]
4848
4949For example, @racket['(1 2 3 )] is equivalent to @racket[(cons 1 (cons 2 (cons 3 '() )))].
@@ -52,30 +52,30 @@ For example, @racket['(1 2 3)] is equivalent to @racket[(cons 1 (cons 2 (cons 3
5252
5353[10 points]
5454
55- Will the following program run forever using only a constant amount of
56- memory, or will it eventually consume all memory and crash? Briefly
57- justify your answer.
55+ Is it possible for the following program to run out of memory? Justify your
56+ answer.
5857
5958@#reader scribble/comment-reader
6059(racketblock
61- (begin (define (flip x)
62- (flop (add1 x)))
63- (define (flop y)
64- (flip (sub1 y)))
65- (flip 5 ))
60+ (define (fact x)
61+ (if (<= x 1 )
62+ 1
63+ (* x (sub1 x))))
6664)
6765
6866How about this one? Again, justify your answer.
6967
7068@#reader scribble/comment-reader
7169(racketblock
72- (begin (define (flip x)
73- (flip (flop (add1 x))))
74- (define (flop y)
75- (flop (flip (sub1 y))))
76- (flip 5 ))
70+ (define (fact x)
71+ (define (fact-prime acc i)
72+ (if (<= i 1 )
73+ acc
74+ (fact-prime (* acc i) (sub1 i))))
75+ (fact-prime 1 x))
7776)
7877
78+ Hint: consider Jig.
7979
8080@bold{Question 3 }
8181
@@ -86,13 +86,15 @@ position?
8686
8787@itemlist[
8888
89- @item{@verbatim{(if e0 e1 e2)}}
89+ @item{@verbatim{(if ( if a0 a1 a2) e1 e2)}}
9090
9191@item{@verbatim{(match e0 [p1 e1] [p2 e2])}}
9292
93- @item{@verbatim{(( λ (x y) e0) e1 e2)}}
93+ @item{@verbatim{(if e0 ( if a0 a1 a2) e2)}}
9494
95- @item{@verbatim{(eq? e0 e1)}}
95+ @item{@verbatim{(add1 e0)}}
96+
97+ @item{@verbatim{(cons e0 e1)}}
9698
9799]
98100
@@ -121,7 +123,7 @@ Here's an example (note: @racket[let] is used for sequencing here):
121123]
122124
123125Implement the following function in the compiler. (You may assume
124- this code will be added to the Loot compiler and may use any functions
126+ this code will be added to the Knock compiler and may use any functions
125127given to you.)
126128
127129@#reader scribble/comment-reader
@@ -131,82 +133,175 @@ given to you.)
131133(define (compile-set-box! e0 e1 c) ... )
132134)
133135
134- @section[#:tag-prefix "m2 " ]{Closure Conversion }
136+ @section[#:tag-prefix "m2 " ]{Program Transformation: Inlining }
135137
136138@bold{Question 5 }
137139
138140[20 points]
139141
140142
141- In our @secref["Loot " ] compiler we used Closure Conversion to
142- help us implement higher-order functions on a target language
143- that does not support higher-order functions natively (x86_64).
143+ In our @secref["Iniquity " ] compiler we introduced function definitions to help
144+ us organize our code. Function definitions came along with function @emph{calls},
145+ and unfortunately function calls come with a performance hit.
146+
147+ One solution is @emph{inlining}: Taking the body of a funtion definition and
148+ replacing a call to that function with an instance of its body. This allows the
149+ programmer to have all the benefits of the function abstraction, without the
150+ overhead.
144151
145- This was done by introducing an appropriate data structure
146- for storing the environment and accessing the stored environment
147- when necessary.
152+ For example, consider the following program:
148153
149- Now imagine that our target was not x86_64, but a dialect of Racket
150- that did not have higher-order functions. We could still perform
151- closure conversion!
154+ @#reader scribble/comment-reader
155+ (racketblock
156+ (begin
157+ (define (f x) (+ x 5 ))
158+ (+ 10 (f 42 )))
159+ )
152160
153- For example , the following application of a constant function :
161+ If you inlined @tt{f} , the result would be the following program :
154162
155163@#reader scribble/comment-reader
156164(racketblock
157- (let ((x 5 )) ((lambda (y) x) 10 ))
165+ (begin
166+ (define (f x) (+ x 5 ))
167+ (+ 10 (+ 42 5 )))
158168)
159169
160- Using the same definitions for @tt{lookup} and @tt{ext} first introduced in
161- @secref["Fraud " ], could be transformed to the following:
170+
171+ Your task is to write and document a function named @tt{inline} which takes a
172+ function @tt{f} and a program @tt{p}, and inlines the function @tt{f} @emph{at
173+ all uses of @tt{f} in the program} (this includes other function definitions!).
174+
162175
163176@#reader scribble/comment-reader
164177(racketblock
178+ (define (inline f p)
179+ ;TODO
180+ )
181+ )
182+
165183
166- (define (lam1 env y)
167- (lookup env 'x ))
184+ You can assume that you have a function @tt{fvs} that given an expression,
185+ returns a list of all the free variables in that expression. This is be
186+ necessary to avoid creating incorrect programs (see Example 2 below). If dealing
187+ with variable clashes and creating new names seems too complicated, you can
188+ assume the existence of a function @tt{barendregtify} which given a program
189+ makes sure that all variables are unique, running it on the following:
168190
169- (let ((x 5 )) (lam1 (ext '() 'x x) 10 ))
191+
192+ @#reader scribble/comment-reader
193+ (racketblock
194+ (begin
195+ (define (f x) (+ x 5 ))
196+ (define (g x) (+ x 10 ))
197+ (f (g 10 )))
170198)
171199
172- Perform closure conversion on the following higher-order program:
200+ Would produce something like:
201+
173202
174203@#reader scribble/comment-reader
175204(racketblock
176- (let ((x 10 )
177- (y 20 )
178- (z 30 ))
179- (( lambda (z) (+ x (( lambda (x) (+ x y)) y) z)) 1 ))
205+ (begin
206+ ( define (f var1) (+ var1 5 ) )
207+ ( define (g var2) (+ var2 10 ))
208+ (f (g 10 ) ))
180209)
181210
182- You may assume @tt{lookup} and @tt{ext} exist.
183211
184- In order to receive full marks, show the steps of your transformation.
212+ In addition to your code, make sure you answer the following question as part of your
213+ submission:
214+
215+ @itemlist[
185216
186- Clarification: I've completely removed @tt{map} as it was only essential to the
187- extra credit below. To get full marks you must closure convert both of the
188- lambdas that are present in the program above.
217+ @item{Recursive functions refer to themselves... What should you do? (You do
218+ not have to worry about mutual recursion between sets of functions, for this
219+ exam we will assume either a function refers to itself directly, or it is not
220+ recusive at all).}
189221
222+ ]
190223
191- @bold{Question 5 Extra Credit}
224+ Other things you should consider:
192225
193- [10 points]
226+ @itemlist[
227+
228+ @item{If @tt{f} does not exist in the program, the program should be unchanged}
194229
195- Apply the full defunctionalization transformation introduced in @secref["Loot " ]
196- to the following code:
230+ @item{You have to be careful with variable shadowing/capture (see Example 2 ).}
231+
232+ ]
233+
234+
235+
236+ @subsection{Example 1 }
197237
198238@#reader scribble/comment-reader
199239(racketblock
200- (define (map f xs)
201- (match xs
202- ['() '() ]
203- [(cons y ys) (cons (f y) (map f ys))]))
204-
205- (define (main)
206- (let ((x 10 )
207- (y 20 )
208- (z 30 ))
209- (map (lambda (z) (+ x ((lambda (x) (+ x y)) y) z)) '(1 2 3 ))))
240+ ;todo
210241)
211242
212- You can reuse whatever you feel is appropriate, if anything, from Question 5.
243+ Would be unchanged.
244+
245+ @subsection{Example 2 }
246+
247+ @#reader scribble/comment-reader
248+ (racketblock
249+ ;todo
250+ )
251+
252+ Becomes:
253+
254+ @#reader scribble/comment-reader
255+ (racketblock
256+ ;todo
257+ )
258+
259+ @subsection{Example 3 }
260+
261+ Don't forget about nested expressions!
262+
263+ @#reader scribble/comment-reader
264+ (racketblock
265+ ;todo
266+ )
267+
268+ Becomes:
269+
270+ @#reader scribble/comment-reader
271+ (racketblock
272+ ;todo
273+ )
274+
275+ @bold{Question 5 Extra Credit}
276+
277+ [10 points]
278+
279+ Provide two graphs in dot format (explained in our lecture on Graphviz/Dot)
280+ that shows the difference between interpreters and compilers. You can lay this
281+ out however you'd like, but the following items should definitely be present in
282+ one, or both, of the graphs (though not necessarily connected in the diagram!).
283+ These are in alphabetical order, so don't assume that their order reveals
284+ anything about how the diagram should be layed out.
285+
286+ @itemlist[
287+
288+ @item{Source Language}
289+ @item{Target Language}
290+ @item{AST}
291+ @item{Code-Gen}
292+ @item{CPU Execution}
293+ @item{Interp}
294+ @item{Parser}
295+ @item{RTS}
296+ @item{Source Language}
297+ @item{Target Language}
298+ @item{Value/Result}
299+
300+ ]
301+
302+ In order to get the points for this , we will take your description in dot and
303+ run @tt{dot} on it. If it does not produce an output, you will get not points.
304+
305+ If it produces an output that is a good-faith effort (i.e. there is a clear
306+ attempt and showing the difference between compilers and interpreters, you will
307+ get 5 points. If it accurately shows the difference you will get 10 points.
0 commit comments