Formulate destructors properly
[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     [else (f x)]))
50
51 (define (ast-find p x)
52   (define (inner y) (ast-find p y))
53   (define (any p x) (fold-left
54                      (lambda (acc y) (if acc #t (p y)))
55                      #f
56                      x))
57   (define (either . fs)
58     (if (null? fs) #f
59         (if (car fs) (car fs)
60             (apply either (cdr fs)))))
61                      
62   (case (ast-type x)
63     ['let (either (p x)
64                   (any inner (let-bindings x))
65                   (any inner (let-body x)))]
66     ['app (either (p x)
67                   (any inner x))]
68     ['lambda (either (p x)
69                      (inner (lambda-body x)))]
70     ['if (either (p x) (any inner (cdr x)))]
71     [else (p x)]))
72
73 (define (let-bindings e)
74   (define (pattern-match x body)
75     (if (eqv? (ast-type x) 'var)
76         (list (cons x body))
77         (let* ([constructor (car x)]
78                [destructor (lambda (i) (dtor-name constructor i))])
79           (flat-map (lambda (y i)
80                       (pattern-match y (list (destructor i) body)))
81                     (cdr x)
82                     (range 0 (length (cdr x)))))))
83   (flat-map (lambda (x) (pattern-match (car x) (cdr x))) (cadr e)))
84 (define let-body cddr)
85
86 (define (lambda? x)
87   (and (list? x) (eq? (car x) 'lambda)))
88
89
90 (define (statement-type x)
91   (cond
92    [(and (list? x)
93          (eqv? (car x) 'data)) 'data]
94    [(and (list? x)
95          (eqv? (car x) 'define)) 'define]
96    [else 'expr]))
97
98 (define (program-datas program)
99   (filter (lambda (x) (eqv? (statement-type x) 'data))
100           program))
101
102 (define (program-defines program)
103   (filter (lambda (x) (eqv? (statement-type x) 'defines))
104           program))
105
106 (define (program-body program)
107   `(let ()
108      ,@(filter (lambda (x) (eqv? (statement-type x) 'expr))
109                program)))
110
111                                         ; gets both constructors and destructors
112                                         ; (data A (foo Int Bool)
113                                         ;         (bar Bool))
114                                         ;        |
115                                         ;        v
116                                         ; (foo . (abs Int (abs Bool A)))
117                                         ; (foo~0 . (abs A Int)
118                                         ; (foo~1 . (abs A Bool)
119                                         ; (bar . (abs Bool A)
120                                         ; (bar~0 . (abs A Bool)
121
122 (define (data-tors data-def)
123   (define (constructor-type t products)
124     (fold-right (lambda (x acc) `(abs ,x ,acc)) t products))
125
126   (define (destructor ctor-name prod-type part-type index)
127     (let ([name (dtor-name ctor-name index)])
128       (cons name `(abs ,prod-type ,part-type))))
129   
130   (let ([type-name (cadr data-def)]
131         [ctors (cddr data-def)])
132     (fold-right
133      (lambda (ctor acc)       
134        (let* ([ctor-name (car ctor)]
135               [products (cdr ctor)]
136               
137               [maker (cons ctor-name (constructor-type type-name products))]
138               
139               [dtors (map (lambda (t i) (destructor ctor-name type-name t i))
140                           products
141                           (range 0 (length products)))])
142          
143          (cons maker (append dtors acc))))
144      '()
145      ctrs)))
146
147 (define (dtor-name ctor-name index)
148   (string->symbol
149    (string-append (symbol->string ctor-name)
150                   "~"
151                   (number->string index))))
152
153 ; for use in normalized form
154 (define lambda-arg caadr)
155 ; for use elsewhere
156 (define lambda-args cadr)
157 (define lambda-body caddr)
158
159                                         ; utils
160 (define (range s n)
161   (if (= 0 n) '()
162       (append (range s (- n 1))
163               (list (+ s (- n 1))))))
164
165 (define (flat-map f . xs) (fold-left append '() (apply map (cons f xs))))
166 (define (repeat x n) (if (<= n 0) '()
167                          (cons x (repeat x (- n 1)))))
168
169
170 (define-syntax push!
171   (syntax-rules ()
172     ((_ s x) (set! s (cons x s)))))
173
174 (define-syntax pop!
175   (syntax-rules ()
176     ((_ s) (let ([x (car s)])
177              (set! s (cdr s))
178              x))))