[racket-dev] [racket] When does 3D syntax get marshalled?

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Tue Jan 22 18:47:46 EST 2013

Your explanation sounds correct, but 3D syntax is not encouraged and not 
supported. I think the fix is to change your macro to avoid 3D syntax. 
It's a little awkward due to the lack of let-for-syntax (and 
splicing-let-for-syntax, I guess), but how about the following (not tested):

(define-syntax-rule (M id body)
   (splicing-let*-syntax
       ([new-tr
         (let ([p-tr (syntax-parameter-value #'p)])
           (λ (syn) (syntax-case syn () [(_ e) (p-tr #'(foo e))])))]
        [id
         (λ (stx)
            (syntax-case stx ()
              [(_ blah)
               #`(splicing-syntax-parameterize
                     ([p (syntax-local-value #'new-tr)])
                   (id blah))])))])
     body))

... except that there doesn't seem to be a splicing-let*-syntax, either, 
so you'll have to do this instead (or use splicing-letrec-syntax, maybe):

(define-syntax-rule (M id body)
   (splicing-let-syntax
       ([new-tr
         (let ([p-tr (syntax-parameter-value #'p)])
           (λ (syn) (syntax-case syn () [(_ e) (p-tr #'(foo e))])))])
     (splicing-let-syntax
         ([id
           (λ (stx)
              (syntax-case stx ()
                [(_ blah)
                 #`(splicing-syntax-parameterize
                       ([p (syntax-local-value #'new-tr)])
                     (id blah))]))])
       body))

Ryan


On 01/22/2013 06:19 PM, J. Ian Johnson wrote:
> [Moving to dev]
> The problem is with the implementation of splicing-syntax-parameterize, which turns the parameterization of p to #,new-tr into a TOP LEVEL define-syntax, which does NOT expand away, leading to this borkage. This calls for an mflatt.
> -Ian
> ----- Original Message -----
> From: "J. Ian Johnson" <ianj at ccs.neu.edu>
> To: "J. Ian Johnson" <ianj at ccs.neu.edu>
> Cc: "users" <users at racket-lang.org>
> Sent: Tuesday, January 22, 2013 6:08:49 PM GMT -05:00 US/Canada Eastern
> Subject: Re: [racket] When does 3D syntax get marshalled?
>
> I found that this example does NOT work if you take the use of M out of its expression context. Problem program:
>
> #lang racket
> (require racket/stxparam racket/splicing)
> (define-syntax-parameter p #f)
> (define-syntax-rule (M id body)
>      (splicing-let-syntax
>       ([id
>         (let* ([p-tr (syntax-parameter-value #'p)]
>                [new-tr (λ (syn) (syntax-case syn () [(_ e) (p-tr #'(foo e))]))])
>           (λ (stx)
>              (syntax-case stx () [(_ blah)
>                                   #`(splicing-syntax-parameterize ([p #,new-tr])
>                                       (id blah))])))])
>       body))
> (define-syntax-rule (F x) (list x))
> (splicing-syntax-parameterize ([p (syntax-rules () [(_ e) e])])
>    (M F (F 'small-example)))
>
> Thoughts?
> -Ian
> ----- Original Message -----
> From: "J. Ian Johnson" <ianj at ccs.neu.edu>
> To: "J. Ian Johnson" <ianj at ccs.neu.edu>
> Cc: "users" <users at racket-lang.org>
> Sent: Tuesday, January 22, 2013 1:48:55 PM GMT -05:00 US/Canada Eastern
> Subject: Re: [racket] When does 3D syntax get marshalled?
>
> Here is a concrete example that is an outline of what I do. It works.
> However, in my project, when I replace F with the form that I actually defined and mix in more for p's transformer, I get that new-tr cannot be marshalled in the compiled code. This baffles me.
>
> #lang racket
> (module A racket
>    (require racket/stxparam racket/splicing)
>    (provide M p)
>    (define-syntax-parameter p #f)
>    (define-syntax-rule (M id body)
>      (splicing-let-syntax
>         ([id
>           (let* ([p-tr (syntax-parameter-value #'p)]
>                  [new-tr (λ (syn) (syntax-case syn () [(_ e) (p-tr #'(foo e #;mix-in-more-here))]))])
>             (λ (stx)
>                (syntax-case stx () [(_ blah)
>                                     #`(splicing-syntax-parameterize ([p #,new-tr])
>                                         (id blah #;mix-in-more-here))])))])
>         body)))
> (module B racket
>    (require (submod ".." A) racket/splicing)
>    (define-syntax-rule (F x) (list x))
>    (splicing-syntax-parameterize ([p (syntax-rules () [(_ e) e])])
>      (printf "~a~%" (M F (F 'small-example)))))
> (require 'B)
>
> Very frustrating.
> -Ian
> ----- Original Message -----
> From: "J. Ian Johnson" <ianj at ccs.neu.edu>
> To: "users" <users at racket-lang.org>
> Sent: Tuesday, January 22, 2013 12:12:28 PM GMT -05:00 US/Canada Eastern
> Subject: [racket] When does 3D syntax get marshalled?
>
> I have a fairly crazy macro that chains together syntax transformers that are stored in syntax-parameters to get a sort of "macro mix-in" if you will. In order to do this, I have code that looks like the following:
> (define old-tr (syntax-parameter-value #'p))
> (define new-tr (syntax-parser [(_ blah) (old-tr #'(modified-blah))]))
> (syntax-parser [(_ macro-in) #'(syntax-parameterize ([p #,new-tr]) macro-out)])
>
> Often this works. However, I am now putting this kind of code inside of a let-syntax that is the product of a macro that is given the identifier to bind in the let-syntax. The use of this macro uses the bound identifier, which (in my head) should just use this transformer, expand away and not have to be marshalled. There is no documentation for the term "3D syntax" so I wasn't sure where I could read why my mental model is flawed.
>
> So, what could be happening here that would cause the marshalling?
>
> -Ian
> ____________________
>    Racket Users list:
>    http://lists.racket-lang.org/users
>
> _________________________
>    Racket Developers list:
>    http://lists.racket-lang.org/dev
>



Posted on the dev mailing list.