Geoff Wozniak
2007-08-08 22:31:54 UTC
I've been working with compiler macros lately and I noticed something
odd with how Allegro CL 8.x handles compiler macros for SETF
functions. I want to make sure I didn't miss something here, because
I can't find anything in the documentation (Allegro CL or otherwise)
about it.
And before proceeding, I am well aware that compiler macros do not
need to be expanded as per the HyperSpec (see 3.2.2.1.3), so the
following seems to be legal, but odd nevertheless.
Here's the basic set up (shamelessly based on something from Nikodemus
Siivola).
;; File A
(defvar *foo* (make-array 32))
(defun (setf foo) (value index symbol)
(setf (getf (svref *foo* index) symbol) value))
(define-compiler-macro (setf foo) (&whole form value index symbol)
(declare (ignore value index symbol))
(format *debug-io* "~&(SETF FOO) form is: ~S~%" form)
form)
(defun another-foo (x) (+ x x))
(define-compiler-macro another-foo (&whole form x)
(declare (ignore x))
(format *debug-io* "~&ANOTHER-FOO form is: ~S~%" form)
form)
;;; File B
(defun example ()
(setf (foo 10 'bar) 'baz)
(another-foo 10))
It works as follows under SBCL.
CL-USER> (values (lisp-implementation-type) (lisp-implementation-
version))
"SBCL"
"1.0.8.12"
CL-USER> (load (compile-file "fileA"))
;;; Etc.
CL-USER> (load (compile-file "fileB"))
;;; Etc.
(SETF FOO) form is: (FUNCALL #"(SETF FOO) #:G0 #:G1 #:G2)
ANOTHER-FOO form is: (ANOTHER-FOO 10)
;;; Etc.
As for Allegro...
CL-USER> (values (lisp-implementation-type) (lisp-implementation-
version))
"International Allegro CL Free Express Edition"
"8.1 [Mac OS X (Intel)] (Jul 23, 2007 22:37)"
CL-USER> (load (compile-file "fileA"))
;;; Etc.
CL-USER> (load (compile-file "fileB"))
;;; Etc.
ANOTHER-FOO form is: (ANOTHER-FOO 10)
;;; Etc.
It prints something when you call it directly, though.
CL-USER> (macroexpand '(setf (foo x y) z))
(LET* ((#:G169 X) (#:G170 Y) (#:G168 Z))
(FUNCALL #'(SETF FOO) #:G168 #:G169 #:G170))
T
CL-USER> (funcall (compiler-macro-function '(setf foo)) (third *) nil)
(SETF FOO) form is: (FUNCALL #'(SETF FOO) #:G168 #:G169 #:G170)
(FUNCALL #'(SETF FOO) #:G168 #:G169 #:G170)
It's not required that the compiler macro be called for the (SETF FOO)
function, but I find it a odd that the one for ANOTHER-FOO gets called
and (SETF FOO) does not.
Am I just missing something with respect to macroexpansion and the
application of compiler macros?
odd with how Allegro CL 8.x handles compiler macros for SETF
functions. I want to make sure I didn't miss something here, because
I can't find anything in the documentation (Allegro CL or otherwise)
about it.
And before proceeding, I am well aware that compiler macros do not
need to be expanded as per the HyperSpec (see 3.2.2.1.3), so the
following seems to be legal, but odd nevertheless.
Here's the basic set up (shamelessly based on something from Nikodemus
Siivola).
;; File A
(defvar *foo* (make-array 32))
(defun (setf foo) (value index symbol)
(setf (getf (svref *foo* index) symbol) value))
(define-compiler-macro (setf foo) (&whole form value index symbol)
(declare (ignore value index symbol))
(format *debug-io* "~&(SETF FOO) form is: ~S~%" form)
form)
(defun another-foo (x) (+ x x))
(define-compiler-macro another-foo (&whole form x)
(declare (ignore x))
(format *debug-io* "~&ANOTHER-FOO form is: ~S~%" form)
form)
;;; File B
(defun example ()
(setf (foo 10 'bar) 'baz)
(another-foo 10))
It works as follows under SBCL.
CL-USER> (values (lisp-implementation-type) (lisp-implementation-
version))
"SBCL"
"1.0.8.12"
CL-USER> (load (compile-file "fileA"))
;;; Etc.
CL-USER> (load (compile-file "fileB"))
;;; Etc.
(SETF FOO) form is: (FUNCALL #"(SETF FOO) #:G0 #:G1 #:G2)
ANOTHER-FOO form is: (ANOTHER-FOO 10)
;;; Etc.
As for Allegro...
CL-USER> (values (lisp-implementation-type) (lisp-implementation-
version))
"International Allegro CL Free Express Edition"
"8.1 [Mac OS X (Intel)] (Jul 23, 2007 22:37)"
CL-USER> (load (compile-file "fileA"))
;;; Etc.
CL-USER> (load (compile-file "fileB"))
;;; Etc.
ANOTHER-FOO form is: (ANOTHER-FOO 10)
;;; Etc.
It prints something when you call it directly, though.
CL-USER> (macroexpand '(setf (foo x y) z))
(LET* ((#:G169 X) (#:G170 Y) (#:G168 Z))
(FUNCALL #'(SETF FOO) #:G168 #:G169 #:G170))
T
CL-USER> (funcall (compiler-macro-function '(setf foo)) (third *) nil)
(SETF FOO) form is: (FUNCALL #'(SETF FOO) #:G168 #:G169 #:G170)
(FUNCALL #'(SETF FOO) #:G168 #:G169 #:G170)
It's not required that the compiler macro be called for the (SETF FOO)
function, but I find it a odd that the one for ANOTHER-FOO gets called
and (SETF FOO) does not.
Am I just missing something with respect to macroexpansion and the
application of compiler macros?