mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-29 22:40:34 +02:00
implement procedure-callers
* module/system/xref.scm: Implement procedure-callers, as the inverse of procedure-callees, with a cache invalidated by changes in modules. * module/ice-9/boot-9.scm (module-use!): Don't poke module observers when module-use! is called for an already-used module.
This commit is contained in:
parent
4f96d42b2d
commit
b190790255
2 changed files with 56 additions and 7 deletions
|
@ -1659,7 +1659,8 @@
|
||||||
;; Add INTERFACE to the list of interfaces used by MODULE.
|
;; Add INTERFACE to the list of interfaces used by MODULE.
|
||||||
;;
|
;;
|
||||||
(define (module-use! module interface)
|
(define (module-use! module interface)
|
||||||
(if (not (eq? module interface))
|
(if (not (or (eq? module interface)
|
||||||
|
(memq interface (module-uses module))))
|
||||||
(begin
|
(begin
|
||||||
;; Newly used modules must be appended rather than consed, so that
|
;; Newly used modules must be appended rather than consed, so that
|
||||||
;; `module-variable' traverses the use list starting from the first
|
;; `module-variable' traverses the use list starting from the first
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#:use-module (system base pmatch)
|
#:use-module (system base pmatch)
|
||||||
#:use-module (system base compile)
|
#:use-module (system base compile)
|
||||||
#:use-module (system vm program)
|
#:use-module (system vm program)
|
||||||
#:export (procedure-callees))
|
#:export (procedure-callees procedure-callers *xref-ignored-modules*))
|
||||||
|
|
||||||
(define (program-callees prog)
|
(define (program-callees prog)
|
||||||
(cond
|
(cond
|
||||||
|
@ -47,22 +47,30 @@
|
||||||
((vector-ref progv i)
|
((vector-ref progv i)
|
||||||
(let ((obj (vector-ref objects i)))
|
(let ((obj (vector-ref objects i)))
|
||||||
(if (variable? obj)
|
(if (variable? obj)
|
||||||
(lp (1+ i) (cons (variable-ref obj) out))
|
(lp (1+ i) (if (variable-bound? obj)
|
||||||
|
(cons (variable-ref obj) out)
|
||||||
|
out))
|
||||||
;; otherwise it's an unmemoized binding
|
;; otherwise it's an unmemoized binding
|
||||||
(pmatch obj
|
(pmatch obj
|
||||||
(,sym (guard (symbol? sym))
|
(,sym (guard (symbol? sym))
|
||||||
(let ((v (module-variable (program-module prog) sym)))
|
(let ((v (module-variable (or (program-module prog)
|
||||||
|
the-root-module)
|
||||||
|
sym)))
|
||||||
(lp (1+ i)
|
(lp (1+ i)
|
||||||
(if v (cons (variable-ref v) out) out))))
|
(if (and v (variable-bound? v))
|
||||||
|
(cons (variable-ref v) out)
|
||||||
|
out))))
|
||||||
((,mod ,sym ,public?)
|
((,mod ,sym ,public?)
|
||||||
;; hm, hacky.
|
;; hm, hacky.
|
||||||
(let ((m (nested-ref the-root-module
|
(let ((m (nested-ref the-root-module
|
||||||
(append '(%app modules) mod))))
|
(append '(%app modules) mod))))
|
||||||
(let ((v (and m (module-variable
|
(let ((v (and m (module-variable
|
||||||
(if public? (module-interface m) m)
|
(if public? (module-public-interface m) m)
|
||||||
sym))))
|
sym))))
|
||||||
(lp (1+ i)
|
(lp (1+ i)
|
||||||
(if v (cons (variable-ref v) out) out)))))))))
|
(if (and v (variable-bound? v))
|
||||||
|
(cons (variable-ref v) out)
|
||||||
|
out)))))))))
|
||||||
(else (lp (1+ i) out)))))))
|
(else (lp (1+ i) out)))))))
|
||||||
(else '())))
|
(else '())))
|
||||||
|
|
||||||
|
@ -75,3 +83,43 @@
|
||||||
((program? proc) (program-callees proc))
|
((program? proc) (program-callees proc))
|
||||||
((procedure-source proc) (hacky-procedure-callees proc))
|
((procedure-source proc) (hacky-procedure-callees proc))
|
||||||
(else '())))
|
(else '())))
|
||||||
|
|
||||||
|
(define *callers-db* #f)
|
||||||
|
|
||||||
|
(define *xref-ignored-modules* '((value-history)))
|
||||||
|
(define (on-module-modified m)
|
||||||
|
(if (not (member (module-name m) *xref-ignored-modules*))
|
||||||
|
(set! *callers-db* #f)))
|
||||||
|
|
||||||
|
(define (ensure-callers-db)
|
||||||
|
(let ((visited '())
|
||||||
|
(db #f))
|
||||||
|
(define (visit-procedure proc)
|
||||||
|
(for-each
|
||||||
|
(lambda (x)
|
||||||
|
(hashq-set! db x (cons proc (hashq-ref db x '()))))
|
||||||
|
(procedure-callees proc)))
|
||||||
|
|
||||||
|
(define (visit-module mod)
|
||||||
|
(set! visited (cons mod visited))
|
||||||
|
(if (not (memq on-module-modified (module-observers mod)))
|
||||||
|
(module-observe mod on-module-modified))
|
||||||
|
(module-for-each
|
||||||
|
(lambda (sym var)
|
||||||
|
(if (variable-bound? var)
|
||||||
|
(let ((x (variable-ref var)))
|
||||||
|
(cond
|
||||||
|
((procedure? x) (visit-procedure x))
|
||||||
|
((module? x) (if (not (memq x visited))
|
||||||
|
(visit-module x)))))))
|
||||||
|
mod))
|
||||||
|
|
||||||
|
(if (not *callers-db*)
|
||||||
|
(begin
|
||||||
|
(set! db (make-hash-table))
|
||||||
|
(visit-module the-root-module)
|
||||||
|
(set! *callers-db* db)))))
|
||||||
|
|
||||||
|
(define (procedure-callers proc)
|
||||||
|
(ensure-callers-db)
|
||||||
|
(hashq-ref *callers-db* proc #f))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue