~ chicken-core (chicken-5) f0ddac9001e419a77cdfd7cfaecb18d82ac527bb
commit f0ddac9001e419a77cdfd7cfaecb18d82ac527bb
Author: Evan Hanson <evhan@foldling.org>
AuthorDate: Mon Feb 15 22:13:35 2016 +1300
Commit: Peter Bex <peter@more-magic.net>
CommitDate: Sat Jun 18 16:43:45 2016 +0200
Drop consequent branch for conditionals that are always false
Also, add a line number prefix to the scrutiny messages for the
always-true and always-false situations, just in case we have enough
info to print them.
Signed-off-by: Peter Bex <peter@more-magic.net>
diff --git a/distribution/manifest b/distribution/manifest
index 711d55c7..663ca0cf 100644
--- a/distribution/manifest
+++ b/distribution/manifest
@@ -187,9 +187,11 @@ tests/test.scm
tests/loopy-test.scm
tests/loopy-loop.scm
tests/r5rs_pitfalls.scm
+tests/specialization-tests.scm
tests/specialization-test-1.scm
tests/specialization-test-2.scm
tests/specialization-test-2.types
+tests/specialization.expected
tests/test-irregex.scm
tests/re-tests.txt
tests/lolevel-tests.scm
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 3eafa1a5..65250104 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -218,15 +218,20 @@
((memq t '(* boolean false undefined noreturn)) #f)
(else #t)))
- (define (always-true t loc x)
- (let ((f (always-true1 t)))
- (when f
- (report-notice
- loc
- "expected a value of type boolean in conditional, but \
- was given a value of type `~a' which is always true:~%~%~a"
- t (pp-fragment x)))
- f))
+ (define (always-true if-node test-node t loc)
+ (and-let* ((_ (always-true1 t)))
+ (report-notice
+ loc "~aexpected a value of type boolean in conditional, but \
+ was given a value of type `~a' which is always true:~%~%~a"
+ (node-source-prefix test-node) t (pp-fragment if-node))
+ #t))
+
+ (define (always-false if-node test-node t loc)
+ (and-let* ((_ (eq? t 'false)))
+ (report-notice
+ loc "~ain conditional, test expression will always return false:~%~%~a"
+ (node-source-prefix test-node) (pp-fragment if-node))
+ #t))
(define (single node what tv loc)
(if (eq? '* tv)
@@ -490,10 +495,13 @@
(a (third subs))
(nor0 noreturn))
(cond
- ((and (always-true rt loc n) specialize)
- ;; drop branch and re-walk updated node
+ ((and (always-true n tst rt loc) specialize)
(set! dropped-branches (add1 dropped-branches))
- (copy-node! (build-node-graph `(let ((,(gensym) ,tst)) ,c)) n)
+ (mutate-node! n `(let ((,(gensym) ,tst)) ,c))
+ (walk n e loc dest tail flow ctags))
+ ((and (always-false n tst rt loc) specialize)
+ (set! dropped-branches (add1 dropped-branches))
+ (mutate-node! n `(let ((,(gensym) ,tst)) ,a))
(walk n e loc dest tail flow ctags))
(else
(let* ((r1 (walk c e loc dest tail (cons (car tags) flow) #f))
diff --git a/tests/runtests.sh b/tests/runtests.sh
index fbb0b5e9..dc9ca87f 100755
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -114,16 +114,22 @@ $compile null.scm -profile -profile-name TEST.profile
$CHICKEN_PROFILE TEST.profile
echo "======================================== scrutiny tests ..."
-$compile typematch-tests.scm -specialize -w
+$compile typematch-tests.scm -specialize -no-warnings
./a.out
-$compile scrutiny-tests.scm -A 2>scrutiny.out -verbose
-# this is sensitive to gensym-names, so make it optional
+$compile scrutiny-tests.scm -analyze-only -verbose 2>scrutiny.out
+$compile specialization-tests.scm -analyze-only -verbose -specialize 2>specialization.out
+
+# these are sensitive to gensym-names, so make them optional
if test \! -f scrutiny.expected; then
cp scrutiny.out scrutiny.expected
fi
+if test \! -f specialization.expected; then
+ cp specialization.out specialization.expected
+fi
diff $DIFF_OPTS scrutiny.expected scrutiny.out
+diff $DIFF_OPTS specialization.expected specialization.out
$compile scrutiny-tests-2.scm -A 2>scrutiny-2.out -verbose
diff --git a/tests/specialization-tests.scm b/tests/specialization-tests.scm
new file mode 100644
index 00000000..667b65c7
--- /dev/null
+++ b/tests/specialization-tests.scm
@@ -0,0 +1,4 @@
+;; both arms of if branches are dropped
+
+(let ((a "yep")) (if (string? a) 'ok 'no))
+(let ((a 'nope)) (if (string? a) 'ok 'no))
diff --git a/tests/specialization.expected b/tests/specialization.expected
new file mode 100644
index 00000000..9ae2fc56
--- /dev/null
+++ b/tests/specialization.expected
@@ -0,0 +1,16 @@
+
+Note: at toplevel:
+ (specialization-tests.scm:3) in procedure call to `string?', the predicate is called with an argument of type `string' and will always return true
+
+Note: at toplevel:
+ (specialization-tests.scm:3) expected a value of type boolean in conditional, but was given a value of type `true' which is always true:
+
+(if (string? a) 'ok 'no)
+
+Note: at toplevel:
+ (specialization-tests.scm:4) in procedure call to `string?', the predicate is called with an argument of type `symbol' and will always return false
+
+Note: at toplevel:
+ (specialization-tests.scm:4) in conditional, test expression will always return false:
+
+(if (string? a) 'ok 'no)
Trap