racket/pkgs/compiler-lib/compiler/private/language.rkt
Matthew Flatt f03d5c0076 raco exe: add ++lang support
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.
2018-09-02 07:53:47 -06:00

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)))))