[racket-dev] expand, local-expand, and syntax-procedure-converted-arguments-property

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Wed Jul 10 23:15:46 EDT 2013

On 07/10/2013 09:04 PM, Asumu Takikawa wrote:
> Hi all,
> I'm currently trying to fix the Typed Racket unit tests. I think I've
> narrowed down the issue to a certain syntax property for keyword
> functions.
> The issue is illustrated by the following example:
>    #lang racket
>    (require racket/file
>             (for-syntax racket/file
>                         racket/keyword-transform))
>    ;; the property is #f
>    (begin-for-syntax
>     (displayln
>       (syntax-case (expand-syntax #'(copy-directory/files 1 2)) ()
>         [(let-values (((temp1) _)
>                       ((temp2) _))
>            (if _
>                (#%plain-app1 copy-directory/files15 e1 ...)
>                (#%plain-app2 copy-directory/files17 e2 ...)))
>          (syntax-procedure-converted-arguments-property #'copy-directory/files15)])))
>    ;; property is syntax
>    (begin-for-syntax
>     (displayln
>       (syntax-case (local-expand #'(copy-directory/files 1 2) 'expression null) ()
>         [(let-values (((temp1) _)
>                       ((temp2) _))
>            (if _
>                (#%plain-app1 copy-directory/files15 e1 ...)
>                (#%plain-app2 copy-directory/files17 e2 ...)))
>          (syntax-procedure-converted-arguments-property #'copy-directory/files15)])))
> There are two syntax-time computations here. Both are expanding an
> application of a keyword function (one with local-expand, one with
> expand) and looking at the resulting syntax.
> The key point here is that I want to find the property looked up by
> `syntax-procedure-converted-arguments-property` on an output identifier
> because Typed Racket needs it to type-check the expansion.
> Unfortunately, as the comments indicate, only the second piece of code
> can find the property. The reason appears to be that the property key is
> actually a private `gensym`ed symbol and the two pieces of code appear
> to get separate instantiations of the kw.rkt module (perhaps at different
> phases).
> To check that, if I modify kw.rkt to use a plain symbol, both of the
> snippets above return the same property value.
> Anyone have any idea how I can keep using `expand` but still be able to
> look up the property?

To get information about a phase-0 '#%app' expansion, you need to call 
the phase-1 version of 'syntax-procedure-converted-arguments-property'. 
That's going to require a bit of phase-crossing trickery, because the 
identifier you want to query is a phase-0 (dynamic) value, and you want 
the result as a phase-0 value, but the phase-1 function naturally 
consumes and produces phase-1 values.

One solution is to use 'quote-syntax', 'eval', and 'phase1-eval' all 
together. Use 'eval' with 'quote-syntax' to convert the phase-0 
identifier to a phase-1 identifier. Use 'phase1-eval' to run the 
computation at phase 1 and capture the phase-1 result as a phase-0 value 
(also using 'quote-syntax').

Here's the code:

(require unstable/macro-testing)

(define (get-converted-args-property proc-id)
        (quote-syntax #,proc-id))
       #:quote quote-syntax)))

(printf "property is ~s\n"
         (syntax-case (expand-syntax #'(copy-directory/files 1 2)) ()
           [(let-values (((temp1) _)
                         ((temp2) _))
              (if _
                  (#%plain-app1 copy-directory/files15 e1 ...)
                  (#%plain-app2 copy-directory/files17 e2 ...)))
            (get-converted-args-property #'copy-directory/files15)]))

Note that by asking 'phase1-eval' to convert the phase-1 result to a 
phase-0 value using 'quote-syntax', we've converted the pair of 
identifiers to a syntax object containing the pair. You'll have to break 
it apart again yourself.


Posted on the dev mailing list.