First-order CPS has $program and $closure forms
[bpt/guile.git] / module / language / cps / reify-primitives.scm
index 9a57bf1..a4d7099 100644 (file)
@@ -1,6 +1,6 @@
 ;;; Continuation-passing style (CPS) intermediate language (IL)
 
-;; Copyright (C) 2013 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2014 Free Software Foundation, Inc.
 
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
   #:export (reify-primitives))
 
 (define (module-box src module name public? bound? val-proc)
-  (let-gensyms (module-sym name-sym public?-sym bound?-sym kbox box)
+  (let-fresh (kbox) (module-var name-var public?-var bound?-var box)
     (build-cps-term
-      ($letconst (('module module-sym module)
-                  ('name name-sym name)
-                  ('public? public?-sym public?)
-                  ('bound? bound?-sym bound?))
+      ($letconst (('module module-var module)
+                  ('name name-var name)
+                  ('public? public?-var public?)
+                  ('bound? bound?-var bound?))
         ($letk ((kbox ($kargs ('box) (box) ,(val-proc box))))
           ($continue kbox src
             ($primcall 'cached-module-box
-                       (module-sym name-sym public?-sym bound?-sym))))))))
+                       (module-var name-var public?-var bound?-var))))))))
 
 (define (primitive-module name)
   (case name
-    ((bytevector-u8-ref bytevector-u8-set!
+    ((bytevector-length
+
+      bytevector-u8-ref bytevector-u8-set!
       bytevector-s8-ref bytevector-s8-set!
 
       bytevector-u16-ref bytevector-u16-set!
                   ($continue k src ($primcall 'box-ref (box)))))))
 
 (define (builtin-ref idx k src)
-  (let-gensyms (idx-sym)
+  (let-fresh () (idx-var)
     (build-cps-term
-      ($letconst (('idx idx-sym idx))
+      ($letconst (('idx idx-var idx))
         ($continue k src
-          ($primcall 'builtin-ref (idx-sym)))))))
+          ($primcall 'builtin-ref (idx-var)))))))
 
 (define (reify-clause ktail)
-  (let-gensyms (kclause kbody wna false str eol kthrow throw)
+  (let-fresh (kclause kbody kthrow) (wna false str eol throw)
     (build-cps-cont
       (kclause ($kclause ('() '() #f '() #f)
                  (kbody
                                  ($continue ktail #f
                                    ($call throw
                                           (wna false str eol false))))))
-                        ,(primitive-ref 'throw kthrow #f))))))))))
-
-;; FIXME: Operate on one function at a time, for efficiency.
-(define (reify-primitives fun)
-  (let ((conts (build-cont-table fun)))
-    (define (visit-fun term)
-      (rewrite-cps-exp term
-        (($ $fun src meta free body)
-         ($fun src meta free ,(visit-cont body)))))
-    (define (visit-cont cont)
-      (rewrite-cps-cont cont
-        (($ $cont sym ($ $kargs names syms body))
-         (sym ($kargs names syms ,(visit-term body))))
-        (($ $cont sym ($ $kentry self (and tail ($ $cont ktail)) ()))
-         ;; A case-lambda with no clauses.  Reify a clause.
-         (sym ($kentry self ,tail (,(reify-clause ktail)))))
-        (($ $cont sym ($ $kentry self tail clauses))
-         (sym ($kentry self ,tail ,(map visit-cont clauses))))
-        (($ $cont sym ($ $kclause arity body))
-         (sym ($kclause ,arity ,(visit-cont body))))
-        (($ $cont)
-         ,cont)))
-    (define (visit-term term)
+                        ,(primitive-ref 'throw kthrow #f)))))
+                 ,#f)))))
+
+(define (reify-primitives/1 fun single-value-conts)
+  (define (visit-clause cont)
+    (rewrite-cps-cont cont
+      (($ $cont label ($ $kclause arity body alternate))
+       (label ($kclause ,arity ,(visit-cont body)
+                      ,(and alternate (visit-clause alternate)))))))
+  (define (visit-cont cont)
+    (rewrite-cps-cont cont
+      (($ $cont label ($ $kargs (name) (var) body))
+       ,(begin
+          (bitvector-set! single-value-conts label #t)
+          (build-cps-cont
+            (label ($kargs (name) (var) ,(visit-term body))))))
+      (($ $cont label ($ $kargs names vars body))
+       (label ($kargs names vars ,(visit-term body))))
+      (($ $cont)
+       ,cont)))
+  (define (visit-term term)
+    (match term
+      (($ $letk conts body)
+       ;; Visit continuations before their uses.
+       (let ((conts (map visit-cont conts)))
+         (build-cps-term
+           ($letk ,conts ,(visit-term body)))))
+      (($ $continue k src exp)
+       (match exp
+         (($ $prim name)
+          (if (bitvector-ref single-value-conts k)
+              (cond
+               ((builtin-name->index name)
+                => (lambda (idx)
+                     (builtin-ref idx k src)))
+               (else (primitive-ref name k src)))
+              (build-cps-term ($continue k src ($void)))))
+         (($ $primcall 'call-thunk/no-inline (proc))
+          (build-cps-term
+            ($continue k src ($call proc ()))))
+         (($ $primcall name args)
+          (cond
+           ((or (prim-instruction name) (branching-primitive? name))
+            ;; Assume arities are correct.
+            term)
+           (else
+            (let-fresh (k*) (v)
+              (build-cps-term
+                ($letk ((k* ($kargs (v) (v)
+                              ($continue k src ($call v args)))))
+                  ,(cond
+                    ((builtin-name->index name)
+                     => (lambda (idx)
+                          (builtin-ref idx k* src)))
+                    (else (primitive-ref name k* src)))))))))
+         (_ term)))))
+
+  (rewrite-cps-cont fun
+    (($ $cont label ($ $kfun src meta self (and tail ($ $cont ktail)) #f))
+     ;; A case-lambda with no clauses.  Reify a clause.
+     (label ($kfun src meta self ,tail ,(reify-clause ktail))))
+    (($ $cont label ($ $kfun src meta self tail clause))
+     (label ($kfun src meta self ,tail ,(visit-clause clause))))))
+
+(define (reify-primitives term)
+  (with-fresh-name-state term
+    (let ((single-value-conts (make-bitvector (label-counter) #f)))
       (rewrite-cps-term term
-        (($ $letk conts body)
-         ($letk ,(map visit-cont conts) ,(visit-term body)))
-        (($ $continue k src exp)
-         ,(match exp
-            (($ $prim name)
-             (match (lookup-cont k conts)
-               (($ $kargs (_))
-                (cond
-                 ((builtin-name->index name)
-                  => (lambda (idx)
-                       (builtin-ref idx k src)))
-                 (else (primitive-ref name k src))))
-               (_ (build-cps-term ($continue k src ($void))))))
-            (($ $fun)
-             (build-cps-term ($continue k src ,(visit-fun exp))))
-            (($ $primcall 'call-thunk/no-inline (proc))
-             (build-cps-term
-               ($continue k src ($call proc ()))))
-            (($ $primcall name args)
-             (cond
-              ((or (prim-instruction name) (branching-primitive? name))
-               ;; Assume arities are correct.
-               term)
-              (else
-               (let-gensyms (k* v)
-                 (build-cps-term
-                   ($letk ((k* ($kargs (v) (v)
-                                 ($continue k src ($call v args)))))
-                     ,(cond
-                       ((builtin-name->index name)
-                        => (lambda (idx)
-                             (builtin-ref idx k* src)))
-                       (else (primitive-ref name k* src)))))))))
-            (_ term)))))
-
-    (visit-fun fun)))
+        (($ $program procs)
+         ($program ,(map (lambda (cont)
+                           (reify-primitives/1 cont single-value-conts))
+                         procs)))))))