-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change DEFINE-CONDITION: signals a TYPE-ERROR if trying to supertype a non-CONDITION #11
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,17 +47,44 @@ PRINT-OBJECT method defined on the class named by NAME." | |
`(let ((,method (find-method #'print-object '() '(,name t) nil))) | ||
(when ,method (remove-method #'print-object ,method))))) | ||
|
||
(defvar *in-define-condition-p* nil | ||
"This will be dynamically binded to indicate an entry into DEFINE-CONDITION, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/binded/bound/ |
||
to distinguish its DEFCLASS from an external DEFCLASS.") | ||
|
||
(defmethod ensure-class-using-class :before (class name &rest args &key direct-superclasses &allow-other-keys) | ||
"In DEFINE-CONDITION: Signals a TYPE-ERROR at the first direct superclass unconforming | ||
with DEFINE-CONDITION, that is, the first encountered superclass in DIRECT-SUPERCLASSES | ||
that is not a subtype of CONDITION. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...subclass of CONDITION |
||
In DEFCLASSes external to DEFINE-CONDITION: Signals an INVALID-SUPERCLASS at the first | ||
encountered superclass that is subtype of CONDITION." | ||
(declare (ignore args)) | ||
(if *in-define-condition-p* | ||
(loop :for superclass :in direct-superclasses | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe switch out the LOOPs for DOLISTs? Just a style thing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure |
||
:do (when (not (subtypep superclass 'condition)) | ||
(error 'type-error | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am kind of interested in the topic of dogfooding ourselves with this one. We will be using |
||
:datum superclass | ||
:expected-type 'condition))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This error is wrong - such a TYPE-ERROR would mean that the superclass is not of type CONDITION, whereas here the error should say that the superclass is not a subtype of CONDITION. Hence, I think that you should go for signaling INVALID-SUPERCLASS in here too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✔️ |
||
(loop :for superclass :in direct-superclasses | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto. |
||
:do (when (subtypep superclass 'condition) | ||
(error 'invalid-superclass | ||
:class name | ||
:superclass superclass | ||
:reason (format nil "Only ~S should~% define a subtype of ~S" | ||
'define-condition 'condition)))))) | ||
|
||
(defun expand-define-condition (name supertypes direct-slots options) | ||
"Defines a new condition type via DEFCLASS, handling the :REPORT options via | ||
defining a PRINT-object method on the newly created class." | ||
(let* ((report-option (find :report options :key #'car)) | ||
(other-options (remove report-option options)) | ||
(supertypes (or supertypes '(condition)))) | ||
`(progn (defclass ,name ,supertypes ,direct-slots ,@other-options) | ||
,@(if report-option | ||
`(,(expand-define-condition-report-method name report-option)) | ||
`(,(expand-define-condition-remove-report-method name))) | ||
',name))) | ||
`(progn | ||
(let ((*in-define-condition-p* t)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This solution creates some new problems. The main issue of having a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure its a good idea, but an alternative I see would be to add a dummy class to |
||
(defclass ,name ,supertypes ,direct-slots ,@other-options)) | ||
,@(if report-option | ||
`(,(expand-define-condition-report-method name report-option)) | ||
`(,(expand-define-condition-remove-report-method name))) | ||
',name))) | ||
|
||
(defmacro define-condition (name (&rest supertypes) direct-slots &rest options) | ||
"Defines or redefines a condition type." | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -579,6 +579,41 @@ | |
(notnot-mv (typep #'condition-27/s1 'generic-function)) | ||
t) | ||
|
||
;;; Test non-CONDITION supertypes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you move this whole section to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✔️ |
||
|
||
(defclass not-a-condition-1 nil nil) | ||
(defclass not-a-condition-2 nil nil) | ||
|
||
(deftest condition-with-non-condition-supertype-1.1 | ||
(signals-type-error not-a-condition 'not-a-condition-1 | ||
(define-condition condition-with-non-condition-supertype-1a (not-a-condition-1) | ||
() | ||
(:report "condition-with-non-condition-supertype-1a"))) | ||
t) | ||
|
||
(define-condition-with-tests condition-28a nil nil) | ||
(define-condition-with-tests condition-28b nil nil) | ||
|
||
(deftest condition-with-non-condition-supertype-1.2 | ||
(signals-type-error not-a-condition 'not-a-condition-1 | ||
(define-condition condition-with-non-condition-supertype-1b (condition-28a | ||
not-a-condition-1 | ||
condition-28b) | ||
() | ||
(:report "condition-with-non-condition-sypertype-1b"))) | ||
t) | ||
|
||
(deftest condition-with-non-condition-supertype-1.3 | ||
(signals-type-error not-a-condition 'not-a-condition-2 | ||
(define-condition condition-with-non-condition-supertype-1c (condition-28b | ||
not-a-condition-2 | ||
not-a-condition-1) | ||
() | ||
(:report "condition-with-non-condition-supertype-1c"))) | ||
t) | ||
|
||
;;; | ||
|
||
;;; Documentation | ||
|
||
;;; Pitman says this should have been in the spec, but it isn't really | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
;;;; t/more-tests.lisp | ||
|
||
(in-package #:portable-condition-system/test) | ||
|
||
;;; Test superclassing a CONDITION in DEFCLASS | ||
|
||
(defclass not-a-condition-0 nil nil) | ||
|
||
(define-condition-with-tests condition-in-super-1a nil nil) | ||
(define-condition-with-tests condition-in-super-1b nil nil) | ||
|
||
(deftest condition-in-defclass-superclass-1.1 | ||
(signals-error (defclass condition-in-defclass-superclass-1a (condition-in-super-1a) | ||
()) | ||
portable-condition-system::invalid-superclass) | ||
t) | ||
|
||
(deftest condition-in-defclass-superclass-1.2 | ||
(signals-error (defclass condition-in-defclass-superclass-1b (not-a-condition-0 | ||
condition-in-super-1b | ||
condition-in-super-1a) | ||
()) | ||
portable-condition-system::invalid-superclass) | ||
t) | ||
|
||
;;; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an obvious ERROR rather than a CONDITION.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️