From: Matthew D Swank
Subject: parse-macro
Date: 
Message-ID: <pan.2006.02.18.11.41.36.935166@c.net>
So I'm implementing parse-macro from CLtL2 to fill out Allegro's
portable environment implementation a little bit, and I am scratching my
head at the specification of macro lambda lists and destructuring lambda
lists.

from the hyperspec:
-------------------
3.4.4: on macro lambda lists

&whole is followed by a single variable that is bound to the entire
macro-call form; this is the value that the macro function receives as
its first argument. If &whole and a following variable appear, they must
appear first in lambda-list, before any other parameter or lambda list
keyword. &whole *can appear at any level of a macro lambda list*. At inner
levels, the &whole variable is bound to the corresponding part of the
argument, as with &rest, but unlike &rest, other arguments are also
allowed. The use of &whole does not affect the pattern of arguments
specified.

3.4.5 on destucturing lambda lists

Destructuring lambda lists are closely related to macro lambda lists; see
Section 3.4.4 (Macro Lambda Lists). A destructuring lambda list can
contain all of the lambda list keywords listed for macro lambda lists
except for &environment, and supports destructuring in the same way. Inner
lambda lists nested within a macro lambda list have the syntax of
destructuring lambda lists.

lambda-list::= (wholevar reqvars optvars restvar keyvars auxvars) |
               (wholevar reqvars optvars . var) 
--------------------

Since &environment can ony appear in top level lambda list of a macro, it
would make sense that after extracting the environment argument from the
macro lambda list (if it exists) it should be possible to parse the
remaining lambda list using destructuring-bind.

However there are two problems:
	1. &whole seems like it should have different semantics in a top
	level macro lambda list than it would in an inner lambda list, or even
	destructuring lambda list.  In a macro the lambda list is a pattern to
	parse the cdr of the form, and &whole allows you to bind the entire form
	to a variable. What is the "entire form" in an inner lambda lists, or the
	top level lambda list in a destructuring-bind?

	2. problem one is complete speculation since I can't get an
	implementation to handle macros defined with &whole args in inner lambda
	lists, or destructuring-bind with &whole arguments anywhere. I usually
	get errors like:
		 (destructuring-bind (&whole foo) '(1 2 3) foo)

		*** - The object to be destructured should be a list with 0 elements,
		not   (1 2 3)

Am I misinterpreting the spec?


Matt

	

 

-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.

From: Pascal Costanza
Subject: Re: parse-macro
Date: 
Message-ID: <45og3tF7ckb7U1@individual.net>
Matthew D Swank wrote:
> So I'm implementing parse-macro from CLtL2 to fill out Allegro's
> portable environment implementation a little bit, and I am scratching my
> head at the specification of macro lambda lists and destructuring lambda
> lists.
> 
> from the hyperspec:
> -------------------
> 3.4.4: on macro lambda lists
> 
> &whole is followed by a single variable that is bound to the entire
> macro-call form; this is the value that the macro function receives as
> its first argument. If &whole and a following variable appear, they must
> appear first in lambda-list, before any other parameter or lambda list
> keyword. &whole *can appear at any level of a macro lambda list*. At inner
> levels, the &whole variable is bound to the corresponding part of the
> argument, as with &rest, but unlike &rest, other arguments are also
> allowed. The use of &whole does not affect the pattern of arguments
> specified.
> 
> 3.4.5 on destucturing lambda lists
> 
> Destructuring lambda lists are closely related to macro lambda lists; see
> Section 3.4.4 (Macro Lambda Lists). A destructuring lambda list can
> contain all of the lambda list keywords listed for macro lambda lists
> except for &environment, and supports destructuring in the same way. Inner
> lambda lists nested within a macro lambda list have the syntax of
> destructuring lambda lists.
> 
> lambda-list::= (wholevar reqvars optvars restvar keyvars auxvars) |
>                (wholevar reqvars optvars . var) 
> --------------------
> 
> Since &environment can ony appear in top level lambda list of a macro, it
> would make sense that after extracting the environment argument from the
> macro lambda list (if it exists) it should be possible to parse the
> remaining lambda list using destructuring-bind.
> 
> However there are two problems:
> 	1. &whole seems like it should have different semantics in a top
> 	level macro lambda list than it would in an inner lambda list, or even
> 	destructuring lambda list.  In a macro the lambda list is a pattern to
> 	parse the cdr of the form, and &whole allows you to bind the entire form
> 	to a variable. What is the "entire form" in an inner lambda lists, or the
> 	top level lambda list in a destructuring-bind?
> 
> 	2. problem one is complete speculation since I can't get an
> 	implementation to handle macros defined with &whole args in inner lambda
> 	lists, or destructuring-bind with &whole arguments anywhere. I usually
> 	get errors like:
> 		 (destructuring-bind (&whole foo) '(1 2 3) foo)
> 
> 		*** - The object to be destructured should be a list with 0 elements,
> 		not   (1 2 3)
> 
> Am I misinterpreting the spec?

&whole doesn't specify how many arguments are allowed to be passed, it 
just grabs the whole form, that's all.

Try (destructuring-bind (&whole foo a b c) '(1 2 3) foo)


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Matthew D Swank
Subject: Re: parse-macro
Date: 
Message-ID: <pan.2006.02.18.12.25.04.882405@c.net>
On Sat, 18 Feb 2006 12:52:28 +0100, Pascal Costanza wrote:

> &whole doesn't specify how many arguments are allowed to be passed, it 
> just grabs the whole form, that's all.
> 
> Try (destructuring-bind (&whole foo a b c) '(1 2 3) foo)
> 
> 
> Pascal

Ok that makes more sense.  So I could, in theory treat macro lambda lists
uniformly by a adding hidden (from the caller) &whole argument to macro
lambda lists that don't have them, and binding the env separately in a
let:

(parse-macro 'foo 
             '(&whole form &environment a &rest args)
             '(`(+ ,@(cdr form))))

==>
(LAMBDA (#:G1075 #:G1076)
  (DECLARE (IGNORABLE #:G1075 #:G1076))
  (LET ((A #:G1076))
    (DESTRUCTURING-BIND
        (&WHOLE FORM &REST ARGS)
        #:G1075
      (BLOCK FOO `(+ ,@(CDR FORM))))))

(parse-macro 'foo 
             '(&environment a &rest args) 
             '(`(+ ,@args)))

==>
(LAMBDA (#:G1078 #:G1079)
  (DECLARE (IGNORABLE #:G1078 #:G1079))
  (LET ((A #:G1079))
    (DESTRUCTURING-BIND
        (&WHOLE #:G1077 &REST ARGS)
        #:G1078
      (BLOCK FOO `(+ ,@ARGS)))))
 

-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: Matthew D Swank
Subject: Re: parse-macro
Date: 
Message-ID: <pan.2006.02.18.12.43.02.585185@c.net>
On Sat, 18 Feb 2006 06:26:49 -0600, Matthew D Swank wrote:


>So I could, in theory treat macro lambda lists
> uniformly by a adding hidden (from the caller) &whole argument to macro
> lambda lists that don't have them, and binding the env separately in a
> let:
> 

On second thought this is a horrible idea as the rest of the macro lambda
list needs to match the cdr of the form, not the whole form.

Matt

-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.