| 1 | |
|---|
| 2 | (load "./util.scm") |
|---|
| 3 | |
|---|
| 4 | (define extend |
|---|
| 5 | (lambda (e r) |
|---|
| 6 | (cons r e))) |
|---|
| 7 | |
|---|
| 8 | (define compile |
|---|
| 9 | (lambda (x e next) |
|---|
| 10 | (cond |
|---|
| 11 | ((symbol? x) (compile-refer x e next)) |
|---|
| 12 | ((pair? x) |
|---|
| 13 | (record-case x |
|---|
| 14 | (quote (obj) (list 'constant obj next)) |
|---|
| 15 | (lambda (vars body) |
|---|
| 16 | (let ((free (find-free body vars))) |
|---|
| 17 | (collect-free free e |
|---|
| 18 | (list 'close |
|---|
| 19 | (length free) |
|---|
| 20 | (compile body |
|---|
| 21 | (cons vars free) |
|---|
| 22 | (list 'return |
|---|
| 23 | (length vars))) |
|---|
| 24 | next)))) |
|---|
| 25 | (if (test then else) |
|---|
| 26 | (let ((thenc (compile then e next)) |
|---|
| 27 | (elsec (compile else e next))) |
|---|
| 28 | (compile test e (list 'test thenc elsec)))) |
|---|
| 29 | (call/cc (x) |
|---|
| 30 | (list 'frame |
|---|
| 31 | next |
|---|
| 32 | (list 'conti |
|---|
| 33 | (list 'argument |
|---|
| 34 | (compile x e '(apply)))))) |
|---|
| 35 | (else |
|---|
| 36 | (recur loop ((args (cdr x)) |
|---|
| 37 | (c (compile (car x) e '(apply)))) |
|---|
| 38 | (if (null? args) |
|---|
| 39 | (list 'frame next c) |
|---|
| 40 | (loop (cdr args) |
|---|
| 41 | (compile (car args) |
|---|
| 42 | e |
|---|
| 43 | (list 'argument c)))))))) |
|---|
| 44 | (else |
|---|
| 45 | (list 'constant x next))))) |
|---|
| 46 | |
|---|
| 47 | (define find-free |
|---|
| 48 | (lambda (x b) |
|---|
| 49 | (cond |
|---|
| 50 | ((symbol? x) (if (set-member? x b) '() (list x))) |
|---|
| 51 | ((pair? x) |
|---|
| 52 | (record-case x |
|---|
| 53 | (quote (obj) '()) |
|---|
| 54 | (lambda (vars body) |
|---|
| 55 | (find-free body (set-union vars b))) |
|---|
| 56 | (if (test then else) |
|---|
| 57 | (set-union (find-free test b) |
|---|
| 58 | (set-union (find-free then b) |
|---|
| 59 | (find-free else b)))) |
|---|
| 60 | (call/cc (exp) (find-free exp b)) |
|---|
| 61 | (else |
|---|
| 62 | (recur next ((x x)) |
|---|
| 63 | '() |
|---|
| 64 | (set-union (find-free (car x) b) |
|---|
| 65 | (next (cdr x))))))) |
|---|
| 66 | (else '())))) |
|---|
| 67 | |
|---|
| 68 | (define collect-free |
|---|
| 69 | (lambda (vars e next) |
|---|
| 70 | (if (null? vars) |
|---|
| 71 | next |
|---|
| 72 | (collect-free (cdr vars) e |
|---|
| 73 | (compile-refer (car vars) e |
|---|
| 74 | (list 'argument next)))))) |
|---|
| 75 | |
|---|
| 76 | (define compile-refer |
|---|
| 77 | (lambda (x e next) |
|---|
| 78 | (compile-lookup x e |
|---|
| 79 | (lambda (n) (list 'refer-local n next)) |
|---|
| 80 | (lambda (n) (list 'refer-free n next))))) |
|---|
| 81 | |
|---|
| 82 | (define compile-lookup |
|---|
| 83 | (lambda (x e return-local return-free) |
|---|
| 84 | (recur nxtlocal ((locals (car e)) (n 0)) |
|---|
| 85 | (if (null? locals) |
|---|
| 86 | (recur nxtfree ((free (cdr e)) (n 0)) |
|---|
| 87 | (if (eq? (car free) x) |
|---|
| 88 | (return-free n) |
|---|
| 89 | (nxtfree (cdr free) (+ n 1)))) |
|---|
| 90 | (if (eq? (car locals) x) |
|---|
| 91 | (return-local n) |
|---|
| 92 | (nxtlocal (cdr locals) (+ n 1))))))) |
|---|
| 93 | |
|---|
| 94 | (define set-member? |
|---|
| 95 | (lambda (x s) |
|---|
| 96 | (cond |
|---|
| 97 | ((null? s) #f) |
|---|
| 98 | ((eq? x (car s)) #t) |
|---|
| 99 | (else (set-member? x (cdr s)))))) |
|---|
| 100 | |
|---|
| 101 | (define set-cons |
|---|
| 102 | (lambda (x s) |
|---|
| 103 | (if (set-member? x s) |
|---|
| 104 | s |
|---|
| 105 | (cons x s)))) |
|---|
| 106 | |
|---|
| 107 | (define set-union |
|---|
| 108 | (lambda (s1 s2) |
|---|
| 109 | (if (null? s1) |
|---|
| 110 | s2 |
|---|
| 111 | (set-union (cdr s1) (set-cons (car s1) s2))))) |
|---|
| 112 | |
|---|
| 113 | (define set-minus |
|---|
| 114 | (lambda (s1 s2) |
|---|
| 115 | (if (null? s1) |
|---|
| 116 | '() |
|---|
| 117 | (if (set-member? (car s1) s2) |
|---|
| 118 | (set-minus (cdr s1) s2) |
|---|
| 119 | (cons (car s1) (set-minus (cdr s1) s2)))))) |
|---|
| 120 | |
|---|
| 121 | (define set-intersect |
|---|
| 122 | (lambda (s1 s2) |
|---|
| 123 | (if (null? s1) |
|---|
| 124 | '() |
|---|
| 125 | (if (set-member? (car s1) s2) |
|---|
| 126 | (cons (car s1) (set-intersect (cdr s1) s2)) |
|---|
| 127 | (set-intersect (cdr s1) s2))))) |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | ;;;; runtime |
|---|
| 131 | |
|---|
| 132 | (define functional |
|---|
| 133 | (lambda (body e) |
|---|
| 134 | (list body e))) |
|---|
| 135 | |
|---|
| 136 | (define stack (make-vector 1000)) |
|---|
| 137 | |
|---|
| 138 | (define push |
|---|
| 139 | (lambda (x s) |
|---|
| 140 | (vector-set! stack s x) |
|---|
| 141 | (+ s 1))) |
|---|
| 142 | |
|---|
| 143 | (define index |
|---|
| 144 | (lambda (s i) |
|---|
| 145 | (vector-ref stack (- (- s i) 1)))) |
|---|
| 146 | |
|---|
| 147 | (define index-set! |
|---|
| 148 | (lambda (s i v) |
|---|
| 149 | (vector-set! stack (- (- s i) 1) v))) |
|---|
| 150 | |
|---|
| 151 | |
|---|
| 152 | ;;;; VM |
|---|
| 153 | |
|---|
| 154 | (define VM |
|---|
| 155 | (lambda (a x f c s) |
|---|
| 156 | (record-case x |
|---|
| 157 | (halt () a) |
|---|
| 158 | (refer-local (n x) |
|---|
| 159 | (VM (index f n) x f c s)) |
|---|
| 160 | (refer-free (n x) |
|---|
| 161 | (VM (index-closure c n) x f c s)) |
|---|
| 162 | (constant (obj x) |
|---|
| 163 | (VM obj x f c s)) |
|---|
| 164 | (close (n body x) |
|---|
| 165 | (VM (closure body n s) x f c (- s n))) |
|---|
| 166 | (test (then else) |
|---|
| 167 | (VM a (if a then else) f c s)) |
|---|
| 168 | (conti (x) |
|---|
| 169 | (VM (continuation s) x f c s)) |
|---|
| 170 | (nuate (stack x) |
|---|
| 171 | (VM a x f c (restore-stack stack))) |
|---|
| 172 | (frame (ret x) |
|---|
| 173 | (VM a x f c (push ret (push f (push c s))))) |
|---|
| 174 | (argument (x) |
|---|
| 175 | (VM a x f c (push a s))) |
|---|
| 176 | (apply () |
|---|
| 177 | (VM a (closure-body a) s a s)) |
|---|
| 178 | (return (n) |
|---|
| 179 | (let ((s (- s n))) |
|---|
| 180 | (VM a (index s 0) (index s 1) (index s 2) (- s 3))))))) |
|---|
| 181 | |
|---|
| 182 | (define continuation |
|---|
| 183 | (lambda (s) |
|---|
| 184 | (closure |
|---|
| 185 | (list 'refer 0 0 (list 'nuate (save-stack s) '(return 0))) |
|---|
| 186 | '()))) |
|---|
| 187 | |
|---|
| 188 | (define closure |
|---|
| 189 | (lambda (body n s) |
|---|
| 190 | (let ((v (make-vector (+ n 1)))) |
|---|
| 191 | (vector-set! v 0 body) |
|---|
| 192 | (recur f ((i 0)) |
|---|
| 193 | (unless (= i n) |
|---|
| 194 | (vector-set! v (+ i 1) (index s i)) |
|---|
| 195 | (f (+ i 1)))) |
|---|
| 196 | v))) |
|---|
| 197 | |
|---|
| 198 | (define closure-body |
|---|
| 199 | (lambda (c) |
|---|
| 200 | (vector-ref c 0))) |
|---|
| 201 | |
|---|
| 202 | (define index-closure |
|---|
| 203 | (lambda (c n) |
|---|
| 204 | (vector-ref c (+ n 1)))) |
|---|
| 205 | |
|---|
| 206 | (define save-stack |
|---|
| 207 | (lambda (s) |
|---|
| 208 | (let ((v (make-vector s))) |
|---|
| 209 | (recur copy ((i 0)) |
|---|
| 210 | (unless (= i s) |
|---|
| 211 | (vector-set! v i (vector-ref stack i)) |
|---|
| 212 | (copy (+ i 1)))) |
|---|
| 213 | v))) |
|---|
| 214 | |
|---|
| 215 | (define restore-stack |
|---|
| 216 | (lambda (v) |
|---|
| 217 | (let ((s (vector-length v))) |
|---|
| 218 | (recur copy ((i 0)) |
|---|
| 219 | (unless (= i s) |
|---|
| 220 | (vector-set! stack i (vector-ref v i)) |
|---|
| 221 | (copy (+ i 1)))) |
|---|
| 222 | s))) |
|---|
| 223 | |
|---|
| 224 | (define lookup |
|---|
| 225 | (lambda (n m e) |
|---|
| 226 | (recur nxtrib ((e e) (rib n)) |
|---|
| 227 | (if (= rib 0) |
|---|
| 228 | (recur nxtelt ((r (car e)) (elt m)) |
|---|
| 229 | (if (= elt 0) |
|---|
| 230 | r |
|---|
| 231 | (nxtelt (cdr r) (- elt 1)))) |
|---|
| 232 | (nxtrib (cdr e) (- rib 1)))))) |
|---|
| 233 | |
|---|
| 234 | (define find-link |
|---|
| 235 | (lambda (n e) |
|---|
| 236 | (if (= n 0) |
|---|
| 237 | e |
|---|
| 238 | (find-link (- n 1) (index e -1))))) |
|---|
| 239 | |
|---|
| 240 | |
|---|
| 241 | (define evaluate |
|---|
| 242 | (lambda (x) |
|---|
| 243 | (let1 code (compile x '() '(halt)) |
|---|
| 244 | (VM '() code 0 '() 0)))) |
|---|
| 245 | |
|---|