From 2b277125b2d14a05710d7c8e4c0a22f97eea662a Mon Sep 17 00:00:00 2001 From: Christophe Rhodes Date: Sat, 19 Oct 2002 01:30:03 +0000 Subject: [PATCH] 0.7.8.47: Fix CONCATENATE like MAKE-SEQUENCE/MERGE/COERCE ... but don't fix MAP, because it looks hard; write a BUG entry instead --- BUGS | 31 +++++++++++++++++++++++++++++++ src/code/seq.lisp | 27 +++++++++++++++++++++++++-- tests/seq.impure.lisp | 15 ++++++++++++--- version.lisp-expr | 2 +- 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/BUGS b/BUGS index dd7758f..4f7bea2 100644 --- a/BUGS +++ b/BUGS @@ -1276,6 +1276,37 @@ WORKAROUND: c. Compiler should not warn on an unknown key :ALLOW-OTHER-KEYS. d. :ALLOW-OTHER-KEYS should be allowed as an ordinary key parameter. +212: "Sequence functions and circular arguments" + COERCE, MERGE and CONCATENATE go into an infinite loop when given + circular arguments; it would be good for the user if they could be + given an error instead (ANSI 17.1.1 allows this behaviour on the part + of the implementation, as conforming code cannot give non-proper + sequences to these functions. MAP also has this problem (and + solution), though arguably the convenience of being able to do + (MAP 'LIST '+ FOO '#1=(1 . #1#)) + might be classed as more important (though signalling an error when + all of the arguments are circular is probably desireable). + +213: "Sequence functions and type checking" + a. MAKE-SEQUENCE, COERCE, MERGE and CONCATENATE cannot deal with + various complicated, though recognizeable, CONS types [e.g. + (CONS * (CONS * NULL)) + which according to ANSI should be recognized] (and, in SAFETY 3 + code, should return a list of LENGTH 2 or signal an error) + b. MAP, when given a type argument that is SUBTYPEP LIST, does not + check that it will return a sequence of the given type. Fixing + it along the same lines as the others (cf. work done around + sbcl-0.7.8.45) is possible, but doing so efficiently didn't look + entirely straightforward. + c. All of these functions will silently accept a type of the form + (CONS INTEGER *) + whether or not the return value is of this type. This is + probably permitted by ANSI (see "Exceptional Situations" under + ANSI MAKE-SEQUENCE), but the DERIVE-TYPE mechanism does not + know about this escape clause, so code of the form + (INTEGERP (CAR (MAKE-SEQUENCE '(CONS INTEGER *) 2))) + can erroneously return T. + DEFUNCT CATEGORIES OF BUGS IR1-#: These labels were used for bugs related to the old IR1 interpreter. diff --git a/src/code/seq.lisp b/src/code/seq.lisp index 93bfa19..9446dc8 100644 --- a/src/code/seq.lisp +++ b/src/code/seq.lisp @@ -634,10 +634,33 @@ specified OUTPUT-TYPE-SPEC." (let ((type (specifier-type output-type-spec))) (cond + ((csubtypep type (specifier-type 'list)) + (cond + ((type= type (specifier-type 'list)) + (apply #'concat-to-list* sequences)) + ((eq type *empty-type*) + (bad-sequence-type-error nil)) + ((type= type (specifier-type 'null)) + (if (every (lambda (x) (or (null x) + (and (vectorp x) (= (length x) 0)))) + sequences) + 'nil + (sequence-type-length-mismatch-error type + ;; FIXME: circular + ;; list issues. And + ;; rightward-drift. + (reduce #'+ + (mapcar #'length + sequences))))) + ((csubtypep (specifier-type '(cons nil t)) type) + (if (notevery (lambda (x) (or (null x) + (and (vectorp x) (= (length x) 0)))) + sequences) + (apply #'concat-to-list* sequences) + (sequence-type-length-mismatch-error type 0))) + (t (sequence-type-too-hairy (type-specifier type))))) ((csubtypep type (specifier-type 'vector)) (apply #'concat-to-simple* output-type-spec sequences)) - ((csubtypep type (specifier-type 'list)) - (apply #'concat-to-list* sequences)) (t (bad-sequence-type-error output-type-spec))))) diff --git a/tests/seq.impure.lisp b/tests/seq.impure.lisp index ec6e74f..dc5a6e3 100644 --- a/tests/seq.impure.lisp +++ b/tests/seq.impure.lisp @@ -296,6 +296,10 @@ ;; MAKE-SEQUENCE (assert-type-error (make-sequence 'cons 0)) (assert-type-error (make-sequence 'null 1)) + ;; KLUDGE: I'm not certain that this test actually tests for what + ;; it should test, in that the type deriver and optimizers might + ;; be too smart for the good of an exhaustive test system. + ;; However, it makes me feel good. -- CSR, 2002-10-18 (assert (null (make-sequence 'null 0))) (assert (= (length (make-sequence 'cons 3)) 3)) ;; and NIL is not a valid type for MAKE-SEQUENCE @@ -312,10 +316,15 @@ (assert (null (merge 'null () () '<))) (assert (= (length (merge 'cons '(1 3) '(2 4) '<)) 4)) (assert-type-error (merge 'nil () () '<)) - ;; tests for MAP/CONCATENATE to come. + ;; CONCATENATE + (assert-type-error (concatenate 'null '(1) "2")) + (assert-type-error (concatenate 'cons #() ())) + (assert (null (concatenate 'null () #()))) + (assert (= (length (concatenate 'cons #() '(1) "2 3")) 4)) + (assert-type-error (concatenate 'nil '(3))) + ;; FIXME: tests for MAP to come when some brave soul implements + ;; the analogous type checking for MAP/%MAP. )) - - ;;; success (quit :unix-status 104) diff --git a/version.lisp-expr b/version.lisp-expr index 5f9e608..9b27384 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -18,4 +18,4 @@ ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.7.8.46" +"0.7.8.47" -- 1.7.10.4