guile-user
[Top][All Lists]
Advanced

[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.

thi


________________________________________
#!/bin/sh
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 http://www.gnu.org/copyleft/gpl.txt 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)'.
;;
;; TODO
;; - 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))

(activate-eformat)

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

(define (q s)                           ; quote
  #["$s"])

(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)
                    ((define-module)
                     (let ((module (cadr form)))
                       (set! curmod module)
                       (let loop ((ls form))
                         (or (null? ls)
                             (case (car ls)
                               ((:use-module)
                                (spew module (cadr ls))
                                (loop (cddr ls)))
                               ((:autoload)
                                (spew module (cadr ls)
                                      '(style . dotted)
                                      '(fontsize . 5)
                                      (let ((len (length (caddr ls))))
                                        `(label . ,#["$len"])))
                                (loop (cdddr ls)))
                               (else (loop (cdr ls))))))))
                    ((use-modules)
                     (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)
                                 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))
                          #t)))
            (cond ((null? files) '("."))
                  (else files))))

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

(define (main)
  (header)
  (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))
  (footer))

(exit (main))

(deactivate-eformat)

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



reply via email to

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