3

Crew,

I'm one of those types that insists on defining my variables with SETF. I've upgraded to a new machine (and a new version of SBCL) and it's not letting me get away with doing that (naturally, I get the appropriate "==> undefined variable..." error)

My problem here is, I've already written 20,000 lines of code (incorrectly) defining my variables with SETF and i don't like the prospect of re-writing all of my code to get the interpreter to digest it all.

Is there a way to shut down that error such that interpretation can continue?

Any help is appreciated.

Sincerely,

-Todd

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
Todd Pierce
  • 161
  • 7
  • you used `setf` instead of `let`, `defparameter` or both? – rsm Jan 20 '18 at 20:49
  • In Common Lisp variables are not defined with SETF. Best change your code. – Rainer Joswig Jan 21 '18 at 22:24
  • 1
    `M-x query-replace-regexp ^(set[qf] \([^ ]*\) \(.*\))$ RET (defparameter \1 \2) RET` then go one at a time, making sure you manually (e.g. recursive edit) anything that spans multiple lines. This only works for top level definitions. If you have been using “setf to define variables” for local variables then I can only suggest that you port your program to a language like BASIC or something else more suited to this style of programming. – Dan Robertson Jan 21 '18 at 22:42
  • Isn't that a warning? – coredump Jan 22 '18 at 15:18

2 Answers2

2

One option is to set up your package environment so that a bare symbol setf refers to my-gross-hack::setf instead of cl:setf. For example, you could set things up like:

(defpackage #:my-gross-hack
  (:use #:cl)
  (:shadow #:setf))

;;; define your own setf here

(defpackage #:my-project
  (use #:cl)
  (shadowing-import-from #:my-gross-hack #:setf))

;;; proceed to use setf willy-nilly
Xach
  • 11,774
  • 37
  • 38
1

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.

coredump
  • 37,664
  • 5
  • 43
  • 77