~ chicken-core (chicken-5) 07e499c13d71abeaf38c295e285d8bc3b8cb1c13


commit 07e499c13d71abeaf38c295e285d8bc3b8cb1c13
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Wed May 4 05:53:32 2011 -0400
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Wed May 4 05:53:32 2011 -0400

    flow-analysis fixes

diff --git a/scrutinizer.scm b/scrutinizer.scm
index b913b439..263f2c5b 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -264,7 +264,6 @@
 				     (let ((t (simplify t)))
 				       (cond ((and (pair? t) (eq? 'or (car t)))
 					      (cdr t))
-					;((eq? t 'noreturn) '())
 					     ((eq? t 'undefined) (return 'undefined))
 					     (else (list t)))))
 				   (cdr t)))
@@ -294,11 +293,14 @@
 	       (else t))
 	     t))))
 
+    ;;XXX this could be better done by combining non-matching arguments/llists
+    ;;    into "(or (procedure ...) (procedure ...))"
     (define (merge-argument-types ts1 ts2) 
       (cond ((null? ts1) 
 	     (cond ((null? ts2) '())
 		   ((memq (car ts2) '(#!rest #!optional)) ts2)
 		   (else '(#!rest))))
+	    ((null? ts2) '(#!rest))	;XXX giving up
 	    ((eq? '#!rest (car ts1))
 	     (cond ((and (pair? ts2) (eq? '#!rest (car ts2)))
 		    `(#!rest
@@ -339,8 +341,9 @@
 	    ((eq? 'procedure t2) (and (pair? t1) (eq? 'procedure (car t1))))
 	    ((and (pair? t1) (eq? 'or (car t1))) (any (cut match <> t2) (cdr t1)))
 	    ((and (pair? t2) (eq? 'or (car t2))) (any (cut match t1 <>) (cdr t2)))
-	    ((memq t1 '(pair list)) (memq t2 '(pair list)))
-	    ((memq t1 '(null list)) (memq t2 '(null list)))
+	    ((eq? t1 'pair) (memq t2 '(pair list)))
+	    ((eq? t1 'list) (memq t2 '(pair list null)))
+	    ((eq? t1 'null) (memq t2 '(null list)))
 	    ((and (pair? t1) (pair? t2) (eq? (car t1) (car t2)))
 	     (case (car t1)
 	       ((procedure)
@@ -459,92 +462,94 @@
 	  (fragment (first (node-subexpressions node)))))
       (d "  call-result: ~a " args)
       (let* ((ptype (car args))
+	     (pptype? (procedure-type? ptype))
 	     (nargs (length (cdr args)))
 	     (xptype `(procedure ,(make-list nargs '*) *)))
-	(when (and (not (procedure-type? ptype))
-		   (not (match xptype ptype)))
-	  (report
-	   loc
-	   (sprintf
-	       "~aexpected a value of type `~a', but was given a value of type `~a'"
-	     (pname) 
-	     xptype
-	     ptype)))
-	(let-values (((atypes values-rest) (procedure-argument-types ptype nargs)))
-	  (d "  argument-types: ~a (~a)" atypes values-rest)
-	  (unless (= (length atypes) nargs)
-	    (let ((alen (length atypes)))
-	      (report 
-	       loc
-	       (sprintf
-		   "~aexpected ~a argument~a, but was given ~a argument~a"
-		 (pname) alen (multiples alen)
-		 nargs (multiples nargs)))))
-	  (do ((args (cdr args) (cdr args))
-	       (atypes atypes (cdr atypes))
-	       (i 1 (add1 i)))
-	      ((or (null? args) (null? atypes)))
-	    (unless (match (car atypes) (car args))
-	      (report
-	       loc
-	       (sprintf
-		   "~aexpected argument #~a of type `~a', but was given an argument of type `~a'"
-		 (pname) i (car atypes) (car args)))))
-	  (let ((r (procedure-result-types ptype values-rest (cdr args))))
-	    ;;XXX we should check whether this is a standard- or extended binding
-	    (let* ((pn (procedure-name ptype))
-		   (op #f))
-	      (when pn
-		(cond ((and (fx= 1 nargs) 
-			    (variable-mark pn '##compiler#predicate)) =>
-			    (lambda (pt)
-			      (cond ((match-specialization (list pt) (cdr args))
-				     (report
-				      loc
-				      (sprintf 
-					  "~athe predicate is called with an argument of type `~a' and will always return true"
-					(pname) (cadr args)))
-				     (when specialize
-				       (specialize-node!
-					node
-					`(let ((#:tmp #(1))) '#t))
-				       (set! op (list pn pt))))
-				    ((match-specialization (list `(not ,pt)) (cdr args))
-				     (report
-				      loc
-				      (sprintf 
-					  "~athe predicate is called with an argument of type `~a' and will always return false"
-					(pname) (cadr args)))
-				     (when specialize
-				       (specialize-node!
-					node
-					`(let ((#:tmp #(1))) '#f))
-				       (set! op (list pt `(not ,pt))))))))
-		      ((and specialize (variable-mark pn '##compiler#specializations)) =>
-		       (lambda (specs)
-			 (let loop ((specs specs))
-			   (cond ((null? specs))
-				 ((match-specialization (first (car specs)) (cdr args))
-				  (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 (loop (cdr specs))))))))
-		(when op
-		  (cond ((assoc op specialization-statistics) =>
-			 (lambda (a) (set-cdr! a (add1 (cdr a)))))
-			(else
-			 (set! specialization-statistics
-			   (cons (cons op 1) 
-				 specialization-statistics))))))
-	      (when (and specialize (not op) (procedure-type? ptype))
-		(set-car! (node-parameters node) #t)
-		(set! safe-calls (add1 safe-calls))))
-	    (d  "  result-types: ~a" r)
-	    r))))
-
+	(cond ((and (not pptype?) (not (match xptype ptype)))
+	       (report
+		loc
+		(sprintf
+		    "~aexpected a value of type `~a', but was given a value of type `~a'"
+		  (pname) 
+		  xptype
+		  ptype))
+	       '*)
+	      (else
+	       (let-values (((atypes values-rest) (procedure-argument-types ptype nargs)))
+		 (d "  argument-types: ~a (~a)" atypes values-rest)
+		 (unless (= (length atypes) nargs)
+		   (let ((alen (length atypes)))
+		     (report 
+		      loc
+		      (sprintf
+			  "~aexpected ~a argument~a, but was given ~a argument~a"
+			(pname) alen (multiples alen)
+			nargs (multiples nargs)))))
+		 (do ((args (cdr args) (cdr args))
+		      (atypes atypes (cdr atypes))
+		      (i 1 (add1 i)))
+		     ((or (null? args) (null? atypes)))
+		   (unless (match (car atypes) (car args))
+		     (report
+		      loc
+		      (sprintf
+			  "~aexpected argument #~a of type `~a', but was given an argument of type `~a'"
+			(pname) i (car atypes) (car args)))))
+		 (let ((r (procedure-result-types ptype values-rest (cdr args))))
+		   ;;XXX we should check whether this is a standard- or extended binding
+		   (let* ((pn (procedure-name ptype))
+			  (op #f))
+		     (when pn
+		       (cond ((and (fx= 1 nargs) 
+				   (variable-mark pn '##compiler#predicate)) =>
+				   (lambda (pt)
+				     (cond ((match-specialization (list pt) (cdr args))
+					    (report
+					     loc
+					     (sprintf 
+						 "~athe predicate is called with an argument of type `~a' and will always return true"
+					       (pname) (cadr args)))
+					    (when specialize
+					      (specialize-node!
+					       node
+					       `(let ((#:tmp #(1))) '#t))
+					      (set! op (list pn pt))))
+					   ((match-specialization (list `(not ,pt)) (cdr args))
+					    (report
+					     loc
+					     (sprintf 
+						 "~athe predicate is called with an argument of type `~a' and will always return false"
+					       (pname) (cadr args)))
+					    (when specialize
+					      (specialize-node!
+					       node
+					       `(let ((#:tmp #(1))) '#f))
+					      (set! op (list pt `(not ,pt))))))))
+			     ((and specialize (variable-mark pn '##compiler#specializations)) =>
+			      (lambda (specs)
+				(let loop ((specs specs))
+				  (cond ((null? specs))
+					((match-specialization (first (car specs)) (cdr args))
+					 (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 (loop (cdr specs))))))))
+		       (when op
+			 (cond ((assoc op specialization-statistics) =>
+				(lambda (a) (set-cdr! a (add1 (cdr a)))))
+			       (else
+				(set! specialization-statistics
+				  (cons (cons op 1) 
+					specialization-statistics))))))
+		     (when (and specialize (not op) (procedure-type? ptype))
+		       (set-car! (node-parameters node) #t)
+		       (set! safe-calls (add1 safe-calls))))
+		   (d  "  result-types: ~a" r)
+		   r))))))
+    
     (define (self-call? node loc)
       (case (node-class node)
 	((##core#call)
@@ -844,11 +849,7 @@
 	       (else #f)))))
 
 (define (procedure-argument-types t n #!optional norest)
-  (cond ((or (memq t '(* procedure)) 
-	     (not-pair? t)
-	     (eq? 'deprecated (car t)))
-	 (values (make-list n '*) #f))
-	((eq? 'procedure (car t))
+  (cond ((and (pair? t) (eq? 'procedure (car t)))
 	 (let* ((vf #f)
 		(llist
 		 (let loop ((at (if (or (string? (second t)) (symbol? (second t)))
@@ -869,23 +870,20 @@
 			 ((and opt (<= m 0)) '())
 			 (else (cons (car at) (loop (cdr at) (sub1 m) opt)))))))
 	   (values llist vf)))
-	(else (bomb "not a procedure type" t))))
+	(else (values (make-list n '*) #f))))
 
 (define (procedure-result-types t values-rest? args)
   (cond (values-rest? args)
-	((or (memq t '(* procedure))
-	     (not-pair? t) )
-	 '*)
-	((eq? 'procedure (car t))
+	((and (pair? t) (eq? 'procedure (car t)))
 	 (call/cc
 	  (lambda (return)
 	    (let loop ((rt (if (or (string? (second t)) (symbol? (second t)))
 			       (cdddr t)
 			       (cddr t))))
 	      (cond ((null? rt) '())
-		    ((eq? '* rt) (return '*))
+		    ((memq rt '(* noreturn)) (return '*))
 		    (else (cons (car rt) (loop (cdr rt)))))))))
-	(else (bomb "not a procedure type" t))))
+	(else '*)))
 
 (define (named? t)
   (and (pair? t) 
Trap