~ chicken-core (chicken-5) d63d1fb8c53e538f22994ad420eaf59c5450ae17


commit d63d1fb8c53e538f22994ad420eaf59c5450ae17
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Fri Aug 19 09:20:23 2011 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Fri Aug 19 09:20:23 2011 +0200

    added tests for typematching; fixed bug in matching of not-types; extract typevars for each specialization match; more obscure stuff

diff --git a/distribution/manifest b/distribution/manifest
index e1a0adfb..03695e3f 100644
--- a/distribution/manifest
+++ b/distribution/manifest
@@ -140,6 +140,7 @@ tests/test-finalizers.scm
 tests/test-finalizers-2.scm
 tests/module-tests-compiled.scm
 tests/scrutiny-tests.scm
+tests/typematch-tests.scm
 tests/scrutiny-tests-2.scm
 tests/scrutiny.expected
 tests/syntax-rule-stress-test.scm
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 4d036ccd..d63e42ba 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -29,7 +29,7 @@
   (hide specialize-node! specialization-statistics
 	procedure-type? named? procedure-result-types procedure-argument-types
 	noreturn-type? rest-type procedure-name d-depth
-	noreturn-procedure-type? trail trail-restore
+	noreturn-procedure-type? trail trail-restore typename
 	compatible-types? type<=? match-types resolve match-argument-types))
 
 
@@ -64,7 +64,7 @@
 ;       | (forall (VAR1 ...) VAL)
 ;       | deprecated
 ;   BASIC = * | string | symbol | char | number | boolean | list | pair | 
-;           procedure | vector | null | eof | undefined | port | 
+;           procedure | vector | null | eof | undefined | port |
 ;           blob | noreturn | pointer | locative | fixnum | float |
 ;           pointer-vector
 ;   COMPLEX = (pair VAL VAL) | (vector VAL) | (list VAL)
@@ -207,41 +207,6 @@
 	     (pp-fragment x))))
 	f))
 
