X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fcondition.lisp;h=a1d40d5f6d42e915814104b6a20da133f1d91ff7;hb=7f1e94ae961a198e00daf281eb1dc858e5b2dcc7;hp=99d09951a5216753787b3c47b5616e39ee602fda;hpb=447788f1b408a8e9ec15ca822851dcd0bee52f82;p=sbcl.git diff --git a/src/code/condition.lisp b/src/code/condition.lisp index 99d0995..a1d40d5 100644 --- a/src/code/condition.lisp +++ b/src/code/condition.lisp @@ -31,8 +31,13 @@ (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) @@ -54,9 +59,6 @@ :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 @@ -66,12 +68,13 @@ (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))) @@ -173,21 +176,21 @@ (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) @@ -233,19 +236,15 @@ ;;;; 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 @@ -257,25 +256,39 @@ :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)) + ;;;; DEFINE-CONDITION @@ -351,7 +364,9 @@ (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)))) @@ -385,7 +400,7 @@ 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") @@ -394,9 +409,9 @@ (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) @@ -409,28 +424,29 @@ ;; 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*) @@ -462,7 +478,7 @@ (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)) @@ -518,10 +534,10 @@ :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) @@ -538,15 +554,9 @@ `#'(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))))) @@ -560,7 +570,7 @@ ',layout (list ,@(slots)) ,documentation - (list ,@default-initargs) + (list ,@direct-default-initargs) ',(all-readers) ',(all-writers) (sb!c:source-location)) @@ -616,7 +626,9 @@ (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)))) @@ -687,9 +699,10 @@ (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 @@ -912,7 +925,8 @@ (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) @@ -967,9 +981,9 @@ ((name :initarg :name :reader implicit-generic-function-name)) (:report (lambda (condition stream) - (let ((*package* (find-package :keyword))) - (format stream "~@" - (implicit-generic-function-name condition)))))) + (format stream "~@" + (implicit-generic-function-name condition))))) (define-condition extension-failure (reference-condition simple-error) ()) @@ -1042,8 +1056,11 @@ SB-EXT:PACKAGE-LOCKED-ERROR-SYMBOL.")) (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."))))) ;;;; various other (not specified by ANSI) CONDITIONs @@ -1383,13 +1400,14 @@ handled by any other handler, it will be muffled.") (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)