All,

Thanks for help debugging and explaining this.

FYI, with Matthew's bug fix merged, and help from Alexis, I've managed to work 
around my issue. It was pretty much the same issue described in thread linked 
to by Dupéron, 
https://groups.google.com/forum/#!topic/racket-users/TGax2h8dVxs, and also in 
the Racket GitHub issue https://github.com/racket/racket/issues/1495.

The workaround seems to be: if you want to stash an identifier in a 
syntax-property, expand into syntax that attaches the syntax-property. That is, 
don't do (define x (syntax-property #'id 'prop #'stx)) and then use x in a 
syntax object, but generate #`(... (syntax-property #'id 'prop #'stx ...))

In my example, the identifier that caused issues was generated by define^, 
which directly called syntax-property in a for-syntax helper function. The 
identifier that worked fine was generated by define^^, which generated syntax 
that included a syntax-property.

Maybe we shouldn't be stashing identifiers in syntax-properties at all, but in 
practice this workaround seems to work (in the implementations of Alexis' 
Rascal and my Cur).

--
William J. Bowman

On Wed, Dec 14, 2016 at 08:14:49AM -0700, Matthew Flatt wrote:
> 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.

Attachment: signature.asc
Description: PGP signature

Reply via email to