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