I think there are two problems in this example.

The first problem is that preserved syntax properties were not actually
preserved in bytecode for a syntax object that has no source location.
(I'm assuming that Alexis's tests were run in DrRacket in it's default
mode of compiling bytecode for `require`d files.) I'll push a repair
for that bug.


The second problem is that syntax objects as property values don't work
the way that you want. That limitation is why, even with the
property-presevation bug fixed, the `free-identifier=?` test fails.
Unfortunately, that's a limitation of syntax objects and properties
that's difficult to resolve.

To explain a little more, consider the program

 https://gist.github.com/mflatt/d569d8f3a89e6815cf18df26adc11053

For now, look at just the `property` submodule. The
`quote-syntax/add-example-property` macro is like `quote-syntax`,
except that it adds an 'example property that holds the current time at
compile time.

An expression like

 (syntax-property (quote-syntax/add-example-property id) 'example)

accesses that compile-time value at run time. If you compile the
program to bytecode, the value shown by running the module later still
reports the time that the module was compiled.

Now consider the enclosing module, which uses the `property` submodule
and accesses the time for both a freshly quoted term and the value of
`id` as exported by the submodule:

 (require 'property)
 (syntax-property (quote-syntax/add-example-property new-id) 'example)
 (syntax-property id 'example)

I think you won't be too surprised that the freshly quoted identifier
has a newer time than the one reported for `id`. Even though both
values were obtained from the same `compile-time` variable, each module
compilation (submodule and enclosing module) gets a fresh instance of
`compile-time`.


In "format-id1.rkt", instead of `compile-time` bound to a timestamp,
you have a quoted syntax object that you can image being implicitly
lifted as

  (define-for-syntax compile-time #'id^)

In much the same way that `(current-inexact-milliseconds)` in

  (define-for-syntax compile-time (current-inexact-milliseconds))

produces a different result for each subsequent compile-time use of the
modules, `#'id^` produces a different syntax object depending on how
its enclosing module is instantiated. Imagine taking the compiled
bytecode, saving it in two places, and loading it as a module from each
place; the `#'id` evaluations for the copies will produce identifiers
that claim to be from different modules relative to the filesystem.

So, here's the limitation: the implicit lifting that happens for a
quoted syntax object, which enables a kind of re-evaluation of that
syntax object in each module instance, doesn't happen for
syntax-property values. More generally, changes to the scope of a
syntax object are not propagated to property values that happen to be
themselves syntax objects. When you put a syntax object into a
property, then you get whatever that syntax object meant at the time it
was attached as a property.

That might still sound ok for your case, because you compile and use
"format-id1.rkt" in-place. Still, the information attached to `#'id^`
changes. While compiling the module, the attached binding information
says "the current module being compiled". When compiling
"format-id2.rkt", the attached binding information for that `#'id^`
says "format-id1.rkt".


To summarize, don't try to attach syntax objects as property values
like that. I know this advice sounds ironic, given that the original
use of properties was for syntax-valued keys like 'origin. Properties
like 'origin are meant to be extracted from just-expanded programs,
though, as opposed to used in a later compilation step. At the same
time, those uses of properties are why we can't just make
`syntax-property` reject property values that are syntax objects.


At Tue, 13 Dec 2016 14:16:49 -0800, Alexis King wrote:
> > On Dec 13, 2016, at 11:23 AM, 'William J. Bowman' via Racket Users
> > <racket-users@googlegroups.com> wrote:
> > 
> > Notice that #'x is not the same identifier as x, and thus does not
> > have the same syntax-properties.
> 
> I’m not convinced this is correct.
> 
> If you insert println statements in the body of define^, inside the
> with-syntax block, you get the following:
> 
>   (println (syntax-property #'x 'definition))
>   (println (syntax-property-preserved? #'x 'definition))
> 
>   ; => #<syntax:format-id1.rkt:49:12 id^>
>   ; => #t
> 
> The syntax properties are definitely maintained in templates used
> by `syntax`.
> 
> > Why does this issue only comes up across a file boundary? I suspect
> > this has to do with the behavior of make-rename-transformer. Since
> > #'x was not getting 'not-free-identifier=? correctly,
> > make-rename-transformer was optimizing this away, although I thought
> > I was preventing that.
> 
> This is more interesting, and it was my first instinct, too. For
> that reason, I replaced uses of make-rename-transformer with uses
> of make-variable-like-transformer from syntax/transformer, but the
> behavior was the same, so I don’t think this has to do with
> make-rename-transformer specifically. However, something more
> interesting happens.
> 
> I changed the macro that define^ defines to insert some debugging
> calls on macro invocation:
> 
>   (define-syntax (id stx)
>     (println (syntax-property #'x 'definition))
>     (println (syntax-property-preserved? #'x 'definition))
>     ((set!-transformer-procedure
>       (make-variable-like-transformer #'x))
>      stx))
> 
> The output of this is much more interesting. When running the source
> module, format-id1.rkt, the result is as one would expect:
> 
>   ; => #<syntax:format-id1.rkt:49:12 id^>
>   ; => #t
> 
> However, when using the defined identifier from format-id2.rkt, the
> result is different:
> 
>   ; => #f
>   ; => #f
> 
> This is extremely interesting, since the first example demonstrates
> that the syntax property is most definitely marked as preserved,
> yet it gets lost by the time format-id2 tries to get at it, despite
> the fact that it should be the same exact syntax object.
> 
> My guess as to what’s going on here is that the issue is not with
> make-rename-transformer but with quote-syntax. The above program
> expands into a macro definition that has (quote-syntax x) in it,
> and the x has a preserved syntax property on it. However, that
> property is not actually preserved, despite being marked as preserved.
> This is different from other uses of preserved syntax properties
> that attach their syntax properties to expressions in the resulting
> program, rather than quoted pieces of syntax.
> 
> This feels very confusing, and it certainly feels like a bug, but
> maybe Matthew has an explanation for this behavior that I don’t
> currently understand?
> 
> Alexis
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to