[racket] syntax-parse #:at
The following example has some tricky hygiene issues that I don't quite understand. The point of the code is to have a form that creates macros by analyzing the pattern and template.
The issue is why do I have to use a name other than 'name' for the pattern variable on the line where it says 'HERE'. If I use the 'name' pattern variable then the syntax-parse form generated by 'make-transformer' will use the wrong lexical context for the literal set. I don't see how the lexical context of the outer 'name' differs from the inner 'new-name', other than the 'new-name' has an extra mark on it. Is that the issue? I tried all sorts of debugging techniques but I can't tell if 'name' has a different lexical context than 'new-name'. I see that marks affect 'bound-identifier=?' but they don't seem to effect 'free-identifier=?' which is what syntax/parse uses to compare literals.
#lang racket
(require (for-syntax syntax/parse)
(for-meta 2 racket/base
syntax/parse))
;; defines a literal and a literal-set that contains the literal
(module literals racket/base
(require syntax/parse)
(provide literal1 literals)
(define literal1 0)
(define-literal-set literals (literal1)))
(module transformer racket/base
(require (for-syntax syntax/parse
(submod "." ".." literals)
racket/base)
racket/splicing
(for-meta 2 syntax/parse
racket/base))
(begin-for-syntax
(define-syntax (make-transformer stx)
(syntax-parse stx
[(_ name pattern template)
#'#'(lambda (stx)
(syntax-parse stx
#:literal-sets ([literals #:at name])
[pattern template]))])))
(provide define-new-syntax)
(define-syntax (define-new-syntax stx)
(syntax-parse stx
[(_ name pattern template)
#'(splicing-let-syntax
([make (lambda (stx)
(syntax-parse stx
[(_ new-name) ;; HERE! If you change this to 'name' it will break
(with-syntax ([output (make-transformer name pattern template)])
#'(define-syntax new-name output))]))]) ; change to 'name' too
(make name))])))
(require (submod "." literals)
(for-syntax (submod "." literals))
(for-meta 2 (submod "." literals))
(submod "." transformer))
(begin-for-syntax
(define-syntax (test stx)
(syntax-parse stx
#:literal-sets (literals)
[(_ literal1) #''ok])))
;; if `literal1' isn't matched as a literal then the call to
;; (test literal1) will fail
(define-new-syntax x
[_ literal1]
(begin
(test literal1)
#'0))
(x literal1)
More explanation about this code:
It was recommended to me that the code which analyzes the pattern and template should execute at a phase higher than the phase of the pattern/template. Since the macro is defined at phase 0 the pattern and template live in phase 1 and should be analyzed in phase 2. I cannot just invoke a macro inside the body of 'define-new-syntax' on the 'pattern' and 'template' parameters because then the macro would get the literal syntax objects #'pattern and #'template instead of the syntax they are bound to. As in
(define-syntax (define-new-syntax stx)
(syntax-parse stx
[(_ name pattern template)
(analyze pattern template)]))
Nor would it be right to make 'analyze' a function at phase 1 and invoke it as (analyze #'pattern #'template) because I need to execute analyze at phase 2.
I get to phase 2 by using a let-syntax trampoline in the output of the 'define-new-syntax' macro. The 'pattern' and 'template' variables will have been replaced with their matched syntax as appropriate so the 'make-transformer' macro will operate on the arguments used at the 'define-new-syntax' use-site.
The resulting 'x' macro does nothing except invoke a phase 1 macro. This test is necessary to insure that 'literal1' was matched as a literal and not a pattern variable.
On 05/17/2012 02:52 PM, Jon Rafkind wrote:
> Ok I see from the syntax/parse source that it uses lctx as the first argument to datum->syntax, so that mostly answers my question.
>
> On 05/17/2012 02:41 PM, Jon Rafkind wrote:
>> What exactly are the semantics of #:at inside a #:literal-sets ([x #:at y]) ?
>>
>> From the docs " If the #:at keyword is given, the lexical context of the lctx term is used to determine which identifiers in the patterns are treated as literals;". In what way is 'lctx' used?
>>
>>
>> ____________________
>> Racket Users list:
>> http://lists.racket-lang.org/users
>
>
>
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120520/0eee8bdc/attachment-0001.html>