~ chicken-core (chicken-5) d3c44a5f74ea8c8461ab0bdb74c4ece07eae32b7


commit d3c44a5f74ea8c8461ab0bdb74c4ece07eae32b7
Author:     Peter Bex <peter@more-magic.net>
AuthorDate: Sun May 7 21:20:32 2017 +0200
Commit:     Evan Hanson <evhan@foldling.org>
CommitDate: Fri May 19 11:22:28 2017 +1200

    Add syntax exports to chicken.condition
    
    The macros condition-case and handle-exceptions really belong to
    chicken.condition, but adding macros to library.scm is problematic
    because the module and eval units rely on library, whereas to add
    macros you'll need to use those two, causing a cyclic dependency.
    
    This dependency cycle is why we have a separate chicken-syntax unit.
    So, we keep the definitions there, but we add them to a separate
    syntax environment which we use in a hand-rolled import library, which
    we use in lieu of an emitted import library based on the module
    definition (which does not contain said macros).
    
    Because we no longer emit the import library, the compiler would
    generate a call to eval to register the module at least in the current
    compilation unit.  To suppress this, we add -no-module-registration
    when compiling library.scm.
    
    Finally, to allow compilation with an older version CHICKEN, we use
    the original syntax environment from chicken if the new
    chicken.condition-macro-environment environment is undefined.  This is
    strictly incorrect because too many macros will be exported by the
    chicken.condition module, but that's not a problem in practice, and
    once we have a bootstrap CHICKEN we can get rid of this hack.
    
    Signed-off-by: Evan Hanson <evhan@foldling.org>

diff --git a/chicken-syntax.scm b/chicken-syntax.scm
index e67051b3..de328d86 100644
--- a/chicken-syntax.scm
+++ b/chicken-syntax.scm
@@ -46,7 +46,69 @@
 
 (provide* chicken-syntax) ; TODO remove after snapshot release
 
-;;; Non-standard macros:
+;;; Exceptions:
+(define ##sys#chicken.condition-macro-environment
+  (let ((me0 (##sys#macro-environment)))
+
+(##sys#extend-macro-environment
+ 'handle-exceptions
+ `((call-with-current-continuation . ,(##sys#primitive-alias 'call-with-current-continuation)))
+ (##sys#er-transformer
+  (lambda (form r c)
+    (##sys#check-syntax 'handle-exceptions form '(_ variable _ . _))
+    (let ((k (r 'k))
+	  (args (r 'args)))
+      `((,(r 'call-with-current-continuation)
+	 (##core#lambda
+	  (,k)
+	  (chicken.condition#with-exception-handler
+	   (##core#lambda (,(cadr form)) (,k (##core#lambda () ,(caddr form))))
+	   (##core#lambda
+	    ()
+	    (##sys#call-with-values
+	     (##core#lambda () ,@(cdddr form))
+	     (##core#lambda
+	      ,args
+	      (,k (##core#lambda () (##sys#apply ##sys#values ,args))))))))))))))
+
+(##sys#extend-macro-environment
+ 'condition-case
+ `((else . ,(##sys#primitive-alias 'else))
+   (memv . ,(##sys#primitive-alias 'memv)))
+ (##sys#er-transformer
+  (lambda (form r c)
+    (##sys#check-syntax 'condition-case form '(_ _ . _))
+    (let ((exvar (r 'exvar))
+	  (kvar (r 'kvar))
+	  (%and (r 'and))
+	  (%memv (r 'memv))
+	  (%else (r 'else)))
+      (define (parse-clause c)
+	(let* ((var (and (symbol? (car c)) (car c)))
+	       (kinds (if var (cadr c) (car c)))
+	       (body (if var
+			 `(##core#let ((,var ,exvar)) ,@(cddr c))
+			 `(##core#let () ,@(cdr c)))))
+	  (if (null? kinds)
+	      `(,%else ,body)
+	      `((,%and ,kvar ,@(map (lambda (k)
+				      `(,%memv (##core#quote ,k) ,kvar)) kinds))
+		,body))))
+      `(,(r 'handle-exceptions) ,exvar
+	(##core#let ((,kvar (,%and (##sys#structure? ,exvar
+						     (##core#quote condition))
+				   (##sys#slot ,exvar 1))))
+		    ,(let ((clauses (map parse-clause (cddr form))))
+		       `(,(r 'cond)
+			 ,@clauses
+			 ,@(if (assq %else clauses)
+			       `()   ; Don't generate two else clauses
+			       `((,%else (chicken.condition#signal ,exvar)))))))
+	,(cadr form))))))
+
+(##sys#macro-subset me0 ##sys#default-macro-environment)))
+
+;;; Other non-standard macros:
 
 (define ##sys#chicken-macro-environment
   (let ((me0 (##sys#macro-environment)))
@@ -868,66 +930,6 @@
 	     (##sys#check-syntax 'define-record-printer (cons head body) '(symbol _))
 	     `(##sys#register-record-printer ',head ,@body) ] ) ))))
 
-
-;;; Exceptions:
-
-(##sys#extend-macro-environment
- 'handle-exceptions 
- `((call-with-current-continuation . ,(##sys#primitive-alias 'call-with-current-continuation)))
- (##sys#er-transformer
-  (lambda (form r c)
-    (##sys#check-syntax 'handle-exceptions form '(_ variable _ . _))
-    (let ((k (r 'k))
-	  (args (r 'args)))
-      `((,(r 'call-with-current-continuation)
-	 (##core#lambda
-	  (,k)
-	  (chicken.condition#with-exception-handler
-	   (##core#lambda (,(cadr form)) (,k (##core#lambda () ,(caddr form))))
-	   (##core#lambda
-	    ()
-	    (##sys#call-with-values
-	     (##core#lambda () ,@(cdddr form))
-	     (##core#lambda 
-	      ,args 
-	      (,k (##core#lambda () (##sys#apply ##sys#values ,args)))) ) ) ) ) ) ) ) ) ) )
-
-(##sys#extend-macro-environment
- 'condition-case 
- `((else . ,(##sys#primitive-alias 'else))
-   (memv . ,(##sys#primitive-alias 'memv)))
- (##sys#er-transformer
-  (lambda (form r c)
-    (##sys#check-syntax 'condition-case form '(_ _ . _))
-    (let ((exvar (r 'exvar))
-	  (kvar (r 'kvar))
-	  (%and (r 'and))
-	  (%memv (r 'memv))
-	  (%else (r 'else)))
-      (define (parse-clause c)
-	(let* ((var (and (symbol? (car c)) (car c)))
-	       (kinds (if var (cadr c) (car c)))
-	       (body (if var
-			 `(##core#let ((,var ,exvar)) ,@(cddr c))
-			 `(##core#let () ,@(cdr c)))))
-	  (if (null? kinds)
-	      `(,%else ,body)
-	      `((,%and ,kvar ,@(map (lambda (k)
-				      `(,%memv (##core#quote ,k) ,kvar)) kinds))
-		,body ) ) ) )
-      `(,(r 'handle-exceptions) ,exvar
-	(##core#let ((,kvar (,%and (##sys#structure? ,exvar
-						     (##core#quote condition))
-				   (##sys#slot ,exvar 1))))
-		    ,(let ((clauses (map parse-clause (cddr form))))
-		       `(,(r 'cond)
-			 ,@clauses
-			 ,@(if (assq %else clauses)
-			       `()   ; Don't generate two else clauses
-			       `((,%else (chicken.condition#signal ,exvar)))))))
-	,(cadr form))))))
-
-
 ;;; SRFI-9:
 
 (##sys#extend-macro-environment
@@ -1350,9 +1352,11 @@
 		   t0 'define-type name))))))))))
 
 
-;; capture current macro env
+;; capture current macro env and add all the preceding ones as well
 
-(##sys#macro-subset me0 ##sys#default-macro-environment)))
+(let ((me* (##sys#macro-subset me0 ##sys#default-macro-environment)))
+  ;; TODO: omit `chicken.condition-m-e' when plain "chicken" module goes away
+  (append ##sys#chicken.condition-macro-environment me*))))
 
 ;; register features
 
diff --git a/chicken.condition.import.scm b/chicken.condition.import.scm
new file mode 100644
index 00000000..00fc0c95
--- /dev/null
+++ b/chicken.condition.import.scm
@@ -0,0 +1,45 @@
+;;;; chicken.condition.import.scm - import library for "chicken.condition" module
+;
+; Copyright (c) 2017, The CHICKEN Team
+; All rights reserved.
+;
+; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
+; conditions are met:
+;
+;   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+;     disclaimer.
+;   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+;     disclaimer in the documentation and/or other materials provided with the distribution.
+;   Neither the name of the author nor the names of its contributors may be used to endorse or promote
+;     products derived from this software without specific prior written permission.
+;
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+; POSSIBILITY OF SUCH DAMAGE.
+
+(##sys#register-core-module
+ 'chicken.condition
+ 'library
+ '((abort . chicken.condition#abort)
+   (signal . chicken.condition#signal)
+   (current-exception-handler . chicken.condition#current-exception-handler)
+   (get-call-chain . chicken.condition#get-call-chain)
+   (print-call-chain . chicken.condition#print-call-chain)
+   (with-exception-handler . chicken.condition#with-exception-handler)
+   (make-property-condition . chicken.condition#make-property-condition)
+   (make-composite-condition . chicken.condition#make-composite-condition)
+   (condition? . chicken.condition#condition?)
+   (condition->list . chicken.condition#condition->list)
+   (condition-predicate . chicken.condition#condition-predicate)
+   (condition-property-accessor . chicken.condition#condition-property-accessor)
+   (get-condition-property . chicken.condition#get-condition-property))
+ ;; OBSOLETE: This can be removed after bootstrapping
+ (if (##sys#symbol-has-toplevel-binding? '##sys#chicken.condition-macro-environment)
+     ##sys#chicken.condition-macro-environment
+     ##sys#chicken-macro-environment))
diff --git a/defaults.make b/defaults.make
index bf3258f4..a7fa5e91 100644
--- a/defaults.make
+++ b/defaults.make
@@ -263,9 +263,9 @@ CHICKEN_PROGRAM_OPTIONS += $(if $(PROFILE_OBJECTS),-profile)
 
 # import libraries
 
-PRIMITIVE_IMPORT_LIBRARIES = chicken chicken.csi chicken.foreign
+PRIMITIVE_IMPORT_LIBRARIES = chicken chicken.condition chicken.csi chicken.foreign
 DYNAMIC_IMPORT_LIBRARIES = srfi-4
-DYNAMIC_CHICKEN_IMPORT_LIBRARIES = bitwise condition errno file.posix	\
+DYNAMIC_CHICKEN_IMPORT_LIBRARIES = bitwise errno file.posix		\
 	fixnum flonum format gc io keyword load locative memory		\
 	platform posix pretty-print process process.signal		\
 	process-context random time time.posix
diff --git a/eval.scm b/eval.scm
index 859cfba0..40be3b71 100644
--- a/eval.scm
+++ b/eval.scm
@@ -894,6 +894,10 @@
      . (##core#require library))
     (chicken.foreign
      . (##core#require-for-syntax chicken-ffi-syntax))
+    (chicken.condition
+     . (##core#begin
+	(##core#require-for-syntax chicken-syntax)
+	(##core#require library)))
     (chicken
      . (##core#begin
 	(##core#require-for-syntax chicken-syntax)
diff --git a/expand.scm b/expand.scm
index e5d8bb50..0395be4a 100644
--- a/expand.scm
+++ b/expand.scm
@@ -175,8 +175,11 @@
 ;;; Macro handling
 
 (define ##sys#macro-environment (make-parameter '()))
+
+;; These are all re-assigned by chicken-syntax.scm:
 (define ##sys#chicken-macro-environment '()) ; used later in chicken.import.scm
 (define ##sys#chicken-ffi-macro-environment '()) ; used later in foreign.import.scm
+(define ##sys#chicken.condition-macro-environment '()) ; used later in chicken.condition.import.scm
 
 (define (##sys#ensure-transformer t #!optional loc)
   (cond ((procedure? t) (##sys#slot (##sys#er-transformer t) 1)) ; DEPRECATED
diff --git a/library.scm b/library.scm
index 27a0b258..4d144d13 100644
--- a/library.scm
+++ b/library.scm
@@ -4450,9 +4450,13 @@ EOF
 ;;; Condition handling:
 
 (module chicken.condition
+    ;; NOTE: We don't emit the import lib.  Due to syntax exports, it
+    ;; has to be a hardcoded primitive module.
     (abort signal current-exception-handler get-call-chain
      print-call-chain with-exception-handler
 
+     ;; [syntax] condition-case handle-exceptions
+
      ;; Condition object manipulation
      make-property-condition make-composite-condition condition?
      condition->list condition-predicate condition-property-accessor
diff --git a/modules.scm b/modules.scm
index 85e7a059..4f90cb11 100644
--- a/modules.scm
+++ b/modules.scm
@@ -421,7 +421,7 @@
     (set! ##sys#module-table (cons (cons name mod) ##sys#module-table)) 
     mod))
 
-;; same as register-builtin, but uses module's name as its library
+;; same as register-core-module, but uses module's name as its library
 (define (##sys#register-primitive-module name vexports #!optional (sexports '()))
   (##sys#register-core-module name name vexports sexports))
 
@@ -1012,7 +1012,7 @@
    (make-property-condition . chicken.condition#make-property-condition)
    (signal . chicken.condition#signal)
    (with-exception-handler . chicken.condition#with-exception-handler))
- (se-subset '(handle-exceptions) ##sys#chicken-macro-environment))
+ (se-subset '(handle-exceptions) ##sys#chicken.condition-macro-environment))
 
 (##sys#register-primitive-module
  'srfi-15 '() (se-subset '(fluid-let) ##sys#chicken-macro-environment))
diff --git a/rules.make b/rules.make
index b82e98a8..3a1e3425 100644
--- a/rules.make
+++ b/rules.make
@@ -506,7 +506,6 @@ $(eval $(call declare-emitted-import-lib-dependency,chicken.time.posix,$(POSIXFI
 $(eval $(call declare-emitted-import-lib-dependency,chicken.process,$(POSIXFILE)))
 $(eval $(call declare-emitted-import-lib-dependency,chicken.process.signal,$(POSIXFILE)))
 $(eval $(call declare-emitted-import-lib-dependency,chicken.bitwise,library))
-$(eval $(call declare-emitted-import-lib-dependency,chicken.condition,library))
 $(eval $(call declare-emitted-import-lib-dependency,chicken.fixnum,library))
 $(eval $(call declare-emitted-import-lib-dependency,chicken.flonum,library))
 $(eval $(call declare-emitted-import-lib-dependency,chicken.gc,library))
@@ -768,8 +767,8 @@ bootstrap-lib = $(CHICKEN) $(call profile-flags, $@) $< $(CHICKEN_LIBRARY_OPTION
 
 library.c: $(SRCDIR)library.scm $(SRCDIR)banner.scm $(SRCDIR)common-declarations.scm
 	$(bootstrap-lib) \
+	-no-module-registration \
 	-emit-import-library chicken.bitwise \
-	-emit-import-library chicken.condition \
 	-emit-import-library chicken.fixnum \
 	-emit-import-library chicken.flonum \
 	-emit-import-library chicken.gc \
diff --git a/tests/compiler-tests.scm b/tests/compiler-tests.scm
index 769b338c..a744449c 100644
--- a/tests/compiler-tests.scm
+++ b/tests/compiler-tests.scm
@@ -2,7 +2,7 @@
 
 
 (import (chicken bitwise) (chicken flonum) (chicken foreign)
-	(srfi 4))
+	(chicken condition) (srfi 4))
 (import-for-syntax data-structures expand)
 
 ;; test dropping of previous toplevel assignments
diff --git a/tests/syntax-tests.scm b/tests/syntax-tests.scm
index 3f061fbf..f1ec80fa 100644
--- a/tests/syntax-tests.scm
+++ b/tests/syntax-tests.scm
@@ -532,7 +532,7 @@
   (c:define-values (a b c) (values 1 2 3)) )
 
 (module prefixed-self-reference2 ()
-  (import scheme (prefix chicken c:))
+  (import scheme (prefix chicken c:) (prefix (chicken condition) c:))
   (c:define-values (a b c) (values 1 2 3))
   (c:print "ok")
   (c:condition-case 
@@ -540,6 +540,8 @@
    (ex () (c:print "caught"))))
 
 (module prefixed-self-reference3 (a)
+  ;; TODO: Switch this around when plain "chicken" has been removed
+  ;(import (prefix scheme s.) (prefix (chicken condition) c.))
   (import (prefix scheme s.) (prefix chicken c.))
   (s.define (a x y)
 	    (c.condition-case (s.+ x y) ((exn) "not numbers")))
Trap