~ chicken-core (chicken-5) 20e7cae502b5efaa51f146c60940f1c68bb5f209
commit 20e7cae502b5efaa51f146c60940f1c68bb5f209
Author: Evan Hanson <evhan@foldling.org>
AuthorDate: Sat Sep 6 09:10:18 2014 +1200
Commit: Peter Bex <peter.bex@xs4all.nl>
CommitDate: Sun Oct 19 14:36:15 2014 +0200
Add scrutiny special case for reverse and specialization for null argument
This preserves the element types of list- and null-type arguments to
reverse in its result type (rather than the less specialized list-of).
Signed-off-by: Peter Bex <peter.bex@xs4all.nl>
diff --git a/scrutinizer.scm b/scrutinizer.scm
index afe3cabe..b363ccd2 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -2269,6 +2269,15 @@
(lambda (node args rtypes)
`((vector ,@(map walked-result (cdr args))))))
+(define-special-case reverse
+ (lambda (node args rtypes)
+ (or (and-let* ((subs (node-subexpressions node))
+ ((= (length subs) 2))
+ (arg1 (walked-result (second args)))
+ ((pair? arg1))
+ ((eq? (car arg1) 'list)))
+ `((list ,@(reverse (cdr arg1)))))
+ rtypes)))
;;; Special cases for make-list/make-vector with a known size
;
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
index 4374337b..930362fa 100644
--- a/tests/typematch-tests.scm
+++ b/tests/typematch-tests.scm
@@ -290,6 +290,10 @@
(mx (list string string) (make-list 2 "a"))
(mx (vector * *) (make-vector 2))
(mx (vector string string) (make-vector 2 "a"))
+(mx null (reverse '()))
+(mx list (reverse (the list (list 1 "2"))))
+(mx (list string fixnum) (reverse (list 1 "2")))
+(mx (list fixnum string) (reverse (cons "1" (cons 2 '()))))
(: f1 (forall (a) ((list-of a) -> a)))
(define (f1 x) (car x))
diff --git a/types.db b/types.db
index 19f01f37..fb8557e5 100644
--- a/types.db
+++ b/types.db
@@ -170,7 +170,9 @@
(append (#(procedure #:clean) append (#!rest *) *)) ; sic
(##sys#append (#(procedure #:clean) ##sys#append (#!rest *) *))
-(reverse (forall (a) (#(procedure #:clean #:enforce) reverse ((list-of a)) (list-of a))))
+;; special cased (see scrutinizer.scm)
+(reverse (forall (a) (#(procedure #:clean #:enforce) reverse ((list-of a)) (list-of a)))
+ ((null) (null) (let ((#(tmp) #(1))) '())))
(memq (forall (a b) (#(procedure #:clean) memq (a (list-of b)) (or false (list-of b))))
((* list) (##core#inline "C_u_i_memq" #(1) #(2))))
Trap