You can handle warnings, so that compilation terminates; while doing so, you can collect enough information to fix your code.
Tested with SBCL 1.3.13.
Handle warnings
I have warnings when using setf
with undefined variables. The following invokes the debugger, from which I can invoke muffle-warning
:
(handler-bind ((warning #'invoke-debugger))
(compile nil '(lambda () (setf *shame* :on-you))))
The warning is of type SIMPLE-WARNING
, which has the following accessors: SIMPLE-CONDITION-FORMAT-CONTROL
and SIMPLE-CONDITION-FORMAT-ARGUMENTS
.
(defparameter *setf-declarations* nil)
(defun handle-undefined-variables (condition)
(when (and (typep condition 'simple-warning)
(string= (simple-condition-format-control condition)
"undefined ~(~A~): ~S"))
(let* ((arguments (simple-condition-format-arguments condition))
(variable (and (eq (first arguments) :variable)
(second arguments))))
(when variable
(proclaim `(special ,variable))
(push variable *setf-declarations*)
(invoke-restart 'muffle-warning)))))
Use that as a handler:
(handler-bind ((warning #'handle-undefined-variables))
;; compilation, quickload, asdf ...
)
The above handler is not robust: the error message might change in future versions, the code assumes the arguments follow a given pattern, ... But this needs only work once, since from now on you are going to declare all your variables.
Fix your code
Now that your code compiles, get rid of the ugly. Or at least, add proper declarations.
(with-open-file (out #P"declarations.lisp" :direction :output)
(let ((*package* (find-package :cl-user)))
(format out
"(in-package :cl-user)~%~%~{(defvar ~(~S~))~%~}"
*setf-declarations*)))
This iterates over all the symbols you collected and write declarations inside a single file.
In my example, it would contain:
(in-package :cl-user)
(defvar *shame*)
Try to cleanly recompile without handling errors, by loading this file early in your compilation process, but after packages are defined. Eventually, you may want to find the time to move those declarations in place of the setf
expressions that triggered a warning.