~ chicken-core (chicken-5) 9f07e332986de5bc94b5bc04735ca599df41615d
commit 9f07e332986de5bc94b5bc04735ca599df41615d
Author: Evan Hanson <evhan@foldling.org>
AuthorDate: Sun Aug 17 18:36:21 2014 +1200
Commit: Peter Bex <peter.bex@xs4all.nl>
CommitDate: Sun Oct 19 14:27:20 2014 +0200
Add scrutiny special cases for make-list/make-vector with known sizes
Signed-off-by: Peter Bex <peter.bex@xs4all.nl>
diff --git a/scrutinizer.scm b/scrutinizer.scm
index c5cd8c4c..afe3cabe 100644
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -110,6 +110,7 @@
(define-constant +fragment-max-length+ 6)
(define-constant +fragment-max-depth+ 4)
(define-constant +maximal-union-type-length+ 20)
+(define-constant +maximal-complex-object-constructor-result-type-length+ 256)
(define specialization-statistics '())
@@ -2269,6 +2270,34 @@
`((vector ,@(map walked-result (cdr args))))))
+;;; Special cases for make-list/make-vector with a known size
+;
+; e.g. (make-list 3 #\a) => (list char char char)
+
+(let ()
+
+ (define (complex-object-constructor-result-type-special-case type)
+ (lambda (node args rtypes)
+ (or (and-let* ((subs (node-subexpressions node))
+ (fill (case (length subs)
+ ((2) '*)
+ ((3) (walked-result (third args)))
+ (else #f)))
+ (sub2 (second subs))
+ ((eq? 'quote (node-class sub2)))
+ (size (first (node-parameters sub2)))
+ ((fixnum? size))
+ ((<= 0 size +maximal-complex-object-constructor-result-type-length+)))
+ `((,type ,@(make-list size fill))))
+ rtypes)))
+
+ (define-special-case make-list
+ (complex-object-constructor-result-type-special-case 'list))
+
+ (define-special-case make-vector
+ (complex-object-constructor-result-type-special-case 'vector)))
+
+
;;; perform check over all typevar instantiations
(define (over-all-instantiations tlist typeenv exact process)
@@ -2312,7 +2341,8 @@
(ddd " over-all-instantiations: ~s exact=~a" tlist exact)
;; process all tlist elements
- (let loop ((ts tlist) (ok #f))
+ (let loop ((ts (delete-duplicates tlist equal?))
+ (ok #f))
(cond ((null? ts)
(cond ((or ok (null? tlist))
(for-each
diff --git a/tests/typematch-tests.scm b/tests/typematch-tests.scm
index 40515957..4374337b 100644
--- a/tests/typematch-tests.scm
+++ b/tests/typematch-tests.scm
@@ -286,6 +286,10 @@
(mx (list fixnum) (take (list 1 2.3) 1))
(mx (list fixnum) (take (cons 1 2.3) 1))
(mx (list fixnum float) (take (list 1 2.3) 2))
+(mx (list * *) (make-list 2))
+(mx (list string string) (make-list 2 "a"))
+(mx (vector * *) (make-vector 2))
+(mx (vector string string) (make-vector 2 "a"))
(: f1 (forall (a) ((list-of a) -> a)))
(define (f1 x) (car x))
diff --git a/types.db b/types.db
index 7d555383..19f01f37 100644
--- a/types.db
+++ b/types.db
@@ -561,6 +561,7 @@
(vector? (#(procedure #:pure #:predicate vector) vector? (*) boolean))
+;; special-cased (see scrutinizer.scm)
(make-vector (forall (a) (#(procedure #:clean #:enforce) make-vector (fixnum #!optional a)
(vector-of a))))
@@ -1993,6 +1994,7 @@
((procedure) (let ((#(tmp) #(1))) '#t))
((procedure list) (let ((#(tmp1) #(1)) (#(tmp2) #(2))) '#t)))
+;; special-cased (see scrutinizer.scm)
(make-list (forall (a) (#(procedure #:clean #:enforce) make-list (fixnum #!optional a) (list-of a))))
(map!
Trap