[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Module dependency graph

From: thi
Subject: Re: Module dependency graph
Date: Mon, 26 Mar 2001 03:52:08 -0800

   From: Keisuke Nishida <address@hidden>
   Date: Sat, 24 Mar 2001 14:48:59 -0500

   Well, I'm not familiar with Guile Scheme as a scripting language,
   so... ;)

it's alright.  the caffeine hadn't kicked in yet, the perl was
invigorating but not bitter.

   Dotted lines are drawn as follows:

     "foo" -> "bar" [style=dotted];

   Available styles are "bold", "dotted", and "filled".

cool.  see below for revision 1.2 ... i commented out some of the graph
style stuff, figuring that people will munge those to taste anyway.


exec guile -s $0 "$@"                           # -*- scheme -*-
;;; ID: use2dot.scm,v 1.2 2001/03/26 10:46:55 ttn Exp
;;; Copyright (C) 2001 Thien-Thi Nguyen
;;; This program is part of ttn-do, released under GNU GPL v2 with ABSOLUTELY
;;; NO WARRANTY.  See for details.

;;; Commentary:

;; Usage: use2dot [OPTIONS] [FILE ...]
;; Display to stdout a DOT specification that describes module dependencies
;; in FILEs.  If FILE is omitted, use the current directory.  For directories,
;; recursively process all files ending in ".scm".
;; A top-level `use-modules' form or a `:use-module' `define-module'-component
;; results in a "solid" style edge.
;; An `:autoload' `define-module'-component results in a "dotted" style edge
;; with label "N" indicating that N names are responsible for triggering the
;; autoload.
;; A top-level `load' or `primitive-load' form results in a a "bold" style
;; edge to a node named with either the file name if the `load' argument is a
;; string, or "[computed in FILE]" otherwise.
;; Options:
;; --default-module MOD  -- Set MOD as the default module (for top-level
;;                          `use-modules' forms that do not follow some
;;                          `define-module' form in a file).  MOD should be
;;                          be a list or `#f', in which case such top-level
;;                          `use-modules' forms are effectively ignored.
;;                          Default value: `(guile)'.
;; - add `--load-synonyms' option
;; - add `--ignore-module' option
;; - handle arbitrary command-line key/value configuration
;; - snarf general dot-format generation into ttn-pers-scheme
;; - snarf grok into GUMM

;;; Code:

(use-modules (ice-9 regex))
(use-modules (ttn echo) (ttn ftw) (ttn eformat) (ttn stringutils))


(define ec ";")                         ; end command (here to pacify emacs)
(define default-module '(guile))

(define (q s)                           ; quote

(define (vv pair)                       ; var=val
  #[$(lambda () (car pair))=$(lambda () (cdr pair))])

(define (spew module use . etc)
  (and module
       (let ((etc-spec (if (null? etc)
                           #[ \[$(lambda () (mapconcat vv etc ","))\]])))
         (echo #[  "${module}" -> "${use}"${etc-spec}$ec]))))

(define (header)
  (echo "digraph use2dot {")
  (for-each (lambda (s) (echo #[  $s$ec]))
            (map vv `((label . ,(q "Guile Module Dependencies"))
                      ;(rankdir . LR)
                      ;(size . ,(q "7.5,10"))
                      (ratio . fill)
                      ;(nodesep . ,(q "0.05"))

(define (grok filename)
  (let* ((p (open-file filename "r"))
         (next (lambda () (read p)))
         (curmod #f))
    (let loop ((form (next)))
      (cond ((eof-object? form))
            ((not (list? form)) (loop (next)))
            (else (case (car form)
                     (let ((module (cadr form)))
                       (set! curmod module)
                       (let loop ((ls form))
                         (or (null? ls)
                             (case (car ls)
                                (spew module (cadr ls))
                                (loop (cddr ls)))
                                (spew module (cadr ls)
                                      '(style . dotted)
                                      '(fontsize . 5)
                                      (let ((len (length (caddr ls))))
                                        `(label . ,#["$len"])))
                                (loop (cdddr ls)))
                               (else (loop (cdr ls))))))))
                     (for-each (lambda (use)
                                 (spew (or curmod default-module) use))
                               (cdr form)))
                    ((load primitive-load)
                     (spew (or curmod default-module)
                           (let ((file (cadr form)))
                             (if (string? file)
                                 #[\[computed in $filename\]]))
                           '(style . bold))))
                  (loop (next)))))))

(define (body files)
  (for-each (lambda (file)
              (ftw file (lambda (filename statinfo flag)
                          (and (eq? 'regular flag)
                               (string-match "\\.scm$" filename)
                               (not (string-match "autoload" filename))
                               (grok filename))
            (cond ((null? files) '("."))
                  (else files))))

(define (footer)
  (echo "}"))

(define (main)
  (let ((cline (cdr (command-line))))
    (cond ((and (not (null? cline))
                (< 1 (length cline))
                (string=? "--default-module" (car cline)))
           (set! default-module (with-input-from-string (cadr cline)
                                  (lambda () (read))))
           (set! cline (cddr cline))))
    (body cline))

(exit (main))


;;; use2dot.scm,v1.2 ends here

reply via email to

[Prev in Thread] Current Thread [Next in Thread]