-
Notifications
You must be signed in to change notification settings - Fork 0
/
interp.rkt
154 lines (138 loc) · 4.16 KB
/
interp.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#lang racket
(provide (all-defined-out))
;; Your assignment code must be in the `..` directory
(require "../ast.rkt")
;; type Value =
;; | Integer
;; | Boolean
;; | Character
;; | String
;; | (Box Value)
;; | (Cons Value Value)
;; type Answer = Value | 'err
;; type REnv = (Listof (List Variable Value))
;; Expr -> Answer
(define (interp e)
(interp-env e '()))
;; Expr REnv -> Answer
(define (interp-env e r)
(match e
[(? value? v) (get-val v)]
[(nil-e) '()]
[(prim-e (? prim? p) es)
(let ((as (interp-env* es r)))
(interp-prim p as))]
[(if-e e0 e1 e2)
(match (interp-env e0 r)
['err 'err]
[v
(if v
(interp-env e1 r)
(interp-env e2 r))])]
[(var-e x)
(lookup r x)]
[(let-e bs body)
(match (interp-env* (get-defs bs) r)
['err 'err]
[vs
(interp-env body (append (zip (get-vars bs) vs) r))])]
[(cond-e cs el)
(interp-cond-env cs el r)]))
;; (Listof Expr) REnv -> (Listof Value) | 'err
(define (interp-env* es r)
(match es
['() '()]
[(cons e es)
(match (interp-env e r)
['err 'err]
[v (cons v (interp-env* es r))])]))
;; (Listof (List Expr Expr)) Expr REnv -> Answer
(define (interp-cond-env cs en r)
(match cs
['() (interp-env en r)]
[(cons (clause eq ea) cs)
(match (interp-env eq r)
['err 'err]
[v
(if v
(interp-env ea r)
(interp-cond-env cs en r))])]))
;; Any -> Boolean
(define (prim? x)
(and (symbol? x)
(memq x '(add1 sub1 zero? abs - char? boolean? integer? integer->char char->integer
string? box? empty? cons cons? box unbox car cdr string-length
make-string string-ref = < <= char=? boolean=? +))))
;; Any -> Boolean
(define (value? x)
(or (int-e? x)
(bool-e? x)
(char-e? x)
(string-e? x)))
;; Expr -> Value
(define (get-val v)
(match v
[(int-e x) x]
[(bool-e x) x]
[(char-e x) x]
[(string-e x) x]))
;; Prim (Listof Answer) -> Answer
(define (interp-prim p as)
(match (cons p as)
[(list p (? value?) ... 'err _ ...) 'err]
[(list '- (? integer? i0)) (- i0)]
[(list '- (? integer? i0) (? integer? i1)) (- i0 i1)]
[(list 'abs (? integer? i0)) (abs i0)]
[(list 'add1 (? integer? i0)) (+ i0 1)]
[(list 'sub1 (? integer? i0)) (- i0 1)]
[(list 'zero? (? integer? i0)) (zero? i0)]
[(list 'char? v0) (char? v0)]
[(list 'integer? v0) (integer? v0)]
[(list 'boolean? v0) (boolean? v0)]
[(list 'integer->char (? codepoint? i0)) (integer->char i0)]
[(list 'char->integer (? char? c)) (char->integer c)]
[(list '+ (? integer? i0) (? integer? i1)) (+ i0 i1)]
[(list 'cons v0 v1) (cons v0 v1)]
[(list 'car (? cons? v0)) (car v0)]
[(list 'cdr (? cons? v0)) (cdr v0)]
[(list 'string? v0) (string? v0)]
[(list 'box? v0) (box? v0)]
[(list 'empty? v0) (empty? v0)]
[(list 'cons? v0) (cons? v0)]
[(list 'cons v0 v1) (cons v0 v1)]
[(list 'box v0) (box v0)]
[(list 'unbox (? box? v0)) (unbox v0)]
[(list 'string-length (? string? v0)) (string-length v0)]
[(list 'make-string (? natural? v0) (? char? v1)) (make-string v0 v1)]
[(list 'string-ref (? string? v0) (? natural? v1))
(if (< v1 (string-length v0))
(string-ref v0 v1)
'err)]
[(list '= (? integer? v0) (? integer? v1)) (= v0 v1)]
[(list '< (? integer? v0) (? integer? v1)) (< v0 v1)]
[(list '<= (? integer? v0) (? integer? v1)) (<= v0 v1)]
[(list 'char=? (? char? v0) (? char? v1)) (char=? v0 v1)]
[(list 'boolean=? (? boolean? v0) (? boolean? v1)) (boolean=? v0 v1)]
[_ 'err]))
;; REnv Variable -> Answer
(define (lookup env x)
(match env
['() 'err]
[(cons (list y v) env)
(match (symbol=? x y)
[#t v]
[#f (lookup env x)])]))
;; REnv Variable Value -> Value
(define (ext r x v)
(cons (list x v) r))
;; Any -> Boolean
(define (codepoint? x)
(and (integer? x)
(<= 0 x #x10FFFF)
(not (<= #xD800 x #xDFFF))))
;; (Listof A) (Listof B) -> (Listof (List A B))
(define (zip xs ys)
(match* (xs ys)
[('() '()) '()]
[((cons x xs) (cons y ys))
(cons (list x y) (zip xs ys))]))