(class-slots nil :type list)
;; report function or NIL
(report nil :type (or function null))
- ;; list of alternating initargs and initforms
- (default-initargs () :type list)
+ ;; list of specifications of the form
+ ;;
+ ;; (INITARG INITFORM THUNK)
+ ;;
+ ;; where THUNK, when called without arguments, returns the value for
+ ;; INITARG.
+ (direct-default-initargs () :type list)
;; class precedence list as a list of CLASS objects, with all
;; non-CONDITION classes removed
(cpl () :type list)
:metaclass-constructor make-condition-classoid
:dd-type structure)
-(defun make-condition-object (actual-initargs)
- (%make-condition-object actual-initargs nil))
-
(defstruct (condition-slot (:copier nil))
(name (missing-arg) :type symbol)
;; list of all applicable initargs
(writers (missing-arg) :type list)
;; true if :INITFORM was specified
(initform-p (missing-arg) :type (member t nil))
- ;; If this is a function, call it with no args. Otherwise, it's the
- ;; actual value.
- (initform (missing-arg) :type t)
+ ;; the initform if :INITFORM was specified, otherwise NIL
+ (initform nil :type t)
+ ;; if this is a function, call it with no args to get the initform value
+ (initfunction (missing-arg) :type t)
;; allocation of this slot, or NIL until defaulted
(allocation nil :type (member :instance :class nil))
- ;; If ALLOCATION is :CLASS, this is a cons whose car holds the value.
+ ;; If ALLOCATION is :CLASS, this is a cons whose car holds the value
(cell nil :type (or cons null))
;; slot documentation
(documentation nil :type (or string null)))
(defun find-slot-default (class slot)
(let ((initargs (condition-slot-initargs slot))
(cpl (condition-classoid-cpl class)))
+ ;; When CLASS or a superclass has a default initarg for SLOT, use
+ ;; that.
(dolist (class cpl)
- (let ((default-initargs (condition-classoid-default-initargs class)))
+ (let ((direct-default-initargs
+ (condition-classoid-direct-default-initargs class)))
(dolist (initarg initargs)
- (let ((val (getf default-initargs initarg *empty-condition-slot*)))
- (unless (eq val *empty-condition-slot*)
- (return-from find-slot-default
- (if (functionp val)
- (funcall val)
- val)))))))
+ (let ((initfunction (third (assoc initarg direct-default-initargs))))
+ (when initfunction
+ (return-from find-slot-default (funcall initfunction)))))))
+ ;; Otherwise use the initform of SLOT, if there is one.
(if (condition-slot-initform-p slot)
- (let ((initform (condition-slot-initform slot)))
- (if (functionp initform)
- (funcall initform)
- initform))
+ (let ((initfun (condition-slot-initfunction slot)))
+ (aver (functionp initfun))
+ (funcall initfun))
(error "unbound condition slot: ~S" (condition-slot-name slot)))))
(defun find-condition-class-slot (condition-class slot-name)
\f
;;;; MAKE-CONDITION
-(defun make-condition (type &rest args)
- #!+sb-doc
- "Make an instance of a condition object using the specified initargs."
- ;; Note: ANSI specifies no exceptional situations in this function.
- ;; signalling simple-type-error would not be wrong.
- (let* ((type (or (and (symbolp type) (find-classoid type nil))
- type))
+(defun allocate-condition (type &rest initargs)
+ (let* ((type (if (symbolp type)
+ (find-classoid type nil)
+ type))
(class (typecase type
(condition-classoid type)
(class
- ;; Punt to CLOS.
- (return-from make-condition
- (apply #'make-instance type args)))
+ (return-from allocate-condition
+ (apply #'allocate-condition (class-name type) initargs)))
(classoid
(error 'simple-type-error
:datum type
:datum type
:expected-type 'condition-class
:format-control
- "~s doesn't designate a condition class."
+ "~s does not designate a condition class."
:format-arguments (list type)))))
- (res (make-condition-object args)))
- (setf (%instance-layout res) (classoid-layout class))
+ (condition (%make-condition-object initargs '())))
+ (setf (%instance-layout condition) (classoid-layout class))
+ (values condition class)))
+
+(defun make-condition (type &rest initargs)
+ #!+sb-doc
+ "Make an instance of a condition object using the specified initargs."
+ ;; Note: ANSI specifies no exceptional situations in this function.
+ ;; signalling simple-type-error would not be wrong.
+ (multiple-value-bind (condition class)
+ (apply #'allocate-condition type initargs)
+
;; Set any class slots with initargs present in this call.
(dolist (cslot (condition-classoid-class-slots class))
(dolist (initarg (condition-slot-initargs cslot))
- (let ((val (getf args initarg *empty-condition-slot*)))
+ (let ((val (getf initargs initarg *empty-condition-slot*)))
(unless (eq val *empty-condition-slot*)
(setf (car (condition-slot-cell cslot)) val)))))
+
;; Default any slots with non-constant defaults now.
(dolist (hslot (condition-classoid-hairy-slots class))
(when (dolist (initarg (condition-slot-initargs hslot) t)
- (unless (eq (getf args initarg *empty-condition-slot*)
+ (unless (eq (getf initargs initarg *empty-condition-slot*)
*empty-condition-slot*)
(return nil)))
- (setf (getf (condition-assigned-slots res) (condition-slot-name hslot))
+ (setf (getf (condition-assigned-slots condition)
+ (condition-slot-name hslot))
(find-slot-default class hslot))))
- res))
+
+ condition))
+
\f
;;;; DEFINE-CONDITION
(setf (condition-slot-initform-p found)
(condition-slot-initform-p sslot))
(setf (condition-slot-initform found)
- (condition-slot-initform sslot)))
+ (condition-slot-initform sslot))
+ (setf (condition-slot-initfunction sslot)
+ (condition-slot-initfunction found)))
(unless (condition-slot-allocation found)
(setf (condition-slot-allocation found)
(condition-slot-allocation sslot))))
report))
(defun %define-condition (name parent-types layout slots documentation
- default-initargs all-readers all-writers
+ direct-default-initargs all-readers all-writers
source-location)
(with-single-package-locked-error
(:symbol name "defining ~A as a condition")
(setf (layout-source-location layout)
source-location))
(let ((class (find-classoid name)))
- (setf (condition-classoid-slots class) slots)
- (setf (condition-classoid-default-initargs class) default-initargs)
- (setf (fdocumentation name 'type) documentation)
+ (setf (condition-classoid-slots class) slots
+ (condition-classoid-direct-default-initargs class) direct-default-initargs
+ (fdocumentation name 'type) documentation)
(dolist (slot slots)
;; Compute effective slots and set up the class and hairy slots
;; (subsets of the effective slots.)
+ (setf (condition-classoid-hairy-slots class) '())
(let ((eslots (compute-effective-slots class))
(e-def-initargs
(reduce #'append
- (mapcar #'condition-classoid-default-initargs
- (condition-classoid-cpl class)))))
+ (mapcar #'condition-classoid-direct-default-initargs
+ (condition-classoid-cpl class)))))
(dolist (slot eslots)
(ecase (condition-slot-allocation slot)
(:class
(unless (condition-slot-cell slot)
(setf (condition-slot-cell slot)
(list (if (condition-slot-initform-p slot)
- (let ((initform (condition-slot-initform slot)))
- (if (functionp initform)
- (funcall initform)
- initform))
+ (let ((initfun (condition-slot-initfunction slot)))
+ (aver (functionp initfun))
+ (funcall initfun))
*empty-condition-slot*))))
(push slot (condition-classoid-class-slots class)))
((:instance nil)
(setf (condition-slot-allocation slot) :instance)
- (when (or (functionp (condition-slot-initform slot))
+ ;; FIXME: isn't this "always hairy"?
+ (when (or (functionp (condition-slot-initfunction slot))
(dolist (initarg (condition-slot-initargs slot) nil)
- (when (functionp (getf e-def-initargs initarg))
+ (when (functionp (third (assoc initarg e-def-initargs)))
(return t))))
(push slot (condition-classoid-hairy-slots class)))))))
(when (boundp '*define-condition-hooks*)
(layout (find-condition-layout name parent-types))
(documentation nil)
(report nil)
- (default-initargs ()))
+ (direct-default-initargs ()))
(collect ((slots)
(all-readers nil append)
(all-writers nil append))
:writers ',(writers)
:initform-p ',initform-p
:documentation ',documentation
- :initform
- ,(if (sb!xc:constantp initform)
- `',(constant-form-value initform)
- `#'(lambda () ,initform)))))))
+ :initform ,(when initform-p `',initform)
+ :initfunction ,(when initform-p
+ `#'(lambda () ,initform))
+ :allocation ',allocation)))))
(dolist (option options)
(unless (consp option)
`#'(lambda (condition stream)
(funcall #',arg condition stream))))))
(:default-initargs
- (do ((initargs (rest option) (cddr initargs)))
- ((endp initargs))
- (let ((val (second initargs)))
- (setq default-initargs
- (list* `',(first initargs)
- (if (sb!xc:constantp val)
- `',(constant-form-value val)
- `#'(lambda () ,val))
- default-initargs)))))
+ (doplist (initarg initform) (rest option)
+ (push ``(,',initarg ,',initform ,#'(lambda () ,initform))
+ direct-default-initargs)))
(t
(error "unknown option: ~S" (first option)))))
',layout
(list ,@(slots))
,documentation
- (list ,@default-initargs)
+ (list ,@direct-default-initargs)
',(all-readers)
',(all-writers)
(sb!c:source-location))
(type-error-expected-type condition)))))
(def!method print-object ((condition type-error) stream)
- (if *print-escape*
+ (if (and *print-escape*
+ (slot-boundp condition 'expected-type)
+ (slot-boundp condition 'datum))
(flet ((maybe-string (thing)
(ignore-errors
(write-to-string thing :lines 1 :readably nil :array nil :pretty t))))
(define-condition undefined-function (cell-error) ()
(:report
(lambda (condition stream)
- (format stream
- "The function ~/sb-impl::print-symbol-with-prefix/ is undefined."
- (cell-error-name condition)))))
+ (let ((*package* (find-package :keyword)))
+ (format stream
+ "The function ~S is undefined."
+ (cell-error-name condition))))))
(define-condition special-form-function (undefined-function) ()
(:report
(define-condition package-at-variance (reference-condition simple-warning)
()
- (:default-initargs :references (list '(:ansi-cl :macro defpackage))))
+ (:default-initargs :references (list '(:ansi-cl :macro defpackage)
+ '(:sbcl :variable *on-package-variance*))))
(define-condition package-at-variance-error (reference-condition simple-condition
package-error)
((name :initarg :name :reader implicit-generic-function-name))
(:report
(lambda (condition stream)
- (let ((*package* (find-package :keyword)))
- (format stream "~@<Implicitly creating new generic function ~S.~:@>"
- (implicit-generic-function-name condition))))))
+ (format stream "~@<Implicitly creating new generic function ~
+ ~/sb-impl::print-symbol-with-prefix/.~:@>"
+ (implicit-generic-function-name condition)))))
(define-condition extension-failure (reference-condition simple-error)
())
(define-condition undefined-alien-function-error (undefined-alien-error) ()
(:report
(lambda (condition stream)
- (declare (ignore condition))
- (format stream "Attempt to call an undefined alien function."))))
+ (if (and (slot-boundp condition 'name)
+ (cell-error-name condition))
+ (format stream "The alien function ~s is undefined."
+ (cell-error-name condition))
+ (format stream "Attempt to call an undefined alien function.")))))
\f
;;;; various other (not specified by ANSI) CONDITIONs
(let ((new (function-redefinition-warning-new-function warning))
(source-location (redefinition-warning-new-location warning)))
(or
- ;; Compiled->Interpreted is interesting.
+ ;; compiled->interpreted is interesting.
(and (typep old 'compiled-function)
(typep new '(not compiled-function)))
- ;; FIN->Regular is interesting.
- (and (typep old 'funcallable-instance)
+ ;; fin->regular is interesting except for interpreted->compiled.
+ (and (typep old '(and funcallable-instance
+ #!+sb-eval (not sb!eval:interpreted-function)))
(typep new '(not funcallable-instance)))
- ;; Different file or unknown location is interesting.
+ ;; different file or unknown location is interesting.
(let* ((old-namestring (function-file-namestring old))
(new-namestring
(or (function-file-namestring new)