For those interested, it turns out you can get a loose approximation of the van Tonder system in Racket in just a few dozen lines of code. Namely, you can write a helper that undoes the macro-introduction scope added by the Racket macro system:
(begin-for-syntax (define ((make-unscoped-transformer proc) stx) (syntax-local-introduce (proc (syntax-local-introduce stx))))) Then you can write some functions and forms for keeping track of which scopes to add when users write quote-syntax: (begin-for-syntax (define current-syntax-introducer (make-parameter #f)) (define (current-syntax-introduce stx) ((or (current-syntax-introducer) (make-syntax-introducer)) stx)) (define (call-with-shared-syntax-introducer proc) (if (current-syntax-introducer) (proc) (parameterize ([current-syntax-introducer (make-syntax-introducer)]) (proc)))) (define (call-with-masked-syntax-introducer proc) (parameterize ([current-syntax-introducer #f]) (proc))) (define-simple-macro (with-shared-syntax-introducer body:expr ...+) (call-with-shared-syntax-introducer (λ () body ...))) (define-simple-macro (with-masked-syntax-introducer body:expr ...+) (call-with-masked-syntax-introducer (λ () body ...)))) You can define an introducing variant of quote-syntax in terms of Racket’s quote-syntax: (begin-for-syntax (define-simple-macro (quote-syntax form) (current-syntax-introduce (quote-syntax/no-introduce form)))) And finally, you can implement syntax and quasisyntax in terms of these other forms and functions. That part is the most amount of work, so I haven’t implemented full versions of either, but I implemented simplified versions that don’t handle ellipses and generate less optimal code. The only interesting thing in their implementations is the placement of with-shared-syntax-introducer and with-masked-syntax-introducer. Both expand into uses of with-shared-syntax-introducer, which is wrapped around the entire expansion, and unsyntax must wrap its expression in with-masked-syntax-introducer in its expansion. This produces a system that seems to have the properties of van Tonder’s system in simple situations. Experimentation leads to some interesting behavior. For example, the following macro is completely uninteresting in a system that uses scoped expansion, but it’s quite interesting in one that uses scoped quotation: (define x 'module) (define-syntax mac (make-unscoped-transformer (syntax-parser [(_) #`(let ([x 'local]) (list x #,#'x))]))) (mac) Under scoped-expansion, the program produces the boring result '(local local), but under scoped-quotation, it produces the much more interesting result '(local module)! Maybe some people would find this confusing, but I think it’s a little neat. If anyone is interested in playing with my hacky, incomplete, and probably buggy embedding of this system in Racket, I’ve posted it here: https://gist.github.com/lexi-lambda/a32aab1bb3eccd416764ef90cbd55b67 As a testament to the power of Racket’s macro system and its macro-writing facilities, the whole thing is only 80 lines of code. -- 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.