chiark / gitweb /
src/class-finalize-*.lisp: Improve finalization error reporting.
[sod] / src / class-finalize-proto.lisp
index 80d0c121ca184554d30d31213e5092f7995eb2d2..2f589b89ede92fee9706c048eed008985e7f9ccd 100644 (file)
 
 (cl:in-package #:sod)
 
+;;;--------------------------------------------------------------------------
+;;; Finalization error handling.
+
+;; These variables are internal to the implementation.
+(defvar-unbound *finalization-errors*
+  "A list of tokens for errors reported about the class being finalized.
+
+   During finalization, this is bound to a list of tokens corresponding to
+   the problems which have been reported so far via `finalization-error'.")
+(defvar-unbound *finalization-error-token*
+  "The token to store in `*finalization-errors*' in the event of an error.")
+
+(export 'finalization-error)
+(defmacro finalization-error ((token &rest args) &body body)
+  "Check for a kind of finalization error denoted by TOKEN and the ARGS.
+
+   The TOKEN and ARGS are convered into an error token as follows.  If no
+   ARGS are given, then the TOKEN itself is evaluated and used directly;
+   otherwise, the token is a list whose first element is the result of
+   evaluating TOKEN, and the remaining elements are the results of evaluating
+   the ARGS.  Error tokens are compared with `equal'.
+
+   If a finalization error denoted by this token has already been reported,
+   then do nothing: the BODY is not evaluated, and the result is nil.
+   Special exception: a nil token denotes a `generic' error which can be
+   repeated indefintely.
+
+   If the BODY signals an error (and doesn't handle it), then the error token
+   is added to a list of reported errors.  That way, future calls to
+   `finalization-error' with an equal error token won't cause the user to be
+   inundated with duplicate reports."
+  `(let ((*finalization-error-token* ,(if (null args) token
+                                         `(list ,token ,@args))))
+     ,@body))
+
+(export 'finalization-failed)
+(defun finalization-failed ()
+  "Give up on finalizing the current class."
+  (throw '%finalization-failed nil))
+
 ;;;--------------------------------------------------------------------------
 ;;; Protocol definition.
 
@@ -108,8 +148,14 @@ (defgeneric finalize-sod-class (class)
 
      * The layout chains are computed.
 
+   Returns a generalized boolean: non-nil if the class has been successfully
+   finalized -- either just now, or if it was finalized already and nothing
+   needed to be done -- or nil if finalization failed -- either just now, or
+   because the class had previously been marked as broken following a failed
+   finalization attempt.
+
    User methods can assume that the class in question has not yet been
-   finalized.  Errors during finalization can be reported in the usual
-   way."))
+   finalized.  Errors during finalization can be reported in the usual way.
+   See also `finalization-error' and `finalization-failed' above."))
 
 ;;;----- That's all, folks --------------------------------------------------