[plt-scheme] an issue with macros expanding to transformers

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Mar 2 18:21:01 EST 2009

An explanation for why you need a `(meta -1)' binding for your macro:

 (define-syntax make-transformer
   (syntax-rules ()
     ((_ (name value) ...) (syntax-rules (<names> name ...)
                             ((_ <names>) '(name ...))
                             ((_ name) value) ...))))
 )

When you move to the right-hand side of `define-syntax', then the
relevant binding level is more more than the context of the definition.
So, if we start from 0, then we move to 1 for the outer `syntax-rules'.
That should be as expected; you're using `syntax-rules' in an
expand-time position.

When you go into a template, as in the right-hand side of a
`syntax-rules' clause, then you go back down one phase level. So from 1
for the outer `syntax-rules', we'd go back down to 0 for the binding of
the inner `syntax-rules'. (A `for ... expand' import will shift this
back up to phase level 1.)

Unusually in this case, the content of the template is itself a
`syntax-rules', which has its own templates. We go down one more level
for the nested template that contains a quote. That is, we go from
level 0 for the inner `syntax-rules' to level -1 for the quote. (Again,
a `for ... expand' import shifts it back to phase level 0, which
corresponds to run-time of the importing module.)

So, the macro needs a binding for `quote' at phase level -1.


At Mon, 02 Mar 2009 08:39:20 -0700, Chongkai Zhu wrote:
> The following works on my computer:
> 
> 
> #!r6rs
> (library (helper)
>         
>          (export make-transformer)
>          (import (rnrs) (for (rnrs) (meta -1)))
>         
>          (define-syntax make-transformer
>            (syntax-rules ()
>              ((_ (name value) ...)
>               (syntax-rules (<names> name ...)
>                 ((_ <names>) '(name ...))
>                 ((_ name) value) ...))))
>          )
> 
> Chongkai
> 
> Michele Simionato wrote:
> > While porting some macros from Ikarus to PLT Scheme I found out an
> > issue
> > that baffles me.
> > Here is the simplified version of the problem. I want to define a
> > second
> > order macro, i.e. a macro which expands to a macro transformer.
> > So I put in a helper module the following make-transformer macro:
> >
> > #!r6rs
> > (library (helper)
> > (define-syntax make-transformer
> >   (syntax-rules ()
> >     ((_ (name value) ...) (syntax-rules (<names> name ...)
> >                             ((_ <names>) '(name ...))
> >                             ((_ name) value) ...))))
> > )
> >
> > Then I tried to use it in a script as follows:
> >
> > #!r6rs
> > (import (rnrs) (for (helper) expand))
> >
> > (define-syntax m (make-transformer (x 1) (y 2)))
> > (display (m x))
> > (display (m y))
> > (display (m <names>))
> >
> > In theory the macro m should be equivalent to
> >
> > (define-syntax m (syntax-rules (<names> x y)
> >                             ((_ <names>) '(x y))
> >                             ((_ x) 1)
> >                             ((_ y) 2)))
> >
> > and actually (m x) returns 1 and (m y) returns 2 as expected.
> > However, (m <names>) does not return '(x y) as it should;
> > instead I get an error:
> >
> >  compile: bad syntax; function application is not allowed, because no #
> > %app syntax transformer is bound in: (quote (x y))
> >
> > (tested in PLT 4.0). How am I supposed to solve this?
> > TIA,
> >
> >                            Michele Simionato
> > _________________________________________________
> >   For list-related administrative tasks:
> >   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> >   
> 
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme


Posted on the users mailing list.