(module-info (module-info-location info) (module-info-qualified-references info) (module-info-toplevel-references info) (vhash-consq name x (module-info-toplevel-definitions info)))) ;; Record the approximate location of the module import. We ;; could parse the #:imports arguments to determine the location ;; of each #:use-module but we'll leave that as an exercise for ;; the reader. (($ loc ($ _ '(guile) 'define-module*)) (module-info loc (module-info-qualified-references info) (module-info-toplevel-references info) (module-info-toplevel-definitions info))) (($ loc ($ _ '(guile) 'process-use-modules)) (module-info loc (module-info-qualified-references info) (module-info-toplevel-references info) (module-info-toplevel-definitions info))) (_ info))) (lambda (x info env locs) ;leaving X's scope info) (lambda (info env) ;finishing (define (defining-module ref env) ;; Return the name of the module that defines REF, a ;; or , in ENV. (let ((name (if (toplevel-ref? ref) (toplevel-ref-name ref) (toplevel-set-name ref)))) (match (vhash-assq name (module-info-toplevel-definitions info)) (#f ;; NAME is not among the top-level definitions of this ;; compilation unit, so check which module provides it. (and=> (module-variable env name) (lambda (variable) (and=> (find (lambda (module) (module-reverse-lookup module variable)) (module-uses env)) module-name)))) (_ (if (toplevel-ref? ref) (toplevel-ref-mod ref) (toplevel-set-mod ref)))))) (define (module-bindings-reexported? module env) ;; Return true if ENV reexports one or more bindings from MODULE. (let ((module (resolve-interface module)) (tag (make-prompt-tag))) (call-with-prompt tag (lambda () (module-for-each (lambda (symbol variable) (when (module-reverse-lookup module variable) (abort-to-prompt tag))) (module-public-interface env)) #f) (const #t)))) (define (module-exports-macros? module) ;; Return #t if MODULE exports one or more macros. (let ((tag (make-prompt-tag))) (call-with-prompt tag (lambda () (module-for-each (lambda (symbol variable) (when (and (variable-bound? variable) (macro? (variable-ref variable))) (abort-to-prompt tag))) module) #f) (const #t)))) (let ((used-modules ;list of modules actually used (fold (lambda (reference modules) (let ((module (defining-module reference env))) (if (or (not module) (vhash-assoc module modules)) modules (vhash-cons module #t modules)))) (module-info-qualified-references info) (module-info-toplevel-references info)))) ;; Compare the modules imported by ENV with USED-MODULES, the ;; list of modules actually referenced. When a module is not in ;; USED-MODULES, check whether ENV reexports bindings from it. (for-each (lambda (module) (unless (or (vhash-assoc (module-name module) used-modules) (module-bindings-reexported? (module-name module) env)) ;; If MODULE exports macros, and if the expansion ;; of those macros doesn't contain s ;; inside MODULE, then we cannot conclude whether ;; or not MODULE is used. (warning 'unused-module (module-info-location info) (module-name module) (not (module-exports-macros? module))))) (module-uses env)))) (module-info #f vlist-null '() vlist-null)))