From: Liam M. Healy
Subject: Macroexpand local macros
Date: 
Message-ID: <Cn6u0K.ByK@ra.nrl.navy.mil>
I am looking for a way to macroexpand local macro(s):
given macro defs and a string, expand that string.
E.g., from something like
  (my-macroexpand '((q1 (x y) `(+ ,x ,y)) (zz (x) `(expt ,x 2))) '(zz (q1 a b)))
I would like to see
  (expt (+ a b))
(yes, ideally I'd like to pass in my macro defs).
I have tried multiple combinations of macrolet and 
macroexpand, to no avail.  In CLtL sec. 8.2, it says
"Any local macro definitions established within env
by macrolet will be considered."  Good.  Now how do I do that?
The exact nature of the environment argument is a mystery to me.

Liam Healy

From: [Invalid-From-Line]
Subject: macroexpand local macros
Date: 
Message-ID: <CnJGnt.2vA@ra.nrl.navy.mil>
In article <············@early-bird.think.com> ······@think.com (Barry Margolin) writes:
> In article <··········@ra.nrl.navy.mil> <··········@nrl.navy.mil> writes:
> >I am looking for a way to macroexpand local macro(s):
> >given macro defs and a string, expand that string.
> >E.g., from something like
> >  (my-macroexpand '((q1 (x y) `(+ ,x ,y)) (zz (x) `(expt ,x 2))) '(zz (q1 a b)))
..
> >The exact nature of the environment argument is a mystery to me.
> 
> It's implementation-dependent.  It's an opaque data structure passed to
> macros that use the &ENV lambda-list keyword -- they can then pass it along
> to MACROEXPAND, GET-SETF-METHOD, etc.
> 
> Here's how you can implement what you want:
> 
> (defun my-macroexpand (macros form)
>   (let ((my-mexp-internal (gensym)))
>     (eval `(macrolet ((,my-mexp-internal (form &env env)
>                          `',(macroexpand form env))
>                       ,@macros)
>              (,my-mexp-internal ',form)))))
> 
> This can be done without using EVAL if you're willing to make
> MY-MACROEXPAND a macro itself.
> -- 
> Barry Margolin
> System Manager, Thinking Machines Corp.
> 
> ······@think.com          {uunet,harvard}!think!barmar

I'm impressed with the compactness and system-indepedence,
but, ... it doesn't work (even correcting &env to &environment):
(my-macroexpand '((q1 (x y) `(+ ,x ,y)) (zz (x) `(expt ,x 2))) '(zz (q1 a b)))
-> '(ZZ (Q1 A B))
I'm not sufficiently adept at commas and backquotes to figure this out.

However, after I posted the original message, I happened across Dick
Waters' macroexpand-all (LISP Pointers, vol VI #1 and anonymous ftp at
merl.com:/pub/lptrs/mexp*).  This does exactly what I want; it does have
a system-depedent part (it handles most of the major ones).  He also
has system-independent code for CLtL 2, but that is not implemented in
Genera.


Liam Healy
From: Barry Margolin
Subject: Re: Macroexpand local macros
Date: 
Message-ID: <2nfka6INN4qa@early-bird.think.com>
The MY-MACROEXPAND code I posted a few days ago was incorrect (it had the
backquote-quote-comma in the wrong place).  Here's a version that works:

(defun my-macroexpand (macros form)
  (let ((my-mexp-internal (gensym)))
    (eval `(macrolet ((,my-mexp-internal (form &environment env)
			 `',(macroexpand form env))
		      ,@macros)
	     (,my-mexp-internal ,form)))))

Note that this only expands a macro if it's the outermost form, e.g.

> (my-macroexpand '((q1 (x y) `(+ ,x ,y))
		    (zz (x) `(expt ,x 2)))
                  '(zz (q1 a b)))
(EXPT (Q1 A B) 2)

Only the ZZ invocation was expanded, not the Q1 invocation.  To get the
internal macros you need a code walker, such as Dick Waters's
macroexpand-all (LISP Pointers, vol VI #1 and anonymous ftp at
merl.com:/pub/lptrs/mexp*).  You may simply be able to replace my call to
MACROEXPAND with this (I haven't tried it).
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar