[racket] Confusion with syntax marks

From: Marco Maggi (marco.maggi-ipsu at poste.it)
Date: Sat Oct 8 15:18:49 EDT 2011

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)

(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 #'(begin arg ...)))))))

(define foo 'a)
 (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:

                       | |
... previous marks ... W W M W W
                             | |

and  the final  result is  that ARG  in the  output  form is
marked with:

... previous marks ... M

Marco Maggi

Posted on the users mailing list.