1 ;;; enter.rkt -- custom module loaders
3 ;; Copyright (C) 2010, 2012 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 Mar 31, 2010 21:53
14 (require syntax/modcode
15 (for-syntax racket/base)
18 (provide get-namespace enter-module module-loader module-loaded?)
20 (struct mod (name load-path timestamp depends))
22 (define loaded (make-hash))
24 (define (module-loaded? path)
25 (with-handlers ([exn? (lambda (_) #f)])
26 (let ([rp (module-path-index-resolve (module-path-index-join path #f))])
27 (hash-has-key? loaded (resolved-module-path-name rp)))))
29 (define (enter-module mod)
30 (dynamic-require mod #f)
33 (define (module-loader orig)
34 (enter-load/use-compiled orig #f))
36 (define (notify re? path)
38 (fprintf (current-error-port) " [re-loading ~a]\n" path)))
40 (define inhibit-eval (make-parameter #f))
42 (define (get-namespace mod)
43 (let ([mod (cond [(symbol? mod) mod]
44 [(string? mod) (find-module! (string->path mod) mod)]
45 [(path? mod) (find-module! mod (path->string mod))]
48 (with-handlers ([exn? (lambda (_) #f)])
49 (parameterize ([inhibit-eval #t])
50 (module->namespace mod))))))
52 (define (find-module! path path-str)
53 (let ([m (or (hash-ref loaded path #f)
54 (let loop ([ps (remove path (resolve-paths path))]
57 [(hash-ref loaded (car ps) #f) =>
59 (add-paths! m (cdr ps))
60 (add-paths! m (cons path seen))
62 [else (loop (cdr ps) (cons (car ps) seen))])))])
63 (list 'file (or (and m (mod-load-path m)) path-str))))
65 (define (add-paths! m ps)
66 (for-each (lambda (p) (hash-set! loaded p m)) ps))
68 (define (resolve-paths path)
69 (define (find root rest)
70 (let* ([alt-root (resolve-path root)]
71 [same? (equal? root alt-root)])
72 (cond [(null? rest) (cons root (if same? '() `(,alt-root)))]
73 [else (let* ([c (car rest)]
75 [rps (find (build-path root c) cs)])
78 (append rps (find (build-path alt-root c) cs))))])))
79 (let ([cmps (explode-path path)])
80 (find (car cmps) (cdr cmps))))
82 (define ((enter-load/use-compiled orig re?) path name)
84 (raise (make-exn:fail "namespace not found"
85 (current-continuation-marks))))
88 (let ([code (get-module-code path "compiled" compile
92 #:notify (lambda (chosen)
93 (notify re? chosen)))]
94 [path (normal-case-path
96 (path->complete-path path
97 (or (current-load-relative-directory)
98 (current-directory)))))])
99 ;; Record module timestamp and dependencies:
106 (module-compiled-imports code)))
108 (add-paths! m (resolve-paths path)))
109 ;; Evaluate the module:
116 (define (get-timestamp path)
117 (file-or-directory-modify-seconds path #f (lambda () -inf.0)))
119 (define (check-latest mod)
120 (let ([mpi (module-path-index-join mod #f)]
122 (let loop ([mpi mpi])
123 (let* ([rpath (module-path-index-resolve mpi)]
124 [path (resolved-module-path-name rpath)])
126 (let ([path (normal-case-path path)])
127 (unless (hash-ref done path #f)
128 (hash-set! done path #t)
129 (let ([mod (hash-ref loaded path #f)])
131 (for-each loop (mod-depends mod))
132 (let ([ts (get-timestamp path)])
133 (when (ts . > . (mod-timestamp mod))
134 (let ([orig (current-load/use-compiled)])
135 (parameterize ([current-load/use-compiled
136 (enter-load/use-compiled orig #f)]
137 [current-module-declare-name rpath])
138 ((enter-load/use-compiled orig #t)
140 (mod-name mod)))))))))))))))