This repository has been archived by the owner on Oct 26, 2023. It is now read-only.
forked from iambrj/imin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interp-Rdyn.rkt
164 lines (154 loc) · 6.12 KB
/
interp-Rdyn.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
155
156
157
158
159
160
161
162
163
164
#lang racket
(require racket/fixnum)
(require "utilities.rkt" (prefix-in runtime-config: "runtime-config.rkt"))
(provide interp-Rdyn interp-Rdyn-prog)
;; Note to maintainers of this code:
;; A copy of this interpreter is in the book and should be
;; kept in sync with this code.
(define (interp-op op)
(match op
['+ fx+]
['- fx-]
['read read-fixnum]
['not (lambda (v) (match v [#t #f] [#f #t]))]
['< (lambda (v1 v2)
(cond [(and (fixnum? v1) (fixnum? v2))
(< v1 v2)]))]
['<= (lambda (v1 v2)
(cond [(and (fixnum? v1) (fixnum? v2))
(<= v1 v2)]))]
['> (lambda (v1 v2)
(cond [(and (fixnum? v1) (fixnum? v2))
(> v1 v2)]))]
['>= (lambda (v1 v2)
(cond [(and (fixnum? v1) (fixnum? v2))
(>= v1 v2)]))]
['boolean? boolean?]
['integer? fixnum?]
['void? void?]
['vector? vector?]
['vector-length vector-length]
['procedure? (match-lambda [`(functions ,xs ,body ,env) #t]
[else #f])]
[else (error 'interp-op "unknown operator ~a" op)]))
(define (op-tags op)
(match op
['+ '((Integer Integer))]
['- '((Integer Integer) (Integer))]
['read '(())]
['not '((Boolean))]
['< '((Integer Integer))]
['<= '((Integer Integer))]
['> '((Integer Integer))]
['>= '((Integer Integer))]
['vector-length '((Vector))]
))
(define type-predicates
(set 'boolean? 'integer? 'vector? 'procedure? 'void?))
(define (tag-value v)
(cond [(boolean? v) (Tagged v 'Boolean)]
[(fixnum? v) (Tagged v 'Integer)]
[(procedure? v) (Tagged v 'Procedure)]
[(vector? v) (Tagged v 'Vector)]
[(void? v) (Tagged v 'Void)]
[else (error 'tag-value "unidentified value ~a" v)]))
(define (check-tag val expected ast)
(define tag (Tagged-tag val))
(unless (eq? tag expected)
(error 'trapped-error "expected ~a tag, not ~a\nin ~v" expected tag ast)))
(define ((interp-Rdyn-exp env) ast)
(verbose 'interp-Rdyn "start" ast)
(define recur (interp-Rdyn-exp env))
(define result
(match ast
[(Var x) (lookup x env)]
[(FunRef f) (lookup f env)]
;; The following deals with the detail of our translation.
;; It keeps the arity of functions in the funref.
[(FunRefArity f n) (lookup f env)]
[(Int n) (Tagged n 'Integer)]
[(Bool b) (Tagged b 'Boolean)]
[(Lambda xs rt body)
(Tagged `(function ,xs ,body ,env) 'Procedure)]
[(Prim 'vector es)
(Tagged (apply vector (for/list ([e es]) (recur e))) 'Vector)]
[(Prim 'vector-ref (list e1 e2))
(define vec (recur e1)) (define i (recur e2))
(check-tag vec 'Vector ast) (check-tag i 'Integer ast)
(unless (< (Tagged-value i) (vector-length (Tagged-value vec)))
(error 'trapped-error "index ~a too big\nin ~v" (Tagged-value i) ast))
(vector-ref (Tagged-value vec) (Tagged-value i))]
[(Prim 'vector-set! (list e1 e2 e3))
(define vec (recur e1)) (define i (recur e2)) (define arg (recur e3))
(check-tag vec 'Vector ast) (check-tag i 'Integer ast)
(unless (< (Tagged-value i) (vector-length (Tagged-value vec)))
(error 'trapped-error "index ~a too big\nin ~v" (Tagged-value i) ast))
(vector-set! (Tagged-value vec) (Tagged-value i) arg)
(Tagged (void) 'Void)]
[(Let x e body)
((interp-Rdyn-exp (cons (cons x (recur e)) env)) body)]
[(Prim 'and (list e1 e2)) (recur (If e1 e2 (Bool #f)))]
[(Prim 'or (list e1 e2))
(define v1 (recur e1))
(match (Tagged-value v1) [#f (recur e2)] [else v1])]
[(Prim 'not (list e1))
(match (Tagged-value (recur e1)) [#f (Tagged #t 'Boolean)]
[else (Tagged #f 'Boolean)])]
[(Prim 'eq? (list e1 e2))
(Tagged (equal? (recur e1) (recur e2)) 'Boolean)]
[(Prim op (list e1))
#:when (set-member? type-predicates op)
(tag-value ((interp-op op) (Tagged-value (recur e1))))]
[(Prim op es)
(define args (map recur es))
(define tags (for/list ([arg args]) (Tagged-tag arg)))
(unless (for/or ([expected-tags (op-tags op)])
(equal? expected-tags tags))
(error 'trapped-error "illegal argument tags ~a\nin ~v" tags ast))
(tag-value
(apply (interp-op op) (for/list ([a args]) (Tagged-value a))))]
[(If q t f)
(match (Tagged-value (recur q)) [#f (recur f)] [else (recur t)])]
[(Apply f es)
(define new-f (recur f))
(define args (map recur es))
(check-tag new-f 'Procedure ast)
(define f-val (Tagged-value new-f))
(match f-val
[`(function ,xs ,body ,lam-env)
(unless (eq? (length xs) (length args))
(error 'trapped-error "number of arguments ~a != arity ~a\nin ~v"
(length args) (length xs) ast))
(define new-env (append (map cons xs args) lam-env))
((interp-Rdyn-exp new-env) body)]
[else (error "interp-Rdyn-exp, expected function, not" f-val)])]))
(verbose 'interp-Rdyn ast result)
result)
(define (interp-Rdyn-def ast)
(match ast
[(Def f xs rt info body) (mcons f `(function ,xs ,body ()))]))
;; This version is for source code in Rdyn.
(define (interp-Rdyn ast)
(match ast
[(ProgramDefsExp info ds body)
(define top-level (map (lambda (d) (interp-Rdyn-def d)) ds))
(for/list ([b top-level])
(set-mcdr! b (match (mcdr b)
[`(function ,xs ,body ())
(Tagged `(function ,xs ,body ,top-level) 'Procedure)])))
(define result ((interp-Rdyn-exp top-level) body))
(check-tag result 'Integer ast)
(Tagged-value result)]
[(Program info body) (interp-Rdyn (ProgramDefsExp info '() body))]))
;; This version is for after shrink.
(define (interp-Rdyn-prog ast)
(match ast
[(ProgramDefs info ds)
(define top-level (map (lambda (d) (interp-Rdyn-def d)) ds))
(for/list ([b top-level])
(set-mcdr! b (match (mcdr b)
[`(function ,xs ,body ())
(Tagged `(function ,xs ,body ,top-level) 'Procedure)])))
(define result ((interp-Rdyn-exp top-level) (Apply (Var 'main) '())))
(check-tag result 'Integer ast)
(Tagged-value result)]))