public
Description: Arc Lisp to C compiler
Homepage:
Clone URL: git://github.com/sacado/arc2c.git
arc2c / cps.arc
100644 93 lines (85 sloc) 3.025 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
; CPS conversion
 
(def make-cont (subx params)
  (let ast (make-lam subx params)
    (assert ast!continuation)
    ast))
 
(def cps (ast k-ast)
  (if
    (or (alit ast) (aref ast) (aquote ast))
      (make-app (list k-ast ast))
    (aset ast)
      (cps-list ast!subx [make-app:list k-ast (make-set _ ast!var)])
    (acnd ast)
      (let xform (fn (k)
        (cps-list (list:car ast!subx) [make-cnd:list (car _) (cps (cadr ast!subx) k) (cps (car:cddr ast!subx) k)]))
        (if (aref k-ast) ; prevent combinatorial explosion
          (xform k-ast)
          (let k (new-var 'k)
            (make-app:list (make-lam (list:xform:make-ref '() k) (list k)) k-ast))))
    (aprim ast)
      (cps-list ast!subx [make-app:list k-ast (make-prim _ ast!op)])
    (anapp ast)
      (let fun (car ast!subx)
        (if (alam fun)
          ; let form
          (cps-list (cdr ast!subx) [make-app (cons (make-lam (list:cps-seq fun!subx k-ast) fun!params) _)])
          (cps-list ast!subx [make-app (cons (car _) (cons k-ast (cdr _)))])))
    (alam ast)
      (let k (new-var 'k)
        (make-app:list k-ast (make-lam (list:cps-seq ast!subx (make-ref '() k)) (cons k ast!params))))
    (aseq ast)
      (cps-seq ast!subx k-ast)
      (err "unknown ast" ast)))
 
(def cps-list (asts inner)
  (let body (fn (x) (cps-list (cdr asts) [inner (cons x _)]))
    (if
      (no asts)
        (inner '())
      (or (alit (car asts)) (aref (car asts)))
        (body (car asts))
        (let r (new-var 'r)
          (cps (car asts) (make-cont (list:body:make-ref '() r) (list r)))))))
 
(def cps-seq (asts k-ast)
  (if
    (no asts)
      (make-app:list k-ast nil)
    (no (cdr asts))
      (cps (car asts) k-ast)
      (let r (new-var 'r)
        (cps (car asts) (make-cont (list:cps-seq (cdr asts) k-ast) (list r))))))
 
 
(def cps-convert (ast)
  (with (ast-cps
          (cps
            ast
            (let r (new-var 'r)
              (make-cont
                (list:make-prim (list:make-ref '() r) '%halt)
                (list r))))
         primvar
         (fn (var)
           (and (aglobal var)
                (is #\% ((string var!id) 0))))
         primitivize nil)
    (= primitivize
       (fn (ast)
         (if
           (and (anapp ast)
                (aref:car ast!subx)
                (primvar ((car ast!subx) 'var)))
             (make-prim (map primitivize (cdr ast!subx))
                        (((car ast!subx) 'var) 'id))
           ; else
             (do (zap [map primitivize _] ast!subx)
                 ast))))
    (if (lookup 'ccc (fv ast))
      ; add this definition for call/cc if call/cc is needed
      (= ast-cps
        (make-app:list
          (make-lam (list ast-cps) (list (new-var '_)))
          (xe '(set ccc (fn (k f) (f k (fn (_ result) (k result))))) '()))))
    (if (lookup '<arc2c>!apply (fv ast))
      (= ast-cps
         (make-app:list
          (make-lam (list ast-cps) (list (new-var '_)))
          (primitivize:xe '(set <arc2c>!apply (fn (k f l) (%apply f k l))) '()))))
    ast-cps))