~ chicken-core (chicken-5) 7eb95c52acc4f57a2dd66c36090d87fdce62412f


commit 7eb95c52acc4f57a2dd66c36090d87fdce62412f
Author:     Peter Bex <peter@more-magic.net>
AuthorDate: Mon May 25 17:42:01 2015 +0200
Commit:     Peter Bex <peter@more-magic.net>
CommitDate: Mon May 25 17:42:01 2015 +0200

    Re-walk `if` nodes after dropping branches
    
    This makes sure the scrutinizer uses the new type of each node after
    converting it into a non-conditional form. For example, the expression
    `(if #t 1 2.0)` should have the type `fixnum` after dropping the
    unreachable branch, rather than its original type `(or fixnum float)`.
    
    Signed-off-by: Peter Bex <peter@more-magic.net>

diff --git a/scrutinizer.scm b/scrutinizer.scm
index ef0e5fb2..26469f44 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -493,48 +493,49 @@
 			   (c (second subs))
 			   (a (third subs))
 			   (nor0 noreturn))
-		      (when (and (always-true rt loc n) specialize)
-			(set! dropped-branches (add1 dropped-branches))
-			(copy-node!
-			 (build-node-graph
-			  `(let ((,(gensym) ,tst)) ,c))
-			 n))
-		      (let* ((r1 (walk c e loc dest tail (cons (car tags) flow) #f))
-			     (nor1 noreturn))
-			(set! noreturn #f)
-			(let* ((r2 (walk a e loc dest tail (cons (cdr tags) flow) #f))
-			       (nor2 noreturn))
-			  (set! noreturn (or nor-1 nor0 (and nor1 nor2)))
-			  ;; when only one branch is noreturn, add blist entries for
-			  ;; all in other branch:
-			  (when (or (and nor1 (not nor2))
-				    (and nor2 (not nor1)))
-			    (let ((yestag (if nor1 (cdr tags) (car tags))))
-			      (for-each
-			       (lambda (ble)
-				 (when (eq? (cdar ble) yestag)
-				   (d "adding blist entry ~a for single returning conditional branch"
-				      ble)
-				   (add-to-blist (caar ble) (car flow) (cdr ble))))
-			       blist)))
-			  (cond ((and (not (eq? '* r1)) (not (eq? '* r2)))
-				 ;;(dd " branches: ~s:~s / ~s:~s" nor1 r1 nor2 r2)
-				 (cond ((and (not nor1) (not nor2)
-					     (not (= (length r1) (length r2))))
-					(report 
-					 loc
-					 (sprintf
-					     "branches in conditional expression differ in the number of results:~%~%~a"
-					   (pp-fragment n)))
-					'*)
-				       (nor1 r2)
-				       (nor2 r1)
-				       (else
-					(dd "merge branch results: ~s + ~s" r1 r2)
-					(map (lambda (t1 t2)
-					       (simplify-type `(or ,t1 ,t2)))
-					     r1 r2))))
-				(else '*)))))))
+		      (cond
+			((and (always-true rt loc n) specialize)
+			 ;; drop branch and re-walk updated node
+			 (set! dropped-branches (add1 dropped-branches))
+			 (copy-node! (build-node-graph `(let ((,(gensym) ,tst)) ,c)) n)
+			 (walk n e loc dest tail flow ctags))
+			(else
+			 (let* ((r1 (walk c e loc dest tail (cons (car tags) flow) #f))
+				(nor1 noreturn))
+			   (set! noreturn #f)
+			   (let* ((r2 (walk a e loc dest tail (cons (cdr tags) flow) #f))
+				 (nor2 noreturn))
+			     (set! noreturn (or nor-1 nor0 (and nor1 nor2)))
+			     ;; when only one branch is noreturn, add blist entries for
+			     ;; all in other branch:
+			     (when (or (and nor1 (not nor2))
+				      (and nor2 (not nor1)))
+			       (let ((yestag (if nor1 (cdr tags) (car tags))))
+				(for-each
+				 (lambda (ble)
+				   (when (eq? (cdar ble) yestag)
+				     (d "adding blist entry ~a for single returning conditional branch"
+					ble)
+				     (add-to-blist (caar ble) (car flow) (cdr ble))))
+				 blist)))
+			     (cond ((and (not (eq? '* r1)) (not (eq? '* r2)))
+				   ;;(dd " branches: ~s:~s / ~s:~s" nor1 r1 nor2 r2)
+				   (cond ((and (not nor1) (not nor2)
+					       (not (= (length r1) (length r2))))
+					  (report
+					   loc
+					   (sprintf
+					       "branches in conditional expression differ in the number of results:~%~%~a"
+					     (pp-fragment n)))
+					  '*)
+					 (nor1 r2)
+					 (nor2 r1)
+					 (else
+					  (dd "merge branch results: ~s + ~s" r1 r2)
+					  (map (lambda (t1 t2)
+						 (simplify-type `(or ,t1 ,t2)))
+					       r1 r2))))
+				  (else '*)))))))))
 		 ((let)
 		  ;; before CPS-conversion, `let'-nodes may have multiple bindings
 		  (let loop ((vars params) (body subs) (e2 '()))
diff --git a/tests/specialization-test-1.scm b/tests/specialization-test-1.scm
index 344e4451..ff82d981 100644
--- a/tests/specialization-test-1.scm
+++ b/tests/specialization-test-1.scm
@@ -56,4 +56,8 @@ return n;}
 			  "         C_fix(2));")))))
   (assert (equal? '(1 2) result)))
 
+;; dropped conditional branch is ignored
+(compiler-typecase (if #t 'a "a")
+  (symbol 1))
+
 )
Trap