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)
(eval
#`(phase1-eval
(syntax-procedure-converted-arguments-property
(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.
Ryan
_________________________
Racket Developers list:
http://lists.racket-lang.org/dev