-    (define (typename t)
-      (case t
-	((*) "anything")
-	((char) "character")
-	(else
-	 (cond ((symbol? t) (symbol->string t))
-	       ((pair? t)
-		(case (car t)
-		  ((procedure) 
-		   (if (or (string? (cadr t)) (symbol? (cadr t)))
-		       (->string (cadr t))
-		       (sprintf "a procedure with ~a returning ~a"
-			 (argument-string (cadr t))
-			 (result-string (cddr t)))))
-		  ((or)
-		   (string-intersperse
-		    (map typename (cdr t))
-		    " OR "))
-		  ((struct)
-		   (sprintf "a structure of type ~a" (cadr t)))
-		  ((forall) 
-		   (sprintf "~a (for all ~a)"
-		     (typename (third t))
-		     (string-intersperse (map symbol->string (second t)) " ")))
-		  ((pair)
-		   (sprintf "a pair wth car ~a and cdr ~a"
-		     (typename (second t))
-		     (typename (third t))))
-		  ((vector)
-		   (sprintf "a vector with element type ~a" (typename (second t))))
-		  ((list)
-		   (sprintf "a list with element type ~a" (typename (second t))))
-		  (else (bomb "invalid type" t))))
-	       (else (bomb "invalid type" t))))))
-
     (define (argument-string args)
       (let* ((len (length args))
 	     (m (multiples len)))
@@ -352,7 +317,7 @@
 	     (pptype? (procedure-type? ptype))
 	     (nargs (length (cdr args)))
 	     (xptype `(procedure ,(make-list nargs '*) *))
-	     (typeenv (or (and pptype? (type-typeenv ptype)) '()))
+	     (typeenv (append-map type-typeenv args))
 	     (op #f))
 	(cond ((and (not pptype?) (not (match-types xptype ptype typeenv)))
 	       (report
@@ -430,22 +395,25 @@
 			      (lambda (specs)
 				(dd "   specializing: ~s" pn)
 				(let loop ((specs specs))
-				  (cond ((null? specs))
-					((match-argument-types
-					  (first (car specs)) (cdr args) typeenv 
-					  #t)
-					 (let ((spec (car specs)))
-					   (set! op (cons pn (car spec)))
-					   (let* ((r2 (and (pair? (cddr spec))
-							   (second spec)))
-						  (rewrite (if r2
-							       (third spec)
-							       (second spec))))
-					     (specialize-node! node rewrite)
-					     (when r2 (set! r r2)))))
-					(else
-					 (trail-restore trail0 typeenv)
-					 (loop (cdr specs))))))))
+				  (and (pair? specs)
+				       (let* ((spec (car specs))
+					      (stype (first spec))
+					      (tenv2 (append (type-typeenv stype) typeenv)))
+					   (cond ((match-argument-types
+						   (first (car specs)) (cdr args) tenv2
+						   #t)
+						  (set! op (cons pn (car spec)))
+						  (set! typeenv tenv2)
+						  (let* ((r2 (and (pair? (cddr spec))
+								  (second spec)))
+							 (rewrite (if r2
+								      (third spec)
+								      (second spec))))
+						    (specialize-node! node rewrite)
+						    (when r2 (set! r r2))))
+						 (else
+						  (trail-restore trail0 tenv2)
+						  (loop (cdr specs))))))))))
 		       (when op
 			 (d "  specialized: `~s'" op)
 			 (cond ((assoc op specialization-statistics) =>
@@ -785,7 +753,11 @@
 		    ;; 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 clause applies in `compiler-typecase'" params (car ts)))
+			     (quit "~ano clause applies in `compiler-typecase' for expression of type `~s':~a" 
+				   (location-name loc) (car ts)
+				   (string-concatenate
+				    (map (lambda (t) (string-append "\n   " (typename t)))
+					 params))))
 			    ((match-types (car types) (car ts) '())
 			     ;; drops exp
 			     (copy-node! (car subs) n)
@@ -813,6 +785,44 @@
       (when (positive? dropped-branches)
 	(debugging 'x "dropped branches" dropped-branches)) ;XXX
       rn)))
+      
+
+(define (typename t)
+  (case t
+    ((*) "anything")
+    ((char) "character")
+    (else
+     (cond ((symbol? t) (symbol->string t))
+	   ((pair? t)
+	    (case (car t)
+	      ((procedure) 
+	       (if (or (string? (cadr t)) (symbol? (cadr t)))
+		   (->string (cadr t))
+		   (sprintf "a procedure with ~a returning ~a"
+		     (argument-string (cadr t))
+		     (result-string (cddr t)))))
+	      ((or)
+	       (string-intersperse
+		(map typename (cdr t))
+		" OR "))
+	      ((struct)
+	       (sprintf "a structure of type ~a" (cadr t)))
+	      ((forall) 
+	       (sprintf "~a (for all ~a)"
+		 (typename (third t))
+		 (string-intersperse (map symbol->string (second t)) " ")))
+	      ((not)
+	       (sprintf "NOT ~a" (typename (second t))))
+	      ((pair)
+	       (sprintf "a pair wth car ~a and cdr ~a"
+		 (typename (second t))
+		 (typename (third t))))
+	      ((vector)
+	       (sprintf "a vector with element type ~a" (typename (second t))))
+	      ((list)
+	       (sprintf "a list with element type ~a" (typename (second t))))
+	      (else (bomb "invalid type" t))))
+	   (else (bomb "invalid type" t))))))
 
 
 ;;; Type-matching
@@ -853,9 +863,11 @@
     (memq a '(#!rest #!optional)))
 
   (define (match-results results1 results2)
-    (cond ((null? results1) (atom? results2))
+    (cond ((null? results1) 
+	   (or (null? results2)
+	       (and (not exact) (eq? '* results2))))
 	  ((eq? '* results1))
-	  ((eq? '* results2))
+	  ((eq? '* results2) (not exact))
 	  ((null? results2) #f)
 	  ((match1 (car results1) (car results2)) 
 	   (match-results (cdr results1) (cdr results2)))
@@ -882,23 +894,7 @@
 		   (set-cdr! e t1)
 		   #t))))
 	  ((eq? t1 '*))
-	  ((eq? t2 '*) (not exact))
-	  ((eq? t1 'noreturn) (not exact))
-	  ((eq? t2 'noreturn) (not exact))
-	  ((eq? t1 'number) 
-	   (and (not exact)
-		(match1 '(or fixnum float) t2)))
-	  ((eq? t2 'number)
-	   (and (not exact)
-		(match1 t1 '(or fixnum float))))
-	  ((eq? 'procedure t1)
-	   (and (pair? t2)
-		(eq? 'procedure (car t2))))
-	  ((eq? 'procedure t2) 
-	   (and (not exact)
-		(pair? t1)
-		(eq? 'procedure (car t1))))
-	  ((and (pair? t1) (eq? 'not (car t1)))
+	  ((and (pair? t1) (eq? 'not (car t1))) ; needs to be done before '* check for t2
 	   (let* ((trail0 trail)
 		  (m (match1 (cadr t1) t2)))
 	     (trail-restore trail0 typeenv)
@@ -917,6 +913,22 @@
 	   (match1 (third t1) t2)) ; assumes typeenv has already been extracted
 	  ((and (pair? t2) (eq? 'forall (car t2)))
 	   (match1 t1 (third t2))) ; assumes typeenv has already been extracted
+	  ((eq? t2 '*) (not exact))
+	  ((eq? t1 'noreturn) (not exact))
+	  ((eq? t2 'noreturn) (not exact))
+	  ((eq? t1 'number) 
+	   (and (not exact)
+		(match1 '(or fixnum float) t2)))
+	  ((eq? t2 'number)
+	   (and (not exact)
+		(match1 t1 '(or fixnum float))))
+	  ((eq? 'procedure t1)
+	   (and (pair? t2)
+		(eq? 'procedure (car t2))))
+	  ((eq? 'procedure t2) 
+	   (and (not exact)
+		(pair? t1)
+		(eq? 'procedure (car t1))))
 	  ((eq? t1 'pair) (match1 '(pair * *) t2))
 	  ((eq? t2 'pair) (match1 t1 '(pair * *)))
 	  ((eq? t1 'list) (match1 '(list *) t2))
diff --git a/tests/runtests.sh b/tests/runtests.sh
index 8691f459..05532ae9 100644
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -70,6 +70,7 @@ $compile inlining-tests.scm -optimize-level 3
 ./a.out
 
 echo "======================================== scrutiny tests ..."
+$compile typematch-tests.scm -scrutinize -analyze-only
 $compile scrutiny-tests.scm -scrutinize -analyze-only -ignore-repository -types ../types.db 2>scrutiny.out -verbose
 
 if test -n "$MSYSTEM"; then
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
new file mode 100644
index 00000000..e735bbde
--- /dev/null
+++ b/tests/typematch-tests.scm
@@ -0,0 +1,75 @@
+;;;; typematch-tests.scm
+
+
+(define-syntax check
+  (syntax-rules ()
+    ((_ x not-x t)
+     (begin
+       (compiler-typecase x
+	 (t 'ok))
+       (compiler-typecase not-x
+	 ((not t) 'ok))))))
+
+(define-syntax checkp
+  (syntax-rules ()
+    ((_ p x t)
+     (let ((tmp x))
+       (if (p tmp)
+	   (compiler-typecase tmp
+	     (t 'ok)))
+       (compiler-typecase (##sys#make-structure 'foo)
+	 ((not t) 'ok))))))
+
+
+;;;
+
+(check 123 1.2 fixnum)
+(check "abc" 1.2 string)
+(check 'abc 1.2 symbol)
+(check #\x 1.2 char)
+(check #t 1.2 boolean)
+(check 123 'a number)
+(check 12.3 'a number)
+(check '(1) 1.2 list)
+(check '(a) 1.2 list)
+(check '(1) 1.2 pair)
+(check '(1 . 2) '() pair)
+(check + 1.2 procedure)
+(check '#(1) 1.2 vector)
+(check '() 1 null)
+(check '() 1.2 list)
+(check (void) 1.2 undefined)
+(check (current-input-port) 1.2 port)
+(check (make-blob 10) 1.2 blob)
+(check (address->pointer 0) 1.2 pointer)
+(check (make-pointer-vector 1) 1.2 pointer-vector)
+(check (make-locative 'a) 1.2 locative)
+(check (##sys#make-structure 'promise) 1 (struct promise))
+(check '(1 . 2.3) '(a) (pair fixnum float))
+(check '#(a) 1 (vector symbol))
+(check '("ok") 1 (list string))
+
+(checkp boolean? #t boolean)
+(checkp boolean? #f boolean)
+(checkp pair? '(1 . 2) pair)
+(checkp null? '() null)
+(checkp list? '(1) list)
+(checkp symbol? 'a symbol)
+(checkp number? '1 number)
+(checkp number? '1.2 number)
+(checkp exact? '1 fixnum)
+(checkp real? '1 number)
+(checkp complex? '1 number)
+(checkp inexact? '1.2 float)
+(checkp char? #\a char)
+(checkp string? "a" string)
+(checkp vector? '#() vector)
+(checkp procedure? + procedure)
+(checkp blob? (make-blob 1) blob)
+(checkp condition? (##sys#make-structure 'condition) (struct condition))
+(checkp fixnum? 1 fixnum)
+(checkp flonum? 1.2 float)
+(checkp port? (current-input-port) port)
+(checkp pointer-vector? (make-pointer-vector 1) pointer-vector)
+(checkp pointer? (address->pointer 1) pointer)
+
Trap