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

First. Note that in A. Explain that in B. Finally.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) (. the value of the outermost factX is a function value which takes a function and produces another function. the value of fac is the value of (facX facX). (fac 10) passes 10 to the function which takes a number n. Then. how 10 is passed to n in the innermost lambda expression. .n 1))))))]) (facX facX))]) (fac 10)) via η reduction. 10 is passed to n in the outermost lambda expression. which evaluates to a function value which takes a number and produces another number.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) (.

. a) {{fun {y} 12} {1 2}} eager: error lazy: 12 b) {fun {x} {{fun {y} 12} {1 2}}} eager: closure c) {+ 1 {fun {y} 12}} eager: error lazy: error lazy: closure d) {+ 1 {{fun {x} {+ 1 13}} {+ 1 {fun {z} 12}}}} eager: error lazy: 15 e) {+ 1 {{fun {x} {+ x 13}} {+ 1 {fun {z} 12}}}} eager: error lazy: error . they both produce a procedure (even if the procedure doesn’t behave exactly the same when applied)..5) (10pts) The following code is a partial implementation of the interpreter for RCFAE. Show the results of each expression in an eager language and a lazy language. Fill in the missing expressions. and mark it when it produces diﬀerent results in an eager language and a lazy language. 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 diﬀerent results in an eager language and a lazy language? Both produce the same result if they both produce the same number. or they both produce an error.

our implementation would return exprV but calling the strict function at identiﬁer look ups would not return exprV. {{fun {y} {{fun {x} {+ 3 x}} y}} 5} . Where did we call the strict function in our implementation? If we instead call the strict function when we look up identiﬁers. – When a function body returns an identiﬁer. 8) (10pts) Note that there is a nested strict call in the following: .7) (5pts) In our implementation of the interpreter for LFAE. 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. what diﬀerence would it make? – When we evaluate addition and subtraction in num-op and when we evaluate the ﬁrst expression of an app case in interp. we call the strict function to enforce evaluation.

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: (define-type LFAE-Value [numV (n number?)] [closureV (param symbol?) (body LFAE?) (ds DefrdSub?)] [exprV (expr LFAE?) (ds DefrdSub?) (value (box/c (or/c false LFAE-Value?)))]) Rewrite the above strict code using cached strict results. (define (strict v) (type-case LFAE-Value v [exprV (expr ds v-box) (if (not (unbox v-box)) (local [(define v (strict (interp expr ds)))] (begin (set-box! v-box v) v)) (unbox v-box))] [else v])) .

Rewrite the above app case for BMFAE.. we introduce variables so that DefrdSub maps names (symbols) to addresses (integers) and Store maps addresses (integers) to values (BMFAE-Value)... [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)))] . [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)))))] ..) In BMFAE.10) (10pts) The following code is an excerpt from the implementation of the interpreter for BFAE: (define (interp expr ds st) .

use an arrow notation for both the store and the environment. An example. not using the more verbose data constructors. Write them out in the order in which the calls to interp occur during evaluation.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 down the arguments and the results using the {} notation. y -> (numV 4)} {} (numV 7) {} x {x -> (numV 3). y -> (numV 4)} {} (numV 4) {} Note that the environment and store read in order from left to right. 0 -> (numV 11)} {fun {x} {seqn {setbox x 2} {openbox x}}} {} {} (closureV ’x {seqn {setbox x 2} {openbox x}} {}) {} {newbox 11} {} {} (boxV 0) {0 -> (numV 11)} . Also. if the ﬁrst 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). (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). y -> (numV 4)} {} (numV 3) {} y {x -> (numV 3).

0 -> (numV 11)} x {x -> (boxV 0)} {0 -> (numV 2). 0 -> (numV 11)} . 0 -> (numV 11)} x {x -> (boxV 0)} {0 -> (numV 11)} (boxV 0) {0 -> (numV 11)} 2 {x -> (boxV 0)} {0 -> (numV 11)} (numV 2) {0 -> (numV 11)} {openbox x} {x -> (boxV 0)} {0 -> (numV 2). 0 -> (numV 11)} (boxV 0) {0 -> (numV 2).(4) exp: env: sto: ans: (5) exp: env: sto: ans: (6) exp: env: sto: ans: (7) exp: env: sto: ans: (8) exp: env: sto: ans: (9) exp: env: sto: ans: (10) exp: env: sto: ans: 11 {} {} (numV 11) {} {seqn {x -> {0 -> (numV {setbox x 2} {openbox x}} (boxV 0)} (numV 11)} 2) {0 -> (numV 2). 0 -> (numV 11)} {setbox x 2} {x -> (boxV 0)} {0 -> (numV 11)} (numV 2) {0 -> (numV 2). 0 -> (numV 11)} (numV 2) {0 -> (numV 2).

. parse : S-expr -> BFAE (define (parse sexp) (cond [(number? sexp) (num sexp)] [(symbol? sexp) (id sexp)] [(pair? sexp) (case (car sexp) [(+) (add (parse (second sexp)) (parse (third sexp)))] [(-) (sub (parse (second sexp)) (parse (third sexp)))] [(fun) (fun (first (second sexp)) (parse (third sexp)))] [(newbox) (newbox (parse (second sexp)))] [(setbox) (setbox (parse (second sexp)) (parse (third sexp)))] [(openbox) (openbox (parse (second sexp)))] [(seqn) (seqn (parse (second sexp)) (parse (third sexp)))] [else (app (parse (first sexp)) (parse (second sexp)))])])) .#lang plai (define-type BFAE [num (n number?)] [add (lhs BFAE?) (rhs BFAE?)] [sub (lhs BFAE?) (rhs BFAE?)] [id (name symbol?)] [fun (param symbol?) (body BFAE?)] [app (fun-expr BFAE?) (arg-expr BFAE?)] [newbox (val-expr BFAE?)] [setbox (box-expr BFAE?) (val-expr BFAE?)] [openbox (box-expr BFAE?)] [seqn (first BFAE?) (second BFAE?)]) (define-type BFAE-Value [numV (n number?)] [closureV (param symbol?) (body BFAE?) (ds DefrdSub?)] [boxV (address integer?)]) (define-type DefrdSub [mtSub] [aSub (name symbol?) (value BFAE-Value?) (rest DefrdSub?)]) (define-type Store [mtSto] [aSto (address integer?) (value BFAE-Value?) (rest Store?)]) (define-type Value*Store [v*s (value BFAE-Value?) (store Store?)]) .. ------------------------------------------------------------.

-> Value*Store (define (interp-two expr1 expr2 ds st handle) (type-case Value*Store (interp expr1 ds st) [v*s (val1 st2) (type-case Value*Store (interp expr2 ds st2) [v*s (val2 st3) (handle val1 val2 st3)])])) . interp-two : BFAE BFAE DefrdSub Store (Value Value Store -> Value*Store .v1 v2) st1)))] [id (name) (v*s (lookup name ds) st)] [fun (param body-expr) (v*s (closureV param body-expr ds) st)] [app (fun-expr arg-expr) (interp-two fun-expr arg-expr ds st (lambda (fun-val arg-val st1) (interp (closureV-body fun-val) (aSub (closureV-param fun-val) arg-val (closureV-ds fun-val)) st1)))] [newbox (expr) (type-case Value*Store (interp expr ds st) [v*s (val st1) (local [(define a (malloc st1))] (v*s (boxV a) (aSto a val st1)))])] [setbox (bx-expr val-expr) (interp-two bx-expr val-expr ds st (lambda (bx-val val st1) (v*s val (aSto (boxV-address bx-val) val st1))))] [openbox (bx-expr) (type-case Value*Store (interp bx-expr ds st) [v*s (bx-val st1) (v*s (store-lookup (boxV-address bx-val) st1) st1)])] [seqn (a b) (interp-two a b ds st (lambda (v1 v2 st1) (v*s v2 st1)))])) ..... ------------------------------------------------------------. interp : BFAE DefrdSub Store -> Value*Store (define (interp bcfae ds st) (type-case BFAE bcfae [num (n) (v*s (numV n) st)] [add (l r) (interp-two l r ds st (lambda (v1 v2 st1) (v*s (num+ v1 v2) st1)))] [sub (l r) (interp-two l r ds st (lambda (v1 v2 st1) (v*s (num..

num-op : (number number -> number) -> (BFAE-Value BFAE-Value -> BFAE-Value) (define (num-op op x y) (numV (op (numV-n x) (numV-n y)))) (define (num+ x y) (num-op + x y)) (define (num...x y)) .x y) (num-op .. store-lookup : number Store -> BFAE-Value (define (store-lookup addr st) (type-case Store st [mtSto () (error ’store-lookup "unallocated")] [aSto (sto-addr val rest-st) (if (= addr sto-addr) val (store-lookup addr rest-st))])) ... malloc : Store -> integer (define (malloc store) (type-case Store store [mtSto () 0] [aSto (addr val rest) (+ addr 1)])) . lookup : symbol DefrdSub -> BFAE-Value (define (lookup name ds) (type-case DefrdSub ds [mtSub () (error ’lookup "free variable")] [aSub (sub-name val rest-ds) (if (symbol=? sub-name name) val (lookup name rest-ds))])) .