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.
