With raw CMUCL, I am able to do the following:
* (in-package #:pg-user)
#<The PLAYGROUND-USER package, 0/9 internal, 0/2 external>
* (in-syntax-kick-reader-macros)
* !$(
ls
-F
)
; [... snip for brevity ...]
#<process 523 :EXITED>
*
However, when I attempt the same thing in a SLIME REPL, I encounter the
following blah stack:
End-of-File on #<String-Input Stream>
[Condition of type END-OF-FILE]
Restarts:
0: [ABORT] Abort handling SLIME request.
1: [ABORT] Return to Top-Level.
Backtrace:
0: (LISP::STRING-INCH #<String-Input Stream> T NIL)
1: (LISP::FLUSH-WHITESPACE #<String-Input Stream>)
2: (LISP::READ-LIST #<String-Input Stream> #<unused-arg>)
3: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL #<String-Input Stream> T NIL T)
4: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL 4 #<String-Input Stream> T
NIL ...)[:EXTERNAL]
5: (LISP::READ-INTERNAL #<String-Input Stream> T NIL T)
6: (READ #<String-Input Stream> T NIL T)
7: (LISP::BACKQUOTE-MACRO #<String-Input Stream> #<unused-arg>)
8: (|!` READER| #<String-Input Stream> #<#1=unused-arg> #<#1#>)
9: (|!$ READER| #<String-Input Stream> #<unused-arg> NIL)
10: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL #1=#<String-Input Stream> NIL
#1# T)
11: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL #1=#<String-Input Stream> NIL
#1# NIL)
12: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL 4 #1=#<String-Input Stream>
NIL #1# ...)[:EXTERNAL]
13: (LISP::READ-INTERNAL #1=#<String-Input Stream> NIL #1# NIL)
14: (READ #1=#<String-Input Stream> NIL #1# NIL)
--more--
FWIW, here are the offending reader macros and relavent code, though I haven't
included the code from _On Lisp_, e.g. AWHEN, AIF, etc.
(defmacro in-syntax-kick-reader-macros ()
`(eval-when (:compile-toplevel :load-toplevel :execute)
(setq *readtable* (copy-readtable nil))
(make-dispatch-macro-character #\!)
(set-dispatch-macro-character #\! #\( #'|!( READER|)
(set-dispatch-macro-character #\! #\' #'|!' READER|)
(set-dispatch-macro-character #\! #\` #'|!` READER|)
(set-dispatch-macro-character #\! #\$ #'|!$ READER|)
(values)))
(defun |!( READER| (stream char n-arg)
(declare (ignore char n-arg))
(let ((*readtable* (copy-readtable *readtable*)))
(setf (readtable-case *readtable*) :preserve)
#-(and)(read-delimited-list #\) stream t)
(funcall (get-macro-character #\() stream #\()))
(defun |!' READER| (stream char n-arg)
(declare (ignore char n-arg))
(let ((*readtable* (copy-readtable *readtable*)))
(setf (readtable-case *readtable*) :preserve)
(funcall (get-macro-character #\') stream #\')))
(defun |!` READER| (stream char n-arg)
(declare (ignore char n-arg))
(let ((*readtable* (copy-readtable *readtable*)))
(setf (readtable-case *readtable*) :preserve)
(funcall (get-macro-character #\`) stream #\`)))
(defun |!$ READER| (stream char n-arg)
(declare (ignore char))
`(sh ,(|!` READER| stream #\` n-arg)))