Discussion:
SETF compiler macro functions in Allegro CL
(too old to reply)
Geoff Wozniak
2007-08-08 22:31:54 UTC
Permalink
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?
Willem Broekema
2007-08-09 14:54:27 UTC
Permalink
Post by Geoff Wozniak
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.
The compiler macro for SETF forms are indeed ignored by the Allegro CL
8.0 compiler. That is a shortcoming in the compiler, but allowed by
ANSI.

This has a somewhat surprising and probably undesirable result: if you
have compiler macros for both (setf foo) [which is ignored by Allegro]
and foo [which is taken into account], then in the form

(setf (foo x) 3)

the compiler will run the compiler macro for foo! This compilation
will generally fail, unless foo happens to expand into a "place". E.g.
with the following:

(define-compiler-macro foo (x)
`(progn ... ,x ...))

the setf form above gets expanded into

(setf (progn ...) 3)

and this will not compile. As a workaround, don't define the compiler
macro for foo, e.g. with #-allegro.

The above is my experience with Allegro 8.0; maybe things have changed
in 8.1.

- Willem

Loading...