guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 01/05: Factor with-cps out to separate module


From: Andy Wingo
Subject: [Guile-commits] 01/05: Factor with-cps out to separate module
Date: Tue, 02 Jun 2015 10:23:02 +0000

wingo pushed a commit to branch master
in repository guile.

commit bac96c10f51b17e06862fc85980242723cac6419
Author: Andy Wingo <address@hidden>
Date:   Tue Jun 2 11:06:37 2015 +0200

    Factor with-cps out to separate module
    
    * module/language/cps2/with-cps.scm: New file.
    * module/language/tree-il/compile-cps2.scm: Use (language cps2 with-cps).
    * module/Makefile.am: Add language/cps2/with-cps.scm.
    
    * .dir-locals.el: Add indentation rules for with-cps.
---
 .dir-locals.el                           |    2 +
 module/Makefile.am                       |    3 +-
 module/language/cps2/with-cps.scm        |  134 ++++++++++++++++++++++++++++++
 module/language/tree-il/compile-cps2.scm |  107 +-----------------------
 4 files changed, 139 insertions(+), 107 deletions(-)

diff --git a/.dir-locals.el b/.dir-locals.el
index 895c112..5e213c5 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -15,6 +15,8 @@
      (eval . (put 'let-fresh           'scheme-indent-function 2))
      (eval . (put 'with-fresh-name-state 'scheme-indent-function 1))
      (eval . (put 'with-fresh-name-state-from-dfg 'scheme-indent-function 1))
+     (eval . (put 'with-cps            'scheme-indent-function 1))
+     (eval . (put 'with-cps-constants  'scheme-indent-function 1))
      (eval . (put 'build-cps-term      'scheme-indent-function 0))
      (eval . (put 'build-cps-exp       'scheme-indent-function 0))
      (eval . (put 'build-cps-cont      'scheme-indent-function 0))
diff --git a/module/Makefile.am b/module/Makefile.am
index 10f634c..b02a8f6 100644
--- a/module/Makefile.am
+++ b/module/Makefile.am
@@ -158,7 +158,8 @@ CPS2_LANG_SOURCES =                                         
\
   language/cps2/simplify.scm                                   \
   language/cps2/spec.scm                                       \
   language/cps2/types.scm                                      \
-  language/cps2/utils.scm
+  language/cps2/utils.scm                                      \
+  language/cps2/with-cps.scm
 
 BYTECODE_LANG_SOURCES =                                                \
   language/bytecode.scm                                                \
diff --git a/module/language/cps2/with-cps.scm 
b/module/language/cps2/with-cps.scm
new file mode 100644
index 0000000..354007e
--- /dev/null
+++ b/module/language/cps2/with-cps.scm
@@ -0,0 +1,134 @@
+;;; Continuation-passing style (CPS) intermediate language (IL)
+
+;; Copyright (C) 2013, 2014, 2015 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
+;;;; License as published by the Free Software Foundation; either
+;;;; version 3 of the License, or (at your option) any later version.
+;;;;
+;;;; This library is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;; Lesser General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU Lesser General Public
+;;;; License along with this library; if not, write to the Free Software
+;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
USA
+
+;;; Commentary:
+;;;
+;;; Guile's CPS language is a label->cont mapping, which seems simple
+;;; enough.  However it's often cumbersome to thread around the output
+;;; CPS program when doing non-trivial transformations, or when building
+;;; a CPS program from scratch.  For example, when visiting an
+;;; expression during CPS conversion, we usually already know the label
+;;; and the $kargs wrapper for the cont, and just need to know the body
+;;; of that cont.  However when building the body of that possibly
+;;; nested Tree-IL expression we will also need to add conts to the
+;;; result, so really it's a process that takes an incoming program,
+;;; adds conts to that program, and returns the result program and the
+;;; result term.
+;;;
+;;; It's a bit treacherous to do in a functional style as once you start
+;;; adding to a program, you shouldn't add to previous versions of that
+;;; program.  Getting that right in the context of this program seed
+;;; that is threaded through the conversion requires the use of a
+;;; pattern, with-cps.
+;;;
+;;; with-cps goes like this:
+;;;
+;;;   (with-cps cps clause ... tail-clause)
+;;;
+;;; Valid clause kinds are:
+;;;
+;;;   (letk LABEL CONT)
+;;;   (letv VAR ...)
+;;;   (let$ X (PROC ARG ...))
+;;;
+;;; letk and letv create fresh CPS labels and variable names,
+;;; respectively.  Labels and vars bound by letk and letv are in scope
+;;; from their point of definition onward.  letv just creates fresh
+;;; variable names for use in other parts of with-cps, while letk binds
+;;; fresh labels to values and adds them to the resulting program.  The
+;;; right-hand-side of letk, CONT, is passed to build-cont, so it should
+;;; be a valid production of that language.
+;;;
+;;; let$ delegates processing to a sub-computation.  The form (PROC ARG
+;;; ...) is syntactically altered to be (PROC CPS ARG ...), where CPS is
+;;; the value of the program being built, at that point in the
+;;; left-to-right with-cps execution.  That form is is expected to
+;;; evaluate to two values: the new CPS term, and the value to bind to
+;;; X.  X is in scope for the following with-cps clauses.  The name was
+;;; chosen because the $ is reminiscent of the $ in CPS data types.
+;;;
+;;; The result of the with-cps form is determined by the tail clause,
+;;; which may be of these two kinds:
+;;;
+;;;   ($ (PROC ARG ...))
+;;;   EXP
+;;;
+;;; $ is like let$, but in tail position.  Otherwise EXP is any kind of
+;;; expression, which should not add to the resulting program.  Ending
+;;; the with-cps with EXP is equivalant to returning (values CPS EXP).
+;;;
+;;; It's a bit of a monad, innit?  Don't tell anyone though!
+;;;
+;;; Sometimes you need to just bind some constants to CPS values.
+;;; with-cps-constants is there for you.  For example:
+;;;
+;;;   (with-cps-constants cps ((foo 34))
+;;;     (build-term ($values (foo))))
+;;;
+;;; The body of with-cps-constants is a with-cps clause, or a sequence
+;;; of such clauses.  But usually you will want with-cps-constants
+;;; inside a with-cps, so it usually looks like this:
+;;;
+;;;   (with-cps cps
+;;;     ...
+;;;     ($ (with-cps-constants ((foo 34))
+;;;          (build-term ($values (foo))))))
+;;;
+;;; which is to say that the $ or the let$ adds the CPS argument for us.
+;;;
+;;; Code:
+
+(define-module (language cps2 with-cps)
+  #:use-module (language cps2)
+  #:use-module (language cps2 utils)
+  #:use-module (language cps intmap)
+  #:export (with-cps with-cps-constants))
+
+(define-syntax with-cps
+  (syntax-rules (letk letv let$ $)
+    ((_ (exp ...) clause ...)
+     (let ((cps (exp ...)))
+       (with-cps cps clause ...)))
+    ((_ cps (letk label cont) clause ...)
+     (let-fresh (label) ()
+       (with-cps (intmap-add! cps label (build-cont cont))
+         clause ...)))
+    ((_ cps (letv v ...) clause ...)
+     (let-fresh () (v ...)
+       (with-cps cps clause ...)))
+    ((_ cps (let$ var (proc arg ...)) clause ...)
+     (call-with-values (lambda () (proc cps arg ...))
+       (lambda (cps var)
+         (with-cps cps clause ...))))
+    ((_ cps ($ (proc arg ...)))
+     (proc cps arg ...))
+    ((_ cps exp)
+     (values cps exp))))
+
+(define-syntax with-cps-constants
+  (syntax-rules ()
+    ((_ cps () clause ...)
+     (with-cps cps clause ...))
+    ((_ cps ((var val) (var* val*) ...) clause ...)
+     (let ((x val))
+       (with-cps cps
+         (letv var)
+         (let$ body (with-cps-constants ((var* val*) ...)
+                      clause ...))
+         (letk label ($kargs ('var) (var) ,body))
+         (build-term ($continue label #f ($const x))))))))
diff --git a/module/language/tree-il/compile-cps2.scm 
b/module/language/tree-il/compile-cps2.scm
index 14cd5f5..932a49d 100644
--- a/module/language/tree-il/compile-cps2.scm
+++ b/module/language/tree-il/compile-cps2.scm
@@ -56,6 +56,7 @@
   #:use-module ((system foreign) #:select (make-pointer pointer->scm))
   #:use-module (language cps2)
   #:use-module (language cps2 utils)
+  #:use-module (language cps2 with-cps)
   #:use-module (language cps primitives)
   #:use-module (language tree-il analyze)
   #:use-module (language tree-il optimize)
@@ -84,110 +85,6 @@
     (scope-counter (1+ scope-id))
     scope-id))
 
-;;; We will traverse the nested Tree-IL expression to build the
-;;; label->cont mapping for the result.  When visiting any particular
-;;; expression, we usually already know the label and the $kargs wrapper
-;;; for the cont, and just need to know the body of that cont.  However
-;;; when building the body of that possibly nested Tree-IL expression we
-;;; will also need to add conts to the result, so really it's a process
-;;; that takes an incoming program, adds conts to that program, and
-;;; returns the result program and the result term.
-;;; 
-;;; It's a bit treacherous to do in a functional style as once you start
-;;; adding to a program, you shouldn't add to previous versions of that
-;;; program.  Getting that right in the context of this program seed
-;;; that is threaded through the conversion requires the use of a
-;;; pattern, with-cps.
-;;;
-;;; with-cps goes like this:
-;;;
-;;;   (with-cps cps clause ... tail-clause)
-;;;
-;;; Valid clause kinds are:
-;;;
-;;;   (letk LABEL CONT)
-;;;   (letv VAR ...)
-;;;   (let$ X (PROC ARG ...))
-;;;
-;;; letk and letv create fresh CPS labels and variable names,
-;;; respectively.  Labels and vars bound by letk and letv are in scope
-;;; from their point of definition onward.  letv just creates fresh
-;;; variable names for use in other parts of with-cps, while letk binds
-;;; fresh labels to values and adds them to the resulting program.  The
-;;; right-hand-side of letk, CONT, is passed to build-cont, so it should
-;;; be a valid production of that language.
-;;;
-;;; let$ delegates processing to a sub-computation.  The form (PROC ARG
-;;; ...) is syntactically altered to be (PROC CPS ARG ...), where CPS is
-;;; the value of the program being built, at that point in the
-;;; left-to-right with-cps execution.  That form is is expected to
-;;; evaluate to two values: the new CPS term, and the value to bind to
-;;; X.  X is in scope for the following with-cps clauses.  The name was
-;;; chosen because the $ is reminiscent of the $ in CPS data types.
-;;;
-;;; The result of the with-cps form is determined by the tail clause,
-;;; which may be of these two kinds:
-;;;
-;;;   ($ (PROC ARG ...))
-;;;   EXP
-;;;
-;;; $ is like let$, but in tail position.  Otherwise EXP is any kind of
-;;; expression, which should not add to the resulting program.  Ending
-;;; the with-cps with EXP is equivalant to returning (values CPS EXP).
-;;;
-;;; It's a bit of a monad, innit?  Don't tell anyone though!
-;;;
-(define-syntax with-cps
-  (syntax-rules (letk letv let$ $)
-    ((_ (exp ...) clause ...)
-     (let ((cps (exp ...)))
-       (with-cps cps clause ...)))
-    ((_ cps (letk label cont) clause ...)
-     (let-fresh (label) ()
-       (with-cps (intmap-add! cps label (build-cont cont))
-         clause ...)))
-    ((_ cps (letv v ...) clause ...)
-     (let-fresh () (v ...)
-       (with-cps cps clause ...)))
-    ((_ cps (let$ var (proc arg ...)) clause ...)
-     (call-with-values (lambda () (proc cps arg ...))
-       (lambda (cps var)
-         (with-cps cps clause ...))))
-    ((_ cps ($ (proc arg ...)))
-     (proc cps arg ...))
-    ((_ cps exp)
-     (values cps exp))))
-
-;;; Sometimes you need to just bind some constants to CPS values.
-;;; with-cps-constants is there for you.  For example:
-;;;
-;;;   (with-cps-constants cps ((foo 34))
-;;;     (build-term ($values (foo))))
-;;;
-;;; The body of with-cps-constants is a with-cps clause, or a sequence
-;;; of such clauses.  But usually you will want with-cps-constants
-;;; inside a with-cps, so it usually looks like this:
-;;;
-;;;   (with-cps cps
-;;;     ...
-;;;     ($ (with-cps-constants ((foo 34))
-;;;          (build-term ($values (foo))))))
-;;;
-;;; which is to say that the $ or the let$ adds the CPS argument for us.
-;;;
-(define-syntax with-cps-constants
-  (syntax-rules ()
-    ((_ cps () clause ...)
-     (with-cps cps clause ...))
-    ((_ cps ((var val) (var* val*) ...) clause ...)
-     (let ((x val))
-       (with-cps cps
-         (letv var)
-         (let$ body (with-cps-constants ((var* val*) ...)
-                      clause ...))
-         (letk label ($kargs ('var) (var) ,body))
-         (build-term ($continue label #f ($const x))))))))
-
 (define (toplevel-box cps src name bound? val-proc)
   (define (lookup cps name bound? k)
     (match (current-topbox-scope)
@@ -1041,8 +938,6 @@ integer."
           env))
 
 ;;; Local Variables:
-;;; eval: (put 'with-cps 'scheme-indent-function 1)
-;;; eval: (put 'with-cps-constants 'scheme-indent-function 1)
 ;;; eval: (put 'convert-arg 'scheme-indent-function 2)
 ;;; eval: (put 'convert-args 'scheme-indent-function 2)
 ;;; End:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]