git.fiddlerwoaroof.com
cl-support/cl-definitions.lisp
4e987026
 ;;; cl-definitions.lisp -- mumble compatibility package for Common Lisp
 ;;;
 ;;; author :  Sandra Loosemore
 ;;; date   :  11 Oct 1991
 ;;;
 ;;; You must load cl-setup and cl-support before trying to compile this 
 ;;; file.
 
 (in-package "MUMBLE-IMPLEMENTATION")
 
 
 ;;;=====================================================================
 ;;; Syntax
 ;;;=====================================================================
 
 (define-mumble-import quote)
 (define-mumble-import function)
 
 ;;; Lambda lists have to have dot syntax converted to &rest.
 
 (define-mumble-macro mumble::lambda (lambda-list &rest body)
   `(function (lambda ,(mung-lambda-list lambda-list) ,@body)))
 
 (defun mung-lambda-list (lambda-list)
   (cond ((consp lambda-list)
 	 (let ((last  (last lambda-list)))
 	   (if (null (cdr last))
 	       lambda-list
 	       `(,@(ldiff lambda-list last) ,(car last) &rest ,(cdr last)))))
 	((null lambda-list)
 	 '())
 	(t
 	 `(&rest ,lambda-list))))
 
 
 ;;; We only funcall and apply things that are real functions.
 
 
 ;;; Gag.  Lucid needs to see the procedure declaration to avoid putting
 ;;; a coerce-to-procedure check in, but there's a compiler bug that causes
 ;;; it to barf if the function is a lambda form.
 
 #+lucid
 (define-mumble-macro mumble::funcall (fn . args)
   (if (and (consp fn) (eq (car fn) 'mumble::lambda))
       `(funcall ,fn ,@args)
       `(funcall (the system::procedure ,fn) ,@args)))
 
 #+(or cmu allegro akcl lispworks mcl)
 (define-mumble-macro mumble::funcall (fn . args)
   `(funcall (the function ,fn) ,@args))
 
 #+wcl
 (define-mumble-macro mumble::funcall (fn . args)
   `(funcall (the lisp:procedure ,fn) ,@args))
 
 #-(or lucid cmu allegro akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::funcall)
 
 
 ;;; Could make this declare its fn argument too
 
 (define-mumble-import apply)
 
 (define-mumble-synonym mumble::map mapcar)
 (define-mumble-synonym mumble::for-each mapc)
 (define-mumble-import some)
 (define-mumble-import every)
 (define-mumble-import notany)
 (define-mumble-import notevery)
 (define-mumble-synonym mumble::procedure? functionp)
 
 
 (define-mumble-import if)
 (define-mumble-import when)
 (define-mumble-import unless)
 
 
 ;;; COND and CASE differ from Common Lisp because of using "else" instead 
 ;;; of "t" as the fall-through case.
 
 (define-mumble-import mumble::else)
 
 (define-mumble-macro mumble::cond (&rest cases)
   (let ((last    (car (last cases))))
     (if (eq (car last) 'mumble::else)
 	`(cond ,@(butlast cases) (t ,@(cdr last)))
 	`(cond ,@cases))))
 
 (define-mumble-macro mumble::case (data &rest cases)
   (let ((last  (car (last cases))))
     (if (eq (car last) 'mumble::else)
 	`(case ,data ,@(butlast cases) (t ,@(cdr last)))
 	`(case ,data ,@cases))))
 
 
 (define-mumble-import and)
 (define-mumble-import or)
 (define-mumble-import not)
 
 (define-mumble-macro mumble::set! (variable value)
   `(setq ,variable ,value))
 (define-mumble-import setf)
 
 
 ;;; AKCL's SETF brokenly tries to macroexpand the place
997cca7b
 ;;; form before looking for a define-setf-expander  Redefine the
4e987026
 ;;; internal function to do the right thing.
 
 #+akcl
 (defun system::setf-expand-1 (place newvalue env)
   (multiple-value-bind (vars vals stores store-form access-form)
       (get-setf-method place env)
     (declare (ignore access-form))
     `(let* ,(mapcar #'list
                     (append vars stores)
                     (append vals (list newvalue)))
        ,store-form)))
 
 
 ;;; Allegro has renamed this stuff as per ANSI CL.
 
997cca7b
 #+(or cmu allegro)
4e987026
 (eval-when (eval compile load)
   (setf (macro-function 'define-setf-method)
 	(macro-function 'define-setf-expander))
   (setf (symbol-function 'get-setf-method)
 	(symbol-function 'get-setf-expansion))
   )
 
 (define-mumble-import let)
 (define-mumble-import let*)
 
 (define-mumble-macro mumble::letrec (bindings &rest body)
   `(let ,(mapcar #'car bindings)
      ,@(mapcar #'(lambda (b) (cons 'setq b)) bindings)
      (locally ,@body)))
 
 (define-mumble-import flet)
 (define-mumble-import labels)
 
 (define-mumble-macro mumble::dynamic-let (bindings &rest body)
   `(let ,bindings
      (declare (special ,@(mapcar #'car bindings)))
      ,@body))
 
 (define-mumble-macro mumble::dynamic (name)
   `(locally (declare (special ,name)) ,name))
 
997cca7b
 (define-setf-expander mumble::dynamic (name)
4e987026
   (let ((store  (gensym)))
     (values nil
 	    nil
 	    (list store)
 	    `(locally (declare (special ,name)) (setf ,name ,store))
 	    `(locally (declare (special ,name)) ,name))))
 
 
 (define-mumble-macro mumble::begin (&rest body)
   `(progn ,@body))
 
 (define-mumble-import block)
 (define-mumble-import return-from)
 
 (define-mumble-import do)
 (define-mumble-import dolist)
 (define-mumble-import dotimes)
 
 (define-mumble-import values)
 (define-mumble-import multiple-value-bind)
 
 (define-mumble-macro mumble::let/cc (variable &rest body)
   (let ((tagvar  (gensym)))
     `(let* ((,tagvar   (gensym))
 	    (,variable (let/cc-aux ,tagvar)))
 	(catch ,tagvar (locally ,@body)))))
 
 (defun let/cc-aux (tag)
   #'(lambda (&rest values)
       (throw tag (values-list values))))
 
 
 (define-mumble-import unwind-protect)
 
 (define-mumble-import declare)
 (define-mumble-import ignore)
 
 
 ;;; IGNORABLE is part of ANSI CL but not implemented by Lucid yet.
 ;;; IGNORE in Lucid seems to behave like what ANSI CL says IGNORABLE 
 ;;; should do, but there doesn't seem to be any way to rename it.
 
 #+(or lucid akcl lispworks wcl)
 (progn
   (proclaim '(declaration mumble::ignorable))
   (define-mumble-import mumble::ignorable))
 
 #+(or cmu mcl allegro)
 (define-mumble-import cl:ignorable)
 
 #-(or lucid cmu allegro akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::ignorable)
 
 
 (define-mumble-import type)
 
 
 
 ;;;=====================================================================
 ;;; Definitions
 ;;;=====================================================================
 
 
 ;;; *** This shouldn't really do a DEFPARAMETER, since that proclaims
 ;;; *** the variable SPECIAL and makes any LETs of the variable do
 ;;; *** special binding rather than lexical binding.  But if you just
 ;;; *** SETF the variable, you'll get a compiler warning about an
 ;;; *** undeclared free variable on every reference!!!  Argggh.
 
 (define-mumble-macro mumble::define (pattern &rest value)
   (if (consp pattern)
       `(defun ,(car pattern) ,(mung-lambda-list (cdr pattern)) ,@value)
       `(defparameter ,pattern ,(car value))))
 
 (define-mumble-macro mumble::define-integrable (pattern &rest value)
   (if (consp pattern)
       `(progn
 	 (eval-when (eval compile load)
 	   (proclaim '(inline ,(car pattern))))
 	 (defun ,(car pattern) ,(mung-lambda-list (cdr pattern)) ,@value))
       `(defconstant ,pattern ,(car value))))
 
 
 (define-mumble-macro mumble::define-syntax (pattern . body)
   `(defmacro ,(car pattern) ,(mung-lambda-list (cdr pattern)) ,@body))
 
 (define-mumble-macro mumble::define-local-syntax (pattern . body)
   `(eval-when (eval compile)
      (defmacro ,(car pattern) ,(mung-lambda-list (cdr pattern)) ,@body)))
 
 
 (define-mumble-macro mumble::define-setf (getter setter)
   `(define-setf-method ,getter (&rest subforms)
      (define-setf-aux ',setter ',getter subforms)))
 
 (defun define-setf-aux (setter getter subforms)
   (let ((temps    nil)
 	(tempvals nil)
 	(args     nil)
 	(store  (gensym)))
     (dolist (x subforms)
       (if (constantp x)
 	  (push x args)
 	  (let ((temp  (gensym)))
 	    (push temp temps)
 	    (push x tempvals)
 	    (push temp args))))
     (setq temps (nreverse temps))
     (setq tempvals (nreverse tempvals))
     (setq args (nreverse args))
     (values temps
 	    tempvals
 	    (list store)
 	    `(,setter ,store ,@args)
 	    `(,getter ,@args))))
 
 
 ;;; Declaring variables special will make the compiler not proclaim
 ;;; about references to them.
 ;;; A proclamation works to disable undefined function warnings in 
 ;;; most Lisps.  Harlequin seems to offer no way to shut up these warnings.
 ;;; In allegro, we have to work around a bug in the compiler's handling
 ;;; of PROCLAIM.
 
 (define-mumble-macro mumble::predefine (pattern)
   `(eval-when (eval compile)
      #+allegro (let ((excl::*compiler-environment* nil))
 		 (do-predefine ',pattern))
      #-allegro (do-predefine ',pattern)
      ))
 
 (eval-when (eval compile load)
   (defun do-predefine (pattern)
     (if (consp pattern)
         (proclaim `(ftype (function ,(mung-decl-lambda-list (cdr pattern)) t)
 			  ,(car pattern)))
 	(proclaim `(special ,pattern))))
   (defun mung-decl-lambda-list (lambda-list)
     (cond ((consp lambda-list)
 	   (cons 't (mung-decl-lambda-list (cdr lambda-list))))
 	  ((null lambda-list)
 	   '())
 	  (t
 	   '(&rest t))))
   )
 
 
 ;;; CMUCL doesn't complain about function redefinitions, but Lucid does.
 
 #+(or cmu akcl mcl lispworks wcl)
 (define-mumble-macro mumble::redefine (pattern . value)
   `(mumble::define ,pattern ,@value))
 
 #+lucid
 (define-mumble-macro mumble::redefine (pattern . value)
   `(let ((lcl:*redefinition-action*  nil))
      (mumble::define ,pattern ,@value)))
 
 #+allegro
 (define-mumble-macro mumble::redefine (pattern . value)
   `(let ((excl:*redefinition-warnings*  nil))
      (mumble::define ,pattern ,@value)))
 
 #-(or cmu lucid allegro akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::redefine)
 
 
 #+(or cmu akcl mcl lispworks wcl)
 (define-mumble-macro mumble::redefine-syntax (pattern . body)
   `(mumble::define-syntax ,pattern ,@body))
 
 #+lucid
 (define-mumble-macro mumble::redefine-syntax (pattern . body)
   `(eval-when (eval compile load)
      (let ((lcl:*redefinition-action*  nil))
        (mumble::define-syntax ,pattern ,@body))))
 
 #+allegro
 (define-mumble-macro mumble::redefine-syntax (pattern . body)
   `(eval-when (eval compile load)
      (let ((excl:*redefinition-warnings*  nil))
        (mumble::define-syntax ,pattern ,@body))))
   
 #-(or cmu lucid allegro akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::redefine-syntax)
 
 
 
 ;;;=====================================================================
 ;;; Equivalence
 ;;;=====================================================================
 
 (define-mumble-function-inline mumble::eq? (x y)
   (eq x y))
 (define-mumble-function-inline mumble::eqv? (x y)
   (eql x y))
 
 (define-mumble-function mumble::equal? (x1 x2)
   (cond ((eql x1 x2)
 	 t)
 	((consp x1)
 	 (and (consp x2)
 	      (mumble::equal? (car x1) (car x2))
 	      (mumble::equal? (cdr x1) (cdr x2))))
 	((simple-string-p x1)
 	 (and (simple-string-p x2)
 	      (string= x1 x2)))
 	((simple-vector-p x1)
 	 (and (simple-vector-p x2)
 	      (eql (length (the simple-vector x1))
 		   (length (the simple-vector x2)))
 	      (every #'mumble::equal?
 		     (the simple-vector x1)
 		     (the simple-vector x2))))
 	(t nil)))
 
 
 ;;;=====================================================================
 ;;; Lists
 ;;;=====================================================================
 
 (define-mumble-function-inline mumble::pair? (x)
   (consp x))
 
 (define-mumble-import cons)
 
 
 ;;; Can't import this directly because of type problems.
 
 (define-mumble-synonym mumble::list list)
 
 (define-mumble-function-inline mumble::make-list (length &optional (init nil))
   (the list
        (make-list length :initial-element init)))
 
 (define-mumble-import car)
 (define-mumble-import cdr)
 (define-mumble-import caar)
 (define-mumble-import cadr)
 (define-mumble-import cadr)
 (define-mumble-import cddr)
 (define-mumble-import caaar)
 (define-mumble-import caadr)
 (define-mumble-import caadr)
 (define-mumble-import caddr)
 (define-mumble-import cdaar)
 (define-mumble-import cdadr)
 (define-mumble-import cdadr)
 (define-mumble-import cdddr)
 (define-mumble-import caaaar)
 (define-mumble-import caaadr)
 (define-mumble-import caaadr)
 (define-mumble-import caaddr)
 (define-mumble-import cadaar)
 (define-mumble-import cadadr)
 (define-mumble-import cadadr)
 (define-mumble-import cadddr)
 (define-mumble-import cdaaar)
 (define-mumble-import cdaadr)
 (define-mumble-import cdaadr)
 (define-mumble-import cdaddr)
 (define-mumble-import cddaar)
 (define-mumble-import cddadr)
 (define-mumble-import cddadr)
 (define-mumble-import cddddr)
 
 (define-mumble-function-inline mumble::null? (x)
   (null x))
 
 (define-mumble-function mumble::list? (x)
   (cond ((null x) t)
 	((consp x) (mumble::list? (cdr x)))
 	(t nil)))
 
 (define-mumble-function-inline mumble::length (x)
   (the fixnum (length (the list x))))
 
 (define-mumble-import append)
 (define-mumble-import nconc)
 
 (define-mumble-function-inline mumble::reverse (x)
   (the list (reverse (the list x))))
 (define-mumble-function-inline mumble::nreverse (x)
   (the list (nreverse (the list x))))
 
 (define-mumble-function-inline mumble::list-tail (list n)
   (nthcdr n list))
 (define-mumble-function-inline mumble::list-ref (list n)
   (nth n list))
 
 (define-mumble-import last)
 (define-mumble-import butlast)
 
997cca7b
 (define-setf-expander mumble::list-ref (list n)
4e987026
   (get-setf-method `(nth ,n ,list)))
 
 (define-mumble-function-inline mumble::memq (object list)
   (member object list :test #'eq))
 (define-mumble-function-inline mumble::memv (object list)
   (member object list))
 (define-mumble-function-inline mumble::member (object list)
   (member object list :test #'mumble::equal?))
 
 ;;; *** The Lucid compiler is not doing anything inline for assq so
 ;;; *** I'm rewriting this  -- jcp
 (define-mumble-function mumble::assq (object list)
   (if (null list)
       nil
       (if (eq object (caar list))
           (car list)
 	  (mumble::assq object (cdr list)))))
 	
 (define-mumble-function-inline mumble::assv (object list)
   (assoc object list))
 (define-mumble-function-inline mumble::assoc (object list)
   (assoc object list :test #'mumble::equal?))
 
 (define-mumble-import push)
 (define-mumble-import pop)
 
 (define-mumble-synonym mumble::list-copy copy-list)
 
 
 ;;;=====================================================================
 ;;; Symbols
 ;;;=====================================================================
 
 (define-mumble-function-inline mumble::symbol? (x)
   (symbolp x))
 (define-mumble-synonym mumble::symbol->string symbol-name)
 
 (define-mumble-function-inline mumble::string->symbol (x)
   (intern x))
 
 
 ;;; We want a gensym that follows the new ANSI CL gensym-name-stickiness
 ;;; decision.
 
 #+(or lucid akcl wcl)
 (define-mumble-function mumble::gensym (&optional (prefix "G"))
   (gensym prefix))
 
 #+(or cmu allegro mcl lispworks)
 (define-mumble-import gensym)
 
 #-(or lucid akcl wcl cmu allegro mcl lispworks)
 (missing-mumble-definition mumble::gensym)
 
 (define-mumble-function mumble::gensym? (x)
   (and (symbolp x)
        (not (symbol-package x))))
 
 (defun symbol-append (&rest symbols)
   (intern (apply #'concatenate 'string (mapcar #'symbol-name symbols))))
 (define-mumble-import symbol-append)
 
 
 ;;;=====================================================================
 ;;; Characters
 ;;;=====================================================================
 
 (define-mumble-function-inline mumble::char? (x)
   (characterp x))
 
 (define-mumble-synonym mumble::char=? char=)
 (define-mumble-synonym mumble::char<? char<)
 (define-mumble-synonym mumble::char>? char>)
 (define-mumble-synonym mumble::char>=? char>=)
 (define-mumble-synonym mumble::char<=? char<=)
 
 (define-mumble-synonym mumble::char-ci=? char-equal)
 (define-mumble-synonym mumble::char-ci<? char-lessp)
 (define-mumble-synonym mumble::char-ci>? char-greaterp)
 (define-mumble-synonym mumble::char-ci>=? char-not-lessp)
 (define-mumble-synonym mumble::char-ci<=? char-not-greaterp)
 
 (define-mumble-synonym mumble::char-alphabetic? alpha-char-p)
 (define-mumble-synonym mumble::char-numeric? digit-char-p)
 
 (define-mumble-function mumble::char-whitespace? (c)
   (member c '(#\space #\tab #\newline #\linefeed #\page #\return)))
 
 (define-mumble-synonym mumble::char-upper-case? upper-case-p)
 (define-mumble-synonym mumble::char-lower-case? lower-case-p)
 
 (define-mumble-synonym mumble::char->integer char-code)
 (define-mumble-synonym mumble::integer->char code-char)
 
 (define-mumble-import char-upcase)
 (define-mumble-import char-downcase)
 (define-mumble-import char-name)
 
 (define-mumble-synonym mumble::char->digit digit-char-p)
 
 
 ;;;=====================================================================
 ;;; Strings
 ;;;=====================================================================
 
 (define-mumble-function-inline mumble::string? (x)
   (simple-string-p x))
 
 (define-mumble-function-inline mumble::make-string
       (length &optional (init nil init-p))
   (the simple-string
        (if init-p
 	   (make-string length :initial-element init)
 	   (make-string length))))
 
 (define-mumble-function-inline mumble::string (char &rest more-chars)
   (the simple-string (coerce (cons char more-chars) 'string)))
 
 (define-mumble-function-inline mumble::string-length (string)
   (the fixnum (length (the simple-string string))))
 
 (define-mumble-function-inline mumble::string-ref (x n)
   (the character (schar (the simple-string x) (the fixnum n))))
 
997cca7b
 (define-setf-expander mumble::string-ref (string n)
4e987026
   (get-setf-method `(schar ,string ,n)))
 
 (define-mumble-synonym mumble::string=? string=)
 (define-mumble-synonym mumble::string<? string<)
 (define-mumble-synonym mumble::string>? string>)
 (define-mumble-synonym mumble::string<=? string<=)
 (define-mumble-synonym mumble::string>=? string>=)
 
 (define-mumble-synonym mumble::string-ci=? string-equal)
 (define-mumble-synonym mumble::string-ci<? string-lessp)
 (define-mumble-synonym mumble::string-ci>? string-greaterp)
 (define-mumble-synonym mumble::string-ci<=? string-not-greaterp)
 (define-mumble-synonym mumble::string-ci>=? string-not-lessp)
 
 (define-mumble-function-inline mumble::substring (string start end)
   (the simple-string (subseq (the simple-string string) start end)))
 
 (define-mumble-function-inline mumble::string-append
       (string &rest more-strings)
   (declare (type simple-string string))
   (the simple-string (apply #'concatenate 'string string more-strings)))
 
 (define-mumble-function-inline mumble::string->list (string)
   (the list (coerce (the simple-string string) 'list)))
 
 (define-mumble-function-inline mumble::list->string (list)
   (the simple-string (coerce (the list list) 'string)))
 
 (define-mumble-function-inline mumble::string-copy (string)
   (the simple-string (copy-seq (the simple-string string))))
 
 (define-mumble-import string-upcase)
 (define-mumble-import string-downcase)
 
 
 ;;;=====================================================================
 ;;; Vectors
 ;;;=====================================================================
 
 (define-mumble-function-inline mumble::vector? (x)
   (simple-vector-p x))
 
 (define-mumble-function-inline mumble::make-vector
       (length &optional (init nil init-p))
   (declare (type fixnum length))
   (the simple-vector
        (if init-p
 	   (make-array length :initial-element init)
 	   (make-array length))))
 
 
 ;;; Can't import directly because types are incompatible.
 
 (define-mumble-synonym mumble::vector vector)
 
 (define-mumble-function-inline mumble::vector-length (vector)
   (the fixnum (length (the simple-vector vector))))
 
 (define-mumble-function-inline mumble::vector-ref (x n)
   (svref (the simple-vector x) (the fixnum n)))
 
997cca7b
 (define-setf-expander mumble::vector-ref (vector n)
4e987026
   (get-setf-method `(svref ,vector ,n)))
 
 (define-mumble-function-inline mumble::vector->list (vector)
   (the list (coerce (the simple-vector vector) 'list)))
 
 (define-mumble-function-inline mumble::list->vector (list)
   (the simple-vector (coerce (the list list) 'simple-vector)))
 
 (define-mumble-function-inline mumble::vector-copy (vector)
   (the simple-vector (copy-seq (the simple-vector vector))))
 
 
 ;;;=====================================================================
 ;;; Numbers
 ;;;=====================================================================
 
 (define-mumble-synonym mumble::number? numberp)
 (define-mumble-synonym mumble::integer? integerp)
 (define-mumble-synonym mumble::rational? rationalp)
 (define-mumble-synonym mumble::float? floatp)
 
 (define-mumble-function-inline mumble::fixnum? (x)
   (typep x 'fixnum))
 
 (define-mumble-synonym mumble::exact->inexact float)
 
 (define-mumble-import =)
 (define-mumble-import <)
 (define-mumble-import >)
 (define-mumble-import <=)
 (define-mumble-import >=)
 
 (define-mumble-synonym mumble::zero? zerop)
 (define-mumble-function-inline mumble::positive? (x)
   (> x 0))
 (define-mumble-function-inline mumble::negative? (x)
   (< x 0))
 
 (define-mumble-import min)
 (define-mumble-import max)
 
 (define-mumble-import +)
 (define-mumble-import *)
 (define-mumble-import -)
 (define-mumble-import /)
 
 (define-mumble-synonym mumble::quotient floor)
 (define-mumble-synonym mumble::remainder rem)
 (define-mumble-synonym mumble::modulo mod)
 
 (define-mumble-function-inline mumble::floor (x)
   (if (floatp x) (ffloor x) (floor (the rational x))))
 (define-mumble-function-inline mumble::ceiling (x)
   (if (floatp x) (fceiling x) (ceiling (the rational x))))
 (define-mumble-function-inline mumble::truncate (x)
   (if (floatp x) (ftruncate x) (truncate (the rational x))))
 (define-mumble-function-inline mumble::round (x)
   (if (floatp x) (fround x) (round (the rational x))))
 
 (define-mumble-synonym mumble::floor->exact floor)
 (define-mumble-synonym mumble::ceiling->exact ceiling)
 (define-mumble-synonym mumble::truncate->exact truncate)
 (define-mumble-synonym mumble::round->exact round)
 
 (define-mumble-import 1+)
 (define-mumble-import 1-)
 (define-mumble-import incf)
 (define-mumble-import decf)
 
 (define-mumble-function mumble::number->string (number &optional (radix 10))
   (let ((*print-base*  radix))
     (prin1-to-string number)))
 
 (define-mumble-function mumble::string->number (string &optional (radix 10))
   (let ((*read-base* radix))
     (read-from-string string)))
 
 (define-mumble-import expt)
 
 
 
 ;;;=====================================================================
 ;;; Tables
 ;;;=====================================================================
 
 (define-mumble-synonym mumble::table? hash-table-p)
 
 (define-mumble-function-inline mumble::make-table ()
   (make-hash-table :test #'eq))
 
 (define-mumble-function-inline mumble::table-entry (table key)
   (gethash key table))
 
997cca7b
 (define-setf-expander mumble::table-entry (table key)
4e987026
   (get-setf-method `(gethash ,key ,table)))
 
 (define-mumble-synonym mumble::table-for-each maphash)
 
 (define-mumble-function mumble::copy-table (old-table)
   (let ((new-table  (make-hash-table :test #'eq
 				     :size (1+ (hash-table-count old-table)))))
     (maphash #'(lambda (key val) (setf (gethash key new-table) val))
 	     old-table)
     new-table))
 
 
 ;;;=====================================================================
 ;;; I/O
 ;;;=====================================================================
 
 (define-mumble-function-inline mumble::call-with-input-file (string proc)
   (with-open-file (stream (expand-filename string) :direction :input)
     (funcall (the function proc) stream)))
 
 (define-mumble-function-inline mumble::call-with-output-file (string proc)
   (with-open-file (stream (expand-filename string)
 			  :direction :output :if-exists :new-version)
     (funcall (the function proc) stream)))
 
 (define-mumble-function-inline mumble::call-with-input-string (string proc)
   (with-input-from-string (stream string)
      (funcall (the function proc) stream)))
 
 (define-mumble-function-inline mumble::call-with-output-string (proc)
   (with-output-to-string (stream)
     (funcall (the function proc) stream)))
 
 (define-mumble-synonym mumble::input-port? input-stream-p)
 (define-mumble-synonym mumble::output-port? output-stream-p)
 
 (define-mumble-function-inline mumble::current-input-port ()
   *standard-input*)
 (define-mumble-function-inline mumble::current-output-port ()
   *standard-output*)
 
 (define-mumble-function-inline mumble::open-input-file (string)
   (open (expand-filename string) :direction :input))
 
 (define-mumble-function-inline mumble::open-output-file (string)
   (open (expand-filename string) :direction :output :if-exists :new-version))
 
 
 (define-mumble-synonym mumble::close-input-port close)
 (define-mumble-synonym mumble::close-output-port close)
 
 (defvar *eof-object* (make-symbol "EOF"))
 
 (define-mumble-function-inline mumble::read
       (&optional (port *standard-input*))
   (read port nil *eof-object*))
 
 (define-mumble-function-inline mumble::read-char
       (&optional (port *standard-input*))
   (read-char port nil *eof-object*))
 
 (define-mumble-function-inline mumble::peek-char
       (&optional (port *standard-input*))
   (peek-char nil port nil *eof-object*))
 
 (define-mumble-function-inline mumble::read-line
       (&optional (port *standard-input*))
   (read-line port nil *eof-object*))
 
 (define-mumble-function-inline mumble::eof-object? (x)
   (eq x *eof-object*))
 
 
 ;;;=====================================================================
 ;;; Printer
 ;;;=====================================================================
 
 (define-mumble-function mumble::internal-write (object port)
   (write object :stream port))
 (define-mumble-function-inline mumble::internal-output-width (port)
   (declare (ignore port))
   nil)
 (define-mumble-function-inline mumble::internal-output-position (port)
   (declare (ignore port))
   nil)
 (define-mumble-synonym mumble::internal-write-char write-char)
 (define-mumble-function-inline mumble::internal-write-string
                                (string port start end)
   (write-string string port :start start :end end))
 (define-mumble-synonym mumble::internal-newline terpri)
 (define-mumble-synonym mumble::internal-fresh-line fresh-line)
 (define-mumble-synonym mumble::internal-finish-output finish-output)
 (define-mumble-synonym mumble::internal-force-output force-output)
 (define-mumble-synonym mumble::internal-clear-output clear-output)
 
 (define-mumble-function mumble::internal-write-to-string (object)
   (write-to-string object))
 
 
 (define-mumble-function-inline mumble::internal-warning (string)
   (warn "~a" string))
 
 (define-mumble-function-inline mumble::internal-error (string)
   (error "~a" string))
 
 
 ;;; Printer stuff used directly by the pretty printer
 
 (define-mumble-import *print-escape*)
 (define-mumble-import *print-circle*)
 (define-mumble-import *print-pretty*)
 (define-mumble-import *print-level*)
 (define-mumble-import *print-length*)
 (define-mumble-import *print-base*)
 (define-mumble-import *print-radix*)
 
 
 ;;; These functions and variables are all defined with the XP stuff.  But,
 ;;; let's export all the symbols from the mumble package.
 
 (define-mumble-import mumble::write)
 (define-mumble-import mumble::print)
 (define-mumble-import mumble::prin1)
 (define-mumble-import mumble::princ)
 (define-mumble-import mumble::pprint)
 (define-mumble-import mumble::prin1-to-string)
 (define-mumble-import mumble::princ-to-string)
 (define-mumble-import mumble::write-char)
 (define-mumble-import mumble::write-string)
 (define-mumble-import mumble::write-line)
 (define-mumble-import mumble::terpri)
 (define-mumble-import mumble::fresh-line)
 (define-mumble-import mumble::finish-output)
 (define-mumble-import mumble::force-output)
 (define-mumble-import mumble::clear-output)
 (define-mumble-import mumble::display)
 (define-mumble-import mumble::newline)
 (define-mumble-import mumble::*print-shared*)
 (define-mumble-import mumble::*print-dispatch*)
 (define-mumble-import mumble::*print-right-margin*)
 (define-mumble-import mumble::*print-miser-width*)
 (define-mumble-import mumble::*print-lines*)
 (define-mumble-import mumble::*default-right-margin*)
 (define-mumble-import mumble::*last-abbreviated-printing*)
 (define-mumble-import mumble::*print-structure*)
 (define-mumble-import mumble::*print-structure-slots*)
 (define-mumble-import mumble::standard-print-dispatch)
 (define-mumble-import mumble::pprint-newline)
 (define-mumble-import mumble::pprint-logical-block)
 (define-mumble-import mumble::pprint-pop)
 (define-mumble-import mumble::pprint-exit-if-list-exhausted)
 (define-mumble-import mumble::pprint-indent)
 (define-mumble-import mumble::pprint-tab)
 (define-mumble-import mumble::pprint-fill)
 (define-mumble-import mumble::pprint-linear)
 (define-mumble-import mumble::pprint-tabular)
 (define-mumble-import mumble::format)
 (define-mumble-import mumble::warning)
 (define-mumble-import mumble::error)
 
 
 ;;; These are keywords for pprint-newline.
 
 (define-mumble-import mumble::linear)
 (define-mumble-import mumble::fill)
 (define-mumble-import mumble::miser)
 (define-mumble-import mumble::mandatory)
 
 ;;; These are keywords for pprint-indent
 
 ;; (define-mumble-import mumble::block)  ; already imported as special form
 (define-mumble-import mumble::current)
 
 ;;; These are keywords for pprint-tab
 
 (define-mumble-import mumble::line)
 (define-mumble-import mumble::section)
 (define-mumble-import mumble::line-relative)
 (define-mumble-import mumble::section-relative)
 
 
 ;;;=====================================================================
 ;;; System Interface
 ;;;=====================================================================
 
 (define-mumble-import macroexpand-1)
 (define-mumble-import macroexpand)
 
 
 ;;; WITH-COMPILATION-UNIT is an ANSI CL feature that isn't yet
 ;;; supported by all Lisps.
 
 #+lucid
 (define-mumble-macro mumble::with-compilation-unit (options &body body)
   (declare (ignore options))
   `(lcl:with-deferred-warnings ,@body))
 
 #+(or cmu mcl allegro lispworks)
 (define-mumble-import with-compilation-unit)
 
 #+(or akcl wcl)
 (define-mumble-macro mumble::with-compilation-unit (options &body body)
   (declare (ignore options))
   `(progn ,@body))
 
 #-(or lucid allegro cmu akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::with-compilation-unit)
 
 
 (define-mumble-function mumble::eval (form &optional compile-p)
   (if compile-p
       (mumble::with-compilation-unit ()
         (eval-compiling-functions form))
       (eval form)))
 
 
 ;;; Simply doing (funcall (compile nil `(lambda () ,form))) would work
 ;;; except that top-level-ness actions would be lost (causing extraneous
 ;;; warning messages about global variables whose references are compiled
 ;;; before a previous predefine is executed, etc).  So make an attempt
 ;;; to process nested top-level forms in order.  This doesn't look for
 ;;; all of the common-lispy things that might show up in macro expansions,
 ;;; but it's close enough.
 
 (defun eval-compiling-functions (form)
   (if (atom form)
       (eval form)
       (let ((fn  (car form)))
 	(cond ((or (eq fn 'mumble::begin)
 		   (eq fn 'progn))
 	       (do ((forms (cdr form) (cdr forms)))
 		   ((null (cdr forms)) (eval-compiling-functions (car forms)))
 		   (eval-compiling-functions (car forms))))
 	      ((eq fn 'mumble::define)
 	       (if (consp (cadr form))
 		   (compile-define form)
 		   (compile-other form)))
 	      ((eq fn 'mumble::define-integrable)
 	       (if (consp (cadr form))
 		   (progn
 		     (proclaim `(inline ,(car (cadr form))))
 		     (compile-define form))
 		   (compile-other form)))
 	      ((eq fn 'mumble::predefine)
 	       (do-predefine (cadr form)))
 	      ((macro-function fn)
 	       (eval-compiling-functions (macroexpand-1 form)))
 	      (t
 	       (compile-other form))))))
 
 (defun compile-define (form)
   (let ((name  (car (cadr form)))
 	(args  (mung-lambda-list (cdr (cadr form))))
 	(body  (cddr form)))
     (compile name `(lambda ,args ,@body))
     name))
 
 (defun compile-other (form)
   (funcall (compile nil `(lambda () ,form))))
 
 
 ;;; Load and compile-file aren't directly imported from the host
 ;;; Common Lisp because we want to do our own defaulting of file
 ;;; name extensions.
 
 (define-mumble-function mumble::load (filename)
   (setq filename (expand-filename filename))
   (if (string= (mumble::filename-type filename) "")
       (let ((source-file  (build-source-filename filename))
 	    (binary-file  (build-binary-filename filename)))
 	(if (and (probe-file binary-file)
 		 (> (file-write-date binary-file)
 		    (file-write-date source-file)))
 	    (load binary-file)
 	    (load source-file)))
       (load filename)))
 
 
 ;;; This is used to control OPTIMIZE declarations in a somewhat more
 ;;; portable way -- different implementations may need slightly different
 ;;; combinations.
 ;;; 0 = do as little as possible when compiling code
 ;;; 1 = use "default" compiler settings
 ;;; 2 = omit safety checks and do "easy" speed optimizations.
 ;;; 3 = do as much as possible; type inference, inlining, etc.  May be slow.
 ;;; #f = don't mess with optimize settings.
 
 (defvar *code-quality* nil)
 (define-mumble-import *code-quality*)
 
 (defun code-quality-hack (q)
   (cond ((eql q 0)
 	 (proclaim '(optimize (speed 1) (safety 3) (compilation-speed 3)
 			      #+cmu (ext:debug 1)  
                               #+(or mcl allegro lispworks) (debug 1)
 			      )))
 	((eql q 1)
 	 (proclaim '(optimize (speed 1) (safety 1) (compilation-speed 3)
 			      #+cmu (ext:debug 1)
                               #+(or mcl allegro lispworks) (debug 1)
 			      )))
 	((eql q 2)
 	 (proclaim '(optimize (speed 3) (safety 0) (compilation-speed 3)
 			      #+cmu (ext:debug 0)
                               #+(or mcl allegro lispworks) (debug 0)
 			      )))
 	((eql q 3)
 	 (proclaim '(optimize (speed 3) (safety 0) (compilation-speed 0)
 			      #+cmu (ext:debug 0)
                               #+(or mcl allegro lispworks) (debug 0)
 			      )))
 	(t
 	 (warn "Bogus *code-quality* setting ~s." q))))
 
 
 ;;; If we don't do this, code generated with high code-quality settings
 ;;; can't be interrupted with ^C.
 
 #+allegro
 (setf compiler:generate-interrupt-checks-switch
       #'(lambda (safety space speed debug)
 	  (declare (ignore safety space speed debug))
 	  t))
 
 
 ;;; Note that we expect the binary filename (if supplied) to be
 ;;; relative to the current directory, not to the source filename.
 ;;; Lucid and AKCL (and maybe other implementations) merge the :output-file
 ;;; pathname with the source filename, but the merge by expand-filename
 ;;; should prevent it from doing anything.
 
 (define-mumble-function mumble::compile-file (filename &optional binary)
   (if *code-quality* (code-quality-hack *code-quality*))
   (setq filename (expand-filename filename))
   (if (string= (mumble::filename-type filename) "")
       (setq filename (build-source-filename filename)))
   (if binary
       (compile-file filename :output-file (expand-filename binary))
       (compile-file filename)))
 
 
 ;;; See cl-init.lisp for initialization of *lisp-binary-file-type*.
 
 (defconstant source-file-type ".scm")
 (defconstant binary-file-type *lisp-binary-file-type*)
 (define-mumble-import source-file-type)
 (define-mumble-import binary-file-type)
 
 
 (defun build-source-filename (filename)
   (mumble::assemble-filename filename filename source-file-type))
 
 (defun build-binary-filename (filename)
   (mumble::assemble-filename filename filename binary-file-type))
 
 (proclaim '(ftype (function (simple-string) simple-string)
 		  mumble::filename-place
 		  mumble::filename-name
 		  mumble::filename-type
 		  expand-filename))
 
 (proclaim '(ftype (function (simple-string simple-string simple-string)
 			    simple-string)
 		  mumble::assemble-filename))
 
 (define-mumble-function mumble::assemble-filename (place name type)
   (concatenate 'string
 	       (mumble::filename-place place)
 	       (mumble::filename-name name)
 	       (mumble::filename-type type)))
 
 (define-mumble-function mumble::filename-place (filename)
   (declare (simple-string filename))
   (let ((slash  (position #\/ filename :from-end t)))
     (if slash
 	(subseq filename 0 (1+ slash))
 	"")))
 
 (define-mumble-function mumble::filename-name (filename)
   (declare (simple-string filename))
   (let* ((slash  (position #\/ filename :from-end t))
 	 (beg    (if slash (1+ slash) 0))
 	 (dot    (position #\. filename :start beg)))
     (if (or slash dot)
 	(subseq filename beg (or dot (length filename)))
 	filename)))
 
 (define-mumble-function mumble::filename-type (filename)
   (declare (simple-string filename))
   (let* ((slash  (position #\/ filename :from-end t))
 	 (beg    (if slash (1+ slash) 0))
 	 (dot    (position #\. filename :start beg)))
     (if dot
 	(subseq filename dot (length filename))
 	"")))
 
 
 ;;; This function is called by all functions that pass filenames down
 ;;; to the operating system.  It does environment variable substitution
 ;;; and merging with *default-pathname-defaults* (set by the cd function).
 ;;; Since this function translates mumble's notion of pathnames into
 ;;; a lower-level representation, this function should never need to
 ;;; be called outside of this file.
 
 (defun expand-filename (filename)
   (declare (simple-string filename))
   (namestring
     (merge-pathnames
       (fix-filename-syntax 
         (if (eql (schar filename 0) #\$)
 	    (let* ((end    (length filename))
 		   (slash  (or (position #\/ filename) end))
 		   (new    (mumble::getenv (subseq filename 1 slash))))
 	      (if new
 		  (concatenate 'string new (subseq filename slash end))
 		  filename))
 	    filename)
         ))))
 
 
 ;;; On non-unix machines, may need to change the mumble unix-like filename
 ;;; syntax to whatever the normal syntax used by the implementation is.
 
 #+mcl
 (defun fix-filename-syntax (filename)
   (substitute #\: #\/ filename))
 
 #-mcl
 (defun fix-filename-syntax (filename)
   filename)
 
 
 ;;; AKCL's compile-file merges the output pathname against the input
 ;;; pathname.  If the output pathname doesn't have an explicit directory
 ;;; but the input pathname does, the wrong thing will happen.  This
 ;;; hack is so that expand-filename will always put a directory
 ;;; specification on both pathnames.
 ;;; Lucid CL does similar merging, but *default-pathname-defaults*
 ;;; already defaults to the truename of the current directory.
 
 #+akcl
 (setf *default-pathname-defaults* (truename "./"))
 
 
 ;;; WCL's *default-pathname-defaults* is OK except that it has a
 ;;; type of .lisp, which is inappropriate.
 
 #+wcl
 (setf *default-pathname-defaults*
       (make-pathname :directory
 		     (pathname-directory *default-pathname-defaults*)))
 
 #+(or mcl lispworks)
 (setf *default-pathname-defaults*
       (truename *default-pathname-defaults*))
 
 
 (define-mumble-function mumble::file-exists? (filename)
   (probe-file (expand-filename filename)))
 
 (define-mumble-function mumble::file-write-date (filename)
   (file-write-date (expand-filename filename)))
 
 (define-mumble-synonym mumble::current-date get-universal-time)
 
 (define-mumble-function mumble::get-run-time ()
   (/ (get-internal-run-time) (float internal-time-units-per-second)))
 
 
 ;;; Get environment variables
 
 #+lucid
 (progn
   (mumble::predefine (mumble::getenv string))
   (define-mumble-synonym mumble::getenv lcl:environment-variable))
 
 #+cmu
 (define-mumble-function mumble::getenv (string)
   (let ((symbol  (intern string (find-package "KEYWORD"))))
     (cdr (assoc symbol extensions:*environment-list*))))
 
 #+(or akcl allegro lispworks)
 (define-mumble-function mumble::getenv (string)
   (system::getenv string))
 
 #+wcl
 (define-mumble-function mumble::getenv (string)
   (lisp:getenv string))
 
 
 ;;; Hmmm.  The Mac doesn't have environment variables, so we'll have to
 ;;; roll our own.
 
 #+mcl
 (progn
   (defvar *environment-alist* '())
   (define-mumble-function mumble::getenv (string)
     (cdr (assoc string *environment-alist* :test #'string=)))
   )
 
 
 #-(or lucid allegro cmu akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::getenv)
 
 
 ;;; Change working directory.
 ;;; This stores a directory pathname in *default-pathname-defaults*.
 ;;; See also expand-filename.
 
 (define-mumble-function mumble::cd (filename)
   (if (not (eql (schar filename (1- (length filename))) #\/))
       (setq filename (concatenate 'string filename "/")))
   (setq *default-pathname-defaults* (pathname (expand-filename filename))))
  
 
 ;;; Leave Lisp
 
 #+lucid
 (define-mumble-synonym mumble::exit lcl:quit)
 
 #+allegro
 (define-mumble-synonym mumble::exit excl:exit)
 
 #+cmu
 (define-mumble-synonym mumble::exit  extensions:quit)
 
 #+akcl
 (define-mumble-synonym mumble::exit lisp:bye)
 
 #+mcl
 (define-mumble-synonym mumble::exit ccl:quit)
 
 #+lispworks
 (define-mumble-synonym mumble::exit lw:bye)
 
 #+wcl
 (define-mumble-synonym mumble::exit lisp:quit)
 
     
 #-(or lucid allegro cmu akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::exit)
 
 
 
 ;;;=====================================================================
 ;;; Reader support
 ;;;=====================================================================
 
 
 ;;; Make the default readtable recognize #f and #t.
 ;;; CMUCL's loader rebinds *readtable* when loading file, so can't
 ;;; setq it here; hack the default readtable instead.
 
 #+(or cmu mcl allegro lispworks)
 (defparameter *mumble-readtable* *readtable*)
 
 #+(or lucid akcl wcl)
 (progn
   (defparameter *mumble-readtable* (copy-readtable nil))
   (setq *readtable* *mumble-readtable*)
   )
 
 #-(or lucid allegro cmu akcl mcl lispworks wcl)
 (missing-mumble-definition *mumble-readtable*)
 
 
 ;;; Lucid's debugger uses the standard readtable rather than *readtable*
 ;;; unless you do this magic trick.
 
 #+lucid
 (sys:add-debugger-binding '*readtable* *mumble-readtable*)
 
 
 
 (set-dispatch-macro-character #\# #\f
     #'(lambda (stream subchar arg)
 	(declare (ignore stream subchar arg))
 	nil))
 
 (set-dispatch-macro-character #\# #\t
     #'(lambda (stream subchar arg)
 	(declare (ignore stream subchar arg))
 	t))
 
 
 
 ;;;=====================================================================
 ;;; Random stuff
 ;;;=====================================================================
 
 (defconstant mumble::lisp-implementation-name *lisp-implementation-name*)
 (define-mumble-import mumble::lisp-implementation-name)
 
 (define-mumble-function mumble::identify-system ()
   (format nil "~a version ~a on ~a"
 	  (or (lisp-implementation-type)
 	      "Generic Common Lisp")
 	  (or (lisp-implementation-version)
 	      "Generic")
 	  (or (machine-type)
 	      "Generic Machine")))
 
 (defconstant mumble::left-to-right-evaluation t)
 (define-mumble-import mumble::left-to-right-evaluation)
 
 
 #+excl
 (define-mumble-function mumble::gc-messages (onoff)
   (setf (sys:gsgc-switch :print) onoff))
 #+cmu
 (define-mumble-function mumble::gc-messages (onoff)
   (setf extensions:*gc-verbose* onoff))
 #+(or lispworks akcl wcl mcl)
 (define-mumble-function mumble::gc-messages (onoff)
   onoff)   ; can't figure out if they have a hook or not
 #+lucid
 (define-mumble-function mumble::gc-messages (onoff)
   (setf lcl:*gc-silence* (not onoff))
   onoff)
 
 
 #-(or lucid cmu allegro akcl mcl lispworks wcl)
 (missing-mumble-definition mumble::gc-messages)
 
 
 (define-mumble-import identity)