I have a rather strange macro. My macro works just like lambda, except
that it only accepts one argument, and inside the body of the lambda, it
annotates all uses of that argument with a syntax property. The macro
looks like this:

  (require (for-syntax racket/syntax
                       syntax/transformer)
           syntax/parse/define)

  (define-syntax-parser strange-λ
    #:literals [#%plain-lambda let-values]
    [(_ x:id body:expr)
     #:with y (generate-temporary #'x)
     #:with wrapped-body
            #'(λ (y)
                (let-syntax ([x (make-variable-like-transformer
                                 (syntax-property
                                  #'y 'marked-by-strange-λ #t))])
                  body))
     #:with (#%plain-lambda (y*)
                            (let-values ()
                              (let-values ()
                                body*)))
            (local-expand #'wrapped-body 'expression '())
     #'(λ (y*) body*)])

(For context, the real-world reason for such a macro is for use with
Turnstile, which annotates bindings with syntax properties to track type
information, but this is a simplified example.)

I can use my new strange-λ macro like this:

  (strange-λ x (+ x 1))

It works. However, Check Syntax does not draw an arrow from the use of x
to the binding of x because neither identifier appears in the fully
expanded program. Therefore, it seems clear that the solution is to add
the necessary 'disappeared-use and 'disappeared-binding syntax
properties:

  (begin-for-syntax
    (define (make-variable-like+disappeared stx)
      (syntax-parser
        [x:id
         (syntax-property stx 'disappeared-use
                          (syntax-local-introduce #'x))]
        [(x:id . rest)
         (syntax-property #`(#,stx . rest) 'disappeared-use
                          (syntax-local-introduce #'x))])))

  (define-syntax-parser strange-λ
    #:literals [#%plain-lambda let-values]
    [(_ x:id body:expr)
     #:with y (generate-temporary #'x)
     #:with wrapped-body
            #'(λ (y)
                (let-syntax ([x (make-variable-like+disappeared
                                 (syntax-property
                                  #'y 'marked-by-strange-λ #t))])
                  body))
     #:with (#%plain-lambda (y*)
                            (let-values ()
                              (let-values ()
                                body*)))
            (local-expand #'wrapped-body 'expression '())
     #:with y*+disappeared
            (syntax-property #'y* 'disappeared-binding
                             (syntax-local-introduce #'x))
     #'(λ (y*+disappeared) body*)])

However, even with these additions, Check Syntax does not appear to be
satisfied, and it does not draw any arrows between the two xs. Looking
at the macro stepper, the fully expanded program does indeed have the
syntax properties in place, so why doesn’t this work?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to