I realized I probably also ought to post my workaround, which I use in
Hackett: I just don’t use preserved syntax properties at all (only
unpreserved ones). I found that sticking syntax objects in preserved
syntax properties was unreliable, probably for the reasons Matthew
mentioned in the aforementioned email thread.

Instead of using preserved syntax properties, I just read the property
earlier, then embed its value (or an expression that produces its value)
in the expanded syntax instead of reading/transferring it “just in
time”. This avoids the need for properties to preserved in bytecode.
What do I mean by this? Well, instead of expanding to something like
this:

    #'(define-syntax x
        (make-variable-like-transformer
          (syntax-property #'x* 'prop (syntax-property #'y 'prop)))

...where 'prop is preserved on #'y, I instead expand to something like
this:

    #`(define-syntax x
        (make-variable-like-transformer
          (syntax-property
           #'x* 'prop
           (quote-syntax #,(syntax-property #'y 'prop))))

This way, the syntax property’s value is actually embedded in the fully
expanded syntax as an expression, and the invocation of
make-variable-like-transformer receives a “hardcoded” value. This means
'prop no longer needs to be preserved on #'y.

I managed to fix your example program with this technique. This changes
the definitions of define-stuff and define-thing to the following:

    (define-syntax-parser define-stuff
      [(_ name:id)
       #:with name* ((make-syntax-introducer) #'name)
       #'(begin
           (define name* 'stuff)
           (define-syntax name
             (make-variable-like-transformer
              (syntax-property #'name* 'prop #'name))))])

    (define-syntax-parser define-thing
      [(_ name:id stuff:id)
       #:with stuff* (local-expand #'stuff 'expression '())
       #`(define-syntax name
           (make-variable-like-transformer
            (syntax-property
             #''thing
             'prop
             (quote-syntax #,(syntax-property #'stuff* 'prop)))))])

Now, you might argue that this technique doesn’t apply in general, since
it explicitly uses quote-syntax, which wouldn’t work for other things
that can be put into preserved syntax properties. That’s true! In fact,
I use prefab structures as my types in Hackett, so I needed to provide
a replacement for preserved properties containing prefab structures.
Fortunately, it is trivial to produce an expression that evaluates to
and value that is a valid preservable syntax property. The function
Hackett uses looks like this:

    (define preservable-property->expression
      (match-lambda
        [(and (app prefab-struct-key (? values prefab-key))
              (app struct->vector (vector _ fields ...)))
         #`(make-prefab-struct
            '#,prefab-key
            #,@(map preservable-property->expression fields))]
        [(? list? lst)
         #`(list #,@(map preservable-property->expression lst))]
        [(cons a b)
         #`(cons #,(preservable-property->expression a)
                 #,(preservable-property->expression b))]
        [(? syntax? stx)
         #`(quote-syntax #,stx)]
        [(and (or (? boolean?) (? symbol?) (? number?) (? char?)
                  (? string?) (? bytes?) (? regexp?))
              datum)
         #`(quote #,datum)]
        [other
         (error 'preservable-property->expression
                "non-preservable syntax property\n  value: ~e"
                other)]))

To use this function, just replace the hardcoded use of quote-syntax to
an evaluated use of preservable-property->expression. Using this
function, define-thing looks like this:

    (define-syntax-parser define-thing
      [(_ name:id stuff:id)
       #:with stuff* (local-expand #'stuff 'expression '())
       #`(define-syntax name
           (make-variable-like-transformer
            (syntax-property
             #''thing
             'prop
             #,(preservable-property->expression
                (syntax-property #'stuff* 'prop)))))])

This wouldn’t work for any use of preservable syntax properties, since
it relies on the particular interplay of make-variable-like-transformer
and local-expand that Turnstile uses. However, I think it will work for
your case.

Alexis

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-dev/67E48B41-45B9-47D4-B47B-DF14FE66B23E%40gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to