From: Malcolm Slaney
Subject: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <49@spar.SPAR.SLB.COM>
Can anybody point me towards some code that will take any Common Lisp
expression and macroexpand all of the macros.  I would like as output
a s'exp that just has the functions from Steele.  I don't think this is too
hard but if somebody else has already done it I would prefer to reuse the
code.  (Don't special forms make this non trivial???)

I want to use this as part of a tool to record storage usage.  I'll first 
do the necessary macroexpands, then wrap a form around each primitive Common
Lisp form that records the memory usage and then write a tool that will
pretty print the information.

Thanks for the help.

						Malcolm Slaney
						·······@spar.slb.com

From: Mike Ogush
Subject: Re: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <640002@hpclmao.HP.COM>
/ ·······@spar.SPAR.SLB.COM (Malcolm Slaney) writes:
>Can anybody point me towards some code that will take any Common Lisp
>expression and macroexpand all of the macros.  I would like as output
>a s'exp that just has the functions from Steele.  I don't think this is too
>hard but if somebody else has already done it I would prefer to reuse the
>code.  (Don't special forms make this non trivial???)
>
>I want to use this as part of a tool to record storage usage.  I'll first 
>do the necessary macroexpands, then wrap a form around each primitive Common
>Lisp form that records the memory usage and then write a tool that will
>pretty print the information.
>
>Thanks for the help.
>
>						Malcolm Slaney
>						·······@spar.slb.com
>----------
>

When I was learning Common LISP, I wrote just such a function so I could see
exactly what s-expressions were being expanded into:


(defun fully-expand-macro (exp)
  (if (consp exp)
    (let ((car-exp (car exp)))
      (if (and (symbolp car-exp) (macro-function car-exp))
        (fully-expand-macro (macroexpand exp))
        (cons car-exp
              (mapcar #'fully-expand-macro (cdr exp)))))
    exp)
  )


Hope this helps


    Mike Ogush

    Computer Languages Lab  
    Hewlett-Packard Company

    ...!hplabs!hpda!mao  or ···········@hplabs.hp.com
From: James Larus
Subject: Re: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <23539@ucbvax.BERKELEY.EDU>
How about:

	(defun macroexpand-all (f)
	  (cond ((atom f) f)
		((and (symbolp (car f)) (macro-function (car f)))
		 (macroexpand-all (macroexpand f)))
		(t (mapcar #'macroexpand-all f))))


/Jim
·····@ginger.Berkeley.EDU
ucbvax!larus
From: Skef Wholey
Subject: Re: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <1348@PT.CS.CMU.EDU>
Jim Larus writes:

    From: ·····@paris.Berkeley.EDU (James Larus)
    Subject: Re: Common Lisp Macro Expander Wanted

    How about:

	    (defun macroexpand-all (f)
	      (cond ((atom f) f)
		    ((and (symbolp (car f)) (macro-function (car f)))
		     (macroexpand-all (macroexpand f)))
		    (t (mapcar #'macroexpand-all f))))

This is no good, because it doesn't know the syntax of special forms.
For example, this call causes an error:

  (macroexpand-all '(let ((with-open-file t)) blag))

because it tries to descend blindly into the LET binding list as if it
were a macro call, which it obvously ain't.

It isn't too hard to write a code walker that Does The Right Thing for
special forms in Common Lisp, but unfortunately some implementations
ignore the rules stated in CLtL and make this more difficult than it
ought to be.  Older versions of Symbolics CL were pretty nasty in this
respect, because they had macros expanding into implementation-dependent
special forms and didn't supply macroexpansion functions for all the
things specified as macros in CLtL.  I believe this should have been
fixed by now, but I can't easily check this.

I have this suspicion that dozens of good CL code-walkers have been
written independently, but none have made it into the public domain
because they were written in profit-oriented institutions.  Does anyone
out there have one to donate?

--Skef
From: John Gateley
Subject: Re: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <46438@ti-csl.CSNET>
In article <·····@ucbvax.BERKELEY.EDU> ·····@paris.Berkeley.EDU.UUCP writes:
>How about:
>
>	(defun macroexpand-all (f)
>	  (cond ((atom f) f)
>		((and (symbolp (car f)) (macro-function (car f)))
>		 (macroexpand-all (macroexpand f)))
>		(t (mapcar #'macroexpand-all f))))
>
>
>/Jim
>·····@ginger.Berkeley.EDU
>ucbvax!larus

Almost works, but you have to check special forms to make sure that
they are macro expanded only in the proper places, and then there is
always lambda to deal with. (Hint: Dont macro expand the argument list
for lambdas, and the same is true for the variables in a let). I cant find
anything in CLtL which verifies this, but I think this is correct.
From: ····@lcuxlm.UUCP
Subject: Re: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <1683@lcuxlm.UUCP>
In article <·····@ti-csl.CSNET>, ·······@mips.csc.ti.com (John Gateley) writes:
> 
> Almost works, but you have to check special forms to make sure that
> they are macro expanded only in the proper places, and then there is
> always lambda to deal with. (Hint: Dont macro expand the argument list
> for lambdas, and the same is true for the variables in a let). I cant find
> anything in CLtL which verifies this, but I think this is correct.

I think it turns out that a fully-fledged macroexpanding preprocessor
looks very much like the first pass of a compiler - and among things
you end up having to treat each special-form specially (that's why 
they're special).

Do you have any ides of how to handle local macros (defined 
by MACROLET)?  We ended up just ignoring them - essentially because
(1) MACRO-FUNCTION only knows about global macros (because it's a 
top-level function and (2) to be useful MACROEXPAND would need the 
correct &ENVIRONMENT arg set up.  All in all a hassle... but maybe
I'm missing something... like a screw...


--ilan caron ..!ucbvax!vax135!lcuxlj!ilan
-- 

--Ilan Caron 201-580-5664 ..!allegra!lcuxlj!ilan
#<Standard Disclaimer>
From: Albert Boulanger
Subject: Re: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <23514@bbn.COM>
You can pick up PCL (portable common loops)from XEROX and use its code
walker...

Albert Boulanger
··········@bbn.com
Albert Boulanger
BBN Labs Inc.
··········@bbn.com (arpa)
Phone: (617)873-3891
From: John Gateley
Subject: Re: Common Lisp Macro Expander Wanted
Date: 
Message-ID: <46967@ti-csl.CSNET>
In article <····@lcuxlm.UUCP> ····@lcuxlm.UUCP writes:
> [...]
>Do you have any ides of how to handle local macros (defined 
>by MACROLET)?  We ended up just ignoring them - essentially because
>(1) MACRO-FUNCTION only knows about global macros (because it's a 
>top-level function and (2) to be useful MACROEXPAND would need the 
>correct &ENVIRONMENT arg set up.  All in all a hassle... but maybe
>I'm missing something... like a screw...
>
>--ilan caron ..!ucbvax!vax135!lcuxlj!ilan
>--Ilan Caron 201-580-5664 ..!allegra!lcuxlj!ilan
>#<Standard Disclaimer>

You mentioned that it is just like the first pass of a compiler, and that is
the answer to your question. You just have to pass around an argument
which contains an environment mapping symbols to local macro functions.
When you reach a form which is a local macro function, you just eval
the macro function applied to the form (Yucch ... eval). Macrolet just
extends the environment. Of course, you have to worry about scoping to
do it correctly (where a local macro name might be shadowed by something else).
Hope this helps
John Gateley