~ chicken-core (chicken-5) 94ec8c893a9ededc66ece7f48175856111e55823


commit 94ec8c893a9ededc66ece7f48175856111e55823
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Tue Aug 23 11:19:15 2011 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Tue Aug 23 11:19:15 2011 +0200

    assignment bugfix by sh (also in master); blist/env smashing on call to impure procedure; purity-declaration still has to be figured out

diff --git a/scrutinizer.scm b/scrutinizer.scm
index 6cbcbe0d..f3fed28b 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -31,6 +31,7 @@
 	noreturn-type? rest-type procedure-name d-depth
 	noreturn-procedure-type? trail trail-restore 
 	typename multiples procedure-arguments procedure-results
+	smash-component-types!
 	compatible-types? type<=? match-types resolve match-argument-types))
 
 
@@ -108,7 +109,7 @@
 
 
 (define (scrutinize node db complain specialize)
-  (let ((blist '())
+  (let ((blist '())			; (((VAR . FLOW) TYPE) ...)
 	(aliased '())
 	(noreturn #f)
 	(dropped-branches 0)
@@ -628,9 +629,11 @@
 				      "variable `~a' of type `~a' was modified to a value of type `~a'"
 				    var ot rt)
 				  #t)))))
-		      (when strict-variable-types
-			;; don't use "add-to-blist" since this does not affect aliases
-			(set! blist (alist-cons (cons var (car flow)) rt blist))))
+		      ;; don't use "add-to-blist" since the current operation does not affect aliases
+		      (set! blist
+			(alist-cons (cons var (car flow)) 
+				    (if strict-variable-types rt '*)
+				    blist)))
 		    '(undefined)))
 		 ((##core#primitive ##core#inline_ref) '*)
 		 ((##core#call)
@@ -655,8 +658,15 @@
 			 (pt (and pn (variable-mark pn '##compiler#predicate))))
 		    (let-values (((r specialized?) 
 				  (call-result n args e loc params typeenv)))
+		      (define (smash)
+			(when (and (not strict-variable-types)
+				   (or (not pn)
+				       (not (variable-mark pn '##compiler#pure))))
+			  (smash-component-types! e "env")
+			  (smash-component-types! blist "blist")))
 		      (cond (specialized?
 			     (walk n e loc dest tail flow ctags)
+			     (smash)
 			     ;; keep type, as the specialization may contain icky stuff
 			     ;; like "##core#inline", etc.
 			     (if (eq? '* r)
@@ -714,7 +724,10 @@
 			       (nth-value 
 				0 
 				(procedure-argument-types fn (sub1 len) typeenv))))
-			     r)))))
+			     (smash)
+			     (if (eq? '* r)
+				 r
+				 (map (cut resolve <> typeenv) r)))))))
 		 ((##core#the)
 		  (let-values (((t _) (validate-type (first params) #f)))
 		    (let ((rt (walk (first subs) e loc dest tail flow ctags)))
@@ -749,10 +762,11 @@
 			     (quit "~ano clause applies in `compiler-typecase' for expression of type `~s':~a" 
 				   (location-name loc) (car ts)
 				   (string-concatenate
-				    (map (lambda (t) (string-sprintf "\n    ~a" t))
+				    (map (lambda (t) (sprintf "\n    ~a" t))
 					 params))))
 			    ((match-types (car types) (car ts) 
-					  (append (type-typeenv (car types)) typeenv))
+					  (append (type-typeenv (car types)) typeenv)
+					  #t)
 			     ;; drops exp
 			     (copy-node! (car subs) n)
 			     (walk n e loc dest tail flow ctags))
@@ -782,6 +796,24 @@
       rn)))
       
 
+;;; replace pair/vector types with components to component-less variants in env or blist
+
+(define (smash-component-types! lst where)
+  (do ((lst lst (cdr lst)))
+      ((null? lst))
+    (let loop ((t (cdar lst))
+	       (change! (cute set-cdr! (car lst) <>)))
+      (when (pair? t)
+	(case (car t)
+	  ((pair vector)
+	   (dd "  smashing `~s' in ~a" (caar lst) where)
+	   (change! (car t))
+	   (car t))
+	  ((forall)
+	   (loop (third t)
+		 (cute set-car! (cddr t) <>))))))))
+
+
 ;;; Converting type into string
 
 (define (typename t)
@@ -1008,6 +1040,8 @@
 		(match1 (second t1) (second t2))
 		(match1 t1 (third t2))))
 	  ((and (pair? t1) (eq? 'list (car t1)))
+	   ;;XXX (list T) == (pair T (pair T ... (pair T null)))
+	   ;     should also work in exact mode
 	   (and (not exact) (not all)
 		(or (eq? 'null t2)
 		    (and (pair? t2)
@@ -1506,20 +1540,44 @@
 		(new
 		 (let adjust ((new (cadr e)))
 		   (if (pair? new)
-		       (case (car new)
-			 ((procedure!)
-			  (mark-variable name '##compiler#enforce #t)
-			  `(procedure ,@(cdr new)))
-			 ((procedure!? procedure?!)
-			  (mark-variable name '##compiler#enforce #t)
-			  (mark-variable name '##compiler#predicate (cadr new))
-			  `(procedure ,@(cddr new)))
-			 ((procedure?)
-			  (mark-variable name '##compiler#predicate (cadr new))
-			  `(procedure ,@(cddr new)))
-			 ((forall)
-			  `(forall ,(cadr new) ,(adjust (caddr new))))
-			 (else new))
+		       (cond ((and (list? (car new))
+				   (eq? 'procedure (caar new)))
+			      ;;XXX this format is not used yet:
+			      (let loop ((props (cdar new)))
+				(unless (null? props)
+				  (case (car props)
+				    ((pure)
+				     ;;XXX this overwrites a possibly existing 'standard/
+				     ;;    'extended mark - I don't know if this is
+				     ;;    a problem
+				     (mark-variable name '##compiler#pure #t)
+				     (loop (cdr props)))
+				    ((enforce)
+				     (mark-variable name '##compiler#enforce #t)
+				     (loop (cdr props)))
+				    ((predicate)
+				     (mark-variable name '##compiler#predicate (cadr props))
+				     (loop (cddr props)))
+				    (else
+				     (bomb
+				      "load-type-database: invalid procedure-type property"
+				      (car props))))))
+			      `(procedure ,@(cdr new)))
+			     (else 	;XXX old style, remove at some stage
+			      (case (car new)
+				((procedure!)
+				 (mark-variable name '##compiler#enforce #t)
+				 `(procedure ,@(cdr new)))
+				((procedure!? procedure?!)
+				 (mark-variable name '##compiler#enforce #t)
+				 (mark-variable name '##compiler#predicate (cadr new))
+				 `(procedure ,@(cddr new)))
+				((procedure?)
+				 (mark-variable name '##compiler#predicate (cadr new))
+				 `(procedure ,@(cddr new)))
+				((forall)
+				 `(forall ,(cadr new) ,(adjust (caddr new))))
+				(else new))))
 		       new))))
 	   ;; validation is needed, even though .types-files can be considered
 	   ;; correct, because type variables have to be renamed:
@@ -1649,6 +1707,8 @@
 				continuation lock mmap condition hash-table
 				tcp-listener))
 	     `(struct ,t))
+	    ((eq? t 'immediate)		;XXX undocumented
+	     '(or eof null fixnum char boolean))
 	    ((not (pair? t)) 
 	     (cond ((memq t typevars)
 		    (set! usedvars (cons t usedvars))
diff --git a/tests/scrutiny-2.expected b/tests/scrutiny-2.expected
index 5a7cc085..4e2fa56a 100644
--- a/tests/scrutiny-2.expected
+++ b/tests/scrutiny-2.expected
@@ -19,10 +19,6 @@ Note: at toplevel:
   in procedure call to `list?', the predicate is called with an argument of type
   `list' and will always return true
 
-Note: at toplevel:
-  in procedure call to `list?', the predicate is called with an argument of type
-  `(pair fixnum fixnum)' and will always return false
-
 Note: at toplevel:
   in procedure call to `list?', the predicate is called with an argument of type
   `null' and will always return true
@@ -41,7 +37,7 @@ Note: at toplevel:
 
 Note: at toplevel:
   in procedure call to `null?', the predicate is called with an argument of type
-  `(pair fixnum fixnum)' and will always return false
+  `pair' and will always return false
 
 Note: at toplevel:
   in procedure call to `null?', the predicate is called with an argument of type
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
index 1b5ce750..61622704 100644
--- a/tests/typematch-tests.scm
+++ b/tests/typematch-tests.scm
@@ -104,17 +104,15 @@
 (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 2) 'a number)
+(check '(1) 1.2 (pair fixnum null))
+(check '(a) 1.2 (pair symbol null))
+(check (list 1) '(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)
@@ -123,7 +121,7 @@
 (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))
+(check '("ok") 1 (pair string null))
 
 (ms 123 1.2 fixnum)
 (ms "abc" 1.2 string)
@@ -145,20 +143,22 @@
 (ms '(1 . 2.3) '(a) (pair fixnum float))
 (ms '#(a) 1 (vector symbol))
 (ms '(1) "a" (or pair symbol))
-(ms (list) 'a list)
+(ms (list 1) 'a list)
 (ms '() 'a (or null pair))
 
+(define n 1)
+
 (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 number? (+ n) number)
+(checkp number? (+ n) number)
 (checkp exact? '1 fixnum)
-(checkp real? '1 number)
-(checkp complex? '1 number)
+(checkp real? (+ n) number)
+(checkp complex? (+ n) number)
 (checkp inexact? '1.2 float)
 (checkp char? #\a char)
 (checkp string? "a" string)
@@ -172,15 +172,9 @@
 (checkp pointer-vector? (make-pointer-vector 1) pointer-vector)
 (checkp pointer? (address->pointer 1) pointer)
 
-(m number fixnum)
-(m number float)
-(m list null)
-(m pair (pair number string))
-(m procedure (procedure () *))
 (mn (procedure (*) *) (procedure () *))
 (m (procedure (#!rest) . *) (procedure (*) . *))
 (mn (procedure () *) (procedure () * *))
 
 (mx (forall (a) (procedure (#!rest a) a)) +)
 (mx (or pair null) '(1))
-(mx (or pair null) (list))
Trap