<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <meta http-equiv="content-type" content="text/html;
      charset=ISO-8859-1">
    <pre style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; word-wrap: break-word; white-space: pre-wrap; ">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.</pre>
    <br>
    <br>
    On 05/17/2012 02:52 PM, Jon Rafkind wrote:
    <blockquote cite="mid:4FB564F7.6030106@cs.utah.edu" type="cite">
      <meta content="text/html; charset=ISO-8859-1"
        http-equiv="Content-Type">
      Ok I see from the syntax/parse source that it uses lctx as the
      first argument to datum-&gt;syntax, so that mostly answers my
      question.<br>
      <br>
      On 05/17/2012 02:41 PM, Jon Rafkind wrote:
      <blockquote cite="mid:4FB56262.901@cs.utah.edu" type="cite">
        <meta http-equiv="content-type" content="text/html;
          charset=ISO-8859-1">
        What exactly are the semantics of #:at inside a #:literal-sets
        ([x #:at y]) ?<br>
        <br>
        From the docs "
        <meta http-equiv="content-type" content="text/html;
          charset=ISO-8859-1">
        <span style="color: rgb(0, 0, 0); font-family: serif;
          font-style: normal; font-variant: normal; font-weight: normal;
          letter-spacing: normal; line-height: normal; orphans: 2;
          text-align: left; text-indent: 0px; text-transform: none;
          white-space: normal; widows: 2; word-spacing: 0px;
          -webkit-text-size-adjust: auto; -webkit-text-stroke-width:
          0px; background-color: rgb(255, 255, 255); font-size: medium;
          display: inline !important; float: none; ">If the<span
            class="Apple-converted-space">&nbsp;</span></span><span
          class="RktPn" style="font-family: monospace; white-space:
          normal; color: rgb(132, 60, 36); font-style: normal;
          font-variant: normal; font-weight: normal; letter-spacing:
          normal; line-height: normal; orphans: 2; text-align: left;
          text-indent: 0px; text-transform: none; widows: 2;
          word-spacing: 0px; -webkit-text-size-adjust: auto;
          -webkit-text-stroke-width: 0px; background-color: rgb(255,
          255, 255); ">#:at</span><span style="color: rgb(0, 0, 0);
          font-family: serif; font-style: normal; font-variant: normal;
          font-weight: normal; letter-spacing: normal; line-height:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; white-space: normal; widows: 2;
          word-spacing: 0px; -webkit-text-size-adjust: auto;
          -webkit-text-stroke-width: 0px; background-color: rgb(255,
          255, 255); font-size: medium; display: inline !important;
          float: none; "><span class="Apple-converted-space">&nbsp;</span>keyword
          is given, the lexical context of the<span
            class="Apple-converted-space">&nbsp;</span></span><span
          class="RktVar" style="font-family: monospace; white-space:
          normal; color: rgb(38, 38, 128); font-style: italic;
          font-variant: normal; font-weight: normal; letter-spacing:
          normal; line-height: normal; orphans: 2; text-align: left;
          text-indent: 0px; text-transform: none; widows: 2;
          word-spacing: 0px; -webkit-text-size-adjust: auto;
          -webkit-text-stroke-width: 0px; background-color: rgb(255,
          255, 255); ">lctx</span><span style="color: rgb(0, 0, 0);
          font-family: serif; font-style: normal; font-variant: normal;
          font-weight: normal; letter-spacing: normal; line-height:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; white-space: normal; widows: 2;
          word-spacing: 0px; -webkit-text-size-adjust: auto;
          -webkit-text-stroke-width: 0px; background-color: rgb(255,
          255, 255); font-size: medium; display: inline !important;
          float: none; "><span class="Apple-converted-space">&nbsp;</span>term
          is used to determine which identifiers in the patterns are
          treated as literals;". In what way is 'lctx' used?<br>
        </span> <br>
        <fieldset class="mimeAttachmentHeader"></fieldset>
        <br>
        <pre wrap="">____________________
  Racket Users list:
  <a moz-do-not-send="true" class="moz-txt-link-freetext" href="http://lists.racket-lang.org/users">http://lists.racket-lang.org/users</a>
</pre>
      </blockquote>
      <br>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">____________________
  Racket Users list:
  <a class="moz-txt-link-freetext" href="http://lists.racket-lang.org/users">http://lists.racket-lang.org/users</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>