[racket] Confusion with syntax marks
Eric Dobson wrote:
> I am playing around with syntax marks and have a program
> whose output confuses me.
>
> #lang racket
> (require (for-syntax racket/syntax))
> (define-for-syntax marker (make-syntax-introducer))
> (define-syntax (mark stx)
> (syntax-case stx ()
> ((_ arg ...) (marker #'(begin arg ...)))))
>
> (define foo 'a)
> (mark
> (define foo 'b)
> foo
> (mark foo))
> foo
> (mark foo)
> (mark (mark foo))
>
> This outputs 5 values depending on which foo a binding
> refers to. Racket outputs 'b 'b 'a 'a 'a. But when I use
> the macro stepper and look at the marks on the uses line
> up with the bindings they alternate 'b 'a 'a 'b 'a, which
> is what I was expecting, but the arrows line up with the
> output. Can someone explain why I am getting these
> results?
No answers so... I know nothing of Racket's internals and
the macro stepper, but I guess the "problem" is: you are not
using the marks the way they are meant to be and Racket's
"same marks" predicate does not do what you expect.
Does the following program do what you expect?
#lang racket
(require (for-syntax racket/syntax))
(define (print x)
(display x)
(newline))
(define-for-syntax marker (make-syntax-introducer))
#;(define-syntax (mark stx)
(syntax-case stx ()
((_ arg ...)
(marker #'(begin arg ...)))))
(define-syntax (mark stx)
(syntax-case stx ()
((_ arg ...)
(syntax-local-introduce
(marker
(syntax-local-introduce #'(begin arg ...)))))))
(define foo 'a)
(mark
(define foo 'b)
(print foo)
(print (mark foo)))
(print foo)
(print (mark foo))
(print (mark (mark foo)))
When Racket defines a mark, it uses that mark value itself
as its antimark; this is different from what other expanders
do (for example: psyntax uses #f as universal antimark
capable of annihilating every mark).
The STX syntax object handed to the MARK transformer is
marked by the expander pushing on its marks stack a mark W
specific for such transformer; SYNTAX-CASE duplicates STX's
marks stack into ARG, then pushes W on the marks stack of
ARG; when the transformer returns, the returned syntax
object is marked again by the expander with W. The MARKER
function marks its argument with the mark M.
To do what you want to do: first you have to annihilate
the W added to ARG with the inner SYNTAX-LOCAL-INTRODUCE,
then you add M using MARKER, finally you add W with the
outer SYNTAX-LOCAL-INTRODUCE; this last W is annihilated by
the W added by the expander to the output syntax object.
Summary of marks pushed into ARG:
annihilated
| |
... previous marks ... W W M W W
| |
annihilated
and the final result is that ARG in the output form is
marked with:
... previous marks ... M
HTH
--
Marco Maggi