4ca6eb1e1dc57100a344310ea1494ea2139236e0
[scheme.git] / ast.scm
1 (define (ast-type x)
2   (define (builtin? x)
3     (case x
4       ('+ #t)
5       ('- #t)
6       ('* #t)
7       ('! #t)
8       ('= #t)
9       ('bool->int #t)
10       ('print #t)
11       (else #f)))
12   (cond
13    ((list? x)
14     (case (car x)
15       ('if 'if)
16       ('let 'let)
17       ('lambda 'lambda)
18       ('closure 'closure) ; only available in codegen
19       ('static-string 'static-string) ; only available in codegen
20       (else 'app)))
21    ((builtin? x) 'builtin)
22    ((symbol? x) 'var)
23    ((integer? x) 'int-literal)
24    ((boolean? x) 'bool-literal)
25    ((string? x) 'string-literal)))
26
27 (define (ast-traverse f x)
28   (case (ast-type x)
29     ('let `(let ,(map (lambda (x) (list (car x) (f (cadr x))))
30                       (let-bindings x))
31              ,@(map f (let-body x))))
32     ('app (map f x))
33     ('lambda `(lambda ,(lambda-args x) ,(f (lambda-body x))))
34     ('if `(if ,@(map f (cdr x))))
35     (else x)))
36
37 (define (ast-collect f x)
38   (define (inner y) (ast-collect f y))
39   (case (ast-type x)
40     ['let (append (f x)
41                   (flat-map inner (let-bindings x))
42                   (flat-map inner (let-body x)))]
43     ['app (append (f x)
44                   (flat-map inner x))]
45     ['lambda (append (f x)
46                      (inner (lambda-body x)))]
47     ['if (append (f x)
48                  (flat-map inner (cdr x)))]
49     ['closure (flat-map inner (caddr x))]
50     [else (f x)]))
51
52 (define (ast-find p x)
53   (define (inner y) (ast-find p y))
54   (define (any p x) (fold-left
55                      (lambda (acc y) (if acc #t (p y)))
56                      #f
57                      x))
58   (define (either . fs)
59     (if (null? fs) #f
60         (if (car fs) (car fs)
61             (apply either (cdr fs)))))
62                      
63   (case (ast-type x)
64     ['let (either (p x)
65                   (any inner (let-bindings x))
66                   (any inner (let-body x)))]
67     ['app (either (p x)
68                   (any inner x))]
69     ['lambda (either (p x)
70                      (inner (lambda-body x)))]
71     ['if (either (p x) (any inner (cdr x)))]
72     [else (p x)]))
73
74 (define (let-bindings e)
75   (define (pattern-match binding body)
76     (if (eqv? (ast-type binding) 'var)
77         (list (cons binding body))
78         (let* ([constructor (car binding)]
79                [destructor (lambda (i) (dtor-name constructor i))])
80           (flat-map (lambda (y i)
81                       (pattern-match y `((,(destructor i) ,@body))))
82                     (cdr binding)
83                     (range 0 (length (cdr binding)))))))
84   (flat-map (lambda (x) (pattern-match (car x) (cdr x))) (cadr e)))
85 (define let-body cddr)
86
87 (define (lambda? x)
88   (and (list? x) (eq? (car x) 'lambda)))
89
90
91 (define (statement-type x)
92   (cond
93    [(and (list? x)
94          (eqv? (car x) 'data)) 'data]
95    [(and (list? x)
96          (eqv? (car x) 'define)) 'define]
97    [else 'expr]))
98
99 (define (program-datas program)
100   (filter (lambda (x) (eqv? (statement-type x) 'data))
101           program))
102
103 (define (program-defines program)
104   (filter (lambda (x) (eqv? (statement-type x) 'defines))
105           program))
106
107 (define (program-body program)
108   ; hack to have multi-expression bodies
109   `(let ()
110      ,@(filter (lambda (x) (eqv? (statement-type x) 'expr))
111                program)))
112
113
114                                         ; (A ((foo (Int Bool))
115                                         ;     (bar (Bool)))
116
117 (define data-layout cdr)
118
119                                         ; gets both constructors and destructors
120                                         ; (data A (foo Int Bool)
121                                         ;         (bar Bool))
122                                         ;        |
123                                         ;        v
124                                         ; (foo . (constructor . (abs Int (abs Bool A))))
125                                         ; (foo~0 . (0 . (abs A Int)))
126                                         ; (foo~1 . (1 . (abs A Bool)))
127                                         ; (bar . (constructor . (abs Bool A)))
128                                         ; (bar~0 . (0 . (abs A Bool)))
129
130 (define (data-tors data-layout)
131   (define (constructor-type t products)
132     (fold-right (lambda (x acc) `(abs ,x ,acc)) t products))
133
134   (define (destructor ctor-name prod-type part-type index)
135     (let ([name (dtor-name ctor-name index)])
136       (cons name (cons index `(abs ,prod-type ,part-type)))))
137   
138   (let ([type-name (car data-layout)]
139         [ctors (cdr data-layout)])
140     (fold-right
141      (lambda (ctor acc)       
142        (let* ([ctor-name (car ctor)]
143               [products (cdr ctor)]
144               
145               [maker (cons ctor-name (cons 'constructor (constructor-type type-name products)))]
146               
147               [dtors (map (lambda (t i) (destructor ctor-name type-name t i))
148                           products
149                           (range 0 (length products)))])
150          
151          (cons maker (append dtors acc))))
152      '()
153      ctors)))
154
155                                         ; creates a type environment for a given adt definition
156 (define (data-tors-env data-layout)
157   (map (lambda (x) (cons (car x) (cddr x))) (data-tors data-layout)))
158
159 (define (dtor-name ctor-name index)
160   (string->symbol
161    (string-append (symbol->string ctor-name)
162                   "~"
163                   (number->string index))))
164
165 ; for use in normalized form
166 (define lambda-arg caadr)
167 ; for use elsewhere
168 (define lambda-args cadr)
169 (define lambda-body caddr)
170
171 (define (references prog)
172   (ast-collect
173    (lambda (x)
174      (case (ast-type x)
175        ['var (list x)]
176        [else '()]))
177    prog))
178
179 (define (graph bs)
180   (define (go bs orig-bs)
181     (if (null? bs)
182         '(() . ())
183         (let* [(bind (car bs))
184
185                (vert (car bind))
186                (refs (filter ; only count a reference if its a binding
187                       (lambda (x) (assoc x orig-bs))
188                       (references (cdr bind))))
189                (edges (map (lambda (x) (cons vert x))
190                            refs))
191
192                (rest (if (null? (cdr bs))
193                          (cons '() '())
194                          (go (cdr bs) orig-bs)))
195                (total-verts (cons vert (car rest)))
196                (total-edges (append edges (cdr rest)))]
197           (cons total-verts total-edges))))
198   (go bs bs))
199
200 (define (successors graph v)
201   (define (go v E)
202     (if (null? E)
203         '()
204         (if (eqv? v (caar E))
205             (cons (cdar E) (go v (cdr E)))
206             (go v (cdr E)))))
207   (go v (cdr graph)))
208
209                                         ; takes in a graph (pair of vertices, edges)
210                                         ; returns a list of strongly connected components
211
212                                         ; ((x y w) . ((x . y) (x . w) (w . x))
213
214                                         ; =>
215                                         ; .->x->y
216                                         ; |  |
217                                         ; |  v
218                                         ; .--w
219
220                                         ; ((x w) (y))
221
222                                         ; this uses tarjan's algorithm, to get reverse
223                                         ; topological sorting for free
224 (define (sccs graph)
225   
226   (let* ([indices (make-hash-table)]
227          [lowlinks (make-hash-table)]
228          [on-stack (make-hash-table)]
229          [current 0]
230          [stack '()]
231          [result '()])
232
233     (define (index v)
234       (get-hash-table indices v #f))
235     (define (lowlink v)
236       (get-hash-table lowlinks v #f))
237
238     (letrec
239         ([strong-connect
240           (lambda (v)
241             (begin
242               (put-hash-table! indices v current)
243               (put-hash-table! lowlinks v current)
244               (set! current (+ current 1))
245               (push! stack v)
246               (put-hash-table! on-stack v #t)
247
248               (for-each
249                (lambda (w)
250                  (if (not (hashtable-contains? indices w))
251                                         ; successor w has not been visited, recurse
252                      (begin
253                        (strong-connect w)
254                        (put-hash-table! lowlinks
255                                         v
256                                         (min (lowlink v) (lowlink w))))
257                                         ; successor w has been visited
258                      (when (get-hash-table on-stack w #f)
259                        (put-hash-table! lowlinks v (min (lowlink v) (index w))))))
260                (successors graph v))
261
262               (when (= (index v) (lowlink v))
263                 (let ([scc
264                        (let new-scc ()
265                          (let ([w (pop! stack)])
266                            (put-hash-table! on-stack w #f)
267                            (if (eqv? w v)
268                                (list w)
269                                (cons w (new-scc)))))])
270                   (set! result (cons scc result))))))])
271       (for-each
272        (lambda (v)
273          (when (not (hashtable-contains? indices v)) ; v.index == -1
274            (strong-connect v)))
275        (car graph)))
276     result))
277
278
279                                         ; utils
280
281 (define (range s n)
282   (if (= 0 n) '()
283       (append (range s (- n 1))
284               (list (+ s (- n 1))))))
285
286 (define (flat-map f . xs) (fold-left append '() (apply map (cons f xs))))
287 (define (repeat x n) (if (<= n 0) '()
288                          (cons x (repeat x (- n 1)))))
289
290
291 (define-syntax push!
292   (syntax-rules ()
293     ((_ s x) (set! s (cons x s)))))
294
295 (define-syntax pop!
296   (syntax-rules ()
297     ((_ s) (let ([x (car s)])
298              (set! s (cdr s))
299              x))))