Replacing lexical context in a macro

Hi,

I'm trying to do something about typed/racket issue #1286, and hopefully racket/math issue #75 at some point. I patched require/untyped-contract as below:

(define-syntax (require/untyped-contract stx)
  (syntax-parse stx #:literals (begin quote)
    [(_ (begin form ...) from-module-spec:expr (quote language-spec:id) [name:id T:expr] ...)
     (with-syntax* ([(typed-name ...)  (generate-temporaries #'(name ...))]
                    [(untyped-name ...)  (freshen #'(name ...))]
                    [(untyped2-name ...)  (generate-temporaries #'(name ...))]
                    [typed-module  (generate-temporary #'typed-module)]
                    [untyped-module  (generate-temporary #'untyped-module)]
                    [*racket/base (datum->syntax #'from-module-spec 'racket/base)]
                    [*typed/racket (datum->syntax #'from-module-spec (format-symbol "~a" (syntax-e #'language-spec)))]
                    [*require (datum->syntax #'from-module-spec 'require)]
                    [*language-spec (datum->syntax #'racket/base (format-symbol "~a" (syntax-e #'language-spec)))]
                    [from-module-spec-for-submod
                      (syntax-parse #'from-module-spec #:literals (submod)
                        [(submod (~and base (~or "." "..")) elem ...)
                         (syntax/loc #'from-module-spec (submod base ".." elem ...))]
                        [x #'x])])
       (syntax/loc stx
         (begin
           (module typed-module *typed/racket ; to bind in `T`s
             (*require *language-spec) ; to bind introduced `begin`, etc.
             (begin form ...)
             (require (only-in from-module-spec-for-submod
                               [name untyped2-name] ...))

So, I added a symbol argument (quote language-spec:id), and used it as

(datum->syntax #'from-module-spec (format-symbol "~a" (syntax-e #'language-spec)))

which, in my understanding, just replaces the original lexical context of the (quote language-spec:id) symbol with the #'from-module-spec context? Is there a simpler way to write the above line (e.g. a library function that does just that instead of completely re-making the symbol)?

Thanks!

1 Like

You don't need the extra format-symbol as syntax-e already extracts the symbol in the syntax object. However, it might be desired to preserve the source location and the syntax properties:

(datum->syntax #'from-module-spec
               (syntax-e #'language-spec)
               #'language-spec  ;; source location
               #'language-spec) ;; syntax properties

I have seen this pattern multiple times but haven't seen an API for it.