~ chicken-core (chicken-5) 614611f75f68b98c6f616f82804e46ba18d8e2b7


commit 614611f75f68b98c6f616f82804e46ba18d8e2b7
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Wed Aug 17 10:17:09 2011 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Wed Aug 17 10:17:09 2011 +0200

    added (undocumented) compiler-typecase

diff --git a/chicken-syntax.scm b/chicken-syntax.scm
index e568af0e..47d597ac 100644
--- a/chicken-syntax.scm
+++ b/chicken-syntax.scm
@@ -1263,6 +1263,19 @@
 				     'define-specialization
 				     "invalid argument syntax" arg head)))))))))))))
 
+(##sys#extend-macro-environment
+ 'compiler-typecase '()
+ (##sys#er-transformer
+  (lambda (x r c)
+    (##sys#check-syntax 'compiler-typecase x '(_ _ . #((_ . #(_ 1)) 0)))
+    (let ((var (gensym)))
+      `(##core#let ((,var ,(cadr x)))
+		   (##core#typecase 
+		    ,var		; must be variable (see: CPS transform)
+		    ,@(map (lambda (clause)
+			     (list (car clause) `(##core#begin ,@(cdr clause))))
+			   (cddr x))))))))
+
 
 ;; capture current macro env
 
diff --git a/compiler.scm b/compiler.scm
index b7ca7b03..57cf95eb 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -144,6 +144,7 @@
 ; (##core#module <symbol> #t | (<name> | (<name> ...) ...) <body>)
 ; (##core#let-module-alias ((<alias> <name>) ...) <body>)
 ; (##core#the <type> <exp>)
+; (##core#typecase <exp> (<type> <body>) ... [(else <body>)])
 ; (<exp> {<exp>})
 
 ; - Core language:
@@ -171,6 +172,7 @@
 ; [##core#direct_call {<safe-flag> <debug-info> <call-id> <words>} <exp-f> <exp>...]
 ; [##core#direct_lambda {<id> <mode> (<variable>... [. <variable>]) <size>} <exp>]
 ; [##core#the {<type>} <exp>]
+; [##core#typecase {(<type> ...)} <exp> <body1> ... [<elsebody>]]
 
 ; - Closure converted/prepared language:
 ;
@@ -547,9 +549,17 @@
 
 			((##core#the)
 			 `(##core#the
-			   ,(cadr x)
+			   ,(##sys#strip-syntax (cadr x))
 			   ,(walk (caddr x) e se dest ldest h)))
 
+			((##core#typecase)
+			 `(##core#typecase
+			   ,(walk (cadr x) e se #f #f h)
+			   ,@(map (lambda (cl)
+				    (list (##sys#strip-syntax (car cl))
+					  (walk (cadr cl) e se dest ldest h)))
+				  (cddr x))))
+
 			((##core#immutable)
 			 (let ((c (cadadr x)))
 			   (cond [(assoc c immutable-constants) => cdr]
@@ -1692,6 +1702,9 @@
 	((##core#the)
 	 ;; remove "the" nodes, as they are not used after scrutiny
 	 (walk (car subs) k))
+	((##core#typecase)
+	 ;; same here, the last clause is chosen, exp is dropped
+	 (walk (last subs) k))
 	(else (bomb "bad node (cps)")) ) ) )
   
   (define (walk-call fn args params k)
diff --git a/eval.scm b/eval.scm
index f31c52d4..b47228b3 100644
--- a/eval.scm
+++ b/eval.scm
@@ -721,6 +721,17 @@
 
 			 ((##core#the)
 			  (compile (caddr x) e h tf cntr se))
+			 
+			 ((##core#typecase)
+			  ;; drops exp and requires "else" clause
+			  (cond ((assq 'else (##sys#strip-syntax (cddr x))) =>
+				 (lambda (cl)
+				   (compile (cadr cl) e h tf cntr se)))
+				(else
+				 (##sys#syntax-error-hook
+				  'compiler-typecase
+				  "no `else-clause' in unresolved `compiler-typecase' form"
+				  x))))
 
 			 (else
 			  (fluid-let ((##sys#syntax-context (cons head ##sys#syntax-context)))
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 573de2e7..ee4add57 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -106,6 +106,7 @@
 	(aliased '())
 	(noreturn #f)
 	(dropped-branches 0)
+	(typecases 0)
 	(safe-calls 0))
 
     (define (constant-result lit)
@@ -882,8 +883,7 @@
 				loc
 				(sprintf 
 				    "expression returns ~a values but is declared to have a single result"
-				  (length rt)))
-			       (set! rt (list (first rt))))
+				  (length rt))))
 			     (unless (type<=? t (first rt))
 			       (report-notice
 				loc
@@ -891,6 +891,18 @@
 				    "expression returns a result of type `~a', but is declared to return `~a', which is not a subtype"
 				  (first rt) t)))))
 		      (list t))))
+		 ((##core#typecase)
+		  (let ((ts (walk (first subs) e loc #f #f flow ctags)))
+		    ;; first exp is always a variable so ts must be of length 1
+		    (let loop ((types params) (subs (cdr subs)))
+		      (cond ((null? types) (bomb "no more clauses in `compiler-typecase'" types))
+			    ((match-specialization (list (car types)) ts '() #f)
+			     ;; drops exp
+			     (set! typecases (add1 typecases))
+			     (copy-node! (car subs) n)
+			     (walk n e loc dest tail flow ctags))
+			    (else
+			     (loop (cdr types) (cdr subs)))))))
 		 ((##core#switch ##core#cond)
 		  (bomb "unexpected node class" class))
 		 (else
@@ -911,6 +923,8 @@
 	(debugging 'x "safe calls" safe-calls)) ;XXX
       (when (positive? dropped-branches)
 	(debugging 'x "dropped branches" dropped-branches)) ;XXX
+      (when (positive? typecases)
+	(debugging 'x "expanded typecases" typecases)) ;XXX
       rn)))
 
 
diff --git a/support.scm b/support.scm
index ca0aef72..9c0fca14 100644
--- a/support.scm
+++ b/support.scm
@@ -506,8 +506,25 @@
 		(make-node 'lambda (list (cadr x)) (list (walk (caddr x)))))
 	       ((##core#the)
 		(make-node '##core#the (list (cadr x)) (list (walk (caddr x)))))
+	       ((##core#typecase)
+		;; clause-head is already stripped
+		(let loop ((cls (cddr x)) (types '()) (exps (list (walk (cadr x)))))
+		  (cond ((null? cls) 	; no "else" clause given
+			 (make-node
+			  '##core#typecase 
+			  (reverse types)
+			  (reverse
+			   (cons (make-node '##core#undefined '() '()) exps))))
+			((eq? 'else (caar cls))
+			 (make-node
+			  '##core#typecase
+			  (reverse (cons '* types))
+			  (reverse (cons (walk (cadar cls)) exps))))
+			(else (loop (cdr cls)
+				    (cons (caar cls) types)
+				    (cons (walk (cadar cls)) exps))))))
 	       ((##core#primitive)
-		(let ([arg (cadr x)])
+		(let ((arg (cadr x)))
 		  (make-node
 		   (car x)
 		   (list (if (and (pair? arg) (eq? 'quote (car arg))) (cadr arg) arg))
@@ -573,6 +590,14 @@
 	       (walk (car subs)) ) )
 	((##core#the)
 	 `(the ,(first params) ,(walk (first subs))))
+	((##core#typecase)
+	 `(compiler-typecase
+	   ,(walk (first subs))
+	   ,@(let loop ((types params) (bodies (cdr subs)))
+	       (if (null? types)
+		   `((else ,(walk (car bodies))))
+		   (cons (list (car types) (walk (car bodies)))
+			 (loop (cdr types) (cdr bodies)))))))
 	((##core#call) 
 	 (map walk subs))
 	((##core#callunit) (cons* '##core#callunit (car params) (map walk subs)))
Trap