:derive-type (sequence-result-nth-arg 1))
(defknown nreverse (sequence) sequence ()
- :derive-type #'result-type-first-arg)
+ :derive-type #'result-type-first-arg
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown make-sequence (type-specifier index
&key
(defknown map-into (sequence callable &rest sequence)
sequence
(call)
- :derive-type #'result-type-first-arg)
+ :derive-type #'result-type-first-arg
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
;;; returns the result from the predicate...
(defknown some (callable sequence &rest sequence) t
(defknown fill (sequence t &key (:start index) (:end sequence-end)) sequence
(unsafe)
- :derive-type #'result-type-first-arg)
+ :derive-type #'result-type-first-arg
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown replace (sequence
sequence
(:start2 index)
(:end2 sequence-end))
sequence ()
- :derive-type #'result-type-first-arg)
+ :derive-type #'result-type-first-arg
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown remove
(t sequence &key (:from-end t) (:test callable)
(:count sequence-count) (:key callable))
sequence
(flushable call)
- :derive-type (sequence-result-nth-arg 2))
+ :derive-type (sequence-result-nth-arg 2)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 2))
(defknown nsubstitute
(t t sequence &key (:from-end t) (:test callable)
(:count sequence-count) (:key callable))
sequence
(flushable call)
- :derive-type (sequence-result-nth-arg 3))
+ :derive-type (sequence-result-nth-arg 3)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 3))
(defknown (delete-if delete-if-not)
(callable sequence &key (:from-end t) (:start index) (:end sequence-end)
(:count sequence-count) (:key callable))
sequence
(flushable call)
- :derive-type (sequence-result-nth-arg 2))
+ :derive-type (sequence-result-nth-arg 2)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 2))
(defknown (nsubstitute-if nsubstitute-if-not)
(t callable sequence &key (:from-end t) (:start index) (:end sequence-end)
(:count sequence-count) (:key callable))
sequence
(flushable call)
- :derive-type (sequence-result-nth-arg 3))
+ :derive-type (sequence-result-nth-arg 3)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 3))
(defknown remove-duplicates
(sequence &key (:test callable) (:test-not callable) (:start index)
(:from-end t) (:end sequence-end) (:key callable))
sequence
(unsafely-flushable call)
- :derive-type (sequence-result-nth-arg 1))
+ :derive-type (sequence-result-nth-arg 1)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown find (t sequence &key (:test callable) (:test-not callable)
(:start index) (:from-end t) (:end sequence-end)
;;; not FLUSHABLE, since vector sort guaranteed in-place...
(defknown (stable-sort sort) (sequence callable &key (:key callable)) sequence
(call)
- :derive-type (sequence-result-nth-arg 1))
+ :derive-type (sequence-result-nth-arg 1)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown sb!impl::sort-vector (vector index index function (or function null))
* ; SORT-VECTOR works through side-effect
- (call))
+ (call)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown merge (type-specifier sequence sequence callable
&key (:key callable))
sequence
(call)
- :derive-type (creation-result-type-specifier-nth-arg 1))
+ :derive-type (creation-result-type-specifier-nth-arg 1)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 2 3))
;;; not FLUSHABLE, despite what CMU CL's DEFKNOWN said..
(defknown read-sequence (sequence stream
;;; All but last must be of type LIST, but there seems to be no way to
;;; express that in this syntax. The result must be LIST, but we do
;;; not check it now :-).
-(defknown nconc (&rest t) t ())
-(defknown sb!impl::nconc2 (list t) t ())
+(defknown nconc (&rest t) t ()
+ :destroyed-constant-args (remove-non-constants-and-nils #'butlast))
+(defknown sb!impl::nconc2 (list t) t ()
+ :destroyed-constant-args (remove-non-constants-and-nils #'butlast))
-(defknown nreconc (list t) t ())
+(defknown nreconc (list t) t ()
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown butlast (list &optional unsigned-byte) list (flushable))
-(defknown nbutlast (list &optional unsigned-byte) list ())
+(defknown nbutlast (list &optional unsigned-byte) list ()
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
+
(defknown ldiff (list t) list (flushable))
-(defknown (rplaca rplacd) (cons t) list (unsafe))
+(defknown (rplaca rplacd) (cons t) list (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
-(defknown (nsubst subst) (t t t &key (:key callable) (:test callable)
- (:test-not callable))
+(defknown subst (t t t &key (:key callable) (:test callable)
+ (:test-not callable))
t (flushable unsafe call))
+(defknown nsubst (t t t &key (:key callable) (:test callable)
+ (:test-not callable))
+ t (unsafe call)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 3))
-(defknown (subst-if subst-if-not nsubst-if nsubst-if-not)
+(defknown (subst-if subst-if-not)
(t callable t &key (:key callable))
t (flushable unsafe call))
+(defknown (nsubst-if nsubst-if-not)
+ (t callable t &key (:key callable))
+ t (unsafe call)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 3))
-(defknown (sublis nsublis) (list t &key (:key callable) (:test callable)
- (:test-not callable))
+(defknown sublis (list t &key (:key callable) (:test callable)
+ (:test-not callable))
t (flushable unsafe call))
+(defknown nsublis (list t &key (:key callable) (:test callable)
+ (:test-not callable))
+ t (flushable unsafe call)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 2))
(defknown member (t list &key (:key callable) (:test callable)
(:test-not callable))
(defknown (nunion nintersection nset-difference nset-exclusive-or)
(list list &key (:key callable) (:test callable) (:test-not callable))
list
- (foldable flushable call))
+ (foldable flushable call)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1 2))
(defknown subsetp
(list list &key (:key callable) (:test callable) (:test-not callable))
(callable list &key (:key callable)) list (foldable flushable call))
(defknown (memq assq) (t list) list (foldable flushable unsafe))
-(defknown delq (t list) list (flushable unsafe))
+(defknown delq (t list) list (flushable unsafe)
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 2))
\f
;;;; from the "Hash Tables" chapter:
(flushable unsafe)) ; not FOLDABLE, since hash table contents can change
(defknown sb!impl::gethash3 (t hash-table t) (values t boolean)
(flushable unsafe)) ; not FOLDABLE, since hash table contents can change
-(defknown %puthash (t hash-table t) t (unsafe))
-(defknown remhash (t hash-table) boolean ())
+(defknown %puthash (t hash-table t) t (unsafe)
+ :destroyed-constant-args (nth-constant-args 2))
+(defknown remhash (t hash-table) boolean ()
+ :destroyed-constant-args (nth-constant-args 2))
(defknown maphash (callable hash-table) null (flushable call))
-(defknown clrhash (hash-table) hash-table ())
+(defknown clrhash (hash-table) hash-table ()
+ :destroyed-constant-args (nth-constant-args 2))
(defknown hash-table-count (hash-table) index (flushable))
(defknown hash-table-rehash-size (hash-table) (or (integer 1) (float (1.0)))
(foldable flushable))
(defknown bit ((array bit) &rest index) bit (foldable flushable))
(defknown sbit ((simple-array bit) &rest index) bit (foldable flushable))
+;;; FIXME: :DESTROYED-CONSTANT-ARGS for these is complicated.
(defknown (bit-and bit-ior bit-xor bit-eqv bit-nand bit-nor bit-andc1 bit-andc2
bit-orc1 bit-orc2)
((array bit) (array bit) &optional (or (array bit) (member t nil)))
(defknown array-has-fill-pointer-p (array) boolean
(movable foldable flushable))
(defknown fill-pointer (vector) index (foldable unsafely-flushable))
-(defknown vector-push (t vector) (or index null) ())
-(defknown vector-push-extend (t vector &optional index) index ())
-(defknown vector-pop (vector) t ())
-
+(defknown vector-push (t vector) (or index null) ()
+ :destroyed-constant-args (nth-constant-args 2))
+(defknown vector-push-extend (t vector &optional index) index ()
+ :destroyed-constant-args (nth-constant-args 2))
+(defknown vector-pop (vector) t ()
+ :destroyed-constant-args (nth-constant-args 1))
+
+;;; FIXME: complicated :DESTROYED-CONSTANT-ARGS
(defknown adjust-array
(array (or index list) &key (:element-type type-specifier)
(:initial-element t) (:initial-contents t)
(defknown (nstring-upcase nstring-downcase nstring-capitalize)
(string &key (:start index) (:end sequence-end))
- string ())
+ string ()
+ :destroyed-constant-args (nth-constant-nonempty-sequence-args 1))
(defknown string (string-designator) string
(flushable explicit-check))
(defknown write-byte (integer stream) integer
(explicit-check))
+;;; FIXME: complicated :DESTROYED-CONSTANT-ARGS
(defknown format ((or (member nil t) stream string)
(or string function) &rest t)
(or string null)
\f
;;;; SETF inverses
-(defknown %aset (array &rest t) t (unsafe))
-(defknown %set-row-major-aref (array index t) t (unsafe))
-(defknown %rplaca (cons t) t (unsafe))
-(defknown %rplacd (cons t) t (unsafe))
+(defknown %aset (array &rest t) t (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
+(defknown %set-row-major-aref (array index t) t (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
+(defknown (%rplaca %rplacd) (cons t) t (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
(defknown %put (symbol t t) t (unsafe))
-(defknown %setelt (sequence index t) t (unsafe))
-(defknown %svset (simple-vector index t) t (unsafe))
-(defknown %bitset ((array bit) &rest index) bit (unsafe))
-(defknown %sbitset ((simple-array bit) &rest index) bit (unsafe))
-(defknown %charset (string index character) character (unsafe))
-(defknown %scharset (simple-string index character) character (unsafe))
+(defknown %setelt (sequence index t) t (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
+(defknown %svset (simple-vector index t) t (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
+(defknown %bitset ((array bit) &rest index) bit (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
+(defknown %sbitset ((simple-array bit) &rest index) bit (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
+(defknown %charset (string index character) character (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
+(defknown %scharset (simple-string index character) character (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
(defknown %set-symbol-value (symbol t) t (unsafe))
(defknown (setf symbol-function) (function symbol) function (unsafe))
(defknown %set-symbol-plist (symbol t) t (unsafe))
(defknown (setf fdocumentation) ((or string null) t symbol)
(or string null)
())
-(defknown %setnth (unsigned-byte list t) t (unsafe))
-(defknown %set-fill-pointer (vector index) index (unsafe))
+(defknown %setnth (unsigned-byte list t) t (unsafe)
+ :destroyed-constant-args (nth-constant-args 2))
+(defknown %set-fill-pointer (vector index) index (unsafe)
+ :destroyed-constant-args (nth-constant-args 1))
\f
;;;; ALIEN and call-out-to-C stuff
;; further optimiz'ns) is backwards from the return convention for
;; transforms. -- WHN 19990917
(optimizer nil :type (or function null))
+ ;; a function computing the constant or literal arguments which are
+ ;; destructively modified by the call.
+ (destroyed-constant-args nil :type (or function null))
;; If true, a special-case LTN annotation method that is used in
;; place of the standard type/policy template selection. It may use
;; arbitrary code to choose a template, decide to do a full call, or
(:optimizer (or function null)))
*)
%defknown))
-(defun %defknown (names type attributes &key derive-type optimizer)
+(defun %defknown (names type attributes &key derive-type optimizer destroyed-constant-args)
(let ((ctype (specifier-type type))
(info (make-fun-info :attributes attributes
:derive-type derive-type
- :optimizer optimizer))
+ :optimizer optimizer
+ :destroyed-constant-args destroyed-constant-args))
(target-env *info-environment*))
(dolist (name names)
(let ((old-fun-info (info :function :info name)))
real-ctype)
ctype)))))))))
+(defun remove-non-constants-and-nils (fun)
+ (lambda (list)
+ (remove-if-not #'lvar-value
+ (remove-if-not #'constant-lvar-p (funcall fun list)))))
+
+;;; FIXME: bad name (first because it uses 1-based indexing; second
+;;; because it doesn't get the nth constant arguments)
+(defun nth-constant-args (&rest indices)
+ (lambda (list)
+ (let (result)
+ (do ((i 1 (1+ i))
+ (list list (cdr list))
+ (indices indices))
+ ((null indices) (nreverse result))
+ (when (= i (car indices))
+ (when (constant-lvar-p (car list))
+ (push (car list) result))
+ (setf indices (cdr indices)))))))
+
+;;; FIXME: a number of the sequence functions not only do not destroy
+;;; their argument if it is empty, but also leave it alone if :start
+;;; and :end bound a null sequence, or if :count is 0. This test is a
+;;; bit complicated to implement, verging on the impossible, but for
+;;; extra points (fill #\1 "abc" :start 0 :end 0) should not cause a
+;;; warning.
+(defun nth-constant-nonempty-sequence-args (&rest indices)
+ (lambda (list)
+ (let (result)
+ (do ((i 1 (1+ i))
+ (list list (cdr list))
+ (indices indices))
+ ((null indices) (nreverse result))
+ (when (= i (car indices))
+ (when (constant-lvar-p (car list))
+ (let ((value (lvar-value (car list))))
+ (unless (or (typep value 'null)
+ (typep value '(vector * 0)))
+ (push (car list) result))))
+ (setf indices (cdr indices)))))))
+
(/show0 "knownfun.lisp end of file")