Subject: Re: Handling declarations
From: rpw3@rpw3.org (Rob Warnock)
Date: Fri, 28 Jul 2006 03:53:45 -0500
Newsgroups: comp.lang.lisp
Message-ID: <-YydnRuCt84ETVTZnZ2dnUVZ_radnZ2d@speakeasy.net>
Lars Brinkhoff  <lars.spam@nocrew.org> wrote:
+---------------
| Kent M Pitman <pitman@nhplace.com> writes:
| > you might have a construct like
| >
| >  (defmacro my-let-if (condition bindings &body forms)
| >    `(if ,condition
| >         (let ,bindings ,@forms)
|           (locally ,@forms)))           ;slight alteration
| 
| How do experienced Lispers write macros such as this to handle
| declarations in the body?  I.e. if FORMS has any declarations for
| variables in BINDINGS, you would like to include those in the body of
| LET, but not in LOCALLY.
+---------------

I don't know the portable way, if any, but CMUCL provides an
extension to macro LAMBDA lists which helps with this, the
&PARSE-BODY (&optional body decls doc-strings) keyword, which
could be used to do what you want [I think]:

  (defmacro my-let-if (condition bindings &body (forms decls))
    (multiple-value-bind (binding-decls other-decls)
	(split-decls bindings decls)
      `(if ,condition
	 (let ,bindings ,@binding-decls ,@other-decls ,@forms)
	 (locally ,@other-decls ,@forms))))

where SPLIT-DECLS is left as an exercise for the reader.  ;-}  ;-}

By the way, here's how CMUCL uses &PARSE-BODY to define DEFUN itself:

  (defmacro defun (&whole source name lambda-list &parse-body (body decls doc))
    (multiple-value-bind (valid block-name)
	(valid-function-name-p name)
      (declare (ignore valid))
      (let ((def `(lambda ,lambda-list
		    ,@decls
		    (block ,block-name ,@body))))
	`(c::%defun ',name #',def ,doc ',source))))

The DECLS are separated out so that they can be placed in front of
the BLOCK which wraps BODY (and names it so RETURN-FROM will work).


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607