[plt-dev] syntax-local-value and identifier-mappings
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
(make-typed-id
(if (typed-context?)
#'foo*
#'other-foo))))