Midterm Exam
CS 320, Spring 2012 Student id: Name:
Instructions: You have 120 minutes to complete this closed-book, closed-note, closed-computer exam. Please write all answers in the provided space. You’re free to write your answers in Korean. 1) (10pts) Given the following expression in the FWAE language:
{with {g {fun {x} {f x}}} {with {f {fun {z} {g z}}} {with {y {with {f {fun {x} {f x}}} {f {- y m}}}} {y n}}}}
a) Draw arrows on the above expression from each bound variable to its binding occurrence. b) List the names of free variables: f, m, n, y
and bound variables: f, g, x, y, z
2) (5pts) Which of the following are examples of shadowing? a) {with {’x 8} {with {’x 7} {+ 1 ’x}}} b) {with {’x {with {’x 42} {- 11 ’x}}} {+ 9 ’x}} c) {with {’x 2} {with {’y 4} {+ 21 ’x}}}
3) (5pts) Rewrite the following FWAE code in FAE, that is, rewrite it without using with: {with {y {fun {x} {+ y x}}} {fun {z} {y {- 10 z}}}} {{fun {y} {fun {z} {y {- 10 z}}}} {fun {x} {+ y x}}}
1
4) (10pts) The following code (Let’s call this A):
(let ([fac (lambda (n) (let ([facX (lambda (facX) (lambda (n) (if (zero? n) 1 (* n ((facX facX) (- n 1))))))]) ((facX facX) n)))]) (fac 10))
can be rewritten as follows (Let’s call this B):
(let ([fac (let ([facX (lambda (facX) (lambda (n) (if (zero? n) 1 (* n ((facX facX) (- n 1))))))]) (facX facX))]) (fac 10))
via η reduction. Note that in A, 10 is passed to n in the outermost lambda expression. Explain that in B, how 10 is passed to n in the innermost lambda expression. First, the value of the outermost factX is a function value which takes a function and produces another function. Then, the value of fac is the value of (facX facX), which evaluates to a function value which takes a number and produces another number. Finally, (fac 10) passes 10 to the function which takes a number n.
5) (10pts) The following code is a partial implementation of the interpreter for RCFAE. Fill in the missing expressions. Note that DefrdSub is extended with a new kind of substitution aRecSub for recursion:
; interp : RCFAE DefrdSub -> RCFAE-Value (define (interp rcfae ds) (type-case RCFAE rcfae ... [rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))]))
6) (5pts) Which of the following produce different results in an eager language and a lazy language? Both produce the same result if they both produce the same number, they both produce a procedure (even if the procedure doesn’t behave exactly the same when applied), or they both produce an error. Show the results of each expression in an eager language and a lazy language, and mark it when it produces different results in an eager language and a lazy language.
7) (5pts) In our implementation of the interpreter for LFAE, we call the strict function to enforce evaluation. Where did we call the strict function in our implementation? If we instead call the strict function when we look up identifiers, what difference would it make? – When we evaluate addition and subtraction in num-op and when we evaluate the first expression of an app case in interp. – When a function body returns an identifier, our implementation would return exprV but calling the strict function at identifier look ups would not return exprV.
8) (10pts) Note that there is a nested strict call in the following:
; strict : LFAE-Value -> LFAE-Value (define (strict v) (type-case LFAE-Value v [exprV (expr ds) (strict (interp expr ds))] [else v]))
Write an example showing the need for the nested strict call.
{{fun {y} {{fun {x} {+ 3 x}} y}} 5}
9) (10pts) The following strict code results in redundant evaluations:
; strict : LFAE-Value -> LFAE-Value (define (strict v) (type-case LFAE-Value v [exprV (expr ds) (strict (interp expr ds))] [else v]))
Instead, we cache strict results using the following data structure:
10) (10pts) The following code is an excerpt from the implementation of the interpreter for BFAE:
(define (interp expr ds st) ... [app (f a) (interp-two f a ds st (lambda (fv av st1) (interp (closureV-body fv) (aSub (closureV-param fv) av (closureV-ds fv)) st1)))] ...)
In BMFAE, we introduce variables so that DefrdSub maps names (symbols) to addresses (integers) and Store maps addresses (integers) to values (BMFAE-Value). Rewrite the above app case for BMFAE.
[app (f a) (interp-two f a ds st (lambda (fv av st1) (local [(define a (malloc st1))] (interp (closureV-body fv) (aSub (closureV-param fv) a (closureV-ds fv)) (aSto a av st1)))))]
11) (20pts) Given the following expression: {{fun {x} {seqn {setbox x 2} {openbox x}}} {newbox 11}} write out the arguments to and results of interp each time it is called during the evaluation of a program. Write them out in the order in which the calls to interp occur during evaluation. Write down the arguments and the results using the {} notation, not using the more verbose data constructors. Also, use an arrow notation for both the store and the environment. An example, if the first call to interp were: (interp (parse ‘{+ x y}) (aSub ’x (numV 3) (aSub ’y (numV 4) (mtSub))) (mtSto)) then a model solution would be: exp: env: sto: ans: exp: env: sto: ans: exp: env: sto: ans: {+ x y} {x -> (numV 3), y -> (numV 4)} {} (numV 7) {} x {x -> (numV 3), y -> (numV 4)} {} (numV 3) {} y {x -> (numV 3), y -> (numV 4)} {} (numV 4) {}
Note that the environment and store read in order from left to right. (1) exp: env: sto: ans: (2) exp: env: sto: ans: (3) exp: env: sto: ans: {{fun {x} {seqn {setbox x 2} {openbox x}}} {newbox 11}} {} {} (numV 2) {0 -> (numV 2), 0 -> (numV 11)}
{fun {x} {seqn {setbox x 2} {openbox x}}} {} {} (closureV ’x {seqn {setbox x 2} {openbox x}} {}) {}