[plt-dev] syntax-local-value and identifier-mappings

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Wed Mar 18 17:48:15 EDT 2009

At Mon, 9 Mar 2009 18:22:14 -0600, Matthew Flatt wrote:
> One last possibility, which I had not really considered until now, is
> to have the macro expander treat a transformer binding to a renamer by
> applying a syntax-object renaming immediately, instead of merely
> installing a transformer binding. That sounds promising to me, and I
> could give it a try next week or so.

It seemed strange to me is that running a transformer expression would
determine `free-identifier=?' equivalences. Of course, transformers
create binding forms all the time, so I couldn't quite put my finger on
why that should be a problem...

At Mon, 9 Mar 2009 20:33:17 -0400, Sam TH wrote:
> On Mon, Mar 9, 2009 at 8:22 PM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> So, in one sense, if (as you suggest) `free-identifier=?' cooperated
> with rename transformers, then that would work.  But the other
> constraint is that I need the binding form to operate at the
> expression level, since the code that uses `make-rename-transformer'
> looks like this:
> (define-syntax foo
>    (if (typed-context?)
>        (make-rename-transformer #'foo*)
>        (make-rename-transformer #'other-foo)))
> so something like `define-renaming' wouldn't work.

...but this really should have made me see.

The context of the `foo' definition will be parsed/expanded once and
for all, which means that `free-identifier=?' equivalences in that
context are fixed. But this syntax definition is evaluated many times
afterward, once for each "visit" to the enclosing module. I didn't make
the connection between "expression level" and "can produce different
results at different times", and the latter is a feature that Typed
Scheme relies on.

The problem is easier to see if you think about `for-label' imports,
which don't "visit" the imported module. If a module containing the
above definition is imported `for-label', should `foo' be
`free-label-identifier=?' to `foo*' or `other-foo'? There's no way to
say, because the `if' expression isn't evaluated.

Back to the drawing board.

I think `define-renaming' in roughly its current form (as a pattern of
a transformer binding plus `make-rename-transformer') is useful. It
doesn't solve the problem in Typed Scheme, though.

We could add a `syntax-local-value' that doesn't recur, but now I
wonder: do bindings like `foo' really need to be created with
`make-rename-transformer'? Could they instead be implemented as macro
transformers that are actually procedure instances, so Typed Scheme
could chain through the renaming manually? I have in mind something
like this:

  (define-struct typed-id (orig)
     #:property prop:procedure (lambda (stx self)
                                  (syntax-case stx ()
                                   [(id arg ...)
                                    #`(#,(typed-id-orig self) arg ...)] 
                                   [id (typed-id-orig self)])))

  (define-syntax foo
      (if (typed-context?)

Posted on the dev mailing list.