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

From: Sam TH (samth at ccs.neu.edu)
Date: Wed Mar 18 18:20:42 EDT 2009

On Wed, Mar 18, 2009 at 5:48 PM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> 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.

That makes sense.

> 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))))

No, this won't work.  One problem is that these identifiers appear in
contexts that are not expression positions (in particular, in types).
Another problem is that the relevant identifier may be bound to
something else (such as static struct information), and the only way
the typechecker interferes with it is by using it as the key in a
`free-identifier-mapping'.  So wrapping these identifiers in something
else would break in at least two ways.

I vote for the non-recursive version of `syntax-local-value'  It's the
simpler operation, and the idea of the general form being
implementable in Scheme rather than C is appealing.
sam th
samth at ccs.neu.edu

Posted on the dev mailing list.