1 ;;; modules.rkt -- module metadata
3 ;; Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz
5 ;; This program is free software; you can redistribute it and/or
6 ;; modify it under the terms of the Modified BSD License. You should
7 ;; have received a copy of the license along with this program. If
8 ;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>.
10 ;; Start date: Wed May 06, 2009 02:35
16 module-spec->namespace
17 namespace->module-name
18 namespace->module-path-name
19 module-path-name->name
20 module-spec->path-name
23 (require srfi/13 geiser/enter)
25 (define (ensure-module-spec spec)
26 (cond [(symbol? spec) spec]
27 [(not (string? spec)) #f]
28 [else `(file ,spec)]))
30 (define (module-spec->namespace spec (lang #f) (current #t))
33 (with-handlers ([exn? (const #f)])
34 (load-module lang #f (current-namespace))
35 (module->namespace lang))))
36 (or (get-namespace spec)
38 (and current (current-namespace))))
40 (define nowhere (open-output-nowhere))
42 (define (load-module spec (port #f) (ns #f))
43 (parameterize ([current-error-port (or port nowhere)])
44 (enter-module (ensure-module-spec spec))
46 (current-namespace ns))))
48 (define (namespace->module-path-name ns)
49 (let ([rmp (variable-reference->resolved-module-path
50 (eval '(#%variable-reference) ns))])
51 (and (resolved-module-path? rmp)
52 (resolved-module-path-name rmp))))
54 (define (module-spec->path-name spec)
58 (namespace->module-path-name
59 (module-spec->namespace spec) #f #f)))))
61 (define (module-path-name->name path)
63 (let* ([path (path->string path)]
64 [cpaths (map (compose path->string path->directory-path)
65 (current-library-collection-paths))]
66 [prefix-len (lambda (p)
67 (let ((pl (string-length p)))
68 (if (= pl (string-prefix-length p path))
71 [lens (map prefix-len cpaths)]
72 [real-path (substring path (apply max lens))])
73 (if (absolute-path? real-path)
74 (call-with-values (lambda () (split-path path))
75 (lambda (_ basename __) (path->string basename)))
76 (regexp-replace "\\.[^./]*$" real-path "")))]
77 ;; [(eq? path '#%kernel) "(kernel)"]
79 [(symbol? path) (symbol->string path)]
82 (define namespace->module-name
83 (compose module-path-name->name namespace->module-path-name))
85 (define (skippable-dir? path)
86 (call-with-values (lambda () (split-path path))
87 (lambda (_ basename __)
88 (member (path->string basename) '(".svn" "compiled")))))
90 (define path->symbol (compose string->symbol path->string))
92 (define (path->entry path)
93 (let ([ext (filename-extension path)])
95 (or (bytes=? ext #"rkt") (bytes=? ext #"ss"))
96 (not (bytes=? (bytes-append #"main" ext) (path->bytes path)))
97 (let* ([path (path->string path)]
98 [len (- (string-length path) (bytes-length ext) 1)])
99 (substring path 0 len)))))
101 (define (visit-module-path path kind acc)
102 (define (register e p)
103 (register-path (string->symbol e) (build-path (current-directory) p))
105 (define (find-main ext)
106 (let ([m (build-path path (string-append "main." ext))])
107 (and (file-exists? m) m)))
109 [(file) (let ([entry (path->entry path)])
110 (if (not entry) acc (register entry path)))]
111 [(dir) (cond [(skippable-dir? path) (values acc #f)]
112 [(or (find-main "rkt") (find-main "ss")) =>
113 (curry register (path->string path))]
117 (define (find-modules path acc)
118 (if (directory-exists? path)
119 (parameterize ([current-directory path])
120 (fold-files visit-module-path acc))
123 (define (known-modules)
124 (sort (foldl find-modules '() (current-library-collection-paths)) string<?))
126 (define registered (make-hash))
128 (define (get-path mod) (hash-ref registered mod #f))
130 (define (register-path mod path)
131 (hash-set! registered mod path)
134 (define module-cache #f)
136 (define (update-module-cache)
137 (when (not module-cache) (set! module-cache (known-modules))))
139 (define (module-list)
140 (update-module-cache)
144 (thread update-module-cache)