#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))
     (define mod-lang-mod-datum (if (syntax? mod-lang-mod)
                                    (syntax->datum mod-lang-mod)
                                    mod-lang-mod))
     (unless (module-path? mod-lang-mod-datum)
        (raise-user-error who
                          (string-append
                           "cannot extract module language\n"
                           "  language: ~a\n"
                           (if mod-lang-mod-datum
                               (format "  info field ill-formed: ~e"
                                       mod-lang-mod-datum)
                               "  info field not available: 'module-language"))
                          lang))
     (cons mod-lang-mod-datum
           (hash-keys reader-mods)))))
