(module reloadable mzscheme (require syntax/moddep "logger.ss") (provide reload-module) (define (reload-module modspec path) ;; the path argument is not needed (could use resolve-module-path here), ;; but its always known when this function is called (let* ([name ((current-module-name-resolver) modspec #f #f)]) (log-line "(re)loading module from ~a" modspec) (parameterize ([current-module-declare-name name] [compile-enforce-module-constants #f]) (namespace-require '(only mzscheme module #%top-interaction)) (load/use-compiled path)))) ;; pulls out a value from a module, reloading the module if its source file ;; was modified (provide auto-reload-value) (define module-times (make-hash-table 'equal)) (define (auto-reload-value modspec valname) (let* ([path (resolve-module-path modspec #f)] [last (hash-table-get module-times path #f)] [cur (file-or-directory-modify-seconds path)]) (unless (equal? cur last) (hash-table-put! module-times path cur) (reload-module modspec path)) (dynamic-require modspec valname))) (define poll-freq 2000.0) ; poll at most once every two seconds ;; pulls out a procedure from a module, and returns a wrapped procedure that ;; automatically reloads the module if the file was changed whenever the ;; procedure is used (provide auto-reload-procedure) (define (auto-reload-procedure modspec procname) (let ([path (resolve-module-path modspec #f)] [date #f] [proc #f] [poll #f]) (define (reload) (unless (and proc (< (- (current-inexact-milliseconds) poll) poll-freq)) (set! poll (current-inexact-milliseconds)) (let ([cur (file-or-directory-modify-seconds path)]) (unless (equal? cur date) (set! date cur) (reload-module modspec path) (set! proc (dynamic-require modspec procname)))))) (reload) (lambda xs (reload) (apply proc xs)))) )