-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlecture7A.rkt
134 lines (114 loc) · 3.67 KB
/
lecture7A.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#lang racket
; Zilu Tian
; March 24, 2020
; Metacircular Evaluator, Part 1
(define operator car) ; (+ 1 5)
(define operands cdr)
(define quote-sym cadr) ; 'foo => (quote foo) -> foo
(define cond-clauses cdr) ; (cond (p1 e1) (p2 e2) ...)
(define eval-ow
(λ (exp env)
(cond
; special cases
[(number? exp) exp]
[(symbol? exp) (lookup exp env)] ; x -> 3; car -> #[procedure]
[(eq? (operator exp) 'quote) (quote-sym exp)]
[(eq? (operator exp) 'lambda) (list 'closure (cdr exp) env)]; (λ(x)(+ x y)) -> (closure ((x)(+ x y)) <env>) ; Need to distinguish
[(eq? (operator exp) 'cond)
(evcond (cond-clauses exp) env)]
; default combination
[else (apply-ow (eval-ow (operator exp) env)
((operands exp) env))])))
; apply's job is to take a procedure and apply it to its args after both have been eval
; (list 'closure '((x)(λ (y) (x + y))) '<e0>)
(define proc-type car) ; 'closure
(define proc-body cadadr) ; '(λ (y) (x + y))
(define proc-arg caadr); '(x)
(define proc-env caddr); '<e0>
(define apply-primop apply);
(define apply-ow
(λ (proc args)
(cond [(primitive? proc) (apply-primop proc args)]
[(eq? (proc-type proc) 'closure)
(eval (proc-body proc) (bind proc-arg proc) args (proc-env proc))] ; compound made up by lambda
[else error])))
; l: list of operands
(define first-operand car)
(define evlist
(λ (l env)
(cond [(eq? l '()) '()]
[else (cons (eval-ow (first-operand l) env) ; evaluate the operand
(evlist (cdr l) env))])))
;(eval '(((λ(x) (λ(y)(+ x y))) 3) 4) <e0>)
;->
;(apply (eval '((λ(x)(λ(y)(+ x y))) 3) <e0>)
; (evlist '(4) <e0>))
;->
;(apply (eval '((λ(x)(λ(y)(+ x y))) 3) <e0>)
; (cons (eval '(4) <e0>)
; (evlist '() <e0>)))
;->
;(apply (eval '((λ(x)(λ(y)(+ x y))) 3) <e0>)
; (cons 4 '()))
;->
;(apply (apply (eval '(λ(x)(λ(y)(+ x y))) <e0>)
; '(3))
; '(4))
;->
;(apply (apply '(closure ((x)(λ(y)(+ x y))) <e0>)
; '(3))
; '(4))
;->
;(apply (eval '(λ(y)(+ x y)) <e1>)
; '(4))
;->
;(apply '(closure((y)(+ x y)) <e1>)
; '(4))
;->
;(eval '(+ x y) <e2>)
;->
;(apply (eval '+ <e2>)
; (evlist '(x y) <e2>))
;->
;(apply 'primop-addition '(3 4))
;->
;7
; cond (list '[(> 0 n) (do_a)] '[(<5 n) (do_b)] '[else (do_c)])
(define first-test-expr caar) ; (> 0 n)
(define first-then-body cadar) ; (do_a)
(define rest-clauses cdr) ; [(<5 n) (do_b)] [else (do_c)]
(define evcond
(λ (clauses env)
(cond [(eq? clauses '()) '()]
[(eq? (first-test-expr clauses) 'else)
(eval (first-then-body clauses) env)]
[(false? (eval (first-test-expr clauses) env))
(evcond (next-clause clauses) env)]
[else
(eval (rest-clauses clauses) env)])))
(define bind
(λ (vars vals env)
(cons (pair-up vars vals) env)))
(define pair-up
(λ (vars vals)
(cond [(eq? vars '())
(cond [(eq? vals '()) '()]
[else (error TMA)])]
[(eq? vals '()) (error TFA)]
[else (cons (cons (car vars)
(car vals))
(pair-up (cdr vars) (cdr vals)))])))
(define lookup
(λ (sym env)
(cond [(eq? env '()) (error UBV)]
[else ((λ (vcell)
(cond [(eq? vcell '())
(lookup sym (cdr env))]
[else (cdr vcell)]))
(assq sym (car env)))])))
(define assq
(λ (sym alist) ; symbol and a list of pairs
(cond [(eq? alist '()) '()]
[(eq? sym (caar alist))
(car alist)]
[else (assq sym (cdr alist))])))