I'm trying to write in Racket a module meta-language mylang, which accepts a second language to which is passes the modified body, such that:
(module foo mylang typed/racket body)
is equivalent to:
(module foo typed/racket transformed-body)
where the typed/racket part can be replaced with any other module language, of course.
I attempted a simple version which leaves the body unchanged. It works fine on the command-line, but gives the following error when run in DrRacket:
/usr/share/racket/pkgs/typed-racket-lib/typed-racket/typecheck/tc-toplevel.rkt:479:30: require: namespace mismatch;
reference to a module that is not available
reference phase: 1
referenced module: "/usr/share/racket/pkgs/typed-racket-lib/typed-racket/env/env-req.rkt"
referenced phase level: 0 in: add-mod!
Here's the whole code:
#lang racket
(module mylang racket
(provide (rename-out [-#%module-begin #%module-begin]))
(require (for-syntax syntax/strip-context))
(define-syntax (-#%module-begin stx)
(syntax-case stx ()
[(_ lng . rest)
(let ([lng-sym (syntax-e #'lng)])
(namespace-require `(for-meta -1 ,lng-sym))
(with-syntax ([mb (namespace-symbol->identifier '#%module-begin)])
#`(mb . #,(replace-context #'mb #'rest))))])))
(module foo (submod ".." mylang) typed/racket/base
(ann (+ 1) Number))
(require 'foo)
Requirements (i.e. solutions I'd rather avoid):
- Adding a
(require (only-in typed/racket))inside themylangmodule makes this work, but I'm interested in a general solution, wheremylangdoes not need to know abouttyped/racketat al (i.e. if somebody adds a new languagefoo, thenmylangshould work with it out of the box). Also, I'm not interested in tricks which declare a submodule and immediately
requireand re-provideit, as is done here, because this changes the path to the actual module (somainandtestloose their special behaviour, for example).It is also slower at compile-time, as submodules get visited and/or instantiated more times (this can be seen by writing
(begin-for-syntax (displayln 'here)), and has a noticeable impact for largetyped/racketprograms.Bonus points if the arrows in DrRacket work for built-ins provided by the delegated-to language, e.g. have arrows from
ann,+andNumbertotyped/racket/base, in the example above.