[Top][All Lists]

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

scripts/frisk peek (wip)

From: Thien-Thi Nguyen
Subject: scripts/frisk peek (wip)
Date: Sun, 06 Jan 2002 16:28:34 -0800

hello everyone,

currently writing "scripts/frisk", work-in-progress source appended
below.  here is a sample run:

  cd /home/ttn/build/.gnu/guile-core/scripts/
  ./frisk ../srfi/*.scm
  13 files, 13 modules defined, 18 modules referenced
  5 external, 6 internal whose upstream is external
  x (ice-9 and-let-star)
                           regular        (srfi srfi-2)
  x (ice-9 syncase)
                           regular        (srfi srfi-11)
  x (ice-9 rdelim)
                           regular        (srfi srfi-10)
  x (ice-9 receive)
                           regular        (srfi srfi-8)
                           regular        (srfi srfi-1)
  x (ice-9 session)
                           regular        (srfi srfi-1)
  Compilation finished at Sun Jan  6 16:07:44

to play, try invoking w/ one or more of the following env vars set:
ALL, INT, UP, UPDOWN.  (in final form, the script will take regular
"--options" instead of env vars, which will go away.)

happy hacking,

# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(scripts frisk)) '\'main')'
exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
;;; frisk --- Grok the module interfaces of a body of files

;;      Copyright (C) 2001 Free Software Foundation, Inc.
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this software; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
;; Boston, MA 02111-1307 USA

;;; Author: Thien-Thi Nguyen <address@hidden>

;;; Commentary:

;; Usage: frisk FILE ...
;; Analyze FILE... module interfaces in aggregate (as a "body"),
;; and display a summary.  Modules that are `define-module'd are
;; considered "internal" (and those not, "external").  When module X
;; uses module Y, X is said to be "downstream of" Y, and Y is
;; "upstream of" X.
;; [todo]
;; Module export list:
;;  (frisk . files)
;;  (frisk-silently . files)

;;; Code:

(debug-enable 'backtrace 'debug)        ; here.

(define-module (scripts frisk)
  :use-module ((srfi srfi-1) :select (filter remove fold))
  :export (frisk frisk-silently))

(define default-module '(guile-user))

(define (grok filename note-use!)
  (let* ((p (open-file filename "r"))
         (next (lambda () (read p)))
         (ferret (lambda (use)   ;;; handle "((foo bar) :select ...)"
                   (let ((maybe (car use)))
                     (if (list? maybe)
         (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)
                       (note-use! 'def module #f)
                       (let loop ((ls form))
                         (or (null? ls)
                             (case (car ls)
                                (note-use! 'regular module (ferret (cadr ls)))
                                (loop (cddr ls)))
                                (note-use! 'autoload module (cadr ls))
                                (loop (cdddr ls)))
                               (else (loop (cdr ls))))))))
                     (for-each (lambda (use)
                                 (note-use! 'regular
                                            (or curmod default-module)
                                            (ferret use)))
                               (cdr form)))
                    ((load primitive-load)
                     (note-use! 'computed
                                (or curmod default-module)
                                (let ((file (cadr form)))
                                  (if (string? file)
                                      (format #f "[computed in ~A]"
                  (loop (next)))))))

(define uses (make-object-property))    ; list
(define used (make-object-property))    ; list
(define def? (make-object-property))    ; defined via `define-module'

(define (dump ls)
  (for-each (lambda (z)
              (format #t "~A ~A --- ~A --- ~A\n"
                      (if (def? z) 'i 'x) z (uses z) (used z)))

(define (dump-up ls)
  (for-each (lambda (z)
              (format #t "~A ~A\n" (if (def? z) 'i 'x) z)
              (for-each (lambda (d)
                          (format #t "\t\t\t ~A\t~A\n"
                                  (car d) (cdr d)))
                        (uses z)))

(define (dump-down ls)
  (for-each (lambda (z)
              (format #t "~A ~A\n" (if (def? z) 'i 'x) z)
              (for-each (lambda (d)
                          (format #t "\t\t\t ~A\t~A\n"
                                  (car d) (cdr d)))
                        (used z)))

(define (make-body all)
  (let* ((internal  (filter def? all))
         (external  (remove def? all))
         (up        (filter uses all))
         (down      (filter used all))
         (i-up-is-x (fold (lambda (i so-far)
                            (append so-far
                                    (remove def? (map cdr (uses i)))))
    (lambda (choice)                    ; closure
      (case choice
        ;; data
        ((all)       all)
        ((internal)  internal)
        ((external)  external)
        ((up)        up)
        ((down)      down)
        ((i-up-is-x) i-up-is-x)))))

(define (frisk-silently . files)
  (let* ((all (list))
         (intern (lambda (module)
                   (cond ((member module all) => car)
                         (else (set! (uses module) (list))
                               (set! (used module) (list))
                               (set! all (cons module all))
         (use! (lambda (type module use)
                 (let ((module (intern module))
                       (use (and use (intern use)))) ; ugh
                   (if (eq? type 'def)
                         (set! (def? module) #t))
                         (set! (uses module)
                               (cons (cons type use)
                                     (uses module)))
                         (set! (used use)
                               (cons (cons type module)
                                     (used use))))))))
         (scan (lambda (file)
                 (grok file use!))))
    (for-each scan files)
    (make-body all)))

(define (frisk . files)
  (let* ((body (apply frisk-silently files))
         (all (body 'all))
         (internal (body 'internal))
         (external (body 'external))
         (i-up-is-x (body 'i-up-is-x)))
    (format #t "~A ~A, ~A ~A, ~A ~A\n~A ~A, ~A ~A\n\n"
            (length files)     "files"
            (length internal)  "modules defined"
            (length all)       "modules referenced"
            (length external)  "external"
            (length i-up-is-x) "internal whose upstream is external")
    ((cond ((getenv "UP") dump-up)              ;;; env vars temporary
           ((getenv "UPDOWN") dump)
           (else dump-down))
     (cond ((getenv "ALL") all)
           ((getenv "INT") internal)
           (else external)))))

(define main frisk)

;;; frisk ends here

reply via email to

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