Created
March 20, 2025 19:32
-
-
Save kmicinski/71cb14e72f46c3341b6dcd69bb0e8403 to your computer and use it in GitHub Desktop.
Exercise 3 help
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
;; Consider the folllowing λ-calculus expression, write | |
;; a reduction sequence where each β reduction in the | |
;; sequence uses CBV evaluation order | |
((λ (x) x) | |
((λ (y) y) (λ (z) z))) | |
((λ (x) x) | |
((λ (z) (z z)) (λ (y) (y y)))) | |
;; In Call-by-Value, we have a notion of *values*, which | |
;; are computed results. To call a function, we have to | |
;; reduce its arguments to values. | |
;; | |
;; In Call-by-Name, we are tracking the program's abstract | |
;; syntax tree (or at least, some representation of it) at | |
;; runtime. When we get to an application, instead of reducing | |
;; the argument to a value (like a number, or a closure, | |
;; or an object), we instead bind the variable to the runtime | |
;; representation of the expression corresponding to the argument | |
;; | |
;; CBN β: ((λ (x) e-b) e-a) → e-b[x↦e-a] | |
;; CBV β: ((λ (x) e-b) v) → e-b[x↦v-a] | |
;; in Call-by-Value, we are always assigning variables to | |
;; *values*, represented as data structures at runtime. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
;; Exercise 3: A CE (Control and Environment) interpreter for Scheme | |
;; NOTE: You *MAY* collaborate with other students on this exercise, | |
;; but *not* the later project. Feel free to work with up to two other | |
;; students (groups of three) and submit the same code as them. Use | |
;; that code to begin your solution for p3. | |
;; Name: ________________________________ | |
;; Collaborator 1: ________________________________ | |
;; Collaborator 2: ________________________________ | |
(provide interp-ce) | |
; Interp-ce must correctly interpret any valid scheme-ir program and yield the same value | |
; as DrRacket, except for closures which must be represented as `(closure ,lambda ,environment). | |
; (+ 1 2) can return 3 and (cons 1 (cons 2 '())) can yield '(1 2). For programs that result in a | |
; runtime error, you should return `(error ,message)---giving some reasonable string error message. | |
; Handling errors and some trickier cases will give bonus points. | |
(define (interp-ce exp) | |
(define (interp env exp) | |
(pretty-print exp) | |
(pretty-print env) | |
(match exp | |
[(or (? number?) (? boolean?)) exp] | |
[`(let ([,x ,rhs]) ,body) | |
(interp env `((lambda (,x) ,body) ,rhs))] | |
[`(lambda (,x) ,body) | |
`(closure (lambda (,x) ,body) ,env)] | |
[(? symbol? x) | |
;; look it up | |
(hash-ref env x)] | |
[`(if ,ge ,te ,fe) | |
(if (interp env ge) | |
;; guard was true, evaluate the true branch | |
(interp env te) | |
(interp env fe))] | |
;; not required, but you may want to add this | |
#;[`(apply-prim ,op ,x) | |
'todo] | |
[`(,op ,e0 ,e1) | |
(define (op->rkt op) | |
(match op ['+ +] ['- -] ['* *])) | |
(let ([v0 (interp env e0)] | |
[v1 (interp env e1)] | |
[op+ (op->rkt op)]) | |
(op+ v0 v1))] | |
[`(,ef ,ea) | |
;; | |
(define clo-for-ef (interp env ef)) | |
(match clo-for-ef | |
[`(closure (lambda (,x) ,e-b) ,env+) | |
(let ([v (interp env ea)]) | |
(interp (hash-set env+ x v) e-b))])])) | |
;; TODO: update? | |
(define starting-env (hash)) | |
(interp starting-env exp)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment