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 themylang
module makes this work, but I'm interested in a general solution, wheremylang
does not need to know abouttyped/racket
at al (i.e. if somebody adds a new languagefoo
, thenmylang
should work with it out of the box). Also, I'm not interested in tricks which declare a submodule and immediately
require
and re-provide
it, as is done here, because this changes the path to the actual module (somain
andtest
loose 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/racket
programs.Bonus points if the arrows in DrRacket work for built-ins provided by the delegated-to language, e.g. have arrows from
ann
,+
andNumber
totyped/racket/base
, in the example above.