
When a stand-alone executable created by `raco exe` needs to load modules that start with a `#lang` line, there have been various obstacles to adding the right run-time support via `++lib`. The `++lang` flag addresses those problems and makes it easy to indicate that enough should be embedded to support loading modules with a specified language. There are problems in the way that various handlers interact for the "lang/reader.rkt" versus `(submod "." reader)` search path that converts a language name to a reader. To accomodate the search in a standalone executable (that does not provide access to collections in general), the module name resolver must refrain from raising an exception for a non-existent submodule path that refers to a non-existent collection.
55 lines
2.3 KiB
Racket
55 lines
2.3 KiB
Racket
#lang racket/base
|
|
(require syntax/modcollapse)
|
|
|
|
(provide languages->libraries)
|
|
|
|
;; Used to implement the `++lang` flag for `raco exe`
|
|
(define (languages->libraries langs #:who who)
|
|
(apply
|
|
append
|
|
(for/list ([lang (in-list langs)])
|
|
(define in (open-input-string lang))
|
|
(define mod (read in))
|
|
(define reader-mod
|
|
(let ([submod (collapse-module-path-index
|
|
(module-path-index-join
|
|
`(submod "." reader)
|
|
(module-path-index-join mod #f)))])
|
|
(if (module-declared? submod #t)
|
|
submod
|
|
(collapse-module-path-index
|
|
(module-path-index-join
|
|
"lang/reader.rkt"
|
|
(module-path-index-join mod #f))))))
|
|
(unless (module-declared? reader-mod #t)
|
|
(raise-user-error who
|
|
(string-append
|
|
"cannot find language module\n"
|
|
" language: ~a"
|
|
" module path: ~a")
|
|
lang
|
|
reader-mod))
|
|
(define get-info-proc (dynamic-require reader-mod 'get-info (lambda ()
|
|
(lambda args
|
|
(lambda args #f)))))
|
|
(define reader-mods (make-hash))
|
|
(hash-set! reader-mods reader-mod #t)
|
|
(define get-info (parameterize ([current-reader-guard
|
|
;; Record potential chains of reader modules.
|
|
;; For example, the `s-exp` reader chains to
|
|
;; other reader modules.
|
|
(lambda (mod)
|
|
(hash-set! reader-mods mod #t)
|
|
mod)])
|
|
(get-info-proc in #f #f #f #f)))
|
|
(define mod-lang-mod (get-info 'module-language #f))
|
|
(unless mod-lang-mod
|
|
(raise-user-error who
|
|
(string-append
|
|
"cannot extract module language\n"
|
|
" language: ~a\n"
|
|
" info field not available: 'module-language")
|
|
lang))
|
|
(cons mod-lang-mod
|
|
(hash-keys reader-mods)))))
|