Sample Final 3Date: Wednesday, April 23rd |
AdministrativeThis exam was given last semester. |
| ||||||||||||||||||||||
Remember: the correct answers are short. Also, questions that ask for a verbal answer rather than code should still be answered correctly and based on facts.
Question 1: Scheme Programming | 24 pts |
;; add : Number Number -> Number
;; adds two numbers, with manually constructed contract checking
(define (add x y)
(unless (number? x) (error 'add "bad input: ~s" x))
(unless (number? y) (error 'add "bad input: ~s" y))
(let ([result (+ x y)]) ; <-- this is the actual function body
(unless (number? result) (error 'add "bad output: ~s" result))
result)) |
(define add (contract-binfun
'add ; name for error messages
number? number? ; inputs
number? ; output
(lambda (x y) (+ x y)) ; the actual function
)) |
Question 2: Language Extension: Extending Scheme | 24 pts |
(cdefine (add [x : number?] [y : number?]) : number?
(+ x y)) |
Question 3: The TOY Language | 24 pts |
Question 4: Programming in Lazy Scheme | 24 pts |
(strict (+ 1 2))
(+ 1 (strict (* 3 4)))
(define (foo x) (* 2 (strict (+ x 1)))) |
(define (bad-strict x) x) ; works for the above tests. |
Question 5: SLUG & Type System | 24 pts |
(if (< x 100) (printf "Too small")) |
{bind {{no-op missing1}} ; the no-op definition
{fun {x} ; a function that should use no-op
{if {< x 100}
{print "Too small"}
missing2}}} |
Γ |- x : String
|
The following is the core of the extended TOY implementation from Assignment #7, to be used in the TOY question.
;; eval-body : (Listof TOY) ENV -> VAL
;; evaluates a list of expressions, return the last value.
(define (eval-body exprs env)
(if (null? exprs)
(error 'eval-body "got an empty body")
(let ([1st-value (eval (first exprs) env)]
[other-exprs (rest exprs)])
(if (null? other-exprs)
1st-value
(eval-body other-exprs env)))))
;; eval : TOY env -> VAL
;; evaluates TOY expressions.
(define (eval expr env)
(cases expr
[(Num n) (ScmV n)]
[(Id v) (unbox (lookup v env))]
[(Bind names exprs bound-body)
(eval-body bound-body
(extend names
(map (lambda (e) (eval e env)) exprs)
env))]
[(BindRec names exprs bound-body)
(eval-body bound-body (extend-rec names exprs env))]
[(Fun names bound-body)
(FunV names bound-body env)]
[(RFun names bound-body)
(RFunV names bound-body env)]
[(Call fun-expr arg-exprs)
(let ([fval (eval fun-expr env)]
;; delay the evaluation of the arguments (use if needed)
[arg-vals (lambda ()
(map (lambda (e) (eval e env)) arg-exprs))])
(cases fval
[(PrimV proc) (proc (arg-vals))]
[(FunV names body fun-env)
(eval-body body (extend names (arg-vals) fun-env))]
[(RFunV names body fun-env)
(if (andmap Id? arg-exprs)
(let ([boxes (map (lambda (id) (lookup (Id-name id) env))
arg-exprs)])
(eval-body body (extend-boxes names boxes fun-env)))
(error 'eval "ref-functions expect only identifiers"))]
[else (error 'eval "function call with a non-function: ~s"
fval)]))]
[(If cond-expr then-expr else-expr)
(eval (if (cases (eval cond-expr env)
[(ScmV v) v] ; Scheme value => use as boolean
[else #t]) ; other values are always true
then-expr
else-expr)
env)]
[(Set id expr)
;; note the use of two expressions in this branch
(set-box! (lookup id env) (eval expr env))
bogus]))
;; run : String -> Any
;; evaluate a TOY program contained in a string
(define (run str)
(let ([result (eval (parse str) global-environment)])
(cases result
[(ScmV v) v]
[else (error 'run
"evaluation returned a bad value: ~s" result)])))