MAKE-INSTANCE.
** :ALLOW-OTHER-KEYS NIL is now accepted in an initarg list.
+changes in sbcl-0.8.0 relative to sbcl-0.8alpha.0
+ * SB-MOP:DIRECT-SLOT-DEFINITION-CLASS and
+ SB-MOP:EFFECTIVE-SLOT-DEFINITION-CLASS now have the
+ specified-by-AMOP lambda list of (CLASS &REST INITARGS).
+ * fixed some bugs revealed by Paul Dietz' test suite:
+ ** the GENERIC-FUNCTION type is no longer disjoint from FUNCTION
+ types.
+
+
planned incompatible changes in 0.8.x:
* (not done yet, but planned:) When the profiling interface settles
down, maybe in 0.7.x, maybe later, it might impact TRACE. They both
;; true if other &KEY arguments are allowed
(allowp nil :type boolean))
+(defun canonicalize-args-type-args (required optional rest)
+ (when rest
+ (let ((last-distinct-optional (position rest optional
+ :from-end t
+ :test-not #'type=)))
+ (setf optional
+ (when last-distinct-optional
+ (subseq optional 0 (1+ last-distinct-optional))))))
+ (values required optional rest))
+
+(defun args-types (lambda-list-like-thing)
+ (multiple-value-bind
+ (required optional restp rest keyp keys allowp auxp aux)
+ (parse-lambda-list-like-thing lambda-list-like-thing)
+ (declare (ignore aux))
+ (when auxp
+ (error "&AUX in a FUNCTION or VALUES type: ~S." lambda-list-like-thing))
+ (let ((required (mapcar #'single-value-specifier-type required))
+ (optional (mapcar #'single-value-specifier-type optional))
+ (rest (when restp (single-value-specifier-type rest)))
+ (keywords
+ (collect ((key-info))
+ (dolist (key keys)
+ (unless (proper-list-of-length-p key 2)
+ (error "Keyword type description is not a two-list: ~S." key))
+ (let ((kwd (first key)))
+ (when (find kwd (key-info) :key #'key-info-name)
+ (error "~@<repeated keyword ~S in lambda list: ~2I~_~S~:>"
+ kwd lambda-list-like-thing))
+ (key-info
+ (make-key-info
+ :name kwd
+ :type (single-value-specifier-type (second key))))))
+ (key-info))))
+ (multiple-value-bind (required optional rest)
+ (canonicalize-args-type-args required optional rest)
+ (values required optional rest keyp keywords allowp)))))
+
(defstruct (values-type
(:include args-type
(class-info (type-class-or-lose 'values)))
(:constructor %make-values-type)
(:copier nil)))
-(define-cached-synonym make-values-type)
+
+(defun make-values-type (&rest initargs
+ &key (args nil argsp) &allow-other-keys)
+ (if argsp
+ (if (eq args '*)
+ *wild-type*
+ (multiple-value-bind (required optional rest keyp keywords allowp)
+ (args-types args)
+ (if (and (null required)
+ (null optional)
+ (eq rest *universal-type*)
+ (not keyp))
+ *wild-type*
+ (%make-values-type :required required
+ :optional optional
+ :rest rest
+ :keyp keyp
+ :keywords keywords
+ :allowp allowp))))
+ (apply #'%make-values-type initargs)))
(!define-type-class values)
;;; (SPECIFIER-TYPE 'FUNCTION) and its subtypes
(defstruct (fun-type (:include args-type
- (class-info (type-class-or-lose 'function))))
+ (class-info (type-class-or-lose 'function)))
+ (:constructor %make-fun-type))
;; true if the arguments are unrestrictive, i.e. *
(wild-args nil :type boolean)
;; type describing the return values. This is a values type
;; when multiple values were specified for the return.
(returns (missing-arg) :type ctype))
+(defun make-fun-type (&rest initargs
+ &key (args nil argsp) returns &allow-other-keys)
+ (if argsp
+ (if (eq args '*)
+ (if (eq returns *wild-type*)
+ (specifier-type 'function)
+ (%make-fun-type :wild-args t :returns returns))
+ (multiple-value-bind (required optional rest keyp keywords allowp)
+ (args-types args)
+ (if (and (null required)
+ (null optional)
+ (eq rest *universal-type*)
+ (not keyp))
+ (if (eq returns *wild-type*)
+ (specifier-type 'function)
+ (%make-fun-type :wild-args t :returns returns))
+ (%make-fun-type :required required
+ :optional optional
+ :rest rest
+ :keyp keyp
+ :keywords keywords
+ :allowp allowp
+ :returns returns))))
+ ;; FIXME: are we really sure that we won't make something that
+ ;; looks like a completely wild function here?
+ (apply #'%make-fun-type initargs)))
;;; The CONSTANT-TYPE structure represents a use of the CONSTANT-ARG
;;; "type specifier", which is only meaningful in function argument
(declare (ignore type1 type2))
(specifier-type 'function))
+;;; The union or intersection of a subclass of FUNCTION with a
+;;; FUNCTION type is somewhat complicated.
+(!define-type-method (function :complex-intersection2) (type1 type2)
+ (cond
+ ((type= type1 (specifier-type 'function)) type2)
+ ((csubtypep type1 (specifier-type 'function)) nil)
+ (t :call-other-method)))
+(!define-type-method (function :complex-union2) (type1 type2)
+ (cond
+ ((type= type1 (specifier-type 'function)) type1)
+ (t nil)))
+
;;; ### Not very real, but good enough for redefining transforms
;;; according to type:
(!define-type-method (function :simple-=) (type1 type2)
(!def-type-translator constant-arg (type)
(make-constant-type :type (specifier-type type)))
-;;; Given a LAMBDA-LIST-like values type specification and an ARGS-TYPE
-;;; structure, fill in the slots in the structure accordingly. This is
-;;; used for both FUNCTION and VALUES types.
-(declaim (ftype (function (list args-type) (values)) parse-args-types))
-(defun parse-args-types (lambda-list result)
- (multiple-value-bind (required optional restp rest keyp keys allowp auxp aux)
- (parse-lambda-list-like-thing lambda-list)
- (declare (ignore aux)) ; since we require AUXP=NIL
- (when auxp
- (error "&AUX in a FUNCTION or VALUES type: ~S." lambda-list))
- (setf (args-type-required result)
- (mapcar #'single-value-specifier-type required))
- (setf (args-type-optional result)
- (mapcar #'single-value-specifier-type optional))
- (setf (args-type-rest result)
- (if restp (single-value-specifier-type rest) nil))
- (setf (args-type-keyp result) keyp)
- (collect ((key-info))
- (dolist (key keys)
- (unless (proper-list-of-length-p key 2)
- (error "Keyword type description is not a two-list: ~S." key))
- (let ((kwd (first key)))
- (when (find kwd (key-info) :key #'key-info-name)
- (error "~@<repeated keyword ~S in lambda list: ~2I~_~S~:>"
- kwd lambda-list))
- (key-info (make-key-info :name kwd
- :type (single-value-specifier-type (second key))))))
- (setf (args-type-keywords result) (key-info)))
- (setf (args-type-allowp result) allowp)
- (values)))
-
;;; Return the lambda-list-like type specification corresponding
;;; to an ARGS-TYPE.
(declaim (ftype (function (args-type) list) unparse-args-types))
(result)))
(!def-type-translator function (&optional (args '*) (result '*))
- (let ((res (make-fun-type :returns (values-specifier-type result))))
- (if (eq args '*)
- (setf (fun-type-wild-args res) t)
- (parse-args-types args res))
- res))
+ (make-fun-type :args args :returns (values-specifier-type result)))
(!def-type-translator values (&rest values)
- (let ((res (%make-values-type)))
- (parse-args-types values res)
- res))
+ (make-values-type :args values))
\f
;;;; VALUES types interfaces
;;;;
;;; type, return NIL, NIL.
(defun fun-type-nargs (type)
(declare (type ctype type))
- (if (fun-type-p type)
+ (if (and (fun-type-p type) (not (fun-type-wild-args type)))
(let ((fixed (length (args-type-required type))))
(if (or (args-type-rest type)
(args-type-keyp type)
(flet ((1way (x y)
(!invoke-type-method :simple-intersection2 :complex-intersection2
x y
- :default :no-type-method-found)))
+ :default :call-other-method)))
(declare (inline 1way))
(let ((xy (1way type1 type2)))
- (or (and (not (eql xy :no-type-method-found)) xy)
+ (or (and (not (eql xy :call-other-method)) xy)
(let ((yx (1way type2 type1)))
- (or (and (not (eql yx :no-type-method-found)) yx)
- (cond ((and (eql xy :no-type-method-found)
- (eql yx :no-type-method-found))
+ (or (and (not (eql yx :call-other-method)) yx)
+ (cond ((and (eql xy :call-other-method)
+ (eql yx :call-other-method))
*empty-type*)
(t
(aver (and (not xy) (not yx))) ; else handled above
;;; MAP is %MAP plus a check to make sure that any length specified in
;;; the result type matches the actual result. We also wrap it in a
;;; TRULY-THE for the most specific type we can determine.
-(deftransform map ((result-type-arg fun &rest seqs) * * :node node)
- (let* ((seq-names (make-gensym-list (length seqs)))
+(deftransform map ((result-type-arg fun seq &rest seqs) * * :node node)
+ (let* ((seq-names (make-gensym-list (1+ (length seqs))))
(bare `(%map result-type-arg fun ,@seq-names))
(constant-result-type-arg-p (constant-continuation-p result-type-arg))
;; what we know about the type of the result. (Note that the
;;; handle that case more efficiently, but it's left as an exercise to
;;; the reader, because the code is complicated enough already and I
;;; don't happen to need that functionality right now. -- WHN 20000410
-(deftransform %map ((result-type fun &rest seqs) * * :policy (>= speed space))
+(deftransform %map ((result-type fun seq &rest seqs) * *
+ :policy (>= speed space))
"open code"
- (unless seqs (abort-ir1-transform "no sequence args"))
(unless (constant-continuation-p result-type)
(give-up-ir1-transform "RESULT-TYPE argument not constant"))
(labels ( ;; 1-valued SUBTYPEP, fails unless second value of SUBTYPEP is true
(t
(give-up-ir1-transform
"can't determine result type")))))
- (cond ((and result-type-value (= 1 (length seqs)))
+ (cond ((and result-type-value (null seqs))
;; The consing arity-1 cases can be implemented
;; reasonably efficiently as function calls, and the cost
;; of consing should be significantly larger than
;; function call overhead, so we always compile these
;; cases as full calls regardless of speed-versus-space
;; optimization policy.
- (cond ((subtypep 'list result-type-value)
- '(apply #'%map-to-list-arity-1 fun seqs))
+ (cond ((subtypep result-type-value 'list)
+ '(%map-to-list-arity-1 fun seq))
( ;; (This one can be inefficient due to COERCE, but
;; the current open-coded implementation has the
;; same problem.)
(subtypep result-type-value 'vector)
- `(coerce (apply #'%map-to-simple-vector-arity-1 fun seqs)
+ `(coerce (%map-to-simple-vector-arity-1 fun seq)
',result-type-value))
(t (bug "impossible (?) sequence type"))))
(t
- (let* ((seq-args (make-gensym-list (length seqs))))
+ (let* ((seqs (cons seq seqs))
+ (seq-args (make-gensym-list (length seqs))))
(multiple-value-bind (push-dacc result)
(ecase result-supertype
(null (values nil nil))
(subtypep '(function)
'(function (t &rest t))))
'(nil t)))
-#+nil
(assert (and (subtypep 'function '(function))
(subtypep '(function) 'function)))
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8alpha.0.3"
+"0.8alpha.0.4"