2015-04-13 14:40 GMT+02:00 Matthew Flatt <mfl...@cs.utah.edu>:
> The new macro expander is ready for you to try:
...

>  * A macro that uses `syntax-local-get-shadower` like will have to be
>    revised, and it should be revised to avoid that function. A macro
>    that uses `syntax-local-make-delta-introducer` definitely will have
>    to be revised, because that function is no longer supported. Most
>    macros don't use such obscure functions.

The following example shows two macros  declare  and  vars that work
together.
The declare macro is used to declare identifiers (have some property) and
the macro vars shows how a macro can access the declared identifiers that
are in scope. Here vars simply expands to a list of the declared
identifiers.

Example:

(declare a)            ; module level declaration
(display (vars))
(let ()
  (display (vars))     ; (1)
  (declare x)          ;    here (1) and (2) are to display the same
variables (same scope)
  (display (vars))     ; (2)
  (let ()
    (display (vars))
    (declare s)
    (declare t)
    (display (vars)))
  (declare y)
  (display (vars)))    ; check that s and t are no longer in scope
(declare b)

; displays: (b a)(y x b a)(y x b a)(t s y x b a)(t s y x b a)(y x b a)

My solution in the old macro system used syntax-local-get-shadower
together with syntax-local-introduce to "refresh" the vars identifier
in order to redefine its meaning in each new scope.

In what direction should I look to fix this example?

[The error message with the new macro expander is:
   internal definition: duplicate binding name in: vars]


#lang racket
(require (for-syntax syntax/parse racket/format))

(begin-for-syntax
  (define module-level-variables '())
  ; each internal definition contexts is given an index
  (define intdefs (make-hasheq))
  ; each index is associated to a list of declared names
  (define local-variables (make-hash))

  (define (new-intdef? intdef)     (hash-has-key? intdefs intdef))
  (define (index-of-intdef intdef) (hash-ref! intdefs intdef (hash-count
intdefs)))
  (define (add-local-var! index var)
    (hash-update! local-variables index (λ (old-vars) (cons var old-vars))
'())))

(define-syntax (vars stx)
  (with-syntax ([vs module-level-variables])
    #''vs))

(begin-for-syntax
  (define refresh-identifier (compose syntax-local-introduce
syntax-local-get-shadower)))

(define-syntax (declare stx)
  (syntax-parse stx
    [(_ id)
     (define var (syntax->datum #'id))
     (define ctx (syntax-local-context))
     (cond
       [(eq? ctx 'module)
        (set! module-level-variables (cons var module-level-variables))
        #'(begin)]
       [(list? ctx) ; internal definition context
        (define old-scope? (new-intdef? ctx))
        (define index (index-of-intdef ctx))
        (add-local-var! index var)
        (cond [old-scope? #'(begin)]
              [else       (with-syntax ([vars     (refresh-identifier
#'vars)]
                                        [old-vars
(syntax-local-get-shadower #'vars)]
                                        [index    index]
                                        [....     #'(... ...)])
                            #'(define-syntax (vars st)
                                (define locals (hash-ref local-variables
index))
                                (define others (local-expand #'(old-vars)
(syntax-local-context) #f))
                                ; others = (quote (var ...)) so we skip the
quote here:
                                (with-syntax ([(local  ....) locals]
                                              [(_ (other ....)) others])
                                  #`'(local .... other ....))))])]
       [else (error 'declare
                    (~a "declarations are only allowed at the module level "
                        "and in internal definition contexts"))])]))

(declare a)
(display (vars))
(let ()
  (display (vars))
  (declare x)
  (display (vars))
  (let ()
    (display (vars))
    (declare s)
    (declare t)
    (display (vars)))
  (declare y)
  (display (vars)))
(declare b)

; displays: (b a)(y x b a)(y x b a)(t s y x b a)(t s y x b a)(y x b a)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-dev+unsubscr...@googlegroups.com.
To post to this group, send email to racket-dev@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-dev/CABefVgzTZ7DoHLJSZVgKm6EHBgirhXaoYkD%3D%2BVU7KvuyaLHi_w%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to