Formulate destructors properly
[scheme.git] / ast.scm
diff --git a/ast.scm b/ast.scm
index 8dac3b68833ca430d27015b8a97263a72c531f37..5064ca554bc8033bdbc0b483ac79249cd3312f73 100644 (file)
--- a/ast.scm
+++ b/ast.scm
@@ -7,6 +7,7 @@
       ('! #t)
       ('= #t)
       ('bool->int #t)
+      ('print #t)
       (else #f)))
   (cond
    ((list? x)
       ('let 'let)
       ('lambda 'lambda)
       ('closure 'closure) ; only available in codegen
+      ('static-string 'static-string) ; only available in codegen
       (else 'app)))
    ((builtin? x) 'builtin)
    ((symbol? x) 'var)
    ((integer? x) 'int-literal)
-   ((boolean? x) 'bool-literal)))
+   ((boolean? x) 'bool-literal)
+   ((string? x) 'string-literal)))
 
-;; (define (ast-recurse f x)
-;;   (cond (
+(define (ast-traverse f x)
+  (case (ast-type x)
+    ('let `(let ,(map (lambda (x) (list (car x) (f (cadr x))))
+                     (let-bindings x))
+            ,@(map f (let-body x))))
+    ('app (map f x))
+    ('lambda `(lambda ,(lambda-args x) ,(f (lambda-body x))))
+    ('if `(if ,@(map f (cdr x))))
+    (else x)))
 
-(define let-bindings cadr)
+(define (ast-collect f x)
+  (define (inner y) (ast-collect f y))
+  (case (ast-type x)
+    ['let (append (f x)
+                 (flat-map inner (let-bindings x))
+                 (flat-map inner (let-body x)))]
+    ['app (append (f x)
+                 (flat-map inner x))]
+    ['lambda (append (f x)
+                    (inner (lambda-body x)))]
+    ['if (append (f x)
+                (flat-map inner (cdr x)))]
+    [else (f x)]))
+
+(define (ast-find p x)
+  (define (inner y) (ast-find p y))
+  (define (any p x) (fold-left
+                    (lambda (acc y) (if acc #t (p y)))
+                    #f
+                    x))
+  (define (either . fs)
+    (if (null? fs) #f
+       (if (car fs) (car fs)
+           (apply either (cdr fs)))))
+                    
+  (case (ast-type x)
+    ['let (either (p x)
+                 (any inner (let-bindings x))
+                 (any inner (let-body x)))]
+    ['app (either (p x)
+                 (any inner x))]
+    ['lambda (either (p x)
+                    (inner (lambda-body x)))]
+    ['if (either (p x) (any inner (cdr x)))]
+    [else (p x)]))
+
+(define (let-bindings e)
+  (define (pattern-match x body)
+    (if (eqv? (ast-type x) 'var)
+       (list (cons x body))
+       (let* ([constructor (car x)]
+              [destructor (lambda (i) (dtor-name constructor i))])
+         (flat-map (lambda (y i)
+                     (pattern-match y (list (destructor i) body)))
+                   (cdr x)
+                   (range 0 (length (cdr x)))))))
+  (flat-map (lambda (x) (pattern-match (car x) (cdr x))) (cadr e)))
 (define let-body cddr)
 
 (define (lambda? x)
   (and (list? x) (eq? (car x) 'lambda)))
 
+
+(define (statement-type x)
+  (cond
+   [(and (list? x)
+        (eqv? (car x) 'data)) 'data]
+   [(and (list? x)
+        (eqv? (car x) 'define)) 'define]
+   [else 'expr]))
+
+(define (program-datas program)
+  (filter (lambda (x) (eqv? (statement-type x) 'data))
+         program))
+
+(define (program-defines program)
+  (filter (lambda (x) (eqv? (statement-type x) 'defines))
+         program))
+
+(define (program-body program)
+  `(let ()
+     ,@(filter (lambda (x) (eqv? (statement-type x) 'expr))
+              program)))
+
+                                       ; gets both constructors and destructors
+                                       ; (data A (foo Int Bool)
+                                       ;         (bar Bool))
+                                       ;        |
+                                       ;        v
+                                       ; (foo . (abs Int (abs Bool A)))
+                                       ; (foo~0 . (abs A Int)
+                                       ; (foo~1 . (abs A Bool)
+                                       ; (bar . (abs Bool A)
+                                       ; (bar~0 . (abs A Bool)
+
+(define (data-tors data-def)
+  (define (constructor-type t products)
+    (fold-right (lambda (x acc) `(abs ,x ,acc)) t products))
+
+  (define (destructor ctor-name prod-type part-type index)
+    (let ([name (dtor-name ctor-name index)])
+      (cons name `(abs ,prod-type ,part-type))))
+  
+  (let ([type-name (cadr data-def)]
+        [ctors (cddr data-def)])
+    (fold-right
+     (lambda (ctor acc)       
+       (let* ([ctor-name (car ctor)]
+             [products (cdr ctor)]
+             
+             [maker (cons ctor-name (constructor-type type-name products))]
+             
+             [dtors (map (lambda (t i) (destructor ctor-name type-name t i))
+                         products
+                         (range 0 (length products)))])
+        
+        (cons maker (append dtors acc))))
+     '()
+     ctrs)))
+
+(define (dtor-name ctor-name index)
+  (string->symbol
+   (string-append (symbol->string ctor-name)
+                 "~"
+                 (number->string index))))
+
 ; for use in normalized form
 (define lambda-arg caadr)
 ; for use elsewhere
 (define lambda-args cadr)
 (define lambda-body caddr)
+
+                                       ; utils
+(define (range s n)
+  (if (= 0 n) '()
+      (append (range s (- n 1))
+             (list (+ s (- n 1))))))
+
+(define (flat-map f . xs) (fold-left append '() (apply map (cons f xs))))
+(define (repeat x n) (if (<= n 0) '()
+                        (cons x (repeat x (- n 1)))))
+
+
+(define-syntax push!
+  (syntax-rules ()
+    ((_ s x) (set! s (cons x s)))))
+
+(define-syntax pop!
+  (syntax-rules ()
+    ((_ s) (let ([x (car s)])
+            (set! s (cdr s))
+            x))))