[plt-scheme] inexpressible module imports
I have a whole-module compiler that's trying to construct a require/
rename-in line and I can't create references to the require'd name.
Here's the smallest example I could create. Take a module language
with three forms: an import line, a definition, and a single variable
reference:
;; -- module.ss --
#lang scheme/base
(require (for-syntax scheme/base)
(for-syntax "compile.ss"))
(define-syntax (module-begin stx)
(syntax-case stx ()
[(_ import definition expression)
(with-syntax ([program (compile-program (syntax->datum #'import)
(syntax->datum
#'definition)
(syntax->datum
#'expression))])
#'(#%plain-module-begin program))]))
(provide (except-out (all-from-out scheme/base) #%module-begin)
(rename-out [module-begin #%module-begin]))
;; --
Since we called syntax->datum, we need to call `syntax-local-
introduce' on any variables that come from the input, so that any
introduced references won't be captured. So if we write a program like:
;; -- test.ss --
(module test "module.ss"
(import scheme/math [pi newline])
(define print 42)
newline)
;; --
neither `print' nor `newline' should capture compiler-introduced
references to the scheme/base identifiers of the same name.
But I can't come up with any plausible combination of arguments to
`datum->syntax' and insertions of `syntax-local-introduce' into the
compiler to get that reference to `newline' to refer to the imported
name. Here was my best shot:
;; -- compile.ss --
#lang scheme/base
(require scheme/match)
(require (for-template scheme/base))
(provide compile-program)
(define (compile-program import definition reference)
#`(begin
#,(compile-import import)
#,(compile-definition definition)
(print #,(compile-reference reference))
(newline)))
(define (compile-import import)
(match import
[(list 'import mod (list (? symbol? external) (? symbol?
internal)))
(let ([external-id (datum->syntax #'here external)]
[internal-id (syntax-local-introduce
(datum->syntax #f internal))])
#`(require (rename-in #,mod [#,external-id #,internal-id])))]))
(define (compile-definition definition)
(match definition
[(list 'define (? symbol? x) (? number? n))
(let ([id (syntax-local-introduce (datum->syntax #f x))])
#`(define #,id #,n))]))
(define (compile-reference reference)
(syntax-local-introduce (datum->syntax #f reference)))
;; --
But for some reason, it tries to turn the reference into a #%top
reference. I tried lots of other combinations but to no avail. Is
there something secret about module-imports?
Thanks,
Dave