From: awhite
Subject: Nested macros
Date: 
Message-ID: <pan.2008.07.29.00.21.52.719000@iinet.net.au>
Hi, 

I obviously don't understand macroexpansion.

Silly toy example:

(defmacro with-bob (bob &body body)
  `(let ((,bob 1))
    ,@body))

(defmacro with-alice (alice &body body)
  `(let ((,alice 2))
    ,@body))


(defun do-that-thang (stuff more-stuff)
  (with-bob stuff
    (with-alice more-stuff
      (format t "~A ~A" stuff more-stuff))))




Compiling 'do-that-thang' complains that 'with-alice' is an illegal
function call (sbcl) - fair enough - it's not a function.

Why isn't the nested 'with-alice' macro also expanded? Can I nest
context-creating macros?

Adam

From: Geoff Wozniak
Subject: Re: Nested macros
Date: 
Message-ID: <04abdb80-bd58-4e1b-9648-a405681c865e@79g2000hsk.googlegroups.com>
On Jul 28, 8:21 pm, awhite <·······@iinet.net.au> wrote:
> Why isn't the nested 'with-alice' macro also expanded? Can I nest
> context-creating macros?

Are the macros defined before the function is compiled?  I don't have
any issues with the macroexpansion of your example (even though the
parameters STUFF and MORE-STUFF are never used).
From: awhite
Subject: Re: Nested macros
Date: 
Message-ID: <pan.2008.07.29.03.37.12.406000@iinet.net.au>
On Mon, 28 Jul 2008 19:12:34 -0700, Geoff Wozniak wrote:

> Are the macros defined before the function is compiled?  I don't have
> any issues with the macroexpansion of your example (even though the
> parameters STUFF and MORE-STUFF are never used).

Yes. macroexpand-ing them individually at the REPL seems to come up with
the right result. 

Perhaps the error isn't that 'with-alice' is an illegal function call? To
be honest, the error message doesn't refer to 'with-alice' by name, it
just complains about an illegal function call. 

I assumed that 'with-alice' were the error, because macroexpand-ing the
full form at the REPL doesn't seem to expand the nested 'with-alice', just
the outer 'with-bob' part.

Adam
From: squirrel rage
Subject: Re: Nested macros
Date: 
Message-ID: <0386788c-c621-4cee-801a-79f55568b401@x35g2000hsb.googlegroups.com>
On Jul 28, 11:37 pm, awhite <·······@iinet.net.au> wrote:
> I assumed that 'with-alice' were the error, because macroexpand-ing the
> full form at the REPL doesn't seem to expand the nested 'with-alice', just
> the outer 'with-bob' part.

That is exactly how MACROEXPAND is supposed to behave (see the
hyperspec).

As has been pointed out, your example code seems to be OK.

Perhaps an example lisp session would help.

SW
From: Rainer Joswig
Subject: Re: Nested macros
Date: 
Message-ID: <joswig-32033D.06181429072008@news-europe.giganews.com>
In article <······························@iinet.net.au>,
 awhite <·······@iinet.net.au> wrote:

> Hi, 
> 
> I obviously don't understand macroexpansion.
> 
> Silly toy example:
> 
> (defmacro with-bob (bob &body body)
>   `(let ((,bob 1))
>     ,@body))
> 
> (defmacro with-alice (alice &body body)
>   `(let ((,alice 2))
>     ,@body))
> 
> 
> (defun do-that-thang (stuff more-stuff)
>   (with-bob stuff
>     (with-alice more-stuff
>       (format t "~A ~A" stuff more-stuff))))
> 
> 
> 
> 
> Compiling 'do-that-thang' complains that 'with-alice' is an illegal
> function call (sbcl) - fair enough - it's not a function.
> 
> Why isn't the nested 'with-alice' macro also expanded? Can I nest
> context-creating macros?
> 
> Adam

You may want to add a better error report showing what
you are doing and what error message you get.


Let's try it...

This is SBCL 1.0.16, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (compile-file "/tmp/test.lisp")

; compiling file "/private/tmp/test.lisp" (written 29 JUL 2008 06:14:12 AM):
; compiling (DEFMACRO WITH-BOB ...)
; compiling (DEFMACRO WITH-ALICE ...)
; compiling (DEFUN DO-THAT-THANG ...)
; file: /private/tmp/test.lisp
; in: DEFUN DO-THAT-THANG
;     (DEFUN DO-THAT-THANG (STUFF MORE-STUFF)
;     (WITH-BOB STUFF
;               (WITH-ALICE MORE-STUFF (FORMAT T "~A ~A" STUFF MORE-STUFF))))
; --> PROGN EVAL-WHEN 
; ==>
;   (SB-IMPL::%DEFUN 'DO-THAT-THANG
;                    (SB-INT:NAMED-LAMBDA DO-THAT-THANG (STUFF MORE-STUFF)
;                                         (BLOCK DO-THAT-THANG
;                                           (WITH-BOB STUFF
;                                                     (WITH-ALICE MORE-STUFF
;                                                                 #))))
;                    NIL 'NIL (SB-C:SOURCE-LOCATION))
; 
; caught STYLE-WARNING:
;   The variable STUFF is defined but never used.
; 
; caught STYLE-WARNING:
;   The variable MORE-STUFF is defined but never used.
; 
; compilation unit finished
;   caught 2 STYLE-WARNING conditions


; /tmp/test.fasl written
; compilation finished in 0:00:00
#P"/private/tmp/test.fasl"
T
NIL


SBCL reports is that DO-THAT-THANG has two parameters that are never used.
'

-- 
http://lispm.dyndns.org/
From: awhite
Subject: Re: Nested macros
Date: 
Message-ID: <pan.2008.07.29.05.01.37.844000@iinet.net.au>
On Tue, 29 Jul 2008 06:18:15 +0200, Rainer Joswig wrote:

> You may want to add a better error report showing what
> you are doing and what error message you get.

thanks Rainer. I'm obviously doing something screwy. The first time I
tried my 'with-bob' 'with-alice' toy it didn't work. I've just tried again
at the REPL and it worked fine.

There are actually three macros in question, and are actually defined in
different packages. 

'with-sdl-init' is defined in :roguelib-sdl
'with-sdl-ttf' is defined in :roguelib-sdl
'with-sdl-harness' is defined in :roguelib-test

:roguelib-test does :use :roguelib-sdl

The function I'm trying to compile (and test!) lives in the :roguelib-test
package.

I've confirmed at the REPL that I can access the :roguelib-sdl macros
while (in-package :roguelib-test). Macroexpanding seems to give the right
response.

The code itself looks something like:

(with-sdl-harness screen
  (with-sdl-ttf font "path-to-font" 12
    (... stuff using font and screen lexicals ...)))

'with-sdl-harness' itself wraps the 'with-sdl-init' form.

sbcl complains "illegal function call", and I can't work out exactly what
it's complaining about. I had (wrongly?) assumed that it were treating
'with-sdl-ttf' as being a function call rather than a macro. 

It's bad form to not post the exact code, but I don't have it with me atm. 

Is it possible that I have to wrap the defmacro forms in an 'eval-when'
form? PCL mentions that it's necessary if I want to use a macro in the
same file as it's defined. I've done that for the 'with-sdl-harness' (as
it's to be used in the test functions underneath), but the 'with-sdl-ttf'
and 'with-sdl-init' macros are defined (and loaded) in earlier files.

I'll distill the exact code down later to a smaller size for posting.

Adam
From: Barry Margolin
Subject: Re: Nested macros
Date: 
Message-ID: <barmar-4D9D99.01164329072008@newsgroups.comcast.net>
In article <······························@iinet.net.au>,
 awhite <·······@iinet.net.au> wrote:

> On Tue, 29 Jul 2008 06:18:15 +0200, Rainer Joswig wrote:
> 
> > You may want to add a better error report showing what
> > you are doing and what error message you get.
> 
> thanks Rainer. I'm obviously doing something screwy. The first time I
> tried my 'with-bob' 'with-alice' toy it didn't work. I've just tried again
> at the REPL and it worked fine.
> 
> There are actually three macros in question, and are actually defined in
> different packages. 
> 
> 'with-sdl-init' is defined in :roguelib-sdl
> 'with-sdl-ttf' is defined in :roguelib-sdl
> 'with-sdl-harness' is defined in :roguelib-test
> 
> :roguelib-test does :use :roguelib-sdl
> 
> The function I'm trying to compile (and test!) lives in the :roguelib-test
> package.

Are they also in different source files?  Make sure you load the 
ROGUELIB-SDL file before compiling the file containing the calling 
function.

> 
> I've confirmed at the REPL that I can access the :roguelib-sdl macros
> while (in-package :roguelib-test). Macroexpanding seems to give the right
> response.
> 
> The code itself looks something like:
> 
> (with-sdl-harness screen
>   (with-sdl-ttf font "path-to-font" 12
>     (... stuff using font and screen lexicals ...)))
> 
> 'with-sdl-harness' itself wraps the 'with-sdl-init' form.
> 
> sbcl complains "illegal function call", and I can't work out exactly what
> it's complaining about. I had (wrongly?) assumed that it were treating
> 'with-sdl-ttf' as being a function call rather than a macro. 
> 
> It's bad form to not post the exact code, but I don't have it with me atm. 
> 
> Is it possible that I have to wrap the defmacro forms in an 'eval-when'
> form? PCL mentions that it's necessary if I want to use a macro in the
> same file as it's defined. I've done that for the 'with-sdl-harness' (as
> it's to be used in the test functions underneath), but the 'with-sdl-ttf'
> and 'with-sdl-init' macros are defined (and loaded) in earlier files.
> 
> I'll distill the exact code down later to a smaller size for posting.
> 
> Adam

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Rainer Joswig
Subject: Re: Nested macros
Date: 
Message-ID: <joswig-B94AAE.09195129072008@news-europe.giganews.com>
In article <······························@iinet.net.au>,
 awhite <·······@iinet.net.au> wrote:

> On Tue, 29 Jul 2008 06:18:15 +0200, Rainer Joswig wrote:
> 
> > You may want to add a better error report showing what
> > you are doing and what error message you get.
> 
> thanks Rainer. I'm obviously doing something screwy. The first time I
> tried my 'with-bob' 'with-alice' toy it didn't work. I've just tried again
> at the REPL and it worked fine.
> 
> There are actually three macros in question, and are actually defined in
> different packages. 
> 
> 'with-sdl-init' is defined in :roguelib-sdl
> 'with-sdl-ttf' is defined in :roguelib-sdl
> 'with-sdl-harness' is defined in :roguelib-test
> 
> :roguelib-test does :use :roguelib-sdl
> 
> The function I'm trying to compile (and test!) lives in the :roguelib-test
> package.
> 
> I've confirmed at the REPL that I can access the :roguelib-sdl macros
> while (in-package :roguelib-test). Macroexpanding seems to give the right
> response.
> 
> The code itself looks something like:
> 
> (with-sdl-harness screen
>   (with-sdl-ttf font "path-to-font" 12
>     (... stuff using font and screen lexicals ...)))
> 
> 'with-sdl-harness' itself wraps the 'with-sdl-init' form.
> 
> sbcl complains "illegal function call", and I can't work out exactly what
> it's complaining about. I had (wrongly?) assumed that it were treating
> 'with-sdl-ttf' as being a function call rather than a macro. 
> 
> It's bad form to not post the exact code, but I don't have it with me atm. 
> 
> Is it possible that I have to wrap the defmacro forms in an 'eval-when'
> form? PCL mentions that it's necessary if I want to use a macro in the
> same file as it's defined. I've done that for the 'with-sdl-harness' (as
> it's to be used in the test functions underneath), but the 'with-sdl-ttf'
> and 'with-sdl-init' macros are defined (and loaded) in earlier files.
> 
> I'll distill the exact code down later to a smaller size for posting.
> 
> Adam

What is 'using a macro' really? If you define a macro
in a file and later in the same file there is a function definition
which contains a form with that macro - that's fine.
The compiler knows that macro. After compiling that file,
the compiler forgets the macro. You have to load the compiled
file to make it known to the compiler.

A typical problem happens when you define a function in a file,
later a macro using that function and later a function
using that macro:

;file foo.lisp

(defun bar (...) ...)
(defmacro foo (...)  ... (bar ...) ...)
(defun baz (...) (foo a b c))

But the problem in your code seems to be that
the macro is not known at compile time and
that your macro looks a bit different
from what you posted.

Say if you have

(defun foo ()
   (with-bar 1 2 3
     (baz)))

or

(defun foo1 ()
   (with-bar (bar 1 2 3)
     (baz)))

or

(defun foo1 ()
   (with-bar (1 2 3)
     (baz)))

Which one gives an error with an illegal function
call when the macro WITH-BAR is not defined?

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (compile-file "/tmp/test.lisp")

; compiling file "/private/tmp/test.lisp" (written 29 JUL 2008 09:15:46 AM):
; compiling (DEFUN FOO ...)
; compiling (DEFUN FOO1 ...)
; compiling (DEFUN FOO2 ...)
; file: /private/tmp/test.lisp
; in: DEFUN FOO2
;     (1 2 3)
; 
; caught ERROR:
;   illegal function call

;     (BAZ)
; 
; note: deleting unreachable code

; in: DEFUN FOO1
;     (BAR 1 2 3)
; 
; caught STYLE-WARNING:
;   undefined function: BAR

; in: DEFUN FOO2
;     (BAZ)
; 
; caught STYLE-WARNING:
;   undefined function: BAZ

; in: DEFUN FOO1
;     (BAZ)
; 
; caught STYLE-WARNING:
;   undefined function: BAZ

; in: DEFUN FOO
;     (BAZ)
; 
; caught STYLE-WARNING:
;   undefined function: BAZ

; in: DEFUN FOO2
;     (WITH-BAR (1 2 3) (BAZ))
; 
; caught STYLE-WARNING:
;   undefined function: WITH-BAR

; in: DEFUN FOO1
;     (WITH-BAR (BAR 1 2 3) (BAZ))
; 
; caught STYLE-WARNING:
;   undefined function: WITH-BAR

; in: DEFUN FOO
;     (WITH-BAR 1 2 3 (BAZ))
; 
; caught STYLE-WARNING:
;   undefined function: WITH-BAR

; 
; caught STYLE-WARNING:
;   These functions are undefined:
;     BAR BAZ WITH-BAR
; 
; compilation unit finished
;   caught 1 ERROR condition
;   caught 8 STYLE-WARNING conditions
;   printed 1 note


; /tmp/test.fasl written
; compilation finished in 0:00:00
#P"/private/tmp/test.fasl"
T
T
* 

; ------------------

So, only compiling FOO2 generates that error.

-- 
http://lispm.dyndns.org/
From: Adam White
Subject: Re: Nested macros
Date: 
Message-ID: <488f0373$0$8932$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
On Tue, 29 Jul 2008 09:19:51 +0200, Rainer Joswig wrote:

>> > You may want to add a better error report showing what you are doing
>> > and what error message you get.

Hi Rainer,

sorry for the length.

;;; sdl.lisp


(defpackage #:roguelib-sdl
  (:use #:cl #:cffi #:roguelib)) ; and just for Kenny, soon to require #:cells !

(in-package #:roguelib-sdl)	

(defmacro with-sdl-init (width height bpp systems flags &body body)
  `(unwind-protect 
	(progn
	  (when (minusp (sdl-init ,systems))
	    (error "Unable to initialise SDL subsystem(s) ~A in WITH-SDL-INIT()" ,systems))
	  ,(if (member :sdl-init-video systems)
		`(let ((*surface* (sdl-set-video-mode ,width ,height ,bpp ,flags)))
		   (when (null-pointer-p *surface*)
		     (error "Unable to initialise SDL video mode in WITH-SDL-INIT() !"))
		   ,@body)
		body))
     (sdl-quit)))


(defmacro with-sdl-ttf (fontname fontpath ptsize idx &body body)
  `(progn
     (when (minusp (sdl-ttf-was-init))
       (sdl-ttf-init))
     (let ((,fontname (sdl-ttf-open-font-idx ,fontpath ,ptsize ,idx)))
       (unwind-protect 
	    (progn 
	      ,@body)
	 (sdl-ttf-close-font ,fontname)))))


;;; Now at the REPL


CL-USER> (in-package :roguelib-sdl)
#<PACKAGE "ROGUELIB-SDL">

ROGUELIB-SDL> (macroexpand '(with-sdl-ttf font "/home/" 20 0 (bobby)))
(PROGN
 (WHEN (MINUSP (SDL-TTF-WAS-INIT)) (SDL-TTF-INIT))
 (LET ((FONT (SDL-TTF-OPEN-FONT-IDX "/home/" 20 0)))
   (UNWIND-PROTECT (PROGN (BOBBY)) (SDL-TTF-CLOSE-FONT FONT))))
T

ROGUELIB-SDL> (macroexpand-1 '(with-sdl-events :poll
			       (:key-down (:sym sym) (when (eql sym :sdlk-escape) (sdl-quit)))
			       (:video-expose (sdl-update-screen))))
(WITH-FOREIGN-OBJECT (EVENT 'SDL-EVENT)
                     (LOOP (SDL-POLL-EVENT EVENT)
                           (CASE (FOREIGN-SLOT-VALUE EVENT 'SDL-EVENT 'TYPE)
                             (2
                              (LET ((SYM
                                     (SVREF *SCANCODE-TO-KEY*
                                            (FOREIGN-SLOT-VALUE
                                             (FOREIGN-SLOT-VALUE
                                              (FOREIGN-SLOT-VALUE EVENT
                                                                  'SDL-EVENT
                                                                  'KEY)
                                              'SDL-KEYBOARD-EVENT 'KEYSYM)
                                             'SDL-KEYSYM 'SYM))))
                                (WHEN (EQL SYM :SDLK-ESCAPE) (SDL-QUIT))))
                             (17 (SDL-UPDATE-SCREEN)))))
T

ROGUELIB-SDL> (defmacro with-sdl-harness (window &body body)
		`(with-sdl-init 640 480 32 '(:sdl-init-video) '(:sdl-resizable :sdl-doublebuf)
		   (let ((,window (sdl-get-video-surface)))
		     ,@body
		     (sdl-update-screen)
		     (with-sdl-events :poll
		       (:key-down (:sym sym) (when (eql sym :sdlk-escape) (sdl-quit)))
		       (:video-expose (sdl-update-screen))))))
		       
WITH-SDL-HARNESS

ROGUELIB-SDL> (fboundp 'create-text-box)
T

ROGUELIB-SDL> (with-sdl-harness window
		  (with-sdl-ttf font "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
		    (let* ((textbox (create-text-box "Booyakasha" font 200 30))
			   (srcrect (sdl-rect 0 0 (sdl-surface-w textbox) (sdl-surface-h textbox))))
		      (sdl-blit-surface textbox srcrect window srcrect))))
; in: LAMBDA NIL
;     ((LET ((ROGUELIB-SDL::WINDOW (ROGUELIB-SDL:SDL-GET-VIDEO-SURFACE)))
;      (ROGUELIB-SDL:WITH-SDL-TTF ROGUELIB-SDL:FONT
;                                 "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
;                                 (LET* (# #)
;                                   (ROGUELIB-SDL:SDL-BLIT-SURFACE
;                                    ROGUELIB-SDL::TEXTBOX ROGUELIB-SDL::SRCRECT
;                                    ROGUELIB-SDL::WINDOW
;                                    ROGUELIB-SDL::SRCRECT)))
;      (ROGUELIB-SDL:SDL-UPDATE-SCREEN)
;      (ROGUELIB-SDL:WITH-SDL-EVENTS :POLL
;                                    (:KEY-DOWN (:SYM ROGUELIB-SDL::SYM)
;                                     (WHEN # #))
;                                    (:VIDEO-EXPOSE
;                                     (ROGUELIB-SDL:SDL-UPDATE-SCREEN)))))
; 
; caught ERROR:
;   illegal function call
; 
; compilation unit finished
;   caught 1 ERROR condition
; Evaluation aborted.


Where's the illegal function call? I had assumed that it were the "WITH-SDL-TTF", 
but I've confirmed above at the REPL that it seems to macroexpand ok.

Adam

(WITH-SDL-EVENTS is a bit of a beast, too long to post, but you can see that it expands ok)
From: Adam White
Subject: Re: Nested macros
Date: 
Message-ID: <488f0786$0$8932$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
On Tue, 29 Jul 2008 11:48:03 +0000, Adam White wrote:

> On Tue, 29 Jul 2008 09:19:51 +0200, Rainer Joswig wrote:
> 
>>> > You may want to add a better error report showing what you are doing
>>> > and what error message you get.
> 
> Hi Rainer,
> 
> sorry for the length.
> 
> ;;; sdl.lisp
> 
> (defmacro with-sdl-init (width height bpp systems flags &body body)
>   `(unwind-protect
> 	(progn
> 	  (when (minusp (sdl-init ,systems))
> 	    (error "Unable to initialise SDL subsystem(s) ~A in
> 	    WITH-SDL-INIT()" ,systems))
> 	  ,(if (member :sdl-init-video systems)
         ^^^
Aaaah CRAP! It should have been " ,@(if (member  "


Sorry guys. Goddamn it! I stared and stared at the error message, not 
seeing that the error was an extra parenthesis before the LET form.

One of the (ACL?) developers joked a while ago about the new DWIMANWIW 
(Do What I Mean And Not What I Wrote) interface - any news?


Adam
From: ······@corporate-world.lisp.de
Subject: Re: Nested macros
Date: 
Message-ID: <4f9fa33c-236e-482b-9007-152b603e6697@c58g2000hsc.googlegroups.com>
On 29 Jul., 14:05, Adam White <·······@iinet.net.au> wrote:
> On Tue, 29 Jul 2008 11:48:03 +0000, Adam White wrote:
> > On Tue, 29 Jul 2008 09:19:51 +0200, Rainer Joswig wrote:
>
> >>> > You may want to add a better error report showing what you are doing
> >>> > and what error message you get.
>
> > Hi Rainer,
>
> > sorry for the length.
>
> > ;;; sdl.lisp
>
> > (defmacro with-sdl-init (width height bpp systems flags &body body)
> >   `(unwind-protect
> >    (progn
> >      (when (minusp (sdl-init ,systems))
> >        (error "Unable to initialise SDL subsystem(s) ~A in
> >        WITH-SDL-INIT()" ,systems))
> >      ,(if (member :sdl-init-video systems)
>
>          ^^^
> Aaaah CRAP! It should have been " ,@(if (member  "
>
> Sorry guys. Goddamn it! I stared and stared at the error message, not
> seeing that the error was an extra parenthesis before the LET form.
>
> One of the (ACL?) developers joked a while ago about the new DWIMANWIW
> (Do What I Mean And Not What I Wrote) interface - any news?
>
> Adam

Right, I was about to answer your question, but you found it already.
That's what I mean how it's important to see the original error
message,
since the Lisp was complaining about a relatively simple error.
There are sources for this kind of error when the macro is not
known (as I mentioned before). Another source for this error is
incorrect code generation (like here). The error message already gives
the clue.
In Common Lisp this is relatively easy to spot, since the form
printed is not legal - if there would really be some function calling
going on, there had to be a FUNCALL in front (or a symbol or a lambda
expression).
When the compiler complains about an illegal function call, then it is
a kind
of syntax error on the Lisp level - the code is a valid s-expression,
but not a valid function call according to the Lisp syntax.
I think the error message is good. It shows the code and tells
that what error it is. For finding those expansions, it is sometimes
difficult to use macroexpand. LispWorks for example offers to expand
the expression fully on all levels. Macroexpand would only expand the
top macro, but not macro usage some levels down in the code.
From: Brian
Subject: Re: Nested macros
Date: 
Message-ID: <a01ae5af-62d6-4a5f-bb64-afaaaab355c4@34g2000hsh.googlegroups.com>
On Jul 29, 7:22 am, ·······@corporate-world.lisp.de" <······@corporate-
world.lisp.de> wrote:
> LispWorks for example offers to expand the expression fully
> on all levels. Macroexpand would only expand the top macro,
> but not macro usage some levels down in the code.
If one does (require 'sb-cltl2) in SBCL, SB-CLTL2:MACROEXPAND-ALL
becomes available.
From: Rob Warnock
Subject: Re: Nested macros
Date: 
Message-ID: <a_6dnZfslNsW2w3VnZ2dnUVZ_qrinZ2d@speakeasy.net>
Brian  <··············@gmail.com> wrote:
+---------------
| ·······@corporate-world.lisp.de" <······@corporate-world.lisp.de> wrote:
| > LispWorks for example offers to expand the expression fully
| > on all levels. Macroexpand would only expand the top macro,
| > but not macro usage some levels down in the code.
| If one does (require 'sb-cltl2) in SBCL, SB-CLTL2:MACROEXPAND-ALL
| becomes available.
+---------------

And in CMUCL, it's WALKER:MACROEXPAND-ALL.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Adam White
Subject: Re: Nested macros
Date: 
Message-ID: <488f0e7b$0$8932$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
On Tue, 29 Jul 2008 05:22:10 -0700, ······@corporate-world.lisp.de wrote:

[snip my silly error]

> Right, I was about to answer your question, but you found it already.
> That's what I mean how it's important to see the original error message,
> since the Lisp was complaining about a relatively simple error. There
> are sources for this kind of error when the macro is not known (as I
> mentioned before). Another source for this error is incorrect code
> generation (like here). The error message already gives the clue.

Thanks Rainer. I knew it was bad form to post without the exact cut-and-
pasted error, but I kept thinking about it at work, and (thought) I'd 
nailed down what the error had to be.

Adam
From: Pascal J. Bourguignon
Subject: Re: Nested macros
Date: 
Message-ID: <7ck5f43myc.fsf@pbourguignon.anevia.com>
Adam White <·······@iinet.net.au> writes:
> [...]
> ROGUELIB-SDL> (with-sdl-harness window
> 		  (with-sdl-ttf font "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
> 		    (let* ((textbox (create-text-box "Booyakasha" font 200 30))
> 			   (srcrect (sdl-rect 0 0 (sdl-surface-w textbox) (sdl-surface-h textbox))))
> 		      (sdl-blit-surface textbox srcrect window srcrect))))
> ; in: LAMBDA NIL
> ;     ((LET ((ROGUELIB-SDL::WINDOW (ROGUELIB-SDL:SDL-GET-VIDEO-SURFACE)))
> ;      (ROGUELIB-SDL:WITH-SDL-TTF ROGUELIB-SDL:FONT
> ;                                 "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
> ;                                 (LET* (# #)
> ;                                   (ROGUELIB-SDL:SDL-BLIT-SURFACE
> ;                                    ROGUELIB-SDL::TEXTBOX ROGUELIB-SDL::SRCRECT
> ;                                    ROGUELIB-SDL::WINDOW
> ;                                    ROGUELIB-SDL::SRCRECT)))
> ;      (ROGUELIB-SDL:SDL-UPDATE-SCREEN)
> ;      (ROGUELIB-SDL:WITH-SDL-EVENTS :POLL
> ;                                    (:KEY-DOWN (:SYM ROGUELIB-SDL::SYM)
> ;                                     (WHEN # #))
> ;                                    (:VIDEO-EXPOSE
> ;                                     (ROGUELIB-SDL:SDL-UPDATE-SCREEN)))))
> ; 
> ; caught ERROR:
> ;   illegal function call
> ; 
> ; compilation unit finished
> ;   caught 1 ERROR condition
> ; Evaluation aborted.
>
>
> Where's the illegal function call? I had assumed that it were the "WITH-SDL-TTF", 
> but I've confirmed above at the REPL that it seems to macroexpand ok.
>
> Adam
>
> (WITH-SDL-EVENTS is a bit of a beast, too long to post, but you can see that it expands ok)


clisp says:

C/ROGUELIB-SDL[92]> (with-sdl-harness window
		  (with-sdl-ttf font "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
		    (let* ((textbox (create-text-box "Booyakasha" font 200 30))
			   (srcrect (sdl-rect 0 0 (sdl-surface-w textbox) (sdl-surface-h textbox))))
		      (sdl-blit-surface textbox srcrect window srcrect))))

*** - EVAL:
       (LET ((WINDOW (SDL-GET-VIDEO-SURFACE)))
        (WITH-SDL-TTF FONT "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0 (LET* ((TEXTBOX (CREATE-TEXT-BOX "Booyakasha" FONT 200 30)) (SRCRECT (SDL-RECT 0 0 (SDL-SURFACE-W TEXTBOX) (SDL-SURFACE-H TEXTBOX)))) (SDL-BLIT-SURFACE TEXTBOX SRCRECT WINDOW SRCRECT)))
        (SDL-UPDATE-SCREEN) (WITH-SDL-EVENTS :POLL (:KEY-DOWN (:SYM SYM) (WHEN (EQL SYM :SDLK-ESCAPE) (SDL-QUIT))) (:VIDEO-EXPOSE (SDL-UPDATE-SCREEN))))
      is not a function name; try using a symbol instead
The following restarts are available:
USE-VALUE      :R1      You may input a value to be used instead.
ABORT          :R2      ABORT
C/Break 1 ROGUELIB-SDL[93]> :q


So you are expanding a let inside parentheses:


C/ROGUELIB-SDL[94]> (macroexpand '(with-sdl-harness window
		  (with-sdl-ttf font "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
		    (let* ((textbox (create-text-box "Booyakasha" font 200 30))
			   (srcrect (sdl-rect 0 0 (sdl-surface-w textbox) (sdl-surface-h textbox))))
		      (sdl-blit-surface textbox srcrect window srcrect)))))
(UNWIND-PROTECT
 (PROGN (WHEN (MINUSP (SDL-INIT #1='(:SDL-INIT-VIDEO))) (ERROR "Unable to initialise SDL subsystem(s) ~A in WITH-SDL-INIT()" #1#))
  ((LET ((WINDOW (SDL-GET-VIDEO-SURFACE)))
    (WITH-SDL-TTF FONT "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0 (LET* ((TEXTBOX (CREATE-TEXT-BOX "Booyakasha" FONT 200 30)) (SRCRECT (SDL-RECT 0 0 (SDL-SURFACE-W TEXTBOX) (SDL-SURFACE-H TEXTBOX)))) (SDL-BLIT-SURFACE TEXTBOX SRCRECT WINDOW SRCRECT)))
    (SDL-UPDATE-SCREEN) (WITH-SDL-EVENTS :POLL (:KEY-DOWN (:SYM SYM) (WHEN (EQL SYM :SDLK-ESCAPE) (SDL-QUIT))) (:VIDEO-EXPOSE (SDL-UPDATE-SCREEN))))))
 (SDL-QUIT)) ;
T
C/ROGUELIB-SDL[95]> 

That's why I prefer to use clisp-2.46 rather than sbcl-1.0.18, clearer error messages.

Your error is in:

(defmacro with-sdl-init (width height bpp systems flags &body body)
  `(unwind-protect 
       	(progn
          (when (minusp (sdl-init ,systems))
            (error "Unable to initialise SDL subsystem(s) ~A in WITH-SDL-INIT()" ,systems))
          ,(if (member :sdl-init-video systems)
               `(let ((*surface* (sdl-set-video-mode ,width ,height ,bpp ,flags)))
                  (when (null-pointer-p *surface*)
                    (error "Unable to initialise SDL video mode in WITH-SDL-INIT() !"))
                  ,@body)
               body))
     (sdl-quit)))

In all cases, body is a list of forms, so you should expand it where a
list of forms is expected.  In all cases!


C/ROGUELIB-SDL[95]> (defmacro with-sdl-init (width height bpp systems flags &body body)
  `(unwind-protect 
       	(progn
          (when (minusp (sdl-init ,systems))
            (error "Unable to initialise SDL subsystem(s) ~A in WITH-SDL-INIT()" ,systems))
          ,(if (member :sdl-init-video systems)
               `(let ((*surface* (sdl-set-video-mode ,width ,height ,bpp ,flags)))
                  (when (null-pointer-p *surface*)
                    (error "Unable to initialise SDL video mode in WITH-SDL-INIT() !"))
                  ,@body)
               `(progn
                  ,@body)))
     (sdl-quit)))
WITH-SDL-INIT
C/ROGUELIB-SDL[96]> (macroexpand '(with-sdl-harness window
		  (with-sdl-ttf font "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
		    (let* ((textbox (create-text-box "Booyakasha" font 200 30))
			   (srcrect (sdl-rect 0 0 (sdl-surface-w textbox) (sdl-surface-h textbox))))
		      (sdl-blit-surface textbox srcrect window srcrect)))))
(UNWIND-PROTECT
 (PROGN (WHEN (MINUSP (SDL-INIT #1='(:SDL-INIT-VIDEO))) (ERROR "Unable to initialise SDL subsystem(s) ~A in WITH-SDL-INIT()" #1#))
  (PROGN
   (LET ((WINDOW (SDL-GET-VIDEO-SURFACE)))
    (WITH-SDL-TTF FONT "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0 (LET* ((TEXTBOX (CREATE-TEXT-BOX "Booyakasha" FONT 200 30)) (SRCRECT (SDL-RECT 0 0 (SDL-SURFACE-W TEXTBOX) (SDL-SURFACE-H TEXTBOX)))) (SDL-BLIT-SURFACE TEXTBOX SRCRECT WINDOW SRCRECT)))
    (SDL-UPDATE-SCREEN) (WITH-SDL-EVENTS :POLL (:KEY-DOWN (:SYM SYM) (WHEN (EQL SYM :SDLK-ESCAPE) (SDL-QUIT))) (:VIDEO-EXPOSE (SDL-UPDATE-SCREEN))))))
 (SDL-QUIT)) ;
T


-- 
__Pascal Bourguignon__
From: Adam White
Subject: Re: Nested macros
Date: 
Message-ID: <488f0f61$0$8932$5a62ac22@per-qv1-newsreader-01.iinet.net.au>
On Tue, 29 Jul 2008 14:16:11 +0200, Pascal J. Bourguignon wrote:

[snip my silly error]

> That's why I prefer to use clisp-2.46 rather than sbcl-1.0.18, clearer
> error messages.

Actually, once I saw what the error message was actually saying (rather 
than what I thought it was saying), both implementations were ok. I also 
tried it in cmucl, but the "gc warning" spam sorta got me down.

I *should* be better at reading error messages by now - once you learn to 
piece together error messages generated by incorrect BOOST c++ template 
instantiations, you should be ready for lisp!
 
> Your error is in:
> 
> (defmacro with-sdl-init (width height bpp systems flags &body body)
>   `(unwind-protect
>        	(progn
>           (when (minusp (sdl-init ,systems))
>             (error "Unable to initialise SDL subsystem(s) ~A in
>             WITH-SDL-INIT()" ,systems))
>           ,(if (member :sdl-init-video systems)
>                `(let ((*surface* (sdl-set-video-mode ,width ,height ,bpp
>                ,flags)))
>                   (when (null-pointer-p *surface*)
>                     (error "Unable to initialise SDL video mode in
>                     WITH-SDL-INIT() !"))
>                   ,@body)
>                body))
>      (sdl-quit)))
> 
> In all cases, body is a list of forms, so you should expand it where a
> list of forms is expected.  In all cases!

Thanks Pascal - good advice - appreciated.

Adam
From: Pascal J. Bourguignon
Subject: Re: Nested macros
Date: 
Message-ID: <7cfxps3l4u.fsf@pbourguignon.anevia.com>
Adam White <·······@iinet.net.au> writes:

> On Tue, 29 Jul 2008 14:16:11 +0200, Pascal J. Bourguignon wrote:
>
> [snip my silly error]
>
>> That's why I prefer to use clisp-2.46 rather than sbcl-1.0.18, clearer
>> error messages.
>
> Actually, once I saw what the error message was actually saying (rather 
> than what I thought it was saying), both implementations were ok. I also 
> tried it in cmucl, but the "gc warning" spam sorta got me down.
>
> I *should* be better at reading error messages by now - once you learn to 
> piece together error messages generated by incorrect BOOST c++ template 
> instantiations, you should be ready for lisp!
>  
>> Your error is in:
>> 
>> (defmacro with-sdl-init (width height bpp systems flags &body body)
>>   `(unwind-protect
>>        	(progn
>>           (when (minusp (sdl-init ,systems))
>>             (error "Unable to initialise SDL subsystem(s) ~A in
>>             WITH-SDL-INIT()" ,systems))
>>           ,(if (member :sdl-init-video systems)
>>                `(let ((*surface* (sdl-set-video-mode ,width ,height ,bpp
>>                ,flags)))
>>                   (when (null-pointer-p *surface*)
>>                     (error "Unable to initialise SDL video mode in
>>                     WITH-SDL-INIT() !"))
>>                   ,@body)
>>                body))
>>      (sdl-quit)))
>> 
>> In all cases, body is a list of forms, so you should expand it where a
>> list of forms is expected.  In all cases!
>
> Thanks Pascal - good advice - appreciated.

Ok, then you've seen the error in your 'corrected' macro:

C/ROGUELIB-SDL[106]> (defmacro with-sdl-init (width height bpp systems flags &body body)
                       `(unwind-protect 
                             (progn
                               (when (minusp (sdl-init ,systems))
                                 (error "Unable to initialise SDL subsystem(s) ~A in WITH-SDL-INIT()" ,systems))
                               ,@(if (member :sdl-init-video systems)
                                     `(let ((*surface* (sdl-set-video-mode ,width ,height ,bpp ,flags)))
                                        (when (null-pointer-p *surface*)
                                          (error "Unable to initialise SDL video mode in WITH-SDL-INIT() !"))
                                        ,@body)
                                     body))
                          (sdl-quit)))


which would be visible, if there wasn't another bug in
with-sdl-harness.  You shouldn't quote lists that are not evaluated:

(defmacro with-sdl-harness (window &body body)
  `(with-sdl-init 640 480 32 (:sdl-init-video) (:sdl-resizable :sdl-doublebuf)
                  (let ((,window (sdl-get-video-surface)))
                    ,@body
                    (sdl-update-screen)
                    (with-sdl-events :poll
                      (:key-down (:sym sym) (when (eql sym :sdlk-escape) (sdl-quit)))
                      (:video-expose (sdl-update-screen))))))

Then:

C/ROGUELIB-SDL[109]> (macroexpand '(with-sdl-harness window
                                    (with-sdl-ttf font "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0
                                                  (let* ((textbox (create-text-box "Booyakasha" font 200 30))
                                                         (srcrect (sdl-rect 0 0 (sdl-surface-w textbox) (sdl-surface-h textbox))))
                                                    (sdl-blit-surface textbox srcrect window srcrect)))))
(UNWIND-PROTECT
 (PROGN (WHEN (MINUSP (SDL-INIT #1=(:SDL-INIT-VIDEO))) (ERROR "Unable to initialise SDL subsystem(s) ~A in WITH-SDL-INIT()" #1#))
  LET ((*SURFACE* (SDL-SET-VIDEO-MODE 640 480 32 (:SDL-RESIZABLE :SDL-DOUBLEBUF))))
  (WHEN (NULL-POINTER-P *SURFACE*) (ERROR "Unable to initialise SDL video mode in WITH-SDL-INIT() !"))
  (LET ((WINDOW (SDL-GET-VIDEO-SURFACE)))
   (WITH-SDL-TTF FONT "/home/spudboy/skirmish/roguelib/Vera.ttf" 20 0 
      (LET* ((TEXTBOX (CREATE-TEXT-BOX "Booyakasha" FONT 200 30))
              (SRCRECT (SDL-RECT 0 0 (SDL-SURFACE-W TEXTBOX) (SDL-SURFACE-H TEXTBOX))))
         (SDL-BLIT-SURFACE TEXTBOX SRCRECT WINDOW SRCRECT))) (SDL-UPDATE-SCREEN)
   (WITH-SDL-EVENTS :POLL (:KEY-DOWN (:SYM SYM) (WHEN (EQL SYM :SDLK-ESCAPE) (SDL-QUIT))) (:VIDEO-EXPOSE (SDL-UPDATE-SCREEN)))))
 (SDL-QUIT)) ;
T
C/ROGUELIB-SDL[110]> 


As I said, if an operator is expecting a list as argument, then you
should provide it a list, and vice versa, if you have a list, then
you should always treat it as a list.  Idem for any other type.

-- 
__Pascal Bourguignon__