diff lisp/ilisp/cl-ilisp.lisp @ 4:b82b59fe008d r19-15b3

Import from CVS: tag r19-15b3
author cvs
date Mon, 13 Aug 2007 08:46:56 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/ilisp/cl-ilisp.lisp	Mon Aug 13 08:46:56 2007 +0200
@@ -0,0 +1,617 @@
+;;; -*- Mode: Lisp -*-
+
+;;; cl-ilisp.lisp --
+
+;;; This file is part of ILISP.
+;;; Version: 5.8
+;;;
+;;; Copyright (C) 1990, 1991, 1992, 1993 Chris McConnell
+;;;               1993, 1994 Ivan Vasquez
+;;;               1994, 1995, 1996 Marco Antoniotti and Rick Busdiecker
+;;;               1996 Marco Antoniotti and Rick Campbell
+;;;
+;;; Other authors' names for which this Copyright notice also holds
+;;; may appear later in this file.
+;;;
+;;; Send mail to 'ilisp-request@naggum.no' to be included in the
+;;; ILISP mailing list. 'ilisp@naggum.no' is the general ILISP
+;;; mailing list were bugs and improvements are discussed.
+;;;
+;;; ILISP is freely redistributable under the terms found in the file
+;;; COPYING.
+
+
+
+;;; Common Lisp initializations
+;;; Author: Chris McConnell, ccm@cs.cmu.edu
+
+;;;
+;;; ange-ftp hack added by ivan Wed Mar 10 12:30:15 1993
+;;; ilisp-errors *gc-verbose* addition ivan Tue Mar 16 03:21:51 1993
+;;;
+;;; Rcs_Info: clisp.lisp,v 1.26 1993/09/03 02:05:07 ivan Rel $
+;;;
+;;; Revision 1.19  1993/08/24  22:01:52  ivan
+;;; Use defpackage instead of just IN-PACKAGE.
+;;; Renamed FUNCTION to FUN in ilisp-arglist to get around CMUCL 17b bug.
+;;;
+;;; Revision 1.16  1993/06/29  05:51:35  ivan
+;;; Added Ed Gamble's #'readtable-case fix and Hans Chalupsky's
+;;; allegro-4.1 addition.
+;;;
+;;; Revision 1.8  1993/06/28  00:57:42  ivan
+;;; Stopped using 'COMPILED-FUNCTION-P for compiled check.
+;;;
+;;; Revision 1.3  1993/03/16  23:22:10  ivan
+;;; Added breakp arg to ilisp-trace.
+;;;
+;;;
+
+
+#+(or allegro-v4.0 allegro-v4.1)
+(eval-when (compile load eval)
+  (setq excl:*cltl1-in-package-compatibility-p* t))
+
+
+(in-package "ILISP")
+
+;;;
+;;; GCL 2.2 doesn't have defpackage (yet) so we need to put the export
+;;; here. (toy@rtp.ericsson.se)
+;;;
+;;; Please note that while the comment and the fix posted by Richard
+;;; Toy are correct, they are deprecated by at least one of the ILISP
+;;; maintainers. :) By removing the 'nil' in the following #+, you
+;;; will fix the problem but will not do a good service to the CL
+;;; community.  The right thing to do is to install DEFPACKAGE in your
+;;; GCL and to write the GCL maintainers and to ask them to
+;;; incorporate DEFPACKAGE in their standard builds.
+;;; Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19960715
+;;;
+
+#+(and nil gcl)
+(export '(ilisp-errors
+	  ilisp-save
+	  ilisp-restore
+	  ilisp-symbol-name
+	  ilisp-find-symbol
+	  ilisp-find-package
+	  ilisp-eval
+	  ilisp-compile
+	  ilisp-describe
+	  ilisp-inspect
+	  ilisp-arglist
+	  ilisp-documentation
+	  ilisp-macroexpand
+	  ilisp-macroexpand-1
+	  ilisp-trace
+	  ilisp-untrace
+	  ilisp-compile-file
+	  ilisp-casify
+	  ilisp-matching-symbols))
+
+
+;;;
+(defvar *ilisp-old-result* nil "Used for save/restore of top level values.")
+
+#+:ANSI-CL
+(defun special-form-p (symbol)
+  "Backward compatibility for non ANSI CL's."
+  (special-operator-p symbol))
+
+;;;
+(defmacro ilisp-handler-case (expression &rest handlers)
+  "Evaluate EXPRESSION using HANDLERS to handle errors."
+  handlers
+  (if (macro-function 'handler-case)
+      `(handler-case ,expression ,@handlers)
+      #+allegro `(excl::handler-case ,expression ,@handlers)
+      #+lucid `(lucid::handler-case ,expression ,@handlers)
+      #-(or allegro lucid) expression))
+
+;;;
+(defun ilisp-readtable-case (readtable)
+  (if (fboundp 'readtable-case)
+      (funcall #'readtable-case readtable)
+      #+allegro (case excl:*current-case-mode*
+		  (:case-insensitive-upper :upcase)
+		  (:case-insensitive-lower :downcase)
+		  (otherwise :preserve))
+      #-allegro :upcase))
+
+;;;
+(defmacro ilisp-errors (form)
+  "Handle errors when evaluating FORM."
+  `(let ((*standard-output* *terminal-io*)
+	 (*error-output* *terminal-io*)
+	 #+cmu
+	 (ext:*gc-verbose* nil) ; cmulisp outputs "[GC ...]" which
+				; doesn't read well...
+	 #+ecl
+	 (sys:*gc-verbose* nil) ; ecolisp also outputs "[GC ...]"
+	 )
+     (princ " ")			;Make sure we have output
+     (ilisp-handler-case
+      ,form	
+      (error (error)
+       (with-output-to-string (string)
+	 (format string "ILISP: ~A" error))))))
+
+
+;;;
+(defun ilisp-save ()
+  "Save the current state of the result history."
+  (declare (special / // /// + ++ +++))
+  (unless *ilisp-old-result*
+    (setq *ilisp-old-result* (list /// // +++ ++ + /))))
+
+;;;
+(defun ilisp-restore ()
+  "Restore the old result history."
+  (declare (special / // /// + ++ +++ * ** -))
+  (setq // (pop *ilisp-old-result*)
+	** (first //)
+	/  (pop *ilisp-old-result*)
+	*  (first /)
+	++  (pop *ilisp-old-result*)
+	+   (pop *ilisp-old-result*)
+	-   (pop *ilisp-old-result*))
+  (values-list (pop *ilisp-old-result*)))
+  
+;;; ilisp-symbol-name --
+;;;
+;;; ':capitalize' case added under suggestion by Rich Mallory.
+(defun ilisp-symbol-name (symbol-name)
+  "Return SYMBOL-NAME with the appropriate case as a symbol."
+  (case (ilisp-readtable-case *readtable*)
+    (:upcase (string-upcase symbol-name))
+    (:downcase (string-downcase symbol-name))
+    (:capitalize (string-capitalize symbol-name))
+    (:preserve symbol-name)))
+  
+;;;
+(defun ilisp-find-package (package-name)
+  "Return package PACKAGE-NAME or the current package."
+  (if (string-equal package-name "nil")
+      *package*
+      (or (find-package (ilisp-symbol-name package-name))
+	  (error "Package ~A not found" package-name))))
+
+;;;
+(defun ilisp-find-symbol (symbol-name package-name)
+  "Return the symbol associated with SYMBOL-NAME in PACKAGE-NAME trying to
+handle case issues intelligently."
+  (find-symbol (ilisp-symbol-name symbol-name)
+	       (ilisp-find-package package-name)))
+
+
+;;; The following two functions were in version 5.5.
+;;; They disappeared in version 5.6. I am putting them back in the
+;;; distribution in order to make use of them later if the need
+;;; arises.
+;;; Marco Antoniotti: Jan 2 1995
+#|
+(defun ilisp-filename-hack (filename)
+  "Strip `/user@machine:' prefix from filename."
+  ;; Ivan's hack for getting away with dumb /ivan@bu-conx:/foo/bar/baz
+  ;; filenames...
+  (let ((at-location (position #\@ filename))
+	(colon-location (position #\: filename)))
+    (if (and at-location colon-location)
+	(subseq filename (1+ colon-location))
+	filename)))
+
+
+(defun ilisp-read-form (form package)
+  "Read string FORM in PACKAGE and return the resulting form."
+  (let ((*package* (ilisp-find-package package)))
+    (read-from-string form)))
+|#
+
+;;;
+(defun ilisp-eval (form package filename)
+  "Evaluate FORM in PACKAGE recording FILENAME as the source file."
+  (princ " ")
+  ;; Ivan's hack for getting away with dumb /ivan@bu-conx:/foo/bar/baz
+  ;; filenames...
+  (let* ((at-location (position #\@ filename))
+	 (colon-location (position #\: filename))
+	 (filename
+	  (if (and at-location colon-location)
+	      (subseq filename (1+ colon-location))
+	      filename))
+	 (*package* (ilisp-find-package package))
+	 #+allegro (excl::*source-pathname* filename)
+	 #+allegro (excl::*redefinition-warnings* nil)
+	 #+lucid (lucid::*source-pathname*
+		  (if (probe-file filename)
+		      (truename filename)
+		      (merge-pathnames filename)))
+	 #+lucid (lucid::*redefinition-action* nil)
+	 #+lispworks (compiler::*input-pathname* (merge-pathnames filename))
+	 #+lispworks (compiler::*warn-on-non-top-level-defun* nil)
+	 ;; The LW entries are a mix of Rich Mallory and Jason
+	 ;; Trenouth suggestions
+	 ;; Marco Antoniotti: Jan 2 1995.
+	 )
+    filename
+    (eval (read-from-string form))))
+
+;;;
+(defun ilisp-compile (form package filename)
+  "Compile FORM in PACKAGE recording FILENAME as the source file."
+  (princ " ")
+  ;; This makes sure that function forms are compiled
+  ;; NOTE: Rich Mallory proposed a variation of the next piece of
+  ;; code. for the time being we stick to the following simpler code.
+  ;; Marco Antoniotti: Jan 2 1995.
+  #-lucid
+  (ilisp-eval
+   (format nil "(funcall (compile nil '(lisp:lambda () ~A)))"
+	   form)
+   package
+   filename)
+  
+  ;; The following piece of conditional code is left in the
+  ;; distribution just for historical purposes.
+  ;; It will disappear in the next release.
+  ;; Marco Antoniotti: Jan 2 1995.
+  #+lucid-ilisp-5.6
+  (labels ((compiler (form env)
+		     (if (and (consp form)
+			      (eq (first form) 'function)
+			      (consp (second form)))
+			 #-LCL3.0
+		       (evalhook `(compile nil ,form) nil nil env)
+		       #+LCL3.0
+		       ;; If we have just compiled a named-lambda, and the
+		       ;; name didn't make it in to the procedure object,
+		       ;; then stuff the appropriate symbol in to the
+		       ;; procedure object.
+		       (let* ((proc (evalhook `(compile nil ,form)
+					      nil nil env))
+			      (old-name (and proc (sys:procedure-ref proc 1)))
+			      (lambda (second form))
+			      (name (and (eq (first lambda)
+					     'lucid::named-lambda)
+					 (second lambda))))
+			 (when (or (null old-name)
+				   (and (listp old-name)
+					(eq :internal (car old-name))))
+			       (setf (sys:procedure-ref proc 1) name))
+			 proc)
+		       (evalhook form #'compiler nil env))))
+	  (let ((*evalhook* #'compiler))
+	    (ilisp-eval form package filename)))
+  #+lucid
+  ;; Following form is a patch provided by Christopher Hoover
+  ;; <ch@lks.csi.com>
+  (let ((*package* (ilisp-find-package package))
+ 	(lcl:*source-pathname* (if (probe-file filename)
+ 				   (truename filename)
+ 				 (merge-pathnames filename)))
+ 	(lcl:*redefinition-action* nil))
+    (with-input-from-string (s form)
+			    (lucid::compile-in-core-from-stream s)
+			    (values)))
+  )
+
+;;;
+(defun ilisp-describe (sexp package)
+  "Describe SEXP in PACKAGE."
+  (ilisp-errors
+   (let ((*package* (ilisp-find-package package)))
+     (describe (eval (read-from-string sexp))))))
+
+;;;
+(defun ilisp-inspect (sexp package)
+  "Inspect SEXP in PACKAGE."
+  (ilisp-errors
+   (let ((*package* (ilisp-find-package package)))
+     (inspect (eval (read-from-string sexp))))))
+
+;;;
+(defun ilisp-arglist (symbol package)
+  (ilisp-errors
+    (let ((fn (ilisp-find-symbol symbol package))
+	  (*print-length* nil)
+	  (*print-pretty* t)
+	  (*package* (ilisp-find-package package)))
+      (cond ((null fn)
+	     (format t "Symbol ~s not present in ~s." symbol package))
+	    ((not (fboundp fn))
+	     (format t "~s: undefined~%" fn))
+	    (t
+	     (print-function-arglist fn)))))
+  (values))
+
+
+(defun print-function-arglist (fn)
+  "Pretty arglist printer"
+  (let* ((a (get-function-arglist fn))
+	 (arglist (ldiff a (member '&aux a)))
+	 (desc (ilisp-function-short-description fn)))
+    (format t "~&~s~a" fn (or desc ""))
+    (write-string ": ")
+    (if arglist
+	(write arglist :case :downcase :escape nil)
+      (write-string "()"))
+    (terpri)))
+
+
+
+(defun ilisp-generic-function-p (symbol)
+  (let ((generic-p
+	 (find-symbol "GENERIC-FUNCTION-P"
+		      (or (find-package "PCL")
+			  *package*))))
+    (and generic-p
+	 (fboundp generic-p)
+	 (funcall generic-p symbol))))
+
+
+  
+(defun ilisp-function-short-description (symbol)
+  (cond ((macro-function symbol)
+	 " (Macro)")
+	((special-form-p symbol)
+	 " (Special Form)")
+	((ilisp-generic-function-p symbol)
+	 " (Generic)")))
+
+
+
+(defun get-function-arglist (symbol)
+  (let ((fun (symbol-function symbol)))
+    (cond ((ilisp-generic-function-p symbol)
+	   (funcall
+	    (find-symbol "GENERIC-FUNCTION-PRETTY-ARGLIST"
+			 (or (find-package "PCL") *package*))
+	    fun))
+	  (t
+	   #+allegro
+	   (excl::arglist symbol)
+
+	   #+(or ibcl kcl ecl gcl)
+	   (help symbol)
+
+	   #+lucid
+	   (lucid::arglist symbol)
+	   
+	   #+lispworks
+	   (system::function-lambda-list symbol)
+	   
+	   #-(or allegro lucid kcl ibcl ecl)
+	   (documentation symbol 'function)))))
+
+;;;
+(defun ilisp-documentation (symbol package type)
+  "Return the TYPE documentation for SYMBOL in PACKAGE.  If TYPE is
+\(qualifiers* (class ...)), the appropriate method will be found."
+  (ilisp-errors
+   (let* ((real-symbol (ilisp-find-symbol symbol package))
+	  (type (if (and (not (zerop (length type)))
+			 (eq (elt type 0) #\())
+		    (let ((*package* (ilisp-find-package package)))
+		      (read-from-string type))
+		    (ilisp-find-symbol type package))))
+     (when (listp type)
+       (setq real-symbol
+	     (funcall
+	      (find-symbol "FIND-METHOD" (or (find-package "CLOS")
+					     (find-package "PCL")
+					     *package*))
+	      (symbol-function real-symbol)
+	      (reverse
+	       (let ((quals nil))
+		 (dolist (entry type quals)
+		   (if (listp entry)
+		       (return quals)
+		       (setq quals (cons entry quals))))))
+	      (reverse
+	       (let ((types nil))
+		 (dolist (class (first (last type)) types)
+		   (setq types
+			 (cons (funcall
+				(find-symbol "FIND-CLASS"
+					     (or (find-package "CLOS")
+						 (find-package "PCL")
+						 *package*))
+				class) types))))))))
+     (if real-symbol
+	 (if (symbolp real-symbol)
+	     (documentation real-symbol type)
+	     ;; Prevent compiler complaints
+	     (eval `(documentation ,real-symbol)))
+	 (format nil "~A has no ~A documentation" symbol type)))))
+
+;;;
+(defun ilisp-macroexpand (expression package)
+  "Macroexpand EXPRESSION as long as the top level function is still a
+macro." 
+  (ilisp-errors
+   (let ((*print-length* nil)
+	 (*print-level* nil)
+	 (*package* (ilisp-find-package package)))
+     (pprint (#-allegro macroexpand #+allegro excl::walk
+			(read-from-string expression))))))
+
+;;;
+(defun ilisp-macroexpand-1 (expression package)
+  "Macroexpand EXPRESSION once."
+  (ilisp-errors
+   (let ((*print-length* nil)
+	 (*print-level* nil)
+	 (*package* (ilisp-find-package package)))
+     (pprint (macroexpand-1 (read-from-string expression))))))
+
+;;;
+#-lispworks
+(defun ilisp-trace (symbol package breakp)
+  "Trace SYMBOL in PACKAGE."
+  (declare (ignore breakp)) ; No way to do this in CL.
+  (ilisp-errors
+   (let ((real-symbol (ilisp-find-symbol symbol package)))
+     (when real-symbol (eval `(trace ,real-symbol))))))
+
+;;; Jason Trenouth: SEP 6 94 -- LispWorks can trace-break
+#+lispworks
+(defun ilisp-trace (symbol package breakp)
+  "Trace SYMBOL in PACKAGE."
+  (ilisp-errors
+   (let ((real-symbol (ilisp-find-symbol symbol package)))
+     breakp ;; idiom for (declare (ignorable breakp))
+     (when real-symbol (eval `(trace (,real-symbol :break breakp)))))))
+
+
+
+(defun ilisp-untrace (symbol package)
+  "Untrace SYMBOL in PACKAGE."
+  (ilisp-errors
+   (let ((real-symbol (ilisp-find-symbol symbol package)))
+     (when real-symbol (eval `(untrace ,real-symbol))))))
+   
+;;;
+(defun ilisp-compile-file (file extension)
+  "Compile FILE putting the result in FILE+EXTENSION."
+  (ilisp-errors
+   (compile-file file
+		 :output-file 
+		 (merge-pathnames (make-pathname :type extension) file))))
+
+;;;
+(defun ilisp-casify (pattern string lower-p upper-p)
+  "Return STRING with its characters converted to the case of PATTERN,
+continuing with the last case beyond the end."
+  (cond (lower-p (string-downcase string))
+	(upper-p (string-upcase string))
+	(t
+	 (let (case)
+	   (concatenate
+	    'string
+	    (map 'string
+		 #'(lambda (p s)
+		     (setq case (if (upper-case-p p)
+				    #'char-upcase
+				    #'char-downcase))
+		     (funcall case s))
+		 pattern string)
+	    (map 'string case (subseq string (length pattern))))))))
+
+;;;
+(defun ilisp-words (string)
+  "Return STRING broken up into words.  Each word is (start end
+delimiter)."
+  (do* ((length (length string))
+	(start 0)
+	(end t)
+	(words nil))
+       ((null end) (nreverse words))
+    (if (setq end (position-if-not #'alphanumericp string :start start))
+	(setq words (cons (list end (1+ end) t)
+			  (if (= start end)
+			      words
+			      (cons (list start end nil) words)))
+	      start (1+ end))
+	(setq words (cons (list start length nil) words)))))
+
+;;;
+(defun ilisp-match-words (string pattern words)
+  "Match STRING to PATTERN using WORDS."
+  (do* ((strlen (length string))
+	(words words (cdr words))
+	(word (first words) (first words))
+	(start1 (first word) (first word))
+	(end1 (second word) (second word))
+	(delimiter (third word) (third word))
+	(len (- end1 start1) (and word (- end1 start1)))
+	(start2 0)
+	(end2 len))
+       ((or (null word) (null start2)) start2)
+    (setq end2 (+ start2 len)
+	  start2
+	  (if delimiter
+	      (position (elt pattern start1) string :start start2)
+	      (when (and (<= end2 strlen)
+			 (string= pattern string
+				  :start1 start1 :end1 end1
+				  :start2 start2 :end2 end2))
+		(1- end2))))
+    (when start2 (incf start2))))
+
+;;;
+(defun ilisp-matching-symbols (string package &optional (function-p nil)
+				      (external-p nil)
+				      (prefix-p nil))
+  "Return a list of the symbols that have STRING as a prefix in
+PACKAGE. FUNCTION-P indicates that only symbols with a function value
+should be considered.  EXTERNAL-P indicates that only external symbols
+should be considered.  PREFIX-P means that partial matches should not
+be considered.  The returned strings have the same case as the
+original string."
+  (ilisp-errors
+   (let* ((lower-p (notany #'upper-case-p string))
+	  (upper-p (notany #'lower-case-p string))
+	  (no-casify (eq (ilisp-readtable-case *readtable*) :preserve))
+	  (symbol-string (ilisp-symbol-name string))
+	  (length (length string))
+	  (results nil)
+	  (*print-length* nil)
+	  (*package* (ilisp-find-package package)))
+     (labels
+	 (
+	  ;; Check SYMBOL against PATTERN
+	  (check-symbol (symbol pattern)
+	    (let ((name (symbol-name symbol)))
+	      (when (and (or (not function-p) (fboundp symbol))
+			 (>= (length name) length)
+			 (string= pattern name :end2 length))
+		(push (list (if no-casify
+				name
+				(ilisp-casify pattern name lower-p upper-p)))
+		      results))))
+	  ;; Check SYMBOL against PATTERN using WORDS 
+	  (check-symbol2 (symbol pattern words)
+	    (let ((name (symbol-name symbol)))
+	      (when (and (or (not function-p) (fboundp symbol))
+			 (ilisp-match-words name pattern words))
+		(push (list (if no-casify
+				name
+				(ilisp-casify pattern name lower-p upper-p)))
+		      results)))))
+       (if external-p
+	   (do-external-symbols (symbol *package*)
+	     (check-symbol symbol symbol-string))
+	   (progn
+	     ;; KCL does not go over used symbols.
+	     #+(or kcl ibcl ecl)
+	     (dolist (used-package (package-use-list *package*))
+	       (do-external-symbols (symbol used-package)
+		 (check-symbol symbol symbol-string)))
+	     (do-symbols (symbol *package*)
+	       (check-symbol symbol symbol-string))))
+       (unless (or results prefix-p)
+	 (let ((words (ilisp-words symbol-string)))
+	   (if external-p
+	       (do-external-symbols (symbol *package*)
+		 (check-symbol2 symbol symbol-string words))
+	       (progn
+		 ;; KCL does not go over used symbols.
+		 #+(or kcl ibcl ecl)
+		 (dolist (used-package (package-use-list *package*))
+		   (do-external-symbols (symbol used-package)
+		     (check-symbol2 symbol symbol-string words)))
+		 (do-symbols (symbol *package*)
+		   (check-symbol2 symbol symbol-string words))))))
+       (prin1 results)
+       nil))))
+
+
+(eval-when (load eval)
+  (when
+      #+cmu (eval:interpreted-function-p #'ilisp-matching-symbols)
+      #-cmu (not (compiled-function-p #'ilisp-matching-symbols))
+      (format *standard-output*
+	      "\"ILISP: File is not compiled, use M-x ilisp-compile-inits\"")))
+
+;;; end of file -- cl-ilisp.lisp --