Mercurial > hg > xemacs-beta
diff lisp/oobr/br-clos.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 4103f0995bd7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/oobr/br-clos.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,244 @@ +;;!emacs +;; +;; FILE: br-clos.el +;; SUMMARY: Support routines for CLOS inheritance browsing. +;; USAGE: GNU Emacs Lisp Library +;; KEYWORDS: lisp, oop, tools +;; +;; AUTHOR: Bob Weiner +;; ORG: Motorola Inc. +;; +;; ORIG-DATE: 29-Jul-90 +;; LAST-MOD: 21-Sep-95 at 12:29:40 by Bob Weiner +;; +;; Copyright (C) 1990-1995 Free Software Foundation, Inc. +;; See the file BR-COPY for license information. +;; +;; This file is part of the OO-Browser. +;; +;; DESCRIPTION: +;; +;; Properly supports CLOS multiple inheritance. +;; +;; See 'clos-class-def-regexp' for regular expression that matches class +;; definitions. +;; +;; DESCRIP-END. + +;;; ************************************************************************ +;;; Other required Elisp libraries +;;; ************************************************************************ + +(require 'br-lib) + +;;; ************************************************************************ +;;; User visible variables +;;; ************************************************************************ + +(defvar clos-lib-search-dirs nil + "List of directories below which CLOS Library source files are found. +Subdirectories of Library source are also searched. A Library is a stable +group of classes.") + +(defvar clos-sys-search-dirs nil + "List of directories below which CLOS System source files are found. +Subdirectories of System source are also searched. A System class is one +that is not yet reusable and is likely to change before release.") + +(defconst clos-narrow-view-to-class nil + "*Non-nil means narrow buffer to just the matching class definition when displayed.") + +;;; ************************************************************************ +;;; Internal functions +;;; ************************************************************************ + +(defun clos-get-classes-from-source (filename &optional skip-tags + skip-tags-cleanup) + "Scans FILENAME and returns cons of class list with parents-class alist. +Handles multiple inheritance. Assumes file existence and readability have +already been checked. + With optional SKIP-TAGS non-nil, does not compute and store lookup tags +for element definitions. If SKIP-TAGS is nil, normally a cleanup +function is called after scanning the elements. SKIP-TAGS-CLEANUP +non-nil suppresses this action." + (let ((no-kill (get-file-buffer filename)) + classes class parents parent-cons parent-list signatures) + (if no-kill + (set-buffer no-kill) + (funcall br-view-file-function filename)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (if skip-tags + nil + (setq signatures (clos-scan-features)) + (goto-char (point-min))) + (while (re-search-forward clos-class-def-regexp nil t) + (setq class (buffer-substring (match-beginning 1) (match-end 1)) + parent-list nil) + (while (looking-at clos-parent-regexp) + (setq parent-list + (cons (buffer-substring + (match-beginning 1) + (match-end 1)) + parent-list)) + (goto-char (match-end 0))) + (setq parent-list (nreverse parent-list)) + (if (and (null parent-list) + (not (equal class "t"))) + ;; All classes have t as an ancestor, so if + ;; no parents are listed, make t the sole parent. + (setq parent-list '("t"))) + (setq parent-cons (cons parent-list class)) + ;; Don't have to check whether class-def pattern begins + ;; after a comment since the regexp used for matching + ;; precludes this. + (setq classes (cons class classes) + parents (cons parent-cons parents))))) + (if skip-tags + nil + (clos-get-feature-tags + buffer-file-name (clos-sort-features signatures)) + (or skip-tags-cleanup (br-feature-tags-save))) + (or no-kill (kill-buffer (current-buffer))) + (cons classes (delq nil parents)))) + +(defun clos-get-parents-from-source (filename class-name) + "Scan source in FILENAME and return list of parents of CLASS-NAME. +Assume file existence has already been checked." + (cond ((null class-name) nil) + ((equal filename br-null-path) + ;; This means there is no source for this class, so + ;; since all classes have t as an ancestor and there is no where + ;; to look for parents, make t the sole parent. + '("t")) + (t (car (car (br-rassoc + class-name + (cdr (clos-get-classes-from-source filename t)))))))) + +(defun clos-select-path (paths-htable-elt &optional feature-p) + "Select proper pathname from PATHS-HTABLE-ELT based upon value of optional FEATURE-P. +Selection is between path of class definition and path for features associated +with the class." + (let ((elt (cdr paths-htable-elt))) + (if (consp elt) + (if feature-p (cdr elt) (car elt)) + ;; Both paths are the same. + elt))) + +(defun clos-set-case (type) + "Return string TYPE identifier for use as a class name." + type) + +(defun clos-set-case-type (class-name) + "Return string CLASS-NAME for use as a type identifier." + class-name) + +(defun clos-to-class-end () + "Assuming point is at start of class, move to start of line after end of class." + (interactive) + (goto-char (point-max)) + ) + +(defun clos-to-comments-begin () + "Skip back from current point past any preceding CLOS comments." + (let ((opoint)) + (while + (progn (setq opoint (point)) + ;; To previous line + (if (= 0 (forward-line -1)) + (cond + ;; If begins with ";", then is a comment. + ((looking-at "[ \t]*\\(;\\|$\\)")) + (nil))))) + (goto-char opoint) + ;; Skip past whitespace + (skip-chars-forward " \t\n") + (beginning-of-line))) + +;;; ************************************************************************ +;;; Internal variables +;;; ************************************************************************ + +(defconst clos-class-keyword + "(defclass[ \t]+" + "Keyword regexp preceding a clos class definition.") + +(defconst clos-class-name-before + (concat "^[ \t]*" clos-class-keyword) + "Regexp preceding the class name in a class definition.") + +(defconst clos-class-name-after + "[ \t\n]*\(" + "Regexp following the class name in a class definition.") + + +(defconst clos-identifier-chars "a-zA-Z0-9+*/_~!@$%^&=:<>{}|.-" + "String of chars and char ranges that may be used within a CLOS identifier.") + +(defconst clos-type-identifier-chars "][a-zA-Z0-9+*/_~!@$%^&=<>{}|.-" + "String of chars and char ranges that may be used within a CLOS class name. +No colons allowed.") + +(defconst clos-identifier (concat "\\([" clos-identifier-chars "]+\\)") + "Regular expression matching a CLOS identifier.") + +(defconst clos-class-def-regexp + (concat clos-class-name-before clos-identifier clos-class-name-after) + "Regular expression used to match to class definitions in source text. +Class name identifier is grouped expression 1. Parent class names +follow this expression, which terminates with the parenthesis that begins +the parent class group.") + +(defconst clos-lang-prefix "clos-" + "Prefix string that starts \"br-clos.el\" symbol names.") + +(defconst clos-parent-regexp + (concat "[ \t\n]*" clos-identifier) + "Parent identifier is grouped expression 1.") + +(defconst clos-src-file-regexp ".\\.\\(lisp\\|lsp\\|cl\\|el\\)$" + "Regular expression matching a unique part of CLOS source file names and no others.") + +(defvar clos-children-htable nil + "Htable whose elements are of the form: (LIST-OF-CHILD-CLASSES . CLASS-NAME). +Used to traverse CLOS inheritance graph. 'br-build-children-htable' builds +this list.") +(defvar clos-parents-htable nil + "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME). +Used to traverse CLOS inheritance graph. 'br-build-parents-htable' builds +this list.") +(defvar clos-paths-htable nil + "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH). +FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES. +'br-build-paths-htable' builds this list.") + + +(defvar clos-lib-parents-htable nil + "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME). +Only classes from stable software libraries are used to build the list.") +(defvar clos-lib-paths-htable nil + "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH). +FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES. +Only classes from stable software libraries are used to build the list.") + +(defvar clos-sys-parents-htable nil + "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME). +Only classes from systems that are likely to change are used to build the list.") +(defvar clos-sys-paths-htable nil + "Alist whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH). +FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES. +Only classes from systems that are likely to change are used to build the +list.") + +(defvar clos-lib-prev-search-dirs nil + "Used to check if 'clos-lib-classes-htable' must be regenerated.") +(defvar clos-sys-prev-search-dirs nil + "Used to check if 'clos-sys-classes-htable' must be regenerated.") + +(defvar clos-env-spec nil + "Non-nil value means Environment specification has been given but not yet built. +Nil means current Environment has been built, though it may still require updating.") + +(provide 'br-clos)