<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->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"> </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"> </span>keyword
is given, the lexical context of the<span
class="Apple-converted-space"> </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"> </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>