X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fcondition.lisp;h=c1dc599c132c9af0c97685fe2529098d71e042cf;hb=9bdd2579f980573a74daabe03120ed64b1733b11;hp=a9527504e56e928c074bdd417b53399fd7477026;hpb=a1a34a500b880ab761291350300d8d3184574183;p=sbcl.git diff --git a/src/code/condition.lisp b/src/code/condition.lisp index a952750..c1dc599 100644 --- a/src/code/condition.lisp +++ b/src/code/condition.lisp @@ -13,26 +13,6 @@ (in-package "SB!KERNEL") -;;;; miscellaneous support utilities - -;;; Signalling an error when trying to print an error condition is -;;; generally a PITA, so whatever the failure encountered when -;;; wondering about FILE-POSITION within a condition printer, 'tis -;;; better silently to give up than to try to complain. -(defun file-position-or-nil-for-error (stream &optional (pos nil posp)) - ;; Arguably FILE-POSITION shouldn't be signalling errors at all; but - ;; "NIL if this cannot be determined" in the ANSI spec doesn't seem - ;; absolutely unambiguously to prohibit errors when, e.g., STREAM - ;; has been closed so that FILE-POSITION is a nonsense question. So - ;; my (WHN) impression is that the conservative approach is to - ;; IGNORE-ERRORS. (I encountered this failure from within a homebrew - ;; defsystemish operation where the ERROR-STREAM had been CL:CLOSEd, - ;; I think by nonlocally exiting through a WITH-OPEN-FILE, by the - ;; time an error was reported.) - (if posp - (ignore-errors (file-position stream pos)) - (ignore-errors (file-position stream)))) - ;;;; the CONDITION class (/show0 "condition.lisp 20") @@ -51,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) @@ -193,16 +178,17 @@ (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) @@ -264,7 +250,8 @@ (condition-classoid type) (class ;; Punt to CLOS. - (return-from make-condition (apply #'make-instance type args))) + (return-from make-condition + (apply #'make-instance type args))) (classoid (error 'simple-type-error :datum type @@ -275,7 +262,8 @@ (error 'simple-type-error :datum type :expected-type 'condition-class - :format-control "Bad type argument:~% ~S" + :format-control + "~s does not designate a condition class." :format-arguments (list type))))) (res (make-condition-object args))) (setf (%instance-layout res) (classoid-layout class)) @@ -398,8 +386,12 @@ (defvar *define-condition-hooks* nil) +(defun %set-condition-report (name report) + (setf (condition-classoid-report (find-classoid name)) + report)) + (defun %define-condition (name parent-types layout slots documentation - report 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") @@ -408,10 +400,9 @@ (setf (layout-source-location layout) source-location)) (let ((class (find-classoid name))) - (setf (condition-classoid-slots class) slots) - (setf (condition-classoid-report class) report) - (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) @@ -427,8 +418,8 @@ (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 @@ -445,7 +436,7 @@ (setf (condition-slot-allocation slot) :instance) (when (or (functionp (condition-slot-initform 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*) @@ -477,7 +468,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)) @@ -533,10 +524,8 @@ :writers ',(writers) :initform-p ',initform-p :documentation ',documentation - :initform - ,(if (sb!xc:constantp initform) - `',(constant-form-value initform) - `#'(lambda () ,initform))))))) + :initform ,(when initform-p + `#'(lambda () ,initform))))))) (dolist (option options) (unless (consp option) @@ -548,20 +537,14 @@ (setq report (if (stringp arg) `#'(lambda (condition stream) - (declare (ignore condition)) - (write-string ,arg stream)) + (declare (ignore condition)) + (write-string ,arg stream)) `#'(lambda (condition stream) - (funcall #',arg 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))))) @@ -575,11 +558,16 @@ ',layout (list ,@(slots)) ,documentation - ,report - (list ,@default-initargs) + (list ,@direct-default-initargs) ',(all-readers) ',(all-writers) - (sb!c:source-location))))))) + (sb!c:source-location)) + ;; This needs to be after %DEFINE-CONDITION in case :REPORT + ;; is a lambda referring to condition slot accessors: + ;; they're not proclaimed as functions before it has run if + ;; we're under EVAL or loaded as source. + (%set-condition-report ',name ,report) + ',name))))) ;;;; various CONDITIONs specified by ANSI @@ -763,45 +751,17 @@ ;;; ;;; When SIMPLE, we expect and use SIMPLE-CONDITION-ish FORMAT-CONTROL ;;; and FORMAT-ARGS slots. -(defun %report-reader-error (condition stream &key simple) - (let* ((error-stream (stream-error-stream condition)) - (pos (file-position-or-nil-for-error error-stream))) - (let (lineno colno) - (when (and pos - (< pos sb!xc:array-dimension-limit) - ;; KLUDGE: lseek() (which is what FILE-POSITION - ;; reduces to on file-streams) is undefined on - ;; "some devices", which in practice means that it - ;; can claim to succeed on /dev/stdin on Darwin - ;; and Solaris. This is obviously bad news, - ;; because the READ-SEQUENCE below will then - ;; block, not complete, and the report will never - ;; be printed. As a workaround, we exclude - ;; interactive streams from this attempt to report - ;; positions. -- CSR, 2003-08-21 - (not (interactive-stream-p error-stream)) - (file-position error-stream :start)) - (let ((string - (make-string pos - :element-type (stream-element-type - error-stream)))) - (when (= pos (read-sequence string error-stream)) - (setq lineno (1+ (count #\Newline string)) - colno (- pos - (or (position #\Newline string :from-end t) -1) - 1)))) - (file-position-or-nil-for-error error-stream pos)) - (pprint-logical-block (stream nil) - (format stream - "~S ~@[at ~W ~]~ - ~@[(line ~W~]~@[, column ~W) ~]~ - on ~S" - (class-name (class-of condition)) - pos lineno colno error-stream) - (when simple - (format stream ":~2I~_~?" - (simple-condition-format-control condition) - (simple-condition-format-arguments condition))))))) +(defun %report-reader-error (condition stream &key simple position) + (let ((error-stream (stream-error-stream condition))) + (pprint-logical-block (stream nil) + (if simple + (apply #'format stream + (simple-condition-format-control condition) + (simple-condition-format-arguments condition)) + (prin1 (class-name (class-of condition)) stream)) + (format stream "~2I~@[~_~_~:{~:(~A~): ~S~:^, ~:_~}~]~_~_Stream: ~S" + (stream-error-position-info error-stream position) + error-stream)))) ;;;; special SBCL extension conditions @@ -950,6 +910,12 @@ (define-condition package-at-variance (reference-condition simple-warning) () + (: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) + () (:default-initargs :references (list '(:ansi-cl :macro defpackage)))) (define-condition defconstant-uneql (reference-condition error) @@ -1000,8 +966,9 @@ ((name :initarg :name :reader implicit-generic-function-name)) (:report (lambda (condition stream) - (format stream "~@" - (implicit-generic-function-name condition))))) + (let ((*package* (find-package :keyword))) + (format stream "~@" + (implicit-generic-function-name condition)))))) (define-condition extension-failure (reference-condition simple-error) ()) @@ -1204,7 +1171,7 @@ SB-EXT:PACKAGE-LOCKED-ERROR-SYMBOL.")) (define-condition simple-package-error (simple-condition package-error) ()) -(define-condition simple-reader-package-error (simple-reader-error) ()) +(define-condition simple-reader-package-error (simple-reader-error package-error) ()) (define-condition reader-eof-error (end-of-file) ((context :reader reader-eof-error-context :initarg :context)) @@ -1610,7 +1577,7 @@ the usual naming convention (names like *FOO*) for special variables" (define-condition deprecation-condition () ((name :initarg :name :reader deprecated-name) - (replacement :initarg :replacement :reader deprecated-name-replacement) + (replacements :initarg :replacements :reader deprecated-name-replacements) (since :initarg :since :reader deprecated-since) (runtime-error :initarg :runtime-error :reader deprecated-name-runtime-error))) @@ -1618,14 +1585,21 @@ the usual naming convention (names like *FOO*) for special variables" (let ((*package* (find-package :keyword))) (if *print-escape* (print-unreadable-object (condition stream :type t) - (format stream "~S is deprecated~@[, use ~S~]" + (apply #'format + stream "~S is deprecated.~ + ~#[~; Use ~S instead.~; ~ + Use ~S or ~S instead.~:; ~ + Use~@{~#[~; or~] ~S~^,~} instead.~]" (deprecated-name condition) - (deprecated-name-replacement condition))) - (format stream "~@<~S has been deprecated as of SBCL ~A~ - ~@[, use ~S instead~].~:@>" + (deprecated-name-replacements condition))) + (apply #'format + stream "~@<~S has been deprecated as of SBCL ~A.~ + ~#[~; Use ~S instead.~; ~ + Use ~S or ~S instead.~:; ~ + Use~@{~#[~; or~] ~S~^,~:_~} instead.~]~:@>" (deprecated-name condition) (deprecated-since condition) - (deprecated-name-replacement condition))))) + (deprecated-name-replacements condition))))) (define-condition early-deprecation-warning (style-warning deprecation-condition) ()) @@ -1695,11 +1669,14 @@ the usual naming convention (names like *FOO*) for special variables" (define-nil-returning-restart continue () "Transfer control to a restart named CONTINUE, or return NIL if none exists.") (define-nil-returning-restart store-value (value) - "Transfer control and VALUE to a restart named STORE-VALUE, or return NIL if - none exists.") + "Transfer control and VALUE to a restart named STORE-VALUE, or +return NIL if none exists.") (define-nil-returning-restart use-value (value) - "Transfer control and VALUE to a restart named USE-VALUE, or return NIL if - none exists.")) + "Transfer control and VALUE to a restart named USE-VALUE, or +return NIL if none exists.") + (define-nil-returning-restart print-unreadably () + "Transfer control to a restart named SB-EXT:PRINT-UNREADABLY, or +return NIL if none exists.")) ;;; single-stepping restarts @@ -1722,5 +1699,14 @@ not exists.") condition, stepping into the current form. Signals a CONTROL-ERROR is the restart does not exist.")) -(/show0 "condition.lisp end of file") +;;; Compiler macro magic + +(define-condition compiler-macro-keyword-problem () + ((argument :initarg :argument :reader compiler-macro-keyword-argument)) + (:report (lambda (condition stream) + (format stream "~@" + (compiler-macro-keyword-argument condition))))) +(/show0 "condition.lisp end of file")