I see that the `declare` macro is using `syntax-local-get-shadower` as
a way of storing information in the compile-time environment. The
`syntax-local-get-shadower` function is still the only primitive to
provide that functionality. It's an awkward primitive, and I considered
replacing it with a primitive that is more streamlined to that task,
but it seems more likely that we'll eventually provide a nicer API as a
library built in terms of `syntax-local-get-shadower`.

So, for this macro, it makes sense to continue with
`syntax-local-get-shadower` for now.

The macro currently fails in the new expander for two reasons:

 * There's a bug in the new expander that makes `syntax-local-context`
   produce an inconsistent value. That's the source of of the
   duplicate-definition error.

   I've pushed a repair to the "scope" branch, and I'll update the
   snapshot later today.

 * The strategy of having a fresh mark on `old-vars` (by not using
   `syntax-local-introduce`) doesn't work anymore. An extra scope on
   `old-vars` doesn't prevent it from being captured by the new `vars`
   binding.

   I think the solution is to use `local-expand` before generating the
   `vars` definition, so that `local-expand` sees the old `vars`
   binding. Or, if it's important to delay the lookup that
   `local-expand` performs until `vars` is called, then introduce an
   indirection through a fresh name/scope for each context and use
   `vars` to record that name/scope.

At Mon, 13 Apr 2015 16:09:43 +0200, Jens Axel Søgaard wrote:
> 2015-04-13 14:40 GMT+02:00 Matthew Flatt <[email protected]>:
> > 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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-dev/20150413161226.C328B6501BE%40mail-svr1.cs.utah.edu.
For more options, visit https://groups.google.com/d/optout.

Reply via email to