[Ecls-list] Get the line number where a condition occurs when load-ing a source Lisp file

Juan Jose Garcia-Ripoll juanjose.garciaripoll at googlemail.com
Thu Jun 7 15:22:35 UTC 2012

On Wed, Jun 6, 2012 at 11:03 PM, Antonio Bonifati <
antonio.bonifati at gmail.com> wrote:

> My code is just doing a (load "userfile.lisp") inside a handler-case that
> prints any condition that may happen. As I said I would like to complement
> that error string with a line number so the user knows which line the error
> is and can jump directly to it with his editor. User files are not
> compiled, I load them as source code at runtime. This is perfectly
> acceptable in this application because they need to be  run only once after
> each modification in order to regenerate the static HTML code (e.g. I run
> index.lisp to generate index.html). It isn't worth to compile something
> that you only have to run one time :)

Actually I would claim that this is not an embedding problem, but a Lisp
one. You want to get some information at the file position of the form
which caused the error. This is not attached to a condition because
conditions happen independently of whether the form evaluated was
interpreted, compiled or part of a function that is already installed in
the Lisp image. In other words, it is up to you to know the position of the
file which is being read and do some wrapping that adds the information.

ECL helps you by defining a variable ext::*source-location* when LOAD is
used on a source file. This variable contains a CONS that should NEVER be
changed or stored by the user, but you can get the file as (CAR
EXT:*SOURCE-LOCATION*) and the file position as (CDR
EXT:*SOURCE-LOCATION*). The plan is then to embed your LOAD form inside a

(defparameter *error-message* nil)
(defparameter *error-tag* (cons))

(defun capture-error (condition)
   (setf *error*
      (format nil "At character ~S in file ~S an error was found:~%~A"
         (cdr ext:*source-location*)
         (car ext:*source-location*)
  (throw *error-tag* *error-message*))

(defun safely-load (file)
  (handler-bind ((serious-condition #'capture-error))
     (catch *error-tag*
        (load file)

(SAFELY-LOAD "myfile.lisp") will return either NIL or the formatted error.

In any case I strongly believe that relying on LOAD for this is doomed to
fail. You should create your own version of LOAD, starting from this

(defun my-load (userfile)
  (with-open-file (stream userfile :direction :input :external-format
     (loop for form = (read stream nil nil nil)
        while form
        do (eval-form-with-error-catching form))))

where EVAL-FORM-.... implements something like the code above.


Instituto de Física Fundamental, CSIC
c/ Serrano, 113b, Madrid 28006 (Spain)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/ecl-devel/attachments/20120607/71e94d78/attachment.html>

More information about the ecl-devel mailing list