(defclass around-load-op-mixin () ()
(:documentation "
Mixin to be able to do some actions around load-op"))
;;; !!! Redefining asdf class!
(defclass cl-source-file (around-load-op-mixin source-file) ())
(defmethod perform :around
((o operation) (c around-load-op-mixin))
(let ((*readtable* (copy-readtable nil)))
(call-next-method)
))
So, readtable is bound to a fresh copy of standard readtable
around any asdf operation on cl-source file. It looks like it
works, but it is too early to say. I could (and I think I will)
make my new class instead. E.g.
(defclass f (around-load-op-mixin cl-source-file) ())
So, I can do any changes to a readtable in any file and
I won't harm subsequent files. If I want that subsequent files
were affected by readtable change, I have to add one form
to any such file. E.g. I can write file readtable.lisp which
defines new readtable and stores it to global variable.
Any file which wants to use that readtable should have
a form like
(eval-when (:compile-toplevel :load-toplevel :execute)
(setf *readtable* (copy-readtable <my-variable>)))
Second thing we need is a way to read a form with
*readtable* bound. There is another rather trivial
fix. CL fails to supply an input stream to a form being
eval-read, so it should be fixed.
(defvar *read-eval-stream*
"Something's wrong with #.? "
"Bound to current input stream in the scope of #. ")
(defun sbcl-sharp-dot (stream sub-char numarg)
"code borrowed from sbcl"
(declare (ignore sub-char numarg))
(let ((token (read stream t nil t))
(*read-eval-stream* stream))
(unless *read-suppress*
(unless *read-eval*
(error
"can't read #. from ~S while *READ-EVAL* is NIL"
stream)))
(prog1
(eval token)
))
)
(set-dispatch-macro-char #\# #\. #'sbcl-sharp-dot)
So I can write (with the help of "named-readtables"):
(defreadtable foo (:merge)
(:macro-char #\$
(lambda (&rest ignore)
(declare (ignore ignore))
(print "Ypa!"))))
(defmacro &wrt ()
(let1 *readtable*
(find-readtable (read *read-eval-stream*))
(read *read-eval-stream* t nil t)))
(read-from-string "#.(&wrt foo) $")
"Ypa!"
"Ypa!"
14
What is posted here is a solution already, provided that you
download semi-portable named-readtable by
Tobias C. Rittweiler.
I think more reasonable would be to bind some macro-characters
instead of binding readtable itself. Something like
#.(&with-macro-char #\$ 'some-function) $
But I didn't implement it.
What I ask for is a prior art.
I didn't see anything alike, but I can't say I have read all CL
sources
available to the public :)