gcl.git - GNU Common Lisp

index : gcl.git
GNU Common Lisp
summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamm Maguire <camm@debian.org>2002年06月17日 05:25:31 +0000
committerCamm Maguire <camm@debian.org>2002年06月17日 05:25:31 +0000
commit5b021a5a0f41b84c141cb36fee4908e5be8bb2de (patch)
treedcb4f38240cb68175c9bb8fc241b34266b7c26c9
parent193c02282fa449f82027bae07ff2407c625ed99d (diff)
downloadgcl-initial.tar.gz
pcl import for initial ansi supportfirst initial
Diffstat
-rw-r--r--gcl/pcl/impl/cmu/README 17
-rw-r--r--gcl/pcl/impl/cmu/cmu-low.lisp 217
-rw-r--r--gcl/pcl/impl/cmu/pclcom.lisp 66
-rw-r--r--gcl/pcl/impl/cmu/pclload.lisp 12
-rw-r--r--gcl/pcl/impl/coral/coral-low.lisp 63
-rw-r--r--gcl/pcl/impl/franz/cpatch.lisp 32
-rw-r--r--gcl/pcl/impl/franz/excl-low.lisp 136
-rw-r--r--gcl/pcl/impl/franz/quadlap.lisp 619
-rw-r--r--gcl/pcl/impl/gcl/README 14
-rw-r--r--gcl/pcl/impl/gcl/gcl-low.lisp 309
-rw-r--r--gcl/pcl/impl/gcl/gcl-patches.lisp 225
-rw-r--r--gcl/pcl/impl/gcl/makefile.gcl 38
-rw-r--r--gcl/pcl/impl/gcl/sys-package.lisp 149
-rw-r--r--gcl/pcl/impl/gcl/sys-proclaim.lisp 1448
-rw-r--r--gcl/pcl/impl/gold-hill/gold-low.lisp 51
-rw-r--r--gcl/pcl/impl/gold-hill/gold-patches.lisp 168
-rw-r--r--gcl/pcl/impl/hp/hp-low.lisp 37
-rw-r--r--gcl/pcl/impl/ibcl/ibcl-low.lisp 327
-rw-r--r--gcl/pcl/impl/ibcl/ibcl-patches.lisp 129
-rw-r--r--gcl/pcl/impl/kcl/kcl-low.lisp 438
-rw-r--r--gcl/pcl/impl/kcl/kcl-mods.text 224
-rw-r--r--gcl/pcl/impl/kcl/kcl-notes.text 39
-rw-r--r--gcl/pcl/impl/kcl/kcl-patches.lisp 362
-rw-r--r--gcl/pcl/impl/kcl/makefile.akcl 32
-rw-r--r--gcl/pcl/impl/kcl/misc-kcl-patches.text 340
-rw-r--r--gcl/pcl/impl/kcl/new-kcl-wrapper.text 2157
-rw-r--r--gcl/pcl/impl/kcl/sys-package.lisp 149
-rw-r--r--gcl/pcl/impl/kcl/sys-proclaim.lisp 818
-rw-r--r--gcl/pcl/impl/kcl/sysdef.lisp 121
-rw-r--r--gcl/pcl/impl/lucid/lucid-low.lisp 384
-rw-r--r--gcl/pcl/impl/pyramid/pyr-low.lisp 50
-rw-r--r--gcl/pcl/impl/pyramid/pyr-patches.lisp 9
-rw-r--r--gcl/pcl/impl/symbolics/cloe-low.lisp 32
-rw-r--r--gcl/pcl/impl/symbolics/genera-low.lisp 423
-rw-r--r--gcl/pcl/impl/symbolics/rel-7-2-patches.lisp 387
-rw-r--r--gcl/pcl/impl/symbolics/rel-8-patches.lisp 255
-rw-r--r--gcl/pcl/impl/ti/ti-low.lisp 83
-rw-r--r--gcl/pcl/impl/ti/ti-patches.lisp 105
-rw-r--r--gcl/pcl/impl/vaxlisp/vaxl-low.lisp 80
-rw-r--r--gcl/pcl/impl/xerox/pcl-env-internal.lisp 261
-rw-r--r--gcl/pcl/impl/xerox/pcl-env.lisp 1629
-rw-r--r--gcl/pcl/impl/xerox/pcl-env.text 105
-rw-r--r--gcl/pcl/impl/xerox/xerox-low.lisp 173
-rw-r--r--gcl/pcl/impl/xerox/xerox-patches.lisp 248
-rw-r--r--gcl/pcl/init.lisp 261
-rw-r--r--gcl/pcl/iterate.lisp 1267
-rw-r--r--gcl/pcl/low.lisp 459
-rw-r--r--gcl/pcl/macros.lisp 787
-rw-r--r--gcl/pcl/makefile 40
-rw-r--r--gcl/pcl/methods.lisp 1646
-rw-r--r--gcl/pcl/notes/12-7-88-notes.text 45
-rw-r--r--gcl/pcl/notes/3-17-88-notes.text 167
-rw-r--r--gcl/pcl/notes/3-19-87-notes.text 138
-rw-r--r--gcl/pcl/notes/4-21-87-notes.text 53
-rw-r--r--gcl/pcl/notes/4-29-87-notes.text 80
-rw-r--r--gcl/pcl/notes/5-22-87-notes.text 126
-rw-r--r--gcl/pcl/notes/5-22-89-notes.text 152
-rw-r--r--gcl/pcl/notes/8-28-88-notes.text 537
-rw-r--r--gcl/pcl/notes/get-pcl.text 180
-rw-r--r--gcl/pcl/notes/may-day-notes.text 98
-rw-r--r--gcl/pcl/notes/notes.text 366
-rw-r--r--gcl/pcl/notes/readme.text 11
-rw-r--r--gcl/pcl/old/construct.lisp 1064
-rw-r--r--gcl/pcl/old/dlap.lisp 639
-rw-r--r--gcl/pcl/old/lap.lisp 500
-rw-r--r--gcl/pcl/old/plap.lisp 369
-rw-r--r--gcl/pcl/pkg.lisp 407
-rw-r--r--gcl/pcl/precom1.lisp 51
-rw-r--r--gcl/pcl/precom2.lisp 31
-rw-r--r--gcl/pcl/precom4.lisp 32
-rwxr-xr-xgcl/pcl/saved_gcl_pcl bin0 -> 10001240 bytes
-rw-r--r--gcl/pcl/slots-boot.lisp 404
-rw-r--r--gcl/pcl/slots.lisp 385
-rw-r--r--gcl/pcl/std-class.lisp 1321
-rw-r--r--gcl/pcl/test/bench-precompile.lisp 3
-rw-r--r--gcl/pcl/test/bench.lisp 575
-rw-r--r--gcl/pcl/test/bench.out 21
-rw-r--r--gcl/pcl/test/list-functions.lisp 141
-rw-r--r--gcl/pcl/test/make-test.lisp 47
-rw-r--r--gcl/pcl/test/makediff bin0 -> 953 bytes
-rw-r--r--gcl/pcl/test/time.lisp 156
-rw-r--r--gcl/pcl/vector.lisp 1104
-rw-r--r--gcl/pcl/walk.lisp 2198
83 files changed, 28822 insertions, 0 deletions
diff --git a/gcl/pcl/impl/cmu/README b/gcl/pcl/impl/cmu/README
new file mode 100644
index 000000000..240279387
--- /dev/null
+++ b/gcl/pcl/impl/cmu/README
@@ -0,0 +1,17 @@
+To install,
+
+put this version of PCL in cmucl's source directory, and name it pcl.
+rename the cmucl file tools/pclcom.lisp to tools/pclcom.lisp.original
+link the file impl/cmu/pclcom.lisp to cmucl/tools/pclcom.lisp
+link the file impl/cmu/pclload.lisp to pclload.lisp
+
+For example,
+
+cd cmucl17f
+mv pcl pcl.original
+<<install this PCL in the pcl directory>>
+cd tools
+mv pclcom.lisp pclcom.lisp.original
+ln -s ../pcl/impl/cmu/pclcom.lisp pclcom.lisp
+cd ../pcl
+ln -s impl/cmu/pclload.lisp pclload.lisp
diff --git a/gcl/pcl/impl/cmu/cmu-low.lisp b/gcl/pcl/impl/cmu/cmu-low.lisp
new file mode 100644
index 000000000..459c4453a
--- /dev/null
+++ b/gcl/pcl/impl/cmu/cmu-low.lisp
@@ -0,0 +1,217 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the CMU Lisp version of the file low.
+;;;
+
+(in-package :pcl)
+
+#+small
+(setq *optimize-speed*
+ '(optimize (speed 3) (safety 0) (debug 0.5) (ext:inhibit-warnings 3)))
+
+(defmacro dotimes ((var count &optional (result nil)) &body body)
+ `(lisp:dotimes (,var (the fixnum ,count) ,result)
+ (declare (fixnum ,var))
+ ,@body))
+
+;;; Just use our without-interrupts. We don't have the INTERRUPTS-ON/OFF local
+;;; macros spec'ed in low.lisp, but they aren't used.
+;;;
+(defmacro without-interrupts (&rest stuff)
+ `(sys:without-interrupts ,@stuff))
+
+(defun function-arglist (fcn)
+ "Returns the argument list of a compiled function, if possible."
+ (cond ((symbolp fcn)
+ (when (fboundp fcn)
+ (function-arglist (symbol-function fcn))))
+ ((eval:interpreted-function-p fcn)
+ (eval:interpreted-function-arglist fcn))
+ ((functionp fcn)
+ (let ((lambda-expr (function-lambda-expression fcn)))
+ (if lambda-expr
+ (cadr lambda-expr)
+ (let ((function (kernel:%closure-function fcn)))
+ (values (read-from-string
+ (kernel:%function-arglist function)))))))))
+
+
+;;; And returns the function, not the *name*.
+(defun set-function-name (fcn new-name)
+ "Set the name of a compiled function object."
+ (declare (special *boot-state* *the-class-standard-generic-function*))
+ (cond ((symbolp fcn)
+ (set-function-name (symbol-function fcn) new-name))
+ ((funcallable-instance-p fcn)
+ (if (if (eq *boot-state* 'complete)
+ (typep fcn 'generic-function)
+ (eq (class-of fcn) *the-class-standard-generic-function*))
+ (setf (kernel:%funcallable-instance-info fcn 1) new-name)
+ (typecase fcn
+ (kernel:byte-closure
+ (set-function-name (kernel:byte-closure-function fcn) new-name))
+ (kernel:byte-function
+ (setf (kernel:byte-function-name fcn) new-name))))
+ fcn)
+ ((eval:interpreted-function-p fcn)
+ (setf (eval:interpreted-function-name fcn) new-name)
+ fcn)
+ (t
+ (let ((header (kernel:%closure-function fcn)))
+ #+cmu17
+ (setf (c::%function-name header) new-name)
+ #-cmu17
+ (system:%primitive c::set-function-name header new-name))
+ fcn)))
+
+(in-package "C")
+
+(def-source-context pcl:defmethod (name &rest stuff)
+ (let ((arg-pos (position-if #'listp stuff)))
+ (if arg-pos
+ `(pcl:defmethod ,name ,@(subseq stuff 0 arg-pos)
+ ,(nth-value 2 (pcl::parse-specialized-lambda-list
+ (elt stuff arg-pos))))
+ `(pcl:defmethod ,name "<illegal syntax>"))))
+
+
+(in-package "PCL")
+
+;;;; STD-INSTANCE
+
+;;; Under CMU17 conditional, STD-INSTANCE-P is only used to discriminate
+;;; between functions (including FINs) and normal instances, so we can return
+;;; true on structures also. A few uses of (or std-instance-p fsc-instance-p)
+;;; are changed to pcl-instance-p.
+;;;
+(defmacro std-instance-p (x)
+ `(kernel:%instancep ,x))
+(defmacro pcl-instance-p (x)
+ `(typep (kernel:layout-of ,x) 'wrapper))
+
+
+;;; We define this as STANDARD-INSTANCE, since we're going to clobber the
+;;; layout with some standard-instance layout as soon as we make it, and we
+;;; want the accesor to still be type-correct.
+;;;
+(defstruct (standard-instance
+ (:predicate nil)
+ (:constructor %%allocate-instance--class--fn ())
+ (:alternate-metaclass kernel:instance lisp:standard-class
+ kernel:make-standard-class))
+ (slots nil))
+
+;;; Must immediately setf the std-instance-wrapper after calling this.
+(defmacro %%allocate-instance--class ()
+ `(ext:truly-the standard-instance (kernel:%make-instance 2)))
+
+;;; Both of these operations "work" on structures, which allows the above
+;;; weakening of std-instance-p.
+;;;
+(defmacro std-instance-slots (x) `(kernel:%instance-ref ,x 1))
+(defmacro std-instance-wrapper (x) `(kernel:%instance-layout ,x))
+
+(defmacro built-in-or-structure-wrapper (x) `(kernel:layout-of ,x))
+
+(defmacro get-wrapper (inst)
+ (ext:once-only ((wrapper `(wrapper-of ,inst)))
+ `(progn
+ (assert (typep ,wrapper 'wrapper) () "What kind of instance is this?")
+ ,wrapper)))
+
+(defmacro get-instance-wrapper-or-nil (inst)
+ (ext:once-only ((wrapper `(wrapper-of ,inst)))
+ `(if (typep ,wrapper 'wrapper)
+ ,wrapper
+ nil)))
+
+;;; get-slots harmless
+
+(defmacro get-slots-or-nil (inst)
+ (ext:once-only ((n-inst inst))
+ `(when (pcl-instance-p ,n-inst)
+ (if (std-instance-p ,n-inst)
+ (std-instance-slots ,n-inst)
+ (fsc-instance-slots ,n-inst)))))
+
+
+;;;; Structure-instance stuff:
+
+(pushnew :structure-wrapper *features*)
+
+(defun structure-functions-exist-p ()
+ t)
+
+(defun structure-instance-p (x)
+ (typep x 'lisp:structure-object))
+
+(defun structurep (x)
+ (typep x 'lisp:structure-object))
+
+(defun structure-type (x)
+ (lisp:class-name (kernel:layout-class (kernel:%instance-layout x))))
+
+
+(defun structure-type-p (type)
+ (and (symbolp type)
+ (let ((class (lisp:find-class type nil)))
+ (and class
+ (typep (kernel:layout-info (kernel:class-layout class))
+ 'kernel:defstruct-description)))))
+
+(defun get-structure-dd (type)
+ (kernel:layout-info (kernel:class-layout (lisp:find-class type))))
+
+(defun structure-type-included-type-name (type)
+ (let ((include (kernel::dd-include (get-structure-dd type))))
+ (if (consp include)
+ (car include)
+ include)))
+
+(defun structure-type-slot-description-list (type)
+ (nthcdr (length (let ((include (structure-type-included-type-name type)))
+ (and include (kernel:dd-slots (get-structure-dd include)))))
+ (kernel:dd-slots (get-structure-dd type))))
+
+(defun structure-slotd-name (slotd)
+ (kernel:dsd-name slotd))
+
+(defun structure-slotd-accessor-symbol (slotd)
+ (kernel:dsd-accessor slotd))
+
+(defun structure-slotd-reader-function (slotd)
+ (fdefinition (kernel:dsd-accessor slotd)))
+
+(defun structure-slotd-writer-function (slotd)
+ (unless (kernel:dsd-read-only slotd)
+ (fdefinition `(setf ,(kernel:dsd-accessor slotd)))))
+
+(defun structure-slotd-type (slotd)
+ (kernel:dsd-type slotd))
+
+(defun structure-slotd-init-form (slotd)
+ (kernel::dsd-default slotd))
diff --git a/gcl/pcl/impl/cmu/pclcom.lisp b/gcl/pcl/impl/cmu/pclcom.lisp
new file mode 100644
index 000000000..6be7d94e3
--- /dev/null
+++ b/gcl/pcl/impl/cmu/pclcom.lisp
@@ -0,0 +1,66 @@
+;; This is "target:tools/pclcom.lisp"
+
+(in-package "USER")
+
+(when (find-package "PCL")
+ (setf (compiler-macro-function 'make-instance) nil)
+ ;;
+ ;; Undefine all generic functions exported from Lisp so that bootstrapping
+ ;; doesn't get confused.
+ (let ((class (find-class 'generic-function nil)))
+ (when class
+ (do-external-symbols (sym "LISP")
+ (when (and (fboundp sym)
+ (typep (fdefinition sym) class))
+ (fmakunbound sym))
+ (let ((ssym `(setf ,sym)))
+ (when (and (fboundp ssym)
+ (typep (fdefinition ssym) class))
+ (fmakunbound ssym))))))
+
+ ;; Undefine all PCL classes, and clear CLASS-PCL-CLASS slots.
+ (let ((wot (find-symbol "*FIND-CLASS*" "PCL")))
+ (when (and wot (boundp wot))
+ (do-hash (name ignore (symbol-value wot))
+ (declare (ignore ignore))
+ (let ((class (find-class name nil)))
+ (cond ((not class))
+ ((typep class 'kernel::std-class)
+ (setf (kernel:class-cell-class
+ (kernel:find-class-cell name))
+ nil)
+ (setf (info type kind name) nil))
+ (t
+ (setf (kernel:class-pcl-class class) nil)))))))
+
+ (rename-package "PCL" "OLD-PCL")
+ (make-package "PCL"))
+
+(when (find-package "SLOT-ACCESSOR-NAME")
+ (rename-package "SLOT-ACCESSOR-NAME" "OLD-SLOT-ACCESSOR-NAME"))
+
+(setf c:*suppress-values-declaration* t)
+(pushnew :setf *features*)
+
+(setf (search-list "pcl:") '("target:pcl/"))
+
+(let ((obj (make-pathname :defaults "pcl:defsys"
+ :type (c:backend-fasl-file-type c:*backend*))))
+ (when (< (or (file-write-date obj) 0)
+ (file-write-date "pcl:defsys.lisp"))
+ (compile-file "pcl:defsys" :byte-compile t)))
+
+(load "pcl:defsys" :verbose t)
+
+(import 'kernel:funcallable-instance-p (find-package "PCL"))
+
+(with-compilation-unit
+ (:optimize '(optimize (debug #+small .5 #-small 2)
+ (speed 2) (safety #+small 0 #-small 2)
+ (inhibit-warnings 2))
+ :optimize-interface '(optimize-interface #+small (safety 1))
+ :context-declarations
+ '((:external (declare (optimize-interface (safety 2) (debug 1))))
+ ((:or :macro (:match "$EARLY-") (:match "$BOOT-"))
+ (declare (optimize (speed 0))))))
+ (pcl::compile-pcl))
diff --git a/gcl/pcl/impl/cmu/pclload.lisp b/gcl/pcl/impl/cmu/pclload.lisp
new file mode 100644
index 000000000..39fb098d6
--- /dev/null
+++ b/gcl/pcl/impl/cmu/pclload.lisp
@@ -0,0 +1,12 @@
+(in-package "PCL")
+(unless (find-package "SLOT-ACCESSOR-NAME")
+ (make-package "SLOT-ACCESSOR-NAME"))
+(rename-package "PCL" "PCL" '("OLD-PCL"))
+(rename-package "SLOT-ACCESSOR-NAME" "SLOT-ACCESSOR-NAME"
+ '("OLD-SLOT-ACCESSOR-NAME"))
+(import 'kernel:funcallable-instance-p)
+(load "target:pcl/defsys")
+(load-pcl)
+(rename-package "PCL" "PCL" '())
+(rename-package "SLOT-ACCESSOR-NAME" "SLOT-ACCESSOR-NAME" '())
+
diff --git a/gcl/pcl/impl/coral/coral-low.lisp b/gcl/pcl/impl/coral/coral-low.lisp
new file mode 100644
index 000000000..650dd7517
--- /dev/null
+++ b/gcl/pcl/impl/coral/coral-low.lisp
@@ -0,0 +1,63 @@
+;;;-*-Mode:LISP; Package:(PCL (LISP WALKER)); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+#-:ccl-1.3
+(ccl::add-transform 'std-instance-p
+ :inline
+ #'(lambda (call)
+ (ccl::verify-arg-count call 1 1)
+ (let ((arg (cadr call)))
+ `(and (eq (ccl::%type-of ,arg) 'structure)
+ (eq (%svref ,arg 0) 'std-instance)))))
+
+(eval-when (eval compile load)
+ (proclaim '(inline std-instance-p)))
+
+(defun printing-random-thing-internal (thing stream)
+ (prin1 (ccl::%ptr-to-int thing) stream))
+
+(defun set-function-name-1 (function new-name uninterned-name)
+ (declare (ignore uninterned-name))
+ (cond ((ccl::lfunp function)
+ (ccl::lfun-name function new-name)))
+ function)
+
+
+(defun doctor-dfun-for-the-debugger (gf dfun)
+ #+:ccl-1.3
+ (let* ((gfspec (and (symbolp (generic-function-name gf))
+ (generic-function-name gf)))
+ (arglist (generic-function-pretty-arglist gf)))
+ (when gfspec
+ (setf (get gfspec 'ccl::%lambda-list)
+ (if (and arglist (listp arglist))
+ (format nil "~{~A~^ ~}" arglist)
+ (format nil "~:A" arglist)))))
+ dfun)
+
diff --git a/gcl/pcl/impl/franz/cpatch.lisp b/gcl/pcl/impl/franz/cpatch.lisp
new file mode 100644
index 000000000..23641de54
--- /dev/null
+++ b/gcl/pcl/impl/franz/cpatch.lisp
@@ -0,0 +1,32 @@
+;; -[Thu Feb 22 08:38:07 1990 by jkf]-
+;; cpatch.cl
+;; compiler patch for the fast clos
+;;
+;; copyright (c) 1990 Franz Inc.
+;;
+
+(in-package :comp)
+
+(def-quad-op tail-funcall qp-end-block
+ ;; u = (argcount function-object)
+ ;;
+ ;; does a tail call to the function-object given
+ ;; never returns
+ )
+
+(defun-in-runtime sys::copy-function (func))
+
+(in-package :hyperion)
+
+(def-quad-hyp r-tail-funcall comp::tail-funcall (u d quad)
+ ;; u = (argcount function)
+ ;;
+ (r-move-single-to-loc (treg-loc (car u)) *count-reg*)
+ (r-move-single-to-loc (treg-loc (cadr u)) *fcnin-reg*)
+ (re restore *zero-reg* *zero-reg*)
+ (re move.l `(d #.r-function-start-adj #.*fcnout-reg*) '#.*ctr2-reg*)
+ (re jmpl '(d 0 #.*ctr2-reg*) *zero-reg*)
+ (re nop))
+
+
+
diff --git a/gcl/pcl/impl/franz/excl-low.lisp b/gcl/pcl/impl/franz/excl-low.lisp
new file mode 100644
index 000000000..54c734b4d
--- /dev/null
+++ b/gcl/pcl/impl/franz/excl-low.lisp
@@ -0,0 +1,136 @@
+;;; -*- Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the EXCL (Franz) lisp version of the file portable-low.
+;;;
+;;; This is for version 1.1.2. Many of the special symbols now in the lisp
+;;; package (e.g. lisp::pointer-to-fixnum) will be in some other package in
+;;; a later release so this will need to be changed.
+;;;
+
+(in-package 'pcl)
+
+(defmacro without-interrupts (&body body)
+ `(let ((outer-interrupts excl::*without-interrupts*)
+ (excl::*without-interrupts* 0))
+ (macrolet ((interrupts-on ()
+ '(unless outer-interrupts
+ (setq excl::*without-interrupts* nil)))
+ (interrupts-off ()
+ '(setq excl::*without-interrupts* 0)))
+ ,.body)))
+
+(eval-when (compile load eval)
+ (unless (fboundp 'excl::sy_hash)
+ (setf (symbol-function 'excl::sy_hash)
+ (symbol-function 'excl::_sy_hash-value)))
+ )
+
+(defmacro memq (item list)
+ (let ((list-var (gensym))
+ (item-var (gensym)))
+ `(prog ((,list-var ,list)
+ (,item-var ,item))
+ start
+ (cond ((null ,list-var)
+ (return nil))
+ ((eq (car ,list-var) ,item-var)
+ (return ,list-var))
+ (t
+ (pop ,list-var)
+ (go start))))))
+
+(defun std-instance-p (x)
+ (and (excl::structurep x)
+ (locally
+ (declare #.*optimize-speed*)
+ (eq (svref x 0) 'std-instance))))
+
+(excl::defcmacro std-instance-p (x)
+ (once-only (x)
+ `(and (excl::structurep ,x)
+ (locally
+ (declare #.*optimize-speed*)
+ (eq (svref ,x 0) 'std-instance)))))
+
+(excl::defcmacro fast-method-call-p (x)
+ (once-only (x)
+ `(and (excl::structurep ,x)
+ (locally
+ (declare #.*optimize-speed*)
+ (eq (svref ,x 0) 'fast-method-call)))))
+
+(defmacro %std-instance-wrapper (x)
+ `(svref ,x 1))
+
+(defmacro %std-instance-slots (x)
+ `(svref ,x 2))
+
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~O" (excl::pointer-to-fixnum thing)))
+
+#-vax
+(defun set-function-name-1 (fn new-name ignore)
+ (declare (ignore ignore))
+ (cond ((excl::function-object-p fn)
+ (setf (excl::fn_symdef fn) new-name))
+ (t nil))
+ fn)
+
+(defun function-arglist (f)
+ (excl::arglist f))
+
+(defun symbol-append (sym1 sym2 &optional (package *package*))
+ ;; This is a version of symbol-append from macros.cl
+ ;; It insures that all created symbols are of one case and that
+ ;; case is the current prefered case.
+ ;; This special version of symbol-append is not necessary if all you
+ ;; want to do is compile and run pcl in a case-insensitive-upper
+ ;; version of cl.
+ ;;
+ (let ((string (string-append sym1 sym2)))
+ (case excl::*current-case-mode*
+ ((:case-insensitive-lower :case-sensitive-lower)
+ (setq string (string-downcase string)))
+ ((:case-insensitive-upper :case-sensitive-upper)
+ (setq string (string-upcase string))))
+ (intern string package)))
+
+;;; Define inspector hooks for PCL object instances.
+
+(defun (:property pcl::std-instance :inspector-function) (object)
+ (let ((class (class-of object)))
+ (cons (inspect::make-field-def "class-of :lisp)
+ (mapcar #'(lambda (slot)
+ (inspect::make-field-def
+ (string (slot-definition-name slot))
+ #'(lambda (x)
+ (slot-value-using-class class x slot))
+ :lisp))
+ (slots-to-inspect class object)))))
+
+(defun (:property pcl::std-instance :inspector-type-function) (x)
+ (class-name (class-of x)))
diff --git a/gcl/pcl/impl/franz/quadlap.lisp b/gcl/pcl/impl/franz/quadlap.lisp
new file mode 100644
index 000000000..3d7507e1c
--- /dev/null
+++ b/gcl/pcl/impl/franz/quadlap.lisp
@@ -0,0 +1,619 @@
+;; -[Thu Mar 1 10:54:27 1990 by jkf]-
+;; pcl to quad translation
+;; $Header$
+;;
+;; copyright (c) 1990 Franz Inc.
+;;
+(in-package :compiler)
+
+
+
+
+(defvar *arg-to-treg* nil)
+(defvar *cvar-to-index* nil)
+(defvar *reg-array* nil)
+(defvar *closure-treg* nil)
+(defvar *nargs-treg* nil)
+
+(defvar *debug-sparc* nil)
+
+(defmacro pcl-make-lambda (&key required)
+ `(list 'lambda nil :unknown-type 0 compiler::.function-level.
+ ,required nil nil nil nil nil nil nil nil nil
+ nil 'compiler::none nil nil nil
+ nil nil nil nil nil nil 0 nil))
+
+(defmacro pcl-make-varrec (&key name loc contour-level)
+ `(list ,name nil 0 nil ,loc nil t compiler::.function-level. nil nil :unknown-type nil nil ,contour-level))
+
+(defmacro pcl-make-lap (&key lap constants cframe-size locals)
+ `(list nil ,constants ,lap nil nil ,cframe-size ,locals nil nil nil))
+
+
+(defstruct preg
+ ;; pseudo reg descritpor
+ treg ; associated treg
+ index ; :index if this is an index type reg
+ ; :vector if this is a vector type reg
+ )
+
+
+(defun pcl::excl-lap-closure-generator (closure-vars-names
+ arg-names
+ index-regs
+ vector-regs
+ fixnum-vector-regs
+ t-regs
+ lap-code)
+ (let ((function (pcl::excl-lap-closure-gen closure-vars-names
+ arg-names
+ index-regs
+ (append vector-regs fixnum-vector-regs)
+ t-regs
+ lap-code)))
+ #'(lambda (&rest closure-vals)
+ (insert-closure-vals function closure-vals))))
+
+
+(defun pcl::excl-lap-closure-gen
+ (closure-vars-names arg-names index-regs vector-regs t-regs lap-code)
+ (let ((*quads* nil)
+ (*treg-num* 0)
+ (*all-tregs* nil)
+ (*bb-count* 0)
+ *treg-bv-size*
+ *treg-vector*
+ (*next-catch-frame* 0)
+ (*max-catch-frame* -1)
+ *catch-labels*
+ *top-label*
+ *mv-treg*
+ *mv-treg-target*
+ *zero-treg*
+ *nil-treg*
+ *bbs* *bb* lap
+ ;; bbs
+ *cross-block-regs*
+ *const-tregs* *move-tregs*
+ *actuals*
+ *ignore-argcount*
+ *binds-specs*
+ *bvl-current-bv* ; for bitvector cacher
+ *bvl-used-bvs*
+ *bvl-index*
+ (*inhibit-call-count* t)
+
+ ; this fcn
+ *arg-to-treg*
+ *cvar-to-index*
+ *reg-array*
+ minargs
+ maxargs
+ *closure-treg*
+
+ node
+ otherargregs
+
+ *nargs-treg*
+ )
+
+ (if* *debug-sparc*
+ then (format t ">>** << Generating sparc lap code~%"))
+
+ (setq *nil-treg*
+ #+allegro-v4.0 (new-reg :global t)
+ #-allegro-v4.0 (new-reg)
+ *mv-treg* (new-reg)
+ *mv-treg-target* (list *mv-treg*)
+ *zero-treg* (comp::new-reg))
+
+ ; examine given args
+
+ (setq minargs 0 maxargs 0)
+ (let (requireds)
+ (dolist (arg arg-names)
+ (if* (eq '&rest arg)
+ then (setq maxargs nil)
+ else (if* (null arg)
+ then ; we want a name even though we won't use it
+ (setq arg (gensym)))
+ (incf minargs)
+ (incf maxargs)
+ (push (cons arg (new-reg)) *arg-to-treg*)
+ (push (pcl-make-varrec :name arg
+ :loc (cdr (car *arg-to-treg*))
+ :contour-level 0)
+ requireds)
+ ))
+ (setq node (pcl-make-lambda :required (nreverse requireds))))
+ (setq *arg-to-treg* (nreverse *arg-to-treg*))
+
+ ; build closure vector list
+ (let ((index -1))
+ (dolist (cvar closure-vars-names)
+ (push (cons cvar (incf index)) *cvar-to-index*)))
+
+ (let ((maxreg (max (apply #'max (cons -1 index-regs))
+ (apply #'max (cons -1 vector-regs))
+ (apply #'max (cons -1 t-regs)))))
+ (setq *reg-array* (make-array (1+ maxreg))))
+
+ (dolist (index index-regs)
+ (setf (svref *reg-array* index)
+ (make-preg :treg (new-reg)
+ :index :index)))
+
+ (dolist (vector vector-regs)
+ (setf (svref *reg-array* vector)
+ (make-preg :treg (new-reg)
+ :index :vector)))
+
+ (dolist (tr t-regs)
+ (setf (svref *reg-array* tr) (make-preg :treg (new-reg))))
+
+
+ (if* closure-vars-names
+ then (setq *closure-treg* (new-reg)))
+ (setq *nargs-treg* (new-reg))
+
+ ;; (md-allocate-global-tregs)
+
+ ; function entry
+ (qe nop :arg :first-block)
+ (qe entry)
+ (qe argcount :arg (list minargs maxargs))
+ (qe lambda :d (mapcar #'cdr *arg-to-treg*))
+ (qe register :arg :nargs :d (list *nargs-treg*))
+
+ (if* *closure-treg*
+ then ; put the first closure vector in *closure-treg*
+ (qe extract-closure-vec :d (list *closure-treg*))
+ (let ((offsetreg (new-reg)))
+ (qe const :arg (mdparam 'md-cons-car-adj) :d (list offsetreg))
+ (qe ref :u (list *closure-treg* offsetreg)
+ :d (list *closure-treg*)
+ :arg :long))
+ )
+
+ (excl-gen-quads lap-code)
+
+ (if* *debug-sparc*
+ then (do-quad-list (quad next *quads*)
+ (format t "~a~%" quad))
+
+ (format t "basic blocks~%"))
+
+ (setq *bbs* (qc-compute-basic-blocks *quads*))
+
+ (excl::target-class-case
+ ((:r :m) (setq *actuals* (qc-compute-actuals *bbs*))))
+
+ (qc-live-variable-analysis *bbs*)
+
+ (setq *treg-bv-size* (* 16 (truncate (+ *treg-num* 15) 16)))
+
+ (qc-build-treg-vector)
+
+
+ (let ((*dump-bbs* nil)
+ (r::*local-regs*
+ ; use the in registers that aren't in use
+ (append r::*local-regs*
+ (if* maxargs
+ then (nthcdr maxargs r::*in-regs* )))))
+ (unwind-protect
+ (progn
+ ; machine specific code generation
+ (multiple-value-bind (lap-code literals size-struct locals)
+ #+(target-class r m e)
+ (progn
+ #+allegro-v4.0
+ (md-codegen node *bbs*
+ nil otherargregs)
+ #-allegro-v4.0
+ (md-codegen node *bbs*
+ *nil-treg* *mv-treg* *zero-treg*
+ nil otherargregs))
+
+ #-(target-class r m e) (md-codegen node *bbs*)
+ (setq lap
+ (pcl-make-lap :lap lap-code
+ :constants literals
+ :cframe-size size-struct
+ :locals locals)))
+
+
+ lap)
+ (giveback-bvs)))
+
+ #+ignore
+ (progn (format t "sparc code pre optimization~%")
+ (dolist (instr (lap-lap lap))
+ (format t "> ~a~%" instr)))
+ (md-optimize lap) ; peephole optimize
+ (if* *debug-sparc*
+ then (format t "sparc code post optimization~%")
+ (dolist (instr (lap-lap lap))
+ (format t "> ~a~%" instr)))
+ (md-assemble lap)
+ (setq last-lap lap)
+
+ (nl-runtime-make-a-fcnobj lap)))
+
+(defun qe-slot-access (operand offset dest)
+ ;; access a slot in a structure
+ (let ((temp (new-reg)))
+ (qe const :arg offset :d (list temp))
+ (qe ref :u (list (get-treg-of operand) temp)
+ :d (list (get-treg-of dest))
+ :arg :long)))
+
+
+(defun get-treg-of (operand &optional res-operand)
+ ;; get the appropriate treg for the operand
+ (let ((prefer-treg (and res-operand (simple-get-treg-of res-operand))))
+ (if* (numberp operand)
+ then (let ((treg (new-reg)))
+ (qe const :arg operand :d (list treg))
+ treg)
+ elseif (consp operand)
+ then (ecase (car operand)
+ (:reg
+ (preg-treg (svref *reg-array* (cadr operand))))
+ (:arg
+ (let ((x (cdr (assoc (cadr operand) *arg-to-treg* :test #'eq))))
+ (if* (null x)
+ then (error "where is arg ~s" operand)
+ else x)))
+ (:cvar
+ (let ((res-treg (or prefer-treg (new-reg)))
+ (temp-treg (new-reg)))
+ (qe const :arg (+ (mdparam 'md-svector-data0-adj)
+ (* 4 (cdr (assoc (cadr operand)
+ *cvar-to-index*
+ :test #'eq))))
+ :d (list temp-treg))
+ (qe ref :u (list *closure-treg* temp-treg)
+ :d (list res-treg)
+ :arg :long)
+ res-treg))
+ (:constant
+ (let ((treg (or prefer-treg (new-reg))))
+ (qe const :arg (if* (fixnump (cadr operand))
+ then (* 8 (cadr operand)) ; md!!
+ else (cadr operand))
+ :d (list treg))
+ treg))
+ (:index-constant
+ ; operand invented by jkf to denote an index type constant
+ (let ((treg (or prefer-treg (new-reg))))
+ (qe const :arg (if* (fixnump (cadr operand))
+ then (* 4 (cadr operand)) ; md!!
+ else (cadr operand))
+ :d (list treg))
+ treg)))
+ else (error "bad operand: ~s" operand))))
+
+(defun simple-get-treg-of (operand)
+ ;; get the treg if it is so simple that we don't have to
+ ;; emit any instructions to access it.
+ ;; return nil if we can't do it.
+ (if* (numberp operand)
+ then nil
+ elseif (consp operand)
+ then (case (car operand)
+ (:reg
+ (preg-treg (svref *reg-array* (cadr operand))))
+ (:arg
+ (let ((x (cdr (assoc (cadr operand) *arg-to-treg* :test #'eq))))
+ (if* (null x)
+ then nil
+ else x))))
+
+ else nil))
+
+(defun index-p (operand)
+ ;; determine if the result of this operand is an index value
+ ;* it would be better if conversion between lisp values and
+ ; index values were made explicit in the lap code
+ (and (consp operand)
+ (or (and (eq :reg (car operand))
+ (eq :index (preg-index (svref *reg-array* (cadr operand)))))
+ (member (car operand)
+ '(:i+ :i- :ilogand :ilogxor :i1+)
+ :test #'eq))
+ t))
+
+(defun gen-index-treg (operand)
+ ;; return the non-index type operand in a index treg
+ (if* (and (consp operand)
+ (eq ':constant (car operand)))
+ then (get-treg-of `(:index-constant ,(cadr operand)))
+ else (let ((treg (get-treg-of operand))
+ (new-reg (new-reg))
+ (shift-reg (new-reg)))
+ (qe const :arg 1 :d (list shift-reg))
+ (qe lsr :u (list treg shift-reg) :d (list new-reg))
+ new-reg)))
+
+
+
+
+
+(defun vector-preg-p (operand)
+ (and (consp operand)
+ (eq :reg (car operand))
+ (eq :vector (preg-index (svref *reg-array* (cadr operand))))))
+
+
+
+(defun excl-gen-quads (laps)
+ ;; generate quads from the lap
+ (dolist (lap laps)
+ (if* *debug-sparc* then (format t ">> ~a~%" lap))
+ (block again
+ (let ((opcode (car lap))
+ (op1 (cadr lap))
+ (op2 (caddr lap)))
+ (case opcode
+ (:move
+ ; can be either simple (both args registers)
+ ; or one arg can be complex and the other simple
+ (case (car op2)
+ ((:iref :instance-ref)
+ ;; assume that this is a lisp store
+ ;;(warn "assuming lisp store in ~s" lap)
+ (let (op1-treg)
+ (if* (not (vector-preg-p (cadr op2)))
+ then ; must offset before store
+ (error "must use vector register in ~s" lap)
+ else (setq op1-treg (get-treg-of (cadr op2))))
+
+
+
+ (qe set :u (list op1-treg
+ (get-treg-of (caddr op2))
+ (get-treg-of op1))
+ :arg :lisp)
+ (return-from again)))
+ (:cdr
+ ;; it certainly is a lisp stoer
+ (let (op1-treg const-reg)
+ (setq op1-treg (get-treg-of (cadr op2)))
+ (setq const-reg (new-reg))
+ (qe const :arg (mdparam 'md-cons-cdr-adj)
+ :d (list const-reg))
+
+
+
+ (qe set :u (list op1-treg
+ const-reg
+ (get-treg-of op1))
+ :arg :lisp)
+ (return-from again))))
+
+ ; the 'to'address is simple, the from address may not be
+
+ (let ((index1 (index-p op1))
+ (index2 (index-p op2))
+ (vector1 (vector-preg-p op1))
+ (vector2 (vector-preg-p op2)))
+ (ecase (car op1)
+ ((:reg :cvar :arg :constant :lisp-symbol)
+ (qe move
+ :u (list (get-treg-of op1 op2))
+ :d (list (get-treg-of op2))))
+ (:std-wrapper
+ (qe-slot-access (cadr op1)
+ (+ (* 1 4)
+ (comp::mdparam 'md-svector-data0-adj))
+ op2))
+ (:std-slots
+ (qe-slot-access (cadr op1)
+ (+ (* 2 4)
+ (comp::mdparam 'md-svector-data0-adj))
+ op2))
+ (:fsc-wrapper
+ (qe-slot-access (cadr op1)
+ (+ (* (- 15 1) 4)
+ (comp::mdparam 'md-function-const0-adj))
+ op2))
+ (:fsc-slots
+ (qe-slot-access (cadr op1)
+ (+ (* (- 15 2) 4)
+ (comp::mdparam 'md-function-const0-adj))
+ op2))
+ ((:built-in-wrapper :structure-wrapper :built-in-or-structure-wrapper)
+ (qe call :arg 'pcl::built-in-or-structure-wrapper
+ :u (list (get-treg-of (cadr op1)))
+ :d (list (get-treg-of op2))))
+ (:other-wrapper
+ (warn "do other-wrapper"))
+ ((:i+ :i- :ilogand :ilogxor)
+ (qe arith :arg (cdr (assoc (car op1)
+ '((:i+ . :+)
+ (:i- . :-)
+ (:ilogand . :logand)
+ (:ilogxor . :logxor))
+ :test #'eq))
+ :u (list (get-treg-of (cadr op1))
+ (get-treg-of (caddr op1)))
+ :d (list (get-treg-of op2))))
+ (:i1+
+ (let ((const-reg (new-reg)))
+ (qe const :arg 4 ; an index value of 1
+ :d (list const-reg))
+ (qe arith :arg :+
+ :u (list const-reg
+ (get-treg-of (cadr op1)))
+ :d (list (get-treg-of op2)))))
+
+ ((:iref :cref :instance-ref)
+ (let (op1-treg)
+ (if* (not (vector-preg-p (cadr op1)))
+ then ; must offset before store
+ (error "must use vector register in ~s" lap)
+ else (setq op1-treg (get-treg-of (cadr op1))))
+
+ (qe ref :u (list op1-treg
+ (get-treg-of (caddr op1) op2))
+ :d (list (get-treg-of op2))
+ :arg :long)))
+ (:cdr
+ (let ((const-reg (new-reg)))
+ (qe const :arg (mdparam 'md-cons-cdr-adj)
+ :d (list const-reg))
+ (qe ref :arg :long
+ :u (list (get-treg-of (cadr op1))
+ const-reg)
+ :d (list (get-treg-of op2))))))
+ (if* (not (eq index1 index2))
+ then (let ((shiftamt (new-reg)))
+ (qe const :arg 1 :d (list shiftamt))
+ (if* (and index1 (not index2))
+ then ; converting from index to non-index
+ (qe lsl :u (list (get-treg-of op2) shiftamt)
+ :d (list (get-treg-of op2)))
+ elseif (and (not index1) index2)
+ ; converting to an index
+ then (qe lsr :u (list (get-treg-of op2) shiftamt)
+ :d (list (get-treg-of op2)))))
+ elseif (and vector2 (not vector1))
+ then ; add vector offset
+ (let ((tempreg (new-reg))
+ (vreg (get-treg-of op2)))
+ (qe const :arg (mdparam 'md-svector-data0-adj)
+ :d (list tempreg))
+ (qe arith :arg :+ :u (list vreg tempreg)
+ :d (list vreg))))))
+ (:fix=
+ (let (tr1 tr2)
+ (if* (index-p op1)
+ then (setq tr1 (get-treg-of op1))
+ (if* (not (index-p op2))
+ then (setq tr2 (gen-index-treg op2))
+ else (setq tr2 (get-treg-of op2)))
+ elseif (index-p op2)
+ then ; assert: op1 isn't an index treg
+ (setq tr1 (gen-index-treg op1))
+ (setq tr2 (get-treg-of op2))
+ else (setq tr1 (get-treg-of op1)
+ tr2 (get-treg-of op2)))
+
+
+
+ (qe bcc :u (list tr1 tr2)
+ :arg (cadddr lap)
+ :arg2 :eq )))
+ ((:eq :neq :fix=)
+ (if* (not (eq (index-p op1) (index-p op2)))
+ then (error "non matching operands indexwise in: ~s" lap))
+ (qe bcc :u (list (get-treg-of op1)
+ (get-treg-of op2))
+ :arg (cadddr lap)
+ :arg2 (cdr (assoc opcode '((:eq . :eq)
+ (:neq . :ne))
+ :test #'eq))))
+ (:izerop
+ (qe bcc :u (list (get-treg-of op1)
+ *zero-treg*)
+ :arg (caddr lap)
+ :arg2 :eq))
+ (:std-instance-p
+ (let ((treg (get-treg-of op1))
+ (tempreg (new-reg))
+ (temp2reg (new-reg))
+ (offsetreg (new-reg))
+ (nope (pc-genlab)))
+ (qe typecheck :u (list treg)
+ :arg nope
+ :arg2 '(not structure))
+ (qe const :arg 'pcl::std-instance :d (list tempreg))
+ (qe const :arg (mdparam 'md-svector-data0-adj)
+ :d (list offsetreg))
+ (qe ref :u (list treg offsetreg)
+ :d (list temp2reg)
+ :arg :long)
+ (qe bcc :arg2 :eq :u (list tempreg temp2reg)
+ :arg (caddr lap))
+ (qe label :arg nope)))
+
+ (:fsc-instance-p
+ (let ((treg (get-treg-of op1))
+ (nope (pc-genlab))
+ (offsetreg (new-reg))
+ (tempreg (new-reg))
+ (checkreg (new-reg)))
+ (qe typecheck :u (list treg)
+ :arg nope
+ :arg2 '(not compiled-function))
+ (qe const :arg (mdparam 'md-function-flags-adj)
+ :d (list offsetreg))
+ (qe ref :u (list treg offsetreg) :d (list tempreg)
+ :arg :ubyte)
+ (qe const :arg pcl::funcallable-instance-flag-bit
+ :d (list checkreg))
+ (qe bcc :u (list checkreg tempreg)
+ :arg (caddr lap)
+ :arg2 :bit-and)
+ (qe label :arg nope)))
+ (:built-in-instance-p
+ ; always true
+ (qe bra :arg (caddr lap)))
+ (:jmp
+ (qe tail-funcall :u (list *nargs-treg* (get-treg-of op1))))
+ (:structure-instance-p
+ ; always true
+ (qe bra :arg (caddr lap)))
+
+ (:return
+ (let (op-treg)
+ (if* (index-p op1)
+ then ; convert to lisp before returning
+ (let ((shiftamt (new-reg)))
+ (setq op-treg (new-reg))
+ (qe const :arg 1 :d (list shiftamt))
+ (qe lsl :u (list (get-treg-of op1) shiftamt)
+ :d (list op-treg)))
+ else (setq op-treg (get-treg-of op1)))
+
+ (qe move :u (list op-treg) :d *mv-treg-target*)
+ (qe return :u *mv-treg-target*)))
+
+ (:go
+ (qe bra :arg (cadr lap)))
+
+ (:label
+ (qe label :arg (cadr lap)))
+
+
+
+ (t (warn "ignoring ~s" lap)))))))
+
+
+(defun insert-closure-vals (function closure-vals)
+ ;; build a fucntion from the lap and insert
+ (let ((newfun (sys::copy-function function)))
+ (setf (excl::fn_closure newfun) (list (apply 'vector closure-vals)))
+ newfun))
+
+
+
+; test case:
+; (pcl::defclass foo () (a b c))
+; (pcl::defmethod barx ((a foo) b c) a )
+; (apply 'pcl::excl-lap-closure-generator pcl::*tcase*)
+;
+; to turn it on
+
+(if* (not (and (boundp 'user::noquad)
+ (symbol-value 'user::noquad)))
+ then (setq pcl::*make-lap-closure-generator*
+ 'pcl::excl-lap-closure-generator))
+
+
+
+
+
+
+
diff --git a/gcl/pcl/impl/gcl/README b/gcl/pcl/impl/gcl/README
new file mode 100644
index 000000000..7948b335a
--- /dev/null
+++ b/gcl/pcl/impl/gcl/README
@@ -0,0 +1,14 @@
+Includes changes for gcl version 2.0 by W. Schelter
+
+
+To compile
+
+ln -s impl/gcl/makefile.gcl makefile.gcl
+ln -s impl/gcl/sys-package.lisp sys-package.lisp
+ln -s impl/gcl/sys-proclaim.lisp sys-proclaim.lisp
+make -f makefile.gcl compile
+
+Then to make saved version
+
+make -f makefile.gcl saved_pcl
+
diff --git a/gcl/pcl/impl/gcl/gcl-low.lisp b/gcl/pcl/impl/gcl/gcl-low.lisp
new file mode 100644
index 000000000..66337d4a0
--- /dev/null
+++ b/gcl/pcl/impl/gcl/gcl-low.lisp
@@ -0,0 +1,309 @@
+(in-package "SI")
+(export '(%structure-name
+ %compiled-function-name
+ %set-compiled-function-name))
+(in-package 'pcl)
+(eval-when (compile eval load)
+(setq *EVAL-WHEN-COMPILE* t)
+)
+
+(defmacro memq (item list) `(member ,item ,list :test #'eq))
+(defmacro assq (item list) `(assoc ,item ,list :test #'eq))
+(defmacro posq (item list) `(position ,item ,list :test #'eq))
+
+(defmacro dotimes ((var form &optional (val nil)) &rest body &environment env)
+ (multiple-value-bind (doc decls bod)
+ (extract-declarations body env)
+ (declare (ignore doc))
+ (let ((limit (gensym))
+ (label (gensym)))
+ `(let ((,limit ,form)
+ (,var 0))
+ (declare (fixnum ,limit ,var))
+ ,@decls
+ (block nil
+ (tagbody
+ ,label
+ (when (>= ,var ,limit) (return-from nil ,val))
+ ,@bod
+ (setq ,var (the fixnum (1+ ,var)))
+ (go ,label)))))))
+
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~O" (si:address thing)))
+
+(eval-when (compile load eval)
+(pushnew :turbo-closure *features*)
+(pushnew :turbo-closure-env-size *features*))
+)
+
+(defmacro %svref (vector index)
+ `(svref (the simple-vector ,vector) (the fixnum ,index)))
+
+(defsetf %svref (vector index) (new-value)
+ `(setf (svref (the simple-vector ,vector) (the fixnum ,index))
+ ,new-value))
+
+(si::freeze-defstruct 'pcl::std-instance)
+
+(si::freeze-defstruct 'method-call)
+(si::freeze-defstruct 'fast-method-call)
+
+(defvar *pcl-funcall* `(lambda (loc)
+ (compiler::wt-nl
+ "{object _funobj = " loc ";"
+ "if(type_of(_funobj)==t_cclosure && (_funobj->cc.cc_turbo))
+ (*(_funobj->cc.cc_self))(_funobj->cc.cc_turbo);
+ else if (type_of(_funobj)==t_cfun) (*(_funobj->cc.cc_self))();
+ else super_funcall_no_event(_funobj);}")))
+
+(setq compiler::*super-funcall* *pcl-funcall*)
+
+(defmacro fmc-funcall (fn pv-cell next-method-call &rest args)
+ `(funcall ,fn ,pv-cell ,next-method-call ,@args))
+
+(defun pcl::proclaim-defmethod (x y) y
+ (and (symbolp x)
+ (setf (get x 'compiler::proclaimed-closure ) t)))
+
+
+
+;#+turbo-closure-env-size
+(clines "
+static
+object cclosure_env_nthcdr (n,cc)
+int n; object cc;
+{ object env,*turbo;
+ if(n<0)return Cnil;
+ if(type_of(cc)!=t_cclosure)return Cnil;
+ if((turbo=cc->cc.cc_turbo)==NULL)
+ {env=cc->cc.cc_env;
+ while(n-->0)
+ {if(type_of(env)!=t_cons)return Cnil;
+ env=env->c.c_cdr;}
+ return env;}
+ else
+ {if(n>=fix(*(turbo-1)))return Cnil;
+ return turbo[n];}
+}")
+
+(defentry cclosure-env-nthcdr (int object) (object cclosure_env_nthcdr))
+;; This is the unsafe but fast version.
+(defentry %cclosure-env-nthcdr (int object) (object cclosure_env_nthcdr))
+
+(eval-when (compile eval load)
+(defparameter *gcl-function-inlines*
+ '( (%fboundp (t) compiler::boolean nil nil "(#0)->s.s_gfdef!=OBJNULL")
+ (%symbol-function (t) t nil nil "(#0)->s.s_gfdef")
+ (si:%structure-name (t) t nil nil "(#0)->str.str_def->str.str_self[0]")
+ (si:%compiled-function-name (t) t nil nil "(#0)->cf.cf_name")
+ (si:%set-compiled-function-name (t t) t t nil "((#0)->cf.cf_name)=(#1)")
+ (cclosurep (t) compiler::boolean nil nil "type_of(#0)==t_cclosure")
+ (sfun-p (t) compiler::boolean nil nil "type_of(#0)==t_sfun")
+ (%cclosure-env (t) t nil nil "(#0)->cc.cc_env")
+ (%set-cclosure-env (t t) t t nil "((#0)->cc.cc_env)=(#1)")
+ #+turbo-closure
+ (%cclosure-env-nthcdr (fixnum t) t nil nil "(#1)->cc.cc_turbo[#0]")
+
+ (logxor (fixnum fixnum) fixnum nil nil "((#0) ^ (#1))")))
+
+(defun make-function-inline (inline)
+ (setf (get (car inline) 'compiler::inline-always)
+ (list (if (fboundp 'compiler::flags)
+ (let ((opt (cdr inline)))
+ (list (first opt) (second opt)
+ (logior (if (fourth opt) 1 0) ; allocates-new-storage
+ (if (third opt) 2 0) ; side-effect
+ (if nil 4 0) ; constantp
+ (if (eq (car inline) 'logxor)
+ 8 0)) ;result type from args
+ (fifth opt)))
+ (cdr inline)))))
+)
+
+
+(defmacro define-inlines ()
+ `(progn
+ ,@(mapcan #'(lambda (inline)
+ (let ((name (intern (format nil "~S inline" (car inline))))
+ (vars (mapcar #'(lambda (type)
+ (declare (ignore type))
+ (gensym))
+ (cadr inline))))
+ `((eval-when (compile eval load)
+ (make-function-inline
+ ',(cons name (cdr inline))))
+ ,@(when (or (every #'(lambda (type) (eq type 't))
+ (cadr inline))
+ (char= #\% (aref (symbol-name (car inline)) 0)))
+ `((defun ,(car inline) ,vars
+ ,@(mapcan #'(lambda (var var-type)
+ (unless (eq var-type 't)
+ `((declare (type ,var-type ,var)))))
+ vars (cadr inline))
+ (the ,(caddr inline) (,name ,@vars)))
+ (make-function-inline ',inline))))))
+ *gcl-function-inlines*)))
+
+(define-inlines)
+
+(defsetf si:%compiled-function-name si:%set-compiled-function-name)
+(defsetf %cclosure-env %set-cclosure-env)
+
+(defun set-function-name-1 (fn new-name ignore)
+ (declare (ignore ignore))
+ (cond ((compiled-function-p fn)
+ (si::turbo-closure fn)
+ (when (symbolp new-name) (pcl::proclaim-defmethod new-name nil))
+ (setf (si:%compiled-function-name fn) new-name))
+ ((and (listp fn)
+ (eq (car fn) 'lambda-block))
+ (setf (cadr fn) new-name))
+ ((and (listp fn)
+ (eq (car fn) 'lambda))
+ (setf (car fn) 'lambda-block
+ (cdr fn) (cons new-name (cdr fn)))))
+ fn)
+
+
+(clines "
+
+
+
+object fSuse_fast_links();
+static
+object set_cclosure (result_cc,value_cc,available_size)
+ object result_cc,value_cc; int available_size;
+{
+ object result_env_tail,value_env_tail; int i;
+
+ /* If we are currently using fast linking, */
+ /* make sure to remove the link for result_cc. */
+ (VFUN_NARGS=2,fSuse_fast_links(sLnil,result_cc));
+
+/* use_fast_links(3,Cnil,result_cc); */
+
+ result_env_tail=result_cc->cc.cc_env;
+ value_env_tail=value_cc->cc.cc_env;
+ for(i=available_size;
+ result_env_tail!=Cnil && i>0;
+ result_env_tail=CMPcdr(result_env_tail), value_env_tail=CMPcdr(value_env_tail))
+ CMPcar(result_env_tail)=CMPcar(value_env_tail), i--;
+ result_cc->cc.cc_self=value_cc->cc.cc_self;
+ result_cc->cc.cc_data=value_cc->cc.cc_data;
+
+
+ return result_cc;
+}")
+
+(defentry %set-cclosure (object object int) (object set_cclosure))
+
+
+(defun structure-functions-exist-p ()
+ t)
+
+(si:define-compiler-macro structure-instance-p (x)
+ (once-only (x)
+ `(and (si:structurep ,x)
+ (not (eq (si:%structure-name ,x) 'std-instance)))))
+
+(defun structure-type (x)
+ (and (si:structurep x)
+ (si:%structure-name x)))
+
+(si:define-compiler-macro structure-type (x)
+ (once-only (x)
+ `(and (si:structurep ,x)
+ (si:%structure-name ,x))))
+
+(defun structure-type-p (type)
+ (or (not (null (gethash type *structure-table*)))
+ (let (#+akcl(s-data nil))
+ (and (symbolp type)
+ (setq s-data (get type 'si::s-data))
+
+ (null (si::s-data-type s-data)
+ )))))
+
+
+(defun structure-type-included-type-name (type)
+ (or (car (gethash type *structure-table*))
+ (si::s-data-included (get type 'si::s-data))
+ ))
+
+(defun structure-type-internal-slotds (type)
+ (si::s-data-slot-descriptions (get type 'si::s-data))
+ )
+
+(defun structure-type-slot-description-list (type)
+ (or (cdr (gethash type *structure-table*))
+ (mapcan #'(lambda (slotd)
+ (when (and slotd (car slotd))
+ (let ((offset (fifth slotd)))
+ (let ((reader #'(lambda (x)
+ (si:structure-ref1 x offset)
+ ))
+ (writer #'(lambda (v x)
+ (si:structure-set x type offset v))))
+ #+turbo-closure (si:turbo-closure reader)
+ #+turbo-closure (si:turbo-closure writer)
+ (let* ((reader-sym
+ (let ((*package* *the-pcl-package*))
+ (intern (format nil "~s SLOT~D" type offset))))
+ (writer-sym (get-setf-function-name reader-sym))
+ (slot-name (first slotd))
+ (read-only-p (fourth slotd)))
+ (setf (symbol-function reader-sym) reader)
+ (setf (symbol-function writer-sym) writer)
+ (do-standard-defsetf-1 reader-sym)
+ (list (list slot-name
+ reader-sym
+ (and (not read-only-p) writer))))))))
+ (let ((slotds (structure-type-internal-slotds type))
+ (inc (structure-type-included-type-name type)))
+ (if inc
+ (nthcdr (length (structure-type-internal-slotds inc))
+ slotds)
+ slotds)))))
+
+(defun structure-slotd-name (slotd)
+ (first slotd))
+
+(defun structure-slotd-accessor-symbol (slotd)
+ (second slotd))
+
+(defun structure-slotd-writer-function (slotd)
+ (third slotd))
+
+(defun renew-sys-files()
+ ;; packages:
+ (compiler::get-packages "sys-package.lisp")
+ (with-open-file (st "sys-package.lisp"
+ :direction :output
+ :if-exists :append)
+ (format st "(lisp::in-package \"SI\")
+(export '(%structure-name
+ %compiled-function-name
+ %set-compiled-function-name))
+(in-package \"PCL\")
+"))
+
+ ;; proclaims
+ (compiler::make-all-proclaims "*.fn")
+ (with-open-file (st "sys-proclaim.lisp"
+ :direction :output
+ :if-exists :append)
+ (format st "~%(IN-PACKAGE \"PCL\")~%")
+ (print
+ `(dolist (v ',
+
+ (sloop::sloop for v in-package "PCL"
+ when (get v 'compiler::proclaimed-closure)
+ collect v))
+ (setf (get v 'compiler::proclaimed-closure) t))
+ st)
+ (format st "~%")
+))
+
+
+
diff --git a/gcl/pcl/impl/gcl/gcl-patches.lisp b/gcl/pcl/impl/gcl/gcl-patches.lisp
new file mode 100644
index 000000000..9e666a6c1
--- /dev/null
+++ b/gcl/pcl/impl/gcl/gcl-patches.lisp
@@ -0,0 +1,225 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+
+(in-package "COMPILER")
+
+;; do evaluation of top level forms at compile time.
+(eval-when (compile eval load)
+(setq *EVAL-WHEN-COMPILE* t)
+)
+
+(pushnew :turbo-closure *features*)
+(pushnew :turbo-closure-env-size *features*)
+;; patch around compiler bug.
+
+
+(let ((rset "int Rset;
+"))
+ (unless (search rset compiler::*cmpinclude-string*)
+ (setq compiler::*cmpinclude-string*
+ (concatenate 'string rset compiler::*cmpinclude-string*))))
+
+(when (get 'si::basic-wrapper 'si::s-data)
+ (pushnew :new-kcl-wrapper *features*)
+ (pushnew :structure-wrapper *features*))
+
+
+
+
+#+akcl
+(progn
+
+(unless (fboundp 'real-c2lambda-expr-with-key)
+ (setf (symbol-function 'real-c2lambda-expr-with-key)
+ (symbol-function 'c2lambda-expr-with-key)))
+
+(defun c2lambda-expr-with-key (lambda-list body)
+ (declare (special *sup-used*))
+ (setq *sup-used* t)
+ (real-c2lambda-expr-with-key lambda-list body))
+
+
+;There is a bug in the implementation of *print-circle* that
+;causes some akcl debugging commands (including :bt and :bl)
+;to cause the following error when PCL is being used:
+;Unrecoverable error: value stack overflow.
+
+;When a CLOS object is printed, travel_push_object ends up
+;traversing almost the whole class structure, thereby overflowing
+;the value-stack.
+
+;from lsp/debug.lsp.
+;*print-circle* is badly implemented in kcl.
+;it has two separate problems that should be fixed:
+; 1. it traverses the printed object putting all objects found
+; on the value stack (rather than in a hash table or some
+; other structure; this is a problem because the size of the value stack
+; is fixed, and a potentially unbounded number of objects
+; need to be traversed), and
+; 2. it blindly traverses all slots of any
+; kind of structure including std-object structures.
+; This is safe, but not always necessary, and is very time-consuming
+; for CLOS objects (because it will always traverse every class).
+
+;For now, avoid using *print-circle* T when it will cause problems.
+
+
+
+(eval-when (compile eval )
+(defmacro si::f (op &rest args)
+ `(the fixnum (,op ,@ (mapcar #'(lambda (x) `(the fixnum ,x)) args) )))
+
+(defmacro si::fb (op &rest args)
+ `(,op ,@ (mapcar #'(lambda (x) `(the fixnum ,x)) args) ))
+)
+
+(defun si::display-env (n env)
+ (do ((v (reverse env) (cdr v)))
+ ((or (not (consp v)) (si::fb > (fill-pointer si::*display-string*) n)))
+ (or (and (consp (car v))
+ (listp (cdar v)))
+ (return))
+ (let ((*print-circle* (can-use-print-circle-p (cadar v))))
+ (format si::*display-string* "~s=~s~@[,~]" (caar v) (cadar v) (cdr v)))))
+
+(defun si::display-compiled-env ( plength ihs &aux
+ (base (si::ihs-vs ihs))
+ (end (min (si::ihs-vs (1+ ihs)) (si::vs-top))))
+ (format si::*display-string* "")
+ (do ((i base )
+ (v (get (si::ihs-fname ihs) 'si::debug) (cdr v)))
+ ((or (si::fb >= i end)(si::fb > (fill-pointer si::*display-string*) plength)))
+ (let ((*print-circle* (can-use-print-circle-p (si::vs i))))
+ (format si::*display-string* "~a~@[~d~]=~s~@[,~]"
+ (or (car v) 'si::loc) (if (not (car v)) (si::f - i base)) (si::vs i)
+ (si::fb < (setq i (si::f + i 1)) end)))))
+
+(clines "#define objnull_p(x) ((x==OBJNULL)?Ct:Cnil)")
+(defentry objnull-p (object) (object "objnull_p"))
+
+(defun can-use-print-circle-p (x)
+ (catch 'can-use-print-circle-p
+ (can-use-print-circle-p1 x nil)))
+
+(defun can-use-print-circle-p1 (x so-far)
+ (and (not (objnull-p x)) ; because of deficiencies in the compiler, maybe?
+ (if (member x so-far)
+ (throw 'can-use-print-circle-p t)
+ (let ((so-far (cons x so-far)))
+ (flet ((can-use-print-circle-p (x)
+ (can-use-print-circle-p1 x so-far)))
+ (typecase x
+ (vector (or (not (eq 't (array-element-type x)))
+ (every #'can-use-print-circle-p x)))
+ (cons (and (can-use-print-circle-p (car x))
+ (can-use-print-circle-p (cdr x))))
+ (array (or (not (eq 't (array-element-type x)))
+ (let* ((rank (array-rank x))
+ (dimensions (make-list rank)))
+ (dotimes (i rank)
+ (setf (nth i dimensions) (array-dimension x i)))
+ (or (member 0 dimensions)
+ (do ((cursor (make-list rank :initial-element 0)))
+ (nil)
+ (declare (:dynamic-extent cursor))
+ (unless (can-use-print-circle-p
+ (apply #'aref x cursor))
+ (return nil))
+ (when (si::increment-cursor cursor dimensions)
+ (return t)))))))
+ (t (or (not (si:structurep x))
+ (let* ((def (si:structure-def x))
+ (name (si::s-data-name def))
+ (len (si::s-data-length def))
+ (pfun (si::s-data-print-function def)))
+ (and (null pfun)
+ (dotimes (i len t)
+ (unless (can-use-print-circle-p
+ (si:structure-ref x name i))
+ (return nil)))))))))))))
+
+(defun si::apply-display-fun (display-fun n lis)
+ (let ((*print-length* si::*debug-print-level*)
+ (*print-level* si::*debug-print-level*)
+ (*print-pretty* nil)
+ (*PRINT-CASE* :downcase)
+ (*print-circle* nil)
+ )
+ (setf (fill-pointer si::*display-string*) 0)
+ (format si::*display-string* "{")
+ (funcall display-fun n lis)
+ (when (si::fb > (fill-pointer si::*display-string*) n)
+ (setf (fill-pointer si::*display-string*) n)
+ (format si::*display-string* "..."))
+
+ (format si::*display-string* "}")
+ )
+ si::*display-string*
+ )
+
+;The old definition of this had a bug:
+;sometimes it returned without calling mv-values.
+(defun si::next-stack-frame (ihs &aux line-info li i k na)
+ (cond ((si::fb < ihs si::*ihs-base*)
+ (si::mv-values nil nil nil nil nil))
+ ((let (fun)
+ ;; next lower visible ihs
+ (si::mv-setq (fun i) (si::get-next-visible-fun ihs))
+ (setq na fun)
+ (cond ((and (setq line-info (get fun 'si::line-info))
+ (do ((j (si::f + ihs 1) (si::f - j 1))
+ (form ))
+ ((<= j i) nil)
+ (setq form (si::ihs-fun j))
+ (cond ((setq li (si::get-line-of-form form line-info))
+ (return-from si::next-stack-frame
+ (si::mv-values
+ i fun li
+ ;; filename
+ (car (aref line-info 0))
+ ;;environment
+ (list (si::vs (setq k (si::ihs-vs j)))
+ (si::vs (1+ k))
+ (si::vs (+ k 2)))))))))))))
+ ((and (not (special-form-p na))
+ (not (get na 'si::dbl-invisible))
+ (fboundp na))
+ (si::mv-values i na nil nil
+ (if (si::ihs-not-interpreted-env i)
+ nil
+ (let ((i (si::ihs-vs i)))
+ (list (si::vs i) (si::vs (1+ i)) (si::vs (si::f + i 2)))))))
+ (t (si::mv-values nil nil nil nil nil))))
+)
+
+
+
+
+
+
+
diff --git a/gcl/pcl/impl/gcl/makefile.gcl b/gcl/pcl/impl/gcl/makefile.gcl
new file mode 100644
index 000000000..46a50beb5
--- /dev/null
+++ b/gcl/pcl/impl/gcl/makefile.gcl
@@ -0,0 +1,38 @@
+# makefile for making pcl -- W. Schelter.
+
+# Directions:
+# make -f makefile.gcl compile
+# make -f makefile.gcl saved_pcl
+
+
+LISP=gcl
+
+
+SETUP='(load "sys-package.lisp")' \
+ '(setq *features* (delete (quote kcl) *features*))'\
+ '(load "defsys.lisp")(push (quote kcl) *features*)' \
+ '(setq pcl::*default-pathname-extensions* (cons "lisp" "o"))' \
+ '(setq pcl::*pathname-extensions* (cons "lisp" "o"))' \
+ '(load "sys-proclaim.lisp")(compiler::emit-fn t)'
+
+compile:
+ echo ${SETUP} '(pcl::compile-pcl)' | ${LISP}
+
+saved_pcl:
+ echo ${SETUP} '(pcl::load-pcl)(si::save-system "saved_pcl")' | ${LISP}
+
+
+# remake the sys-package.lisp and sys-proclaim.lisp files
+# Those files may be empty on a first build.
+remake-sys-files:
+ echo ${SETUP} '(pcl::load-pcl)(in-package "PCL")(renew-sys-files)' | ${LISP}
+ cp sys-proclaim.lisp xxx
+ cat xxx | sed -e "s/COMPILER::CMP-ANON//g" > sys-proclaim.lisp
+ rm xxx
+
+
+tar:
+ make -f makefile.gcl tar1 DIR=`pwd`
+
+tar1:
+ (cd .. ; tar cvf - `basename ${DIR}` | gzip -c > `basename ${DIR}`.tgz)
diff --git a/gcl/pcl/impl/gcl/sys-package.lisp b/gcl/pcl/impl/gcl/sys-package.lisp
new file mode 100644
index 000000000..c04430e8c
--- /dev/null
+++ b/gcl/pcl/impl/gcl/sys-package.lisp
@@ -0,0 +1,149 @@
+
+
+;;; Definitions for package SLOT-ACCESSOR-NAME of type ESTABLISH
+(LISP::IN-PACKAGE "SLOT-ACCESSOR-NAME" :USE LISP::NIL :NICKNAMES
+ '("S-A-N"))
+
+;;; Definitions for package PCL of type ESTABLISH
+(LISP::IN-PACKAGE "PCL" :USE LISP::NIL)
+
+;;; Definitions for package ITERATE of type ESTABLISH
+(LISP::IN-PACKAGE "ITERATE" :USE LISP::NIL)
+
+;;; Definitions for package WALKER of type ESTABLISH
+(LISP::IN-PACKAGE "WALKER" :USE LISP::NIL)
+
+;;; Definitions for package SLOT-ACCESSOR-NAME of type EXPORT
+(LISP::IN-PACKAGE "SLOT-ACCESSOR-NAME" :USE 'LISP::NIL :NICKNAMES
+ '("S-A-N"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT 'LISP::NIL)
+
+;;; Definitions for package PCL of type EXPORT
+(LISP::IN-PACKAGE "PCL" :USE '("LISP" "ITERATE" "WALKER"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT
+ '(PCL::CLASS-PRECEDENCE-LIST PCL::SLOT-DEFINITION
+ PCL::COMPUTE-APPLICABLE-METHODS-USING-CLASSES
+ PCL::SLOT-DEFINITION-WRITERS PCL::CLASS-OF
+ PCL::NO-APPLICABLE-METHOD PCL::STANDARD-WRITER-METHOD
+ PCL::ENSURE-CLASS-USING-CLASS PCL::ENSURE-GENERIC-FUNCTION
+ PCL::FIND-METHOD-COMBINATION PCL::UPDATE-DEPENDENT
+ PCL::MAP-DEPENDENTS PCL::SLOT-MISSING PCL::SPECIALIZER
+ PCL::CALL-NEXT-METHOD PCL::ENSURE-GENERIC-FUNCTION-USING-CLASS
+ PCL::SLOT-MAKUNBOUND-USING-CLASS PCL::MAKE-INSTANCES-OBSOLETE
+ PCL::INTERN-EQL-SPECIALIZER PCL::REMOVE-DIRECT-SUBCLASS
+ PCL::METHOD-GENERIC-FUNCTION PCL::METHOD-QUALIFIERS
+ PCL::FUNCALLABLE-STANDARD-CLASS PCL::EXTRACT-LAMBDA-LIST
+ PCL::STANDARD-CLASS PCL::PRINT-OBJECT PCL::STRUCTURE-CLASS
+ PCL::COMPUTE-EFFECTIVE-SLOT-DEFINITION
+ PCL::GENERIC-FUNCTION-DECLARATIONS PCL::MAKE-INSTANCE
+ PCL::METHOD-LAMBDA-LIST PCL::DEFGENERIC
+ PCL::REMOVE-DIRECT-METHOD PCL::STANDARD-DIRECT-SLOT-DEFINITION
+ PCL::GENERIC-FUNCTION-METHODS PCL::VALIDATE-SUPERCLASS
+ PCL::REINITIALIZE-INSTANCE PCL::STANDARD-METHOD
+ PCL::STANDARD-ACCESSOR-METHOD
+ PCL::FUNCALLABLE-STANDARD-INSTANCE PCL::FUNCTION-KEYWORDS
+ PCL::STANDARD PCL::FIND-METHOD PCL::EXTRACT-SPECIALIZER-NAMES
+ PCL::INITIALIZE-INSTANCE PCL::GENERIC-FLET PCL::SLOT-UNBOUND
+ PCL::STANDARD-INSTANCE PCL::SLOT-DEFINITION-TYPE
+ PCL::COMPUTE-EFFECTIVE-METHOD PCL::ALLOCATE-INSTANCE
+ PCL::SYMBOL-MACROLET PCL::GENERIC-FUNCTION
+ PCL::GENERIC-FUNCTION-METHOD-COMBINATION
+ PCL::SPECIALIZER-DIRECT-METHODS PCL::ADD-DIRECT-SUBCLASS
+ PCL::WRITER-METHOD-CLASS PCL::SLOT-DEFINITION-INITARGS
+ PCL::METHOD-SPECIALIZERS PCL::GENERIC-FUNCTION-METHOD-CLASS
+ PCL::ADD-METHOD PCL::WITH-ACCESSORS
+ PCL::SLOT-DEFINITION-ALLOCATION
+ PCL::SLOT-DEFINITION-INITFUNCTION
+ PCL::SLOT-DEFINITION-LOCATION PCL::ADD-DIRECT-METHOD
+ PCL::SLOT-BOUNDP PCL::EQL-SPECIALIZER PCL::SHARED-INITIALIZE
+ PCL::STANDARD-GENERIC-FUNCTION
+ PCL::ACCESSOR-METHOD-SLOT-DEFINITION
+ PCL::SLOT-BOUNDP-USING-CLASS PCL::ADD-DEPENDENT
+ PCL::SPECIALIZER-DIRECT-GENERIC-FUNCTION
+ PCL::WITH-ADDED-METHODS PCL::COMPUTE-CLASS-PRECEDENCE-LIST
+ PCL::REMOVE-DEPENDENT PCL::NEXT-METHOD-P
+ PCL::GENERIC-FUNCTION-NAME PCL::SLOT-VALUE
+ PCL::EFFECTIVE-SLOT-DEFINITION PCL::CLASS-FINALIZED-P
+ PCL::COMPUTE-DISCRIMINATING-FUNCTION PCL::STANDARD-OBJECT
+ PCL::CLASS-DEFAULT-INITARGS PCL::CLASS-DIRECT-SLOTS
+ PCL::FUNCALLABLE-STANDARD-INSTANCE-ACCESS PCL::BUILT-IN-CLASS
+ PCL::NO-NEXT-METHOD PCL::SLOT-MAKUNBOUND
+ PCL::STANDARD-READER-METHOD PCL::GENERIC-FUNCTION-LAMBDA-LIST
+ PCL::GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER
+ PCL::INVALID-METHOD-ERROR PCL::METHOD-COMBINATION-ERROR
+ PCL::SLOT-EXISTS-P PCL::FINALIZE-INHERITANCE
+ PCL::SLOT-DEFINITION-NAME
+ PCL::STANDARD-EFFECTIVE-SLOT-DEFINITION PCL::COMPUTE-SLOTS
+ PCL::CLASS-SLOTS PCL::EFFECTIVE-SLOT-DEFINITION-CLASS
+ PCL::STANDARD-INSTANCE-ACCESS PCL::WITH-SLOTS
+ PCL::DIRECT-SLOT-DEFINITION PCL::DEFINE-METHOD-COMBINATION
+ PCL::MAKE-METHOD-LAMBDA PCL::ENSURE-CLASS
+ PCL::DIRECT-SLOT-DEFINITION-CLASS PCL::METHOD-FUNCTION
+ PCL::STANDARD-SLOT-DEFINITION PCL::CHANGE-CLASS PCL::DEFMETHOD
+ PCL::UPDATE-INSTANCE-FOR-DIFFERENT-CLASS
+ PCL::UPDATE-INSTANCE-FOR-REDEFINED-CLASS
+ PCL::FORWARD-REFERENCED-CLASS PCL::SLOT-DEFINITION-INITFORM
+ PCL::REMOVE-METHOD PCL::READER-METHOD-CLASS PCL::CALL-METHOD
+ PCL::CLASS-PROTOTYPE PCL::CLASS-NAME PCL::FIND-CLASS
+ PCL::DEFCLASS PCL::COMPUTE-APPLICABLE-METHODS
+ PCL::SLOT-VALUE-USING-CLASS PCL::METHOD-COMBINATION
+ PCL::EQL-SPECIALIZER-INSTANCE PCL::GENERIC-LABELS PCL::METHOD
+ PCL::SLOT-DEFINITION-READERS
+ PCL::CLASS-DIRECT-DEFAULT-INITARGS
+ PCL::CLASS-DIRECT-SUBCLASSES PCL::CLASS-DIRECT-SUPERCLASSES
+ PCL::SET-FUNCALLABLE-INSTANCE-FUNCTION))
+
+;;; Definitions for package ITERATE of type EXPORT
+(LISP::IN-PACKAGE "ITERATE" :USE '("WALKER" "LISP"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT
+ '(ITERATE::SUMMING ITERATE::MINIMIZING ITERATE::PLIST-ELEMENTS
+ ITERATE::ITERATE* ITERATE::MAXIMIZING ITERATE::LIST-TAILS
+ ITERATE::*ITERATE-WARNINGS* ITERATE::GATHERING
+ ITERATE::EACHTIME ITERATE::ELEMENTS ITERATE::GATHER
+ ITERATE::LIST-ELEMENTS ITERATE::WHILE ITERATE::ITERATE
+ ITERATE::UNTIL ITERATE::JOINING ITERATE::COLLECTING
+ ITERATE::WITH-GATHERING ITERATE::INTERVAL))
+
+;;; Definitions for package WALKER of type EXPORT
+(LISP::IN-PACKAGE "WALKER" :USE '("LISP"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT
+ '(WALKER::DEFINE-WALKER-TEMPLATE WALKER::*VARIABLE-DECLARATIONS*
+ WALKER::NESTED-WALK-FORM WALKER::VARIABLE-DECLARATION
+ WALKER::WALK-FORM-EXPAND-MACROS-P WALKER::VARIABLE-LEXICAL-P
+ WALKER::VARIABLE-SPECIAL-P WALKER::WALK-FORM
+ WALKER::MACROEXPAND-ALL WALKER::VARIABLE-GLOBALLY-SPECIAL-P))
+
+;;; Definitions for package SLOT-ACCESSOR-NAME of type SHADOW
+(LISP::IN-PACKAGE "SLOT-ACCESSOR-NAME")
+(LISP::SHADOW 'LISP::NIL)
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT 'LISP::NIL)
+
+;;; Definitions for package PCL of type SHADOW
+(LISP::IN-PACKAGE "PCL")
+(LISP::SHADOW '(PCL::DOTIMES PCL::DOCUMENTATION))
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT
+ '(SYSTEM::STRUCTURE-REF SYSTEM::STRUCTURE-DEF SYSTEM::STRUCTUREP))
+
+;;; Definitions for package ITERATE of type SHADOW
+(LISP::IN-PACKAGE "ITERATE")
+(LISP::SHADOW 'LISP::NIL)
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT 'LISP::NIL)
+
+;;; Definitions for package WALKER of type SHADOW
+(LISP::IN-PACKAGE "WALKER")
+(LISP::SHADOW 'LISP::NIL)
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT 'LISP::NIL)
+
+(in-package 'SI)
+(export '(%structure-name
+ %compiled-function-name
+ %set-compiled-function-name))
+(in-package 'pcl)
diff --git a/gcl/pcl/impl/gcl/sys-proclaim.lisp b/gcl/pcl/impl/gcl/sys-proclaim.lisp
new file mode 100644
index 000000000..26f869897
--- /dev/null
+++ b/gcl/pcl/impl/gcl/sys-proclaim.lisp
@@ -0,0 +1,1448 @@
+
+(IN-PACKAGE "PCL")
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) FIXNUM) ONE-INDEX-LIMIT-FN
+ N-N-ACCESSORS-LIMIT-FN CHECKING-LIMIT-FN PV-CACHE-LIMIT-FN
+ ARG-INFO-NUMBER-REQUIRED DEFAULT-LIMIT-FN CACHE-COUNT
+ CACHING-LIMIT-FN PV-TABLE-PV-SIZE EARLY-CLASS-SIZE
+ CPD-COUNT FAST-INSTANCE-BOUNDP-INDEX))
+(PROCLAIM '(FTYPE (FUNCTION (T) FIELD-TYPE) CACHE-FIELD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) FUNCTION) CACHE-LIMIT-FN METHOD-CALL-FUNCTION
+ FAST-METHOD-CALL-FUNCTION))
+(PROCLAIM '(FTYPE (FUNCTION (FIXNUM) T) POWER-OF-TWO-CEILING))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) LIST) CACHE-OVERFLOW PV-TABLE-SLOT-NAME-LISTS
+ PV-TABLE-CALL-LIST))
+(PROCLAIM '(FTYPE (FUNCTION (T) (MEMBER NIL T)) CACHE-VALUEP))
+(PROCLAIM '(FTYPE (FUNCTION (T) SIMPLE-VECTOR) CACHE-VECTOR))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) (VALUES T T)) MAKE-CLASS-PREDICATE-NAME
+ MAKE-KEYWORD))
+(PROCLAIM '(FTYPE (FUNCTION (FIXNUM T) T) %CCLOSURE-ENV-NTHCDR))
+(PROCLAIM
+ '(FTYPE (FUNCTION (FIXNUM FIXNUM T) FIXNUM)
+ COMPUTE-PRIMARY-CACHE-LOCATION))
+(PROCLAIM '(FTYPE (FUNCTION (T) (INTEGER 1 256)) CACHE-NKEYS))
+(PROCLAIM '(FTYPE (FUNCTION (T) (INTEGER 1 512)) CACHE-LINE-SIZE))
+(PROCLAIM '(FTYPE (FUNCTION (T) (OR CACHE NULL)) PV-TABLE-CACHE))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T) *)
+ GET-OPTIMIZED-STD-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ ITERATE::WALK-GATHERING-BODY CACHE-MISS-VALUES
+ MAKE-OPTIMIZED-STD-READER-METHOD-FUNCTION
+ OPTIMIZE-SLOT-VALUE-BY-CLASS-P ACCESSOR-VALUES1
+ EMIT-READER/WRITER EMIT-ONE-OR-N-INDEX-READER/WRITER
+ GENERATING-LISP EMIT-READER/WRITER-FUNCTION
+ EMIT-ONE-OR-N-INDEX-READER/WRITER-FUNCTION
+ WALKER::WALK-LET-IF SET-SLOT-VALUE CONVERT-METHODS
+ |(FAST-METHOD METHOD-LAMBDA-LIST (TRACED-METHOD))|
+ SLOT-VALUE-USING-CLASS-DFUN SLOT-BOUNDP-USING-CLASS-DFUN
+ |(FAST-METHOD METHOD-SPECIALIZERS (TRACED-METHOD))|
+ CHECK-METHOD-ARG-INFO
+ |(FAST-METHOD METHOD-QUALIFIERS (TRACED-METHOD))|
+ LOAD-LONG-DEFCOMBIN MAKE-FINAL-N-N-ACCESSOR-DFUN
+ |(FAST-METHOD ACCESSOR-METHOD-SLOT-NAME (TRACED-METHOD))|
+ MAKE-FINAL-CACHING-DFUN MAKE-FINAL-CONSTANT-VALUE-DFUN
+ GET-CLASS-SLOT-VALUE-1 ACCESSOR-VALUES-INTERNAL
+ MAKE-OPTIMIZED-STD-WRITER-METHOD-FUNCTION
+ MAKE-OPTIMIZED-STD-BOUNDP-METHOD-FUNCTION
+ ITERATE::EXPAND-INTO-LET WALKER::WALK-FORM-INTERNAL
+ ITERATE::RENAME-VARIABLES CONSTANT-VALUE-MISS CACHING-MISS
+ |(FAST-METHOD COMPUTE-DISCRIMINATING-FUNCTION (STANDARD-GENERIC-FUNCTION))|
+ CHECKING-MISS GET-OPTIMIZED-STD-ACCESSOR-METHOD-FUNCTION
+ |(FAST-METHOD FUNCTION-KEYWORDS (STANDARD-METHOD))|
+ |(FAST-METHOD METHOD-PRETTY-ARGLIST (STANDARD-METHOD))|
+ |(FAST-METHOD CLASS-PROTOTYPE (STD-CLASS))|
+ |(FAST-METHOD CLASS-PROTOTYPE (STRUCTURE-CLASS))|
+ |(FAST-METHOD MAKE-INSTANCES-OBSOLETE (SYMBOL))|
+ |(FAST-METHOD METHOD-FUNCTION (STANDARD-METHOD))|
+ |(FAST-METHOD COMPUTE-DISCRIMINATING-FUNCTION-ARGLIST-INFO (STANDARD-GENERIC-FUNCTION))|))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T) *)
+ |(FAST-METHOD COMPUTE-EFFECTIVE-METHOD (GENERIC-FUNCTION LONG-METHOD-COMBINATION T))|
+ |(FAST-METHOD UPDATE-INSTANCE-FOR-DIFFERENT-CLASS (STANDARD-OBJECT STANDARD-OBJECT))|
+ |(FAST-METHOD SHARED-INITIALIZE (SLOT-OBJECT T))|
+ COMPUTE-DISCRIMINATING-FUNCTION-ARGLIST-INFO-INTERNAL
+ ADD-METHOD-DECLARATIONS WALK-METHOD-LAMBDA
+ MAKE-TWO-CLASS-ACCESSOR-DFUN
+ |(FAST-METHOD (SETF SLOT-ACCESSOR-FUNCTION) (T EFFECTIVE-SLOT-DEFINITION T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (CLASS-EQ-SPECIALIZER T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (EQL-SPECIALIZER T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (CLASS T))|
+ |(FAST-METHOD (SETF DOCUMENTATION) (T STANDARD-SLOT-DEFINITION))|
+ |(FAST-METHOD ADD-READER-METHOD (SLOT-CLASS T T))|
+ |(FAST-METHOD ADD-WRITER-METHOD (SLOT-CLASS T T))|
+ |(FAST-METHOD ADD-BOUNDP-METHOD (SLOT-CLASS T T))|
+ |(FAST-METHOD (SETF CLASS-SLOT-VALUE) (T STD-CLASS T))|
+ |(FAST-METHOD SLOT-VALUE-USING-CLASS (STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-VALUE-USING-CLASS (STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STANDARD-SLOT-DEFINITION T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (STANDARD-METHOD T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STANDARD-ACCESSOR-METHOD T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (STANDARD-GENERIC-FUNCTION T))|))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T) *)
+ |(FAST-METHOD ALLOCATE-INSTANCE (STRUCTURE-CLASS))|
+ |(FAST-METHOD MAKE-INSTANCE (SYMBOL))|
+ |(FAST-METHOD DEFAULT-INITARGS (SLOT-CLASS T))|
+ |(FAST-METHOD INITIALIZE-INSTANCE (SLOT-OBJECT))|
+ |(FAST-METHOD DESCRIBE-OBJECT (T T))|
+ |(FAST-METHOD DESCRIBE-OBJECT (SLOT-OBJECT T))|
+ |(FAST-METHOD SLOTS-TO-INSPECT (SLOT-CLASS SLOT-OBJECT))|
+ |(FAST-METHOD DESCRIBE-OBJECT (STANDARD-GENERIC-FUNCTION T))|
+ |(FAST-METHOD DESCRIBE-OBJECT (CLASS T))|
+ |(FAST-METHOD COMPUTE-APPLICABLE-METHODS-USING-CLASSES (GENERIC-FUNCTION T))|
+ GET-ACCESSOR-FROM-SVUC-METHOD-FUNCTION
+ |(FAST-METHOD SLOT-ACCESSOR-FUNCTION (EFFECTIVE-SLOT-DEFINITION T))|
+ BOOTSTRAP-ACCESSOR-DEFINITION GET-ACCESSOR-METHOD-FUNCTION
+ EMIT-CHECKING-OR-CACHING EMIT-CHECKING-OR-CACHING-FUNCTION
+ SETF-SLOT-VALUE-USING-CLASS-DFUN LOAD-SHORT-DEFCOMBIN
+ INITIALIZE-INSTANCE-SIMPLE-FUNCTION
+ MAKE-SHARED-INITIALIZE-FORM-LIST
+ MAKE-ONE-CLASS-ACCESSOR-DFUN
+ MAKE-FINAL-ONE-INDEX-ACCESSOR-DFUN MAKE-FINAL-CHECKING-DFUN
+ ACCESSOR-VALUES SET-CLASS-SLOT-VALUE-1
+ GENERATE-DISCRIMINATION-NET REAL-MAKE-METHOD-LAMBDA
+ ORDER-SPECIALIZERS ACCESSOR-MISS
+ |(FAST-METHOD REINITIALIZE-INSTANCE :AFTER (SLOT-CLASS))|
+ |(FAST-METHOD DOCUMENTATION (STANDARD-SLOT-DEFINITION))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-SLOT-DEFINITION (SLOT-CLASS T))|
+ |(FAST-METHOD NO-APPLICABLE-METHOD (T))|
+ |(FAST-METHOD CHANGE-CLASS (T SYMBOL))|
+ |(FAST-METHOD CLASS-SLOT-VALUE (STD-CLASS T))|
+ |(FAST-METHOD LEGAL-QUALIFIERS-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-SPECIALIZERS-P (STANDARD-METHOD T))|))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T) *) MEMF-CODE-CONVERTER
+ CACHE-MISS-VALUES-INTERNAL
+ GENERATE-DISCRIMINATION-NET-INTERNAL
+ MAKE-LONG-METHOD-COMBINATION-FUNCTION
+ DO-SHORT-METHOD-COMBINATION
+ |(FAST-METHOD (SETF SLOT-VALUE-USING-CLASS) (T STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|))
+(PROCLAIM '(FTYPE (FUNCTION (T T T T T T *) *) REAL-MAKE-A-METHOD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T *) *) MAKE-ONE-INDEX-ACCESSOR-DFUN
+ WALKER::WALK-DECLARATIONS GET-SECONDARY-DISPATCH-FUNCTION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T *) *)
+ MAKE-EFFECTIVE-METHOD-FUNCTION-SIMPLE1
+ ITERATE::RENAME-LET-BINDINGS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T *) *) NESTED-WALK-FORM SLOT-VALUE-OR-DEFAULT
+ MAKE-EFFECTIVE-METHOD-FUNCTION
+ GET-EFFECTIVE-METHOD-FUNCTION MAKE-N-N-ACCESSOR-DFUN
+ MAKE-CHECKING-DFUN LOAD-DEFGENERIC TYPES-FROM-ARGUMENTS
+ MAKE-DEFAULT-INITARGS-FORM-LIST MAKE-FINAL-ACCESSOR-DFUN
+ MAKE-ACCESSOR-TABLE GET-SIMPLE-INITIALIZATION-FUNCTION
+ GET-COMPLEX-INITIALIZATION-FUNCTIONS
+ COMPUTE-SECONDARY-DISPATCH-FUNCTION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T) *)
+ |(FAST-METHOD UPDATE-INSTANCE-FOR-REDEFINED-CLASS (STANDARD-OBJECT T T T))|
+ ITERATE::ITERATE-TRANSFORM-BODY))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) NON-NEGATIVE-FIXNUM) CACHE-NLINES
+ CACHE-MAX-LOCATION CACHE-SIZE CACHE-MASK))
+(PROCLAIM '(FTYPE (FUNCTION (T STREAM T) T) PRINT-DFUN-INFO))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T) T)
+ |(FAST-METHOD ALLOCATE-INSTANCE (STANDARD-CLASS))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (FUNCALLABLE-STANDARD-CLASS STANDARD-CLASS))|
+ |(FAST-METHOD ALLOCATE-INSTANCE (FUNCALLABLE-STANDARD-CLASS))|
+ |(FAST-METHOD MAKE-READER-METHOD-FUNCTION (FUNCALLABLE-STANDARD-CLASS T))|
+ |(FAST-METHOD MAKE-WRITER-METHOD-FUNCTION (FUNCALLABLE-STANDARD-CLASS T))|
+ |(FAST-METHOD MAKE-INSTANCE (CLASS))|
+ |(FAST-METHOD REINITIALIZE-INSTANCE (SLOT-OBJECT))|
+ MAKE-EFFECTIVE-METHOD-FUNCTION1
+ MAKE-EFFECTIVE-METHOD-FUNCTION-INTERNAL
+ MAKE-EFFECTIVE-METHOD-FUNCTION-TYPE MEMF-TEST-CONVERTER
+ LOAD-PRECOMPILED-DFUN-CONSTRUCTOR TWO-CLASS-DFUN-INFO
+ WALKER::WALK-LET/LET* WALKER::WALK-PROG/PROG*
+ WALKER::WALK-DO/DO* WALKER::WALK-BINDINGS-2 OPTIMIZE-READER
+ OPTIMIZE-WRITER
+ |(FAST-METHOD SAME-SPECIALIZER-P (SPECIALIZER SPECIALIZER))|
+ EMIT-CHECKING-OR-CACHING-FUNCTION-PRELIMINARY
+ |(FAST-METHOD SAME-SPECIALIZER-P (CLASS CLASS))|
+ MAYBE-EXPAND-ACCESSOR-FORM
+ |(FAST-METHOD ADD-DIRECT-SUBCLASS (CLASS CLASS))|
+ INITIALIZE-INSTANCE-SIMPLE
+ |(FAST-METHOD SAME-SPECIALIZER-P (CLASS-EQ-SPECIALIZER CLASS-EQ-SPECIALIZER))|
+ GET-WRAPPERS-FROM-CLASSES
+ |(FAST-METHOD SAME-SPECIALIZER-P (EQL-SPECIALIZER EQL-SPECIALIZER))|
+ LOAD-PRECOMPILED-IIS-ENTRY FILL-CACHE-P ADJUST-CACHE
+ |(FAST-METHOD REMOVE-DIRECT-SUBCLASS (CLASS CLASS))|
+ EXPAND-CACHE EXPAND-SYMBOL-MACROLET-INTERNAL
+ |(FAST-METHOD ADD-DIRECT-METHOD (CLASS METHOD))|
+ BOOTSTRAP-SET-SLOT EXPAND-DEFCLASS
+ |(FAST-METHOD REMOVE-DIRECT-METHOD (CLASS METHOD))|
+ |(FAST-METHOD UPDATE-GF-DFUN (STD-CLASS T))|
+ |(FAST-METHOD ADD-DIRECT-METHOD (SPECIALIZER-WITH-OBJECT METHOD))|
+ |(FAST-METHOD REMOVE-DIRECT-METHOD (SPECIALIZER-WITH-OBJECT METHOD))|
+ |(FAST-METHOD SLOT-ACCESSOR-STD-P (EFFECTIVE-SLOT-DEFINITION T))|
+ WALKER::WALK-TEMPLATE
+ |(FAST-METHOD REINITIALIZE-INSTANCE :BEFORE (SLOT-CLASS))|
+ |(FAST-METHOD DOCUMENTATION (T))|
+ |(FAST-METHOD DOCUMENTATION (DOCUMENTATION-MIXIN))|
+ |(FAST-METHOD DIRECT-SLOT-DEFINITION-CLASS (STRUCTURE-CLASS T))|
+ |(FAST-METHOD DIRECT-SLOT-DEFINITION-CLASS (STD-CLASS T))|
+ |(FAST-METHOD EFFECTIVE-SLOT-DEFINITION-CLASS (STD-CLASS T))|
+ |(FAST-METHOD EFFECTIVE-SLOT-DEFINITION-CLASS (STRUCTURE-CLASS T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS (SLOT-CLASS T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS :AROUND (STRUCTURE-CLASS T))|
+ |(FAST-METHOD REMOVE-READER-METHOD (SLOT-CLASS T))|
+ |(FAST-METHOD REMOVE-WRITER-METHOD (SLOT-CLASS T))|
+ |(FAST-METHOD REMOVE-BOUNDP-METHOD (SLOT-CLASS T))|
+ |(FAST-METHOD MAKE-READER-METHOD-FUNCTION (SLOT-CLASS T))|
+ |(FAST-METHOD MAKE-WRITER-METHOD-FUNCTION (SLOT-CLASS T))|
+ |(FAST-METHOD MAKE-BOUNDP-METHOD-FUNCTION (SLOT-CLASS T))|
+ |(FAST-METHOD INFORM-TYPE-SYSTEM-ABOUT-CLASS (STD-CLASS T))|
+ |(FAST-METHOD COMPATIBLE-META-CLASS-CHANGE-P (T T))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (CLASS CLASS))|
+ |(FAST-METHOD CHANGE-CLASS (STANDARD-OBJECT STANDARD-CLASS))|
+ |(FAST-METHOD CHANGE-CLASS (STANDARD-OBJECT FUNCALLABLE-STANDARD-CLASS))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (CLASS BUILT-IN-CLASS))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (SLOT-CLASS FORWARD-REFERENCED-CLASS))|
+ |(FAST-METHOD ADD-DEPENDENT (DEPENDENT-UPDATE-MIXIN T))|
+ |(FAST-METHOD REMOVE-DEPENDENT (DEPENDENT-UPDATE-MIXIN T))|
+ |(FAST-METHOD MAP-DEPENDENTS (DEPENDENT-UPDATE-MIXIN T))|
+ |(FAST-METHOD PRINT-OBJECT (T T))|
+ |(FAST-METHOD PRINT-OBJECT (CLASS T))|
+ |(FAST-METHOD PRINT-OBJECT (SLOT-DEFINITION T))|
+ |(FAST-METHOD PRINT-OBJECT (STANDARD-METHOD-COMBINATION T))|
+ |(FAST-METHOD INFORM-TYPE-SYSTEM-ABOUT-CLASS (STRUCTURE-CLASS T))|
+ |(FAST-METHOD PRINT-OBJECT (STANDARD-METHOD T))|
+ |(FAST-METHOD PRINT-OBJECT (STANDARD-ACCESSOR-METHOD T))|
+ |(FAST-METHOD REINITIALIZE-INSTANCE (STANDARD-METHOD))|
+ |(FAST-METHOD LEGAL-DOCUMENTATION-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-LAMBDA-LIST-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-METHOD-FUNCTION-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-QUALIFIER-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-SLOT-NAME-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-SPECIALIZER-P (STANDARD-METHOD T))|
+ |(FAST-METHOD PRINT-OBJECT (GENERIC-FUNCTION T))|
+ |(FAST-METHOD INITIALIZE-INSTANCE :AFTER (STANDARD-GENERIC-FUNCTION))|
+ MAKE-DISPATCH-LAMBDA
+ |(FAST-METHOD REINITIALIZE-INSTANCE :AFTER (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD COMPUTE-APPLICABLE-METHODS (GENERIC-FUNCTION T))|))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T) T)
+ |(FAST-METHOD COMPUTE-CLASS-PRECEDENCE-LIST (SLOT-CLASS))|
+ CAN-OPTIMIZE-ACCESS
+ |(FAST-METHOD WRAPPER-FETCHER (FUNCALLABLE-STANDARD-CLASS))|
+ OPTIMIZE-SLOT-VALUE
+ |(FAST-METHOD SLOTS-FETCHER (FUNCALLABLE-STANDARD-CLASS))|
+ OPTIMIZE-SET-SLOT-VALUE
+ |(FAST-METHOD RAW-INSTANCE-ALLOCATOR (FUNCALLABLE-STANDARD-CLASS))|
+ DECLARE-STRUCTURE OPTIMIZE-SLOT-BOUNDP PRINT-CACHE
+ FIRST-FORM-TO-LISP ITERATE::OPTIMIZE-ITERATE-FORM
+ WRAP-METHOD-GROUP-SPECIFIER-BINDINGS MAKE-TOP-LEVEL-FORM
+ INVALIDATE-WRAPPER STANDARD-COMPUTE-EFFECTIVE-METHOD
+ MAKE-OPTIMIZED-STD-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ MAKE-OPTIMIZED-STD-SETF-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ MAKE-OPTIMIZED-STD-SLOT-BOUNDP-USING-CLASS-METHOD-FUNCTION
+ WALKER::RECONS ITERATE::OPTIMIZE-GATHERING-FORM
+ WALKER::WALK-MULTIPLE-VALUE-SETQ
+ |(FAST-METHOD CLASS-CONSTRUCTORS (SLOT-CLASS))|
+ |(FAST-METHOD CLASS-SLOT-CELLS (STD-CLASS))|
+ |(FAST-METHOD SPECIALIZER-CLASS (CLASS))|
+ |(FAST-METHOD SPECIALIZER-CLASS (EQL-SPECIALIZER))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-METHODS (CLASS))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-GENERIC-FUNCTIONS (CLASS))|
+ |(FAST-METHOD GENERIC-FUNCTION-PRETTY-ARGLIST (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD SPECIALIZER-METHOD-TABLE (EQL-SPECIALIZER))|
+ |(FAST-METHOD SPECIALIZER-METHOD-TABLE (CLASS-EQ-SPECIALIZER))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-METHODS (SPECIALIZER-WITH-OBJECT))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-GENERIC-FUNCTIONS (SPECIALIZER-WITH-OBJECT))|
+ VARIABLE-DECLARATION
+ |(FAST-METHOD CLASS-PREDICATE-NAME (T))|
+ |(FAST-METHOD INITIALIZE-INTERNAL-SLOT-FUNCTIONS (EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-DEFINITION-ALLOCATION (STRUCTURE-SLOT-DEFINITION))|
+ |(FAST-METHOD FINALIZE-INHERITANCE (STRUCTURE-CLASS))|
+ |(FAST-METHOD FINALIZE-INHERITANCE (STD-CLASS))|
+ |(FAST-METHOD COMPUTE-DEFAULT-INITARGS (SLOT-CLASS))|
+ |(FAST-METHOD CLASS-FINALIZED-P (PCL-CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS (STD-CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS :AROUND (STD-CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS (STRUCTURE-CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS :AROUND (STRUCTURE-CLASS))|
+ |(FAST-METHOD CLASS-DIRECT-DEFAULT-INITARGS (SLOT-CLASS))|
+ |(FAST-METHOD CLASS-DEFAULT-INITARGS (SLOT-CLASS))|
+ ITERATE::SIMPLE-EXPAND-GATHERING-FORM
+ ITERATE::RENAME-AND-CAPTURE-VARIABLES
+ ITERATE::VARIABLE-SAME-P GET-FUNCTION-GENERATOR
+ GET-NEW-FUNCTION-GENERATOR TRACE-METHOD-INTERNAL
+ ONE-INDEX-DFUN-INFO ONE-CLASS-DFUN-INFO MAP-ALL-ORDERS
+ NOTE-PV-TABLE-REFERENCE WALKER::RELIST-INTERNAL
+ MAKE-DFUN-CALL WALKER::WALK-TAGBODY-1 WALKER::WALK-LAMBDA
+ OPTIMIZE-GF-CALL-INTERNAL WALKER::WALK-COMPILER-LET
+ |(FAST-METHOD MAKE-INSTANCES-OBSOLETE (STD-CLASS))|
+ SKIP-FAST-SLOT-ACCESS-P WALKER::WALK-UNEXPECTED-DECLARE
+ WALKER::WALK-FLET WALKER::WALK-IF WALKER::WALK-LABELS
+ WALKER::WALK-LET WALKER::WALK-LET* WALKER::WALK-LOCALLY
+ |(FAST-METHOD CLASS-DIRECT-SLOTS (BUILT-IN-CLASS))|
+ WALKER::WALK-MACROLET
+ |(FAST-METHOD CLASS-SLOTS (BUILT-IN-CLASS))|
+ |(FAST-METHOD CLASS-DIRECT-DEFAULT-INITARGS (BUILT-IN-CLASS))|
+ FIX-SLOT-ACCESSORS
+ |(FAST-METHOD WRAPPER-FETCHER (STANDARD-CLASS))|
+ WALKER::WALK-MULTIPLE-VALUE-BIND
+ |(FAST-METHOD CLASS-DEFAULT-INITARGS (BUILT-IN-CLASS))|
+ WALKER::WALK-SETQ
+ |(FAST-METHOD SLOTS-FETCHER (STANDARD-CLASS))|
+ WALKER::WALK-SYMBOL-MACROLET
+ |(FAST-METHOD RAW-INSTANCE-ALLOCATOR (STANDARD-CLASS))|
+ EMIT-SLOT-READ-FORM WALKER::WALK-TAGBODY EMIT-BOUNDP-CHECK
+ WALKER::WALK-DO WALKER::WALK-DO* WALKER::WALK-PROG
+ WALKER::WALK-NAMED-LAMBDA WALKER::WALK-PROG*
+ EXPAND-DEFGENERIC EMIT-GREATER-THAN-1-DLAP EMIT-1-T-DLAP
+ MAKE-METHOD-INITARGS-FORM-INTERNAL ENTRY-IN-CACHE-P
+ CONVERT-TABLE MAKE-METHOD-SPEC TRACE-EMF-CALL-INTERNAL
+ FLUSH-CACHE-TRAP SET-FUNCTION-NAME-1 OBSOLETE-INSTANCE-TRAP
+ COMPUTE-PRECEDENCE PRINT-STD-INSTANCE
+ |SETF PCL METHOD-FUNCTION-GET| |SETF PCL PLIST-VALUE|
+ WALKER::WITH-AUGMENTED-ENVIRONMENT-INTERNAL
+ |(FAST-METHOD ACCESSOR-METHOD-CLASS (STANDARD-ACCESSOR-METHOD))|
+ |(FAST-METHOD ACCESSOR-METHOD-CLASS (STANDARD-WRITER-METHOD))|
+ INITIALIZE-INTERNAL-SLOT-GFS*
+ |(FAST-METHOD METHOD-QUALIFIERS (STANDARD-METHOD))|
+ SKIP-OPTIMIZE-SLOT-VALUE-BY-CLASS-P
+ |(FAST-METHOD GENERIC-FUNCTION-LAMBDA-LIST (GENERIC-FUNCTION))|
+ |(FAST-METHOD GF-FAST-METHOD-FUNCTION-P (STANDARD-GENERIC-FUNCTION))|
+ COMPUTE-EFFECTIVE-METHOD SORT-APPLICABLE-METHODS
+ SORT-METHODS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T) T)
+ |(FAST-METHOD SLOT-UNBOUND (T T T))|
+ |(FAST-METHOD FIND-METHOD-COMBINATION (GENERIC-FUNCTION (EQL STANDARD) T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-METHOD (GENERIC-FUNCTION SHORT-METHOD-COMBINATION T))|
+ LOAD-FUNCTION-GENERATOR EXPAND-EMF-CALL-METHOD MAKE-FGEN
+ BOOTSTRAP-MAKE-SLOT-DEFINITIONS
+ BOOTSTRAP-ACCESSOR-DEFINITIONS1
+ MAKE-FINAL-ORDINARY-DFUN-INTERNAL
+ WALKER::WALK-TEMPLATE-HANDLE-REPEAT COMPUTE-PV-SLOT
+ WALKER::WALK-BINDINGS-1 OPTIMIZE-INSTANCE-ACCESS
+ OPTIMIZE-ACCESSOR-CALL MAKE-METHOD-INITARGS-FORM-INTERNAL1
+ UPDATE-SLOTS-IN-PV MAKE-PARAMETER-REFERENCES MAKE-EMF-CACHE
+ GET-MAKE-INSTANCE-FUNCTION-INTERNAL
+ |(FAST-METHOD (SETF SLOT-ACCESSOR-STD-P) (T EFFECTIVE-SLOT-DEFINITION T))|
+ MAKE-INSTANCE-FUNCTION-COMPLEX
+ |(FAST-METHOD ENSURE-CLASS-USING-CLASS (T NULL))|
+ MAKE-INSTANCE-FUNCTION-SIMPLE
+ |(FAST-METHOD ENSURE-CLASS-USING-CLASS (T PCL-CLASS))|
+ OPTIMIZE-GENERIC-FUNCTION-CALL
+ REAL-MAKE-METHOD-INITARGS-FORM
+ |(FAST-METHOD COMPUTE-SLOT-ACCESSOR-INFO (EFFECTIVE-SLOT-DEFINITION T T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STD-CLASS T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (DOCUMENTATION-MIXIN T))|
+ |(FAST-METHOD (SETF DOCUMENTATION) (T T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STRUCTURE-CLASS T))|
+ |(FAST-METHOD (SETF DOCUMENTATION) (T DOCUMENTATION-MIXIN))|
+ |(FAST-METHOD READER-METHOD-CLASS (SLOT-CLASS T))|
+ |(FAST-METHOD WRITER-METHOD-CLASS (SLOT-CLASS T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (BUILT-IN-CLASS T))|
+ |(FAST-METHOD SLOT-BOUNDP-USING-CLASS (STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-MAKUNBOUND-USING-CLASS (STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STRUCTURE-SLOT-DEFINITION T))|
+ |(FAST-METHOD SLOT-BOUNDP-USING-CLASS (STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-MAKUNBOUND-USING-CLASS (STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (STANDARD-ACCESSOR-METHOD T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STANDARD-METHOD T))|
+ |(FAST-METHOD REMOVE-NAMED-METHOD (T T))|))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T *) T) MAKE-EFFECTIVE-METHOD-FUNCTION-SIMPLE
+ MAKE-EMF-FROM-METHOD EXPAND-EFFECTIVE-METHOD-FUNCTION
+ NAMED-OBJECT-PRINT-FUNCTION FIND-CLASS-FROM-CELL
+ FIND-CLASS-PREDICATE-FROM-CELL INITIALIZE-INFO
+ GET-EFFECTIVE-METHOD-FUNCTION1 GET-DECLARATION
+ GET-METHOD-FUNCTION-PV-CELL EMIT-MISS METHOD-FUNCTION-GET
+ PROBE-CACHE MAP-CACHE PRECOMPUTE-EFFECTIVE-METHODS
+ RECORD-DEFINITION WALKER::CONVERT-MACRO-TO-LAMBDA CPL-ERROR
+ REAL-ADD-METHOD
+ REAL-ENSURE-GF-USING-CLASS--GENERIC-FUNCTION
+ REAL-ENSURE-GF-USING-CLASS--NULL
+ COMPUTE-SECONDARY-DISPATCH-FUNCTION1
+ ENSURE-GENERIC-FUNCTION-USING-CLASS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T) T) REAL-LOAD-DEFCLASS
+ WALKER::WALK-TEMPLATE-HANDLE-REPEAT-1
+ BOOTSTRAP-MAKE-SLOT-DEFINITION EMIT-SLOT-ACCESS
+ OPTIMIZE-GF-CALL SET-ARG-INFO1 LOAD-DEFCLASS
+ MAKE-EARLY-CLASS-DEFINITION
+ |(FAST-METHOD (SETF SLOT-VALUE-USING-CLASS) (T STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T) T)
+ |(FAST-METHOD SLOT-MISSING (T T T T))| EXPAND-DEFMETHOD
+ LOAD-DEFMETHOD-INTERNAL))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T FIXNUM) T) GET-CACHE
+ FILL-CACHE-FROM-CACHE-P))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T *) T) EMIT-DLAP
+ GET-SECONDARY-DISPATCH-FUNCTION1))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T *) T) CHECK-INITARGS-2-PLIST
+ CHECK-INITARGS-2-LIST WALKER::WALK-ARGLIST MAKE-EMF-CALL
+ CAN-OPTIMIZE-ACCESS1 EMIT-FETCH-WRAPPER FILL-CACHE
+ REAL-GET-METHOD CHECK-INITARGS-1 GET-METHOD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T *) T) LOAD-DEFMETHOD
+ MAKE-DEFMETHOD-FORM MAKE-DEFMETHOD-FORM-INTERNAL
+ EARLY-MAKE-A-METHOD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T *) T) FILL-DFUN-CACHE
+ EARLY-ADD-NAMED-METHOD REAL-ADD-NAMED-METHOD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T T) T)
+ GET-SECONDARY-DISPATCH-FUNCTION2))
+(PROCLAIM '(FTYPE (FUNCTION (T T FIXNUM) T) COMPUTE-STD-CPL-PHASE-3))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T T T *) T)
+ BOOTSTRAP-INITIALIZE-CLASS))
+(PROCLAIM
+ '(FTYPE (FUNCTION NIL *) COUNT-ALL-DFUNS EMIT-N-N-READERS
+ EMIT-N-N-WRITERS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (*) *) UNTRACE-METHOD LIST-LARGE-CACHES
+ UPDATE-MAKE-INSTANCE-FUNCTION-TABLE INVALID-METHOD-ERROR
+ METHOD-COMBINATION-ERROR))
+(PROCLAIM
+ '(FTYPE (FUNCTION NIL T) RENEW-SYS-FILES
+ GET-EFFECTIVE-METHOD-GENSYM SHOW-EMF-CALL-TRACE
+ BOOTSTRAP-META-BRAID BOOTSTRAP-BUILT-IN-CLASSES
+ LIST-ALL-DFUNS DEFAULT-METHOD-ONLY-DFUN-INFO
+ INITIALIZE-CHECKING-OR-CACHING-FUNCTION-LIST
+ CACHES-TO-ALLOCATE UPDATE-DISPATCH-DFUNS MAKE-CACHE
+ IN-THE-COMPILER-P STRUCTURE-FUNCTIONS-EXIST-P
+ ALLOCATE-FUNCALLABLE-INSTANCE-2 %%ALLOCATE-INSTANCE--CLASS
+ ALLOCATE-FUNCALLABLE-INSTANCE-1 DISPATCH-DFUN-INFO
+ INITIAL-DISPATCH-DFUN-INFO INITIAL-DFUN-INFO
+ NO-METHODS-DFUN-INFO SHOW-FREE-CACHE-VECTORS MAKE-CPD
+ MAKE-ARG-INFO SHOW-DFUN-CONSTRUCTORS))
+(PROCLAIM '(FTYPE (FUNCTION (FIXNUM T T) *) COMPUTE-CACHE-PARAMETERS))
+(PROCLAIM '(FTYPE (FUNCTION (FIXNUM T *) *) FIND-FREE-CACHE-LINE))
+(PROCLAIM
+ '(FTYPE (FUNCTION (*) T) |__si::MAKE-DFUN-INFO|
+ |__si::MAKE-NO-METHODS| |__si::MAKE-INITIAL|
+ |__si::MAKE-INITIAL-DISPATCH| |__si::MAKE-DISPATCH|
+ |__si::MAKE-DEFAULT-METHOD-ONLY|
+ |__si::MAKE-ACCESSOR-DFUN-INFO|
+ |__si::MAKE-ONE-INDEX-DFUN-INFO| MAKE-FAST-METHOD-CALL
+ |__si::MAKE-N-N| MAKE-FAST-INSTANCE-BOUNDP
+ |__si::MAKE-ONE-CLASS| |__si::MAKE-TWO-CLASS|
+ |__si::MAKE-ONE-INDEX| |__si::MAKE-CHECKING|
+ |__si::MAKE-ARG-INFO| FIX-EARLY-GENERIC-FUNCTIONS
+ STRING-APPEND |__si::MAKE-CACHING|
+ |__si::MAKE-CONSTANT-VALUE| FALSE
+ |STRUCTURE-OBJECT class constructor|
+ PV-WRAPPERS-FROM-PV-ARGS MAKE-PV-TABLE
+ |__si::MAKE-PV-TABLE| INTERN-PV-TABLE
+ CALLED-FIN-WITHOUT-FUNCTION |__si::MAKE-STD-INSTANCE|
+ MAKE-INITIALIZE-INFO |__si::MAKE-CACHE| MAKE-PROGN
+ WALKER::UNBOUND-LEXICAL-FUNCTION
+ |__si::MAKE-CLASS-PRECEDENCE-DESCRIPTION| MAKE-METHOD-CALL
+ TRUE USE-PACKAGE-PCL ZERO))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) *) TYPE-FROM-SPECIALIZER *NORMALIZE-TYPE
+ DEFAULT-CODE-CONVERTER CONVERT-TO-SYSTEM-TYPE
+ EMIT-CONSTANT-VALUE PCL-DESCRIBE GET-GENERIC-FUNCTION-INFO
+ EARLY-METHOD-FUNCTION
+ EARLY-METHOD-STANDARD-ACCESSOR-SLOT-NAME
+ SPECIALIZER-FROM-TYPE CLASS-EQ-TYPE STRUCTURE-WRAPPER
+ FIND-STRUCTURE-CLASS MAKE-DISPATCH-DFUN FIND-WRAPPER
+ PARSE-DEFMETHOD PROTOTYPES-FOR-MAKE-METHOD-LAMBDA
+ EMIT-ONE-CLASS-READER EMIT-ONE-CLASS-WRITER
+ EMIT-TWO-CLASS-READER EMIT-TWO-CLASS-WRITER
+ EMIT-ONE-INDEX-READERS EMIT-ONE-INDEX-WRITERS
+ NET-CODE-CONVERTER EMIT-IN-CHECKING-CACHE-P
+ COMPILE-IIS-FUNCTIONS ANALYZE-LAMBDA-LIST
+ COMPUTE-APPLICABLE-METHODS-EMF GET-DISPATCH-FUNCTION
+ GENERIC-FUNCTION-NAME-P MAKE-FINAL-DISPATCH-DFUN
+ STRUCTURE-SLOTD-INIT-FORM PARSE-METHOD-GROUP-SPECIFIER
+ METHOD-PROTOTYPE-FOR-GF EARLY-COLLECT-INHERITANCE))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T FIXNUM *) T) GET-CACHE-FROM-CACHE
+ COMPUTE-PRIMARY-CACHE-LOCATION-FROM-LOCATION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) T) COMPILE-LAMBDA-UNCOMPILED GF-LAMBDA-LIST
+ CACHING-CACHE CONSTANT-VALUE-CACHE COMPILE-LAMBDA-DEFERRED
+ FUNCALLABLE-INSTANCE-P SHOW-DFUN-COSTS
+ RESET-CLASS-INITIALIZE-INFO GET-CACHE-VECTOR
+ CONSTANT-SYMBOL-P FREE-CACHE-VECTOR
+ EARLY-METHOD-LAMBDA-LIST ARG-INFO-VALID-P DFUN-ARG-SYMBOL
+ EARLY-METHOD-CLASS EARLY-GF-P EARLY-GF-NAME
+ CACHING-DFUN-INFO COMPUTE-APPLICABLE-METHODS-EMF-STD-P
+ CONSTANT-VALUE-DFUN-INFO RESET-CLASS-INITIALIZE-INFO-1
+ FREE-CACHE PARSE-SPECIALIZERS RESET-INITIALIZE-INFO
+ EARLY-METHOD-QUALIFIERS PROCLAIM-INCOMPATIBLE-SUPERCLASSES
+ WRAPPER-OF EARLY-METHOD-STANDARD-ACCESSOR-P
+ FUNCTION-PRETTY-ARGLIST GET-MAKE-INSTANCE-FUNCTION
+ CHECK-WRAPPER-VALIDITY UNPARSE-SPECIALIZERS
+ %SYMBOL-FUNCTION FINAL-ACCESSOR-DFUN-TYPE
+ COMPLICATED-INSTANCE-CREATION-METHOD DEFAULT-STRUCTUREP
+ UPDATE-GF-INFO CACHE-OWNER DEFAULT-STRUCTURE-INSTANCE-P
+ DEFAULT-STRUCTURE-TYPE STRUCTURE-TYPE
+ COMPUTE-STD-CPL-PHASE-2 GET-PV-CELL-FOR-CLASS
+ STRUCTURE-TYPE-INCLUDED-TYPE-NAME
+ STRUCTURE-TYPE-SLOT-DESCRIPTION-LIST CACHE-P
+ STRUCTURE-SLOTD-NAME STRUCTURE-SLOTD-ACCESSOR-SYMBOL SFUN-P
+ DEFAULT-SECONDARY-DISPATCH-FUNCTION
+ STRUCTURE-SLOTD-WRITER-FUNCTION FIND-CYCLE-REASONS
+ EARLY-CLASS-DEFINITION ECD-SOURCE STRUCTURE-SLOTD-TYPE
+ FORMAT-CYCLE-REASONS ECD-METACLASS CPD-CLASS
+ EARLY-CLASS-PRECEDENCE-LIST
+ METHODS-CONTAIN-EQL-SPECIALIZER-P MAKE-TYPE-PREDICATE
+ CPD-SUPERS DEFAULT-TEST-CONVERTER EXPAND-LONG-DEFCOMBIN
+ INITIAL-P EARLY-CLASS-NAME-OF FORCE-CACHE-FLUSHES CPD-AFTER
+ EXPAND-SHORT-DEFCOMBIN MAKE-CALL-METHODS
+ DEFAULT-CONSTANT-CONVERTER EARLY-CLASS-SLOTDS
+ INITIAL-DISPATCH-P DISPATCH-P EARLY-SLOT-DEFINITION-NAME
+ SLOT-READER-SYMBOL GBOUNDP GMAKUNBOUND
+ EARLY-SLOT-DEFINITION-LOCATION WALKER::ENV-LOCK
+ DEFAULT-CONSTANTP MAKE-INITIAL-DFUN DEFAULT-METHOD-ONLY-P
+ FGEN-TEST EARLY-ACCESSOR-METHOD-SLOT-NAME
+ SLOT-WRITER-SYMBOL LOOKUP-FGEN WALKER::ENV-DECLARATIONS
+ ACCESSOR-DFUN-INFO-P WALKER::ENV-LEXICAL-VARIABLES
+ FGEN-GENERATOR FGEN-SYSTEM LIST-DFUN %FBOUNDP
+ SLOT-BOUNDP-SYMBOL ONE-INDEX-DFUN-INFO-P CCLOSUREP
+ MAP-ALL-GENERIC-FUNCTIONS FAST-METHOD-CALL-P
+ MAKE-STRUCTURE-SLOT-BOUNDP-FUNCTION N-N-P
+ EARLY-CLASS-DIRECT-SUBCLASSES FAST-INSTANCE-BOUNDP-P
+ MAKE-FUNCTION-INLINE METHOD-FUNCTION-PV-TABLE
+ LIST-LARGE-CACHE METHOD-FUNCTION-METHOD STORE-FGEN
+ CLASS-PRECEDENCE-DESCRIPTION-P ONE-CLASS-P
+ INFORM-TYPE-SYSTEM-ABOUT-STD-CLASS
+ UNENCAPSULATED-FDEFINITION
+ MAKE-DEFAULT-METHOD-GROUP-DESCRIPTION
+ METHOD-FUNCTION-NEEDS-NEXT-METHODS-P DFUN-INFO-P
+ MAKE-OPTIMIZED-STRUCTURE-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ FTYPE-DECLARATION-FROM-LAMBDA-LIST NO-METHODS-P
+ WALKER::ENV-WALK-FUNCTION FGEN-GENSYMS
+ WALKER::GET-IMPLEMENTATION-DEPENDENT-WALKER-TEMPLATE
+ TWO-CLASS-P COUNT-DFUN ARG-INFO-LAMBDA-LIST
+ MAKE-INITFUNCTION ARG-INFO-PRECEDENCE
+ MAKE-OPTIMIZED-STRUCTURE-SETF-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ ARG-INFO-METATYPES ITERATE::VARIABLES-FROM-LET
+ FGEN-GENERATOR-LAMBDA WALKER::ENV-WALK-FORM
+ ARG-INFO-NUMBER-OPTIONAL
+ MAKE-OPTIMIZED-STRUCTURE-SLOT-BOUNDP-USING-CLASS-METHOD-FUNCTION
+ ARG-INFO-KEY/REST-P INITIALIZE-INFO-P ONE-INDEX-P
+ ECD-CLASS-NAME ARG-INFO-KEYWORDS COPY-CACHE
+ GF-INFO-SIMPLE-ACCESSOR-TYPE COMPUTE-LINE-SIZE
+ GF-PRECOMPUTE-DFUN-AND-EMF-P CANONICAL-SLOT-NAME
+ GF-INFO-STATIC-C-A-M-EMF WALKER::GET-WALKER-TEMPLATE
+ CHECKING-P EARLY-CLASS-SLOTS GF-INFO-C-A-M-EMF-STD-P
+ STRUCTURE-TYPE-INTERNAL-SLOTDS GF-INFO-FAST-MF-P
+ UNDEFMETHOD-1 EARLY-COLLECT-CPL EARLY-COLLECT-SLOTS
+ ARG-INFO-P METHOD-LL->GENERIC-FUNCTION-LL
+ FAST-METHOD-CALL-ARG-INFO EARLY-COLLECT-DEFAULT-INITARGS
+ ARG-INFO-NKEYS ECD-SUPERCLASS-NAMES GF-DFUN-CACHE
+ GF-DFUN-INFO METHOD-CALL-P STRUCTURE-SLOT-BOUNDP
+ FUNCTION-RETURNING-NIL ITERATE::SEQUENCE-ACCESSOR
+ ACCESSOR-DFUN-INFO-ACCESSOR-TYPE ECD-CANONICAL-SLOTS
+ EVAL-FORM ONE-INDEX-DFUN-INFO-INDEX ECD-OTHER-INITARGS
+ SLOT-INITARGS-FROM-STRUCTURE-SLOTD TYPE-CLASS
+ ONE-CLASS-WRAPPER0 EXTRACT-PARAMETERS CLASS-PREDICATE
+ EXTRACT-REQUIRED-PARAMETERS MAKE-CLASS-EQ-PREDICATE
+ TWO-CLASS-WRAPPER1 MAKE-EQL-PREDICATE CHECKING-FUNCTION
+ BOOTSTRAP-ACCESSOR-DEFINITIONS INITIALIZE-INFO-KEY
+ BOOTSTRAP-CLASS-PREDICATES GET-BUILT-IN-CLASS-SYMBOL
+ INITIALIZE-INFO-WRAPPER GET-BUILT-IN-WRAPPER-SYMBOL
+ DO-STANDARD-DEFSETF-1 CACHING-P GFS-OF-TYPE
+ LEGAL-CLASS-NAME-P STRUCTURE-TYPE-P CONSTANT-VALUE-P
+ USE-DEFAULT-METHOD-ONLY-DFUN-P
+ INITIALIZE-INFO-CACHED-COMBINED-INITARGS-FORM-LIST
+ WRAPPER-FIELD NEXT-WRAPPER-FIELD SETFBOUNDP
+ GET-SETF-FUNCTION-NAME USE-CACHING-DFUN-P
+ MAKE-PV-TYPE-DECLARATION MAKE-CALLS-TYPE-DECLARATION
+ MAP-SPECIALIZERS SLOT-VECTOR-SYMBOL MAKE-PERMUTATION-VECTOR
+ VARIABLE-GLOBALLY-SPECIAL-P STRUCTURE-OBJECT-P
+ EXPAND-MAKE-INSTANCE-FORM MAKE-CONSTANT-FUNCTION
+ FUNCTION-RETURNING-T SORT-SLOTS SORT-CALLS SYMBOL-PKG-NAME
+ CLASS-HAS-A-FORWARD-REFERENCED-SUPERCLASS-P
+ INITIALIZE-INFO-BOUND-SLOTS INITIALIZE-INFO-CACHED-VALID-P
+ GET-MAKE-INSTANCE-FUNCTIONS
+ INITIALIZE-INFO-CACHED-RI-VALID-P
+ INITIALIZE-INFO-CACHED-INITARGS-FORM-LIST
+ INITIALIZE-INFO-CACHED-NEW-KEYS UPDATE-C-A-M-GF-INFO
+ INITIALIZE-INFO-CACHED-DEFAULT-INITARGS-FUNCTION
+ UPDATE-GF-SIMPLE-ACCESSOR-TYPE UPDATE-GFS-OF-CLASS
+ INITIALIZE-INFO-CACHED-SHARED-INITIALIZE-T-FUNCTION
+ DO-STANDARD-DEFSETFS-FOR-DEFCLASS STANDARD-SVUC-METHOD
+ INITIALIZE-INFO-CACHED-SHARED-INITIALIZE-NIL-FUNCTION
+ %CCLOSURE-ENV STRUCTURE-SVUC-METHOD
+ INITIALIZE-INFO-CACHED-CONSTANTS CLASS-OF
+ METHOD-FUNCTION-PLIST
+ INITIALIZE-INFO-CACHED-COMBINED-INITIALIZE-FUNCTION
+ INITIALIZE-INFO-CACHED-MAKE-INSTANCE-FUNCTION
+ INITIALIZE-INFO-CACHED-MAKE-INSTANCE-FUNCTION-SYMBOL
+ INTERNED-SYMBOL-P GDEFINITION UPDATE-CLASS-CAN-PRECEDE-P
+ %STD-INSTANCE-WRAPPER %STD-INSTANCE-SLOTS PV-TABLEP
+ STD-INSTANCE-P COMPUTE-MCASE-PARAMETERS COMPUTE-CLASS-SLOTS
+ MAKE-PV-TABLE-TYPE-DECLARATION INTERN-EQL-SPECIALIZER
+ NET-TEST-CONVERTER MAKE-INSTANCE-FUNCTION-SYMBOL
+ UPDATE-ALL-C-A-M-GF-INFO UPDATE-PV-TABLE-CACHE-INFO
+ DFUN-INFO-CACHE EXTRACT-LAMBDA-LIST NO-METHODS-CACHE
+ ARG-INFO-APPLYP CACHING-DFUN-COST INITIAL-CACHE
+ SYSTEM:%STRUCTURE-NAME INITIAL-DISPATCH-CACHE
+ SYSTEM:%COMPILED-FUNCTION-NAME CHECK-CACHE DISPATCH-CACHE
+ CLASS-FROM-TYPE DEFAULT-METHOD-ONLY-CACHE DNET-METHODS-P
+ ACCESSOR-DFUN-INFO-CACHE METHOD-FUNCTION-FROM-FAST-FUNCTION
+ ONE-INDEX-DFUN-INFO-CACHE ONE-INDEX-DFUN-INFO-ACCESSOR-TYPE
+ METHOD-CALL-CALL-METHOD-ARGS KEYWORD-SPEC-NAME N-N-CACHE
+ GENERIC-CLOBBERS-FUNCTION N-N-ACCESSOR-TYPE
+ FAST-METHOD-CALL-PV-CELL WRAPPER-FOR-STRUCTURE
+ ONE-CLASS-CACHE EXTRACT-SPECIALIZER-NAMES
+ FAST-METHOD-CALL-NEXT-METHOD-CALL ONE-CLASS-ACCESSOR-TYPE
+ ONE-CLASS-INDEX BUILT-IN-WRAPPER-OF TWO-CLASS-CACHE
+ BUILT-IN-OR-STRUCTURE-WRAPPER1 TWO-CLASS-ACCESSOR-TYPE
+ TWO-CLASS-INDEX GET-MAKE-INSTANCE-FUNCTION-SYMBOL
+ ALLOCATE-CACHE-VECTOR TWO-CLASS-WRAPPER0
+ FLUSH-CACHE-VECTOR-INTERNAL ONE-INDEX-CACHE
+ EARLY-CLASS-NAME ONE-INDEX-ACCESSOR-TYPE ONE-INDEX-INDEX
+ INTERN-FUNCTION-NAME CHECKING-CACHE))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T *) *) COERCE-TO-CLASS GET-METHOD-FUNCTION
+ GET-FUNCTION GET-FUNCTION1 PARSE-METHOD-OR-SPEC
+ EXTRACT-DECLARATIONS GET-DFUN-CONSTRUCTOR MAP-ALL-CLASSES
+ MAKE-CACHING-DFUN MAKE-METHOD-FUNCTION-INTERNAL
+ PARSE-SPECIALIZED-LAMBDA-LIST MAKE-METHOD-LAMBDA-INTERNAL
+ MAKE-CONSTANT-VALUE-DFUN MAKE-FINAL-DFUN-INTERNAL
+ COMPILE-LAMBDA WALK-FORM MACROEXPAND-ALL ENSURE-CLASS
+ ENSURE-GENERIC-FUNCTION DISPATCH-DFUN-COST))
+(PROCLAIM '(FTYPE (FUNCTION (T T *) (VALUES T T)) SYMBOL-APPEND))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T *) T) CAPITALIZE-WORDS
+ INITIALIZE-INTERNAL-SLOT-GFS FIND-CLASS
+ MAKE-TYPE-PREDICATE-NAME SET-DFUN TRACE-METHOD
+ FIND-CLASS-CELL MAKE-FINAL-DFUN PV-TABLE-LOOKUP-PV-ARGS
+ USE-DISPATCH-DFUN-P WALKER::RELIST* WALKER::RELIST
+ FIND-CLASS-PREDICATE EARLY-METHOD-SPECIALIZERS
+ USE-CONSTANT-VALUE-DFUN-P MAKE-EARLY-GF
+ ALLOCATE-FUNCALLABLE-INSTANCE SET-ARG-INFO
+ INITIALIZE-METHOD-FUNCTION UPDATE-DFUN MAKE-SPECIALIZABLE
+ ALLOCATE-STRUCTURE-INSTANCE ALLOCATE-STANDARD-INSTANCE
+ WALKER::WALKER-ENVIRONMENT-BIND-1
+ ITERATE::FUNCTION-LAMBDA-P ITERATE::MAYBE-WARN
+ MAKE-WRAPPER))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T) *) SLOT-BOUNDP SLOT-VALUE SAUT-CLASS
+ SPECIALIZER-APPLICABLE-USING-TYPE-P COMPUTE-TEST
+ GET-NEW-FUNCTION-GENERATOR-INTERNAL COMPUTE-CODE
+ CLASS-APPLICABLE-USING-CLASS-P SAUT-AND SAUT-NOT
+ SAUT-PROTOTYPE DESTRUCTURE ENSURE-CLASS-VALUES
+ MAKE-DIRECT-SLOTD SLOT-MAKUNBOUND
+ MAKE-INSTANCE-FUNCTION-TRAP
+ GENERATE-FAST-CLASS-SLOT-ACCESS-P MUTATE-SLOTS-AND-CALLS
+ INVOKE-EMF EMIT-DEFAULT-ONLY-FUNCTION SPLIT-DECLARATIONS
+ EMIT-DEFAULT-ONLY SLOT-NAME-LISTS-FROM-SLOTS EMIT-CHECKING
+ UPDATE-SLOT-VALUE-GF-INFO EMIT-CACHING SDFUN-FOR-CACHING
+ SLOT-UNBOUND-INTERNAL MAKE-INSTANCE-1 SET-FUNCTION-NAME
+ COMPUTE-STD-CPL-PHASE-1 FORM-LIST-TO-LISP
+ FIND-SUPERCLASS-CHAIN SAUT-CLASS-EQ
+ COMPUTE-APPLICABLE-METHODS-USING-TYPES
+ CHECK-INITARGS-VALUES SAUT-EQL INSURE-DFUN *SUBTYPEP
+ ITERATE::PARSE-DECLARATIONS INITIAL-DFUN))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T) T) ADD-METHOD DO-SATISFIES-DEFTYPE
+ MEMF-CONSTANT-CONVERTER COMPUTE-CONSTANTS
+ CLASS-CAN-PRECEDE-P SAUT-NOT-CLASS SAUT-NOT-CLASS-EQ
+ SAUT-NOT-PROTOTYPE GF-MAKE-FUNCTION-FROM-EMF SAUT-NOT-EQL
+ SUPERCLASSES-COMPATIBLE-P CLASSES-HAVE-COMMON-SUBCLASS-P
+ DESCRIBE-PACKAGE PRINTING-RANDOM-THING-INTERNAL
+ MAKE-CLASS-PREDICATE METHOD-FUNCTION-RETURNING-NIL
+ METHOD-FUNCTION-RETURNING-T VARIABLE-CLASS MAKE-PLIST
+ REMTAIL DESTRUCTURE-INTERNAL ACCESSOR-MISS-FUNCTION
+ UPDATE-INITIALIZE-INFO-INTERNAL N-N-DFUN-INFO MAKE-CAXR
+ MAKE-CDXR CHECKING-DFUN-INFO
+ FUNCALLABLE-STANDARD-INSTANCE-ACCESS MAKE-PV-TABLE-INTERNAL
+ FIND-SLOT-DEFINITION WALKER::WALK-REPEAT-EVAL
+ WALKER::NOTE-DECLARATION MAKE-DFUN-LAMBDA-LIST
+ WALKER::NOTE-LEXICAL-BINDING MAKE-DLAP-LAMBDA-LIST
+ ADD-DIRECT-SUBCLASSES COMPUTE-PV MAKE-DFUN-ARG-LIST
+ COMPUTE-CALLS MAKE-FAST-METHOD-CALL-LAMBDA-LIST
+ UPDATE-ALL-PV-TABLE-CACHES UPDATE-CLASS
+ MAP-PV-TABLE-REFERENCES-OF ADD-SLOT-ACCESSORS
+ WALKER::ENVIRONMENT-FUNCTION REMOVE-DIRECT-SUBCLASSES
+ REMOVE-SLOT-ACCESSORS SYMBOL-LESSP SYMBOL-OR-CONS-LESSP
+ |SETF PCL FIND-CLASS| |SETF PCL FIND-CLASS-PREDICATE|
+ PV-WRAPPERS-FROM-ALL-ARGS PV-TABLE-LOOKUP
+ PROCLAIM-DEFGENERIC UPDATE-CPL LIST-EQ UPDATE-SLOTS
+ COMPUTE-APPLICABLE-METHODS-FUNCTION VARIABLE-LEXICAL-P
+ VARIABLE-SPECIAL-P UPDATE-INITS UPDATE-STD-OR-STR-METHODS
+ SET-STANDARD-SVUC-METHOD EMIT-1-NIL-DLAP PLIST-VALUE
+ SET-STRUCTURE-SVUC-METHOD
+ EMIT-1-WRAPPER-COMPUTE-PRIMARY-CACHE-LOCATION
+ MEC-ALL-CLASSES-INTERNAL
+ EMIT-N-WRAPPER-COMPUTE-PRIMARY-CACHE-LOCATION
+ MEC-ALL-CLASSES %SET-CCLOSURE-ENV MEC-ALL-CLASS-LISTS
+ REDEFINE-FUNCTION METHODS-CONVERTER COMPUTE-LAYOUT NO-SLOT
+ PV-WRAPPERS-FROM-ALL-WRAPPERS NET-CONSTANT-CONVERTER
+ AUGMENT-TYPE CHANGE-CLASS-INTERNAL VALUE-FOR-CACHING
+ |SETF PCL METHOD-FUNCTION-PLIST| GET-KEY-ARG GET-KEY-ARG1
+ SET-METHODS SET-FUNCTION-PRETTY-ARGLIST
+ FIND-STANDARD-II-METHOD MAKE-EARLY-ACCESSOR
+ DOCTOR-DFUN-FOR-THE-DEBUGGER COMPUTE-STD-CPL
+ |SETF PCL GDEFINITION| MAKE-DISCRIMINATING-FUNCTION-ARGLIST
+ ADD-FORMS CPL-INCONSISTENT-ERROR
+ REDIRECT-EARLY-FUNCTION-INTERNAL ADD-TO-CVECTOR
+ BOOTSTRAP-SLOT-INDEX QUALIFIER-CHECK-RUNTIME
+ CPL-FORWARD-REFERENCED-CLASS-ERROR REAL-REMOVE-METHOD
+ WALKER::ENVIRONMENT-MACRO CANONICALIZE-SLOT-SPECIFICATION
+ CANONICALIZE-DEFCLASS-OPTION SET-WRAPPER
+ DEAL-WITH-ARGUMENTS-OPTION PARSE-QUALIFIER-PATTERN
+ SWAP-WRAPPERS-AND-SLOTS ITERATE::MV-SETQ
+ MAKE-UNORDERED-METHODS-EMF CLASS-MIGHT-PRECEDE-P
+ ITERATE::EXTRACT-SPECIAL-BINDINGS
+ WALKER::VARIABLE-SYMBOL-MACRO-P RAISE-METATYPE
+ SLOT-EXISTS-P PROCLAIM-DEFMETHOD STANDARD-INSTANCE-ACCESS
+ REMOVE-METHOD
+ SET-FUNCALLABLE-INSTANCE-FUNCTION
+ SYSTEM:%SET-COMPILED-FUNCTION-NAME FDEFINE-CAREFULLY
+ MAKE-INTERNAL-READER-METHOD-FUNCTION
+ MAKE-STD-READER-METHOD-FUNCTION
+ MAKE-STD-WRITER-METHOD-FUNCTION
+ ITERATE::SIMPLE-EXPAND-ITERATE-FORM
+ MAKE-STD-BOUNDP-METHOD-FUNCTION))
+(PROCLAIM '(FTYPE (FUNCTION NIL FIXNUM) GET-WRAPPER-CACHE-NUMBER))
+(IN-PACKAGE "PCL")
+
+(DOLIST (V '(|(FAST-WRITER-METHOD SLOT-OBJECT DIRECT-METHODS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT SLOTS)|
+ |(FAST-WRITER-METHOD SLOT-CLASS SLOTS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT DIRECT-SLOTS)|
+ |(FAST-WRITER-METHOD SLOT-CLASS DIRECT-SLOTS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT FROM-DEFCLASS-P)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT METHODS)|
+ |(FAST-WRITER-METHOD STANDARD-GENERIC-FUNCTION METHODS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT OPTIONS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT DIRECT-SUBCLASSES)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT DIRECT-SUPERCLASSES)|
+ ADD-READER-METHOD
+ SHORT-COMBINATION-IDENTITY-WITH-ONE-ARGUMENT
+ REMOVE-READER-METHOD |LISP::T class predicate|
+ EQL-SPECIALIZER-P |(SETF GENERIC-FUNCTION-NAME)|
+ OBJECT-PLIST SLOT-DEFINITION-DEFSTRUCT-ACCESSOR-SYMBOL
+ |PCL::STANDARD-OBJECT class predicate|
+ |PCL::STANDARD-SLOT-DEFINITION class predicate|
+ |PCL::STANDARD-DIRECT-SLOT-DEFINITION class predicate|
+ |PCL::STANDARD-EFFECTIVE-SLOT-DEFINITION class predicate|
+ |PCL::STANDARD-METHOD-COMBINATION class predicate|
+ |(FAST-READER-METHOD SLOT-OBJECT METHOD)|
+ |PCL::BUILT-IN-CLASS class predicate| SPECIALIZER-TYPE
+ |LISP::RATIO class predicate|
+ |LISP::RATIONAL class predicate| GF-DFUN-STATE
+ |(SETF GENERIC-FUNCTION-METHOD-CLASS)|
+ |(FAST-READER-METHOD SLOT-OBJECT DEFSTRUCT-ACCESSOR-SYMBOL)|
+ |(FAST-READER-METHOD STRUCTURE-SLOT-DEFINITION DEFSTRUCT-ACCESSOR-SYMBOL)|
+ |(SETF GENERIC-FUNCTION-METHOD-COMBINATION)|
+ CLASS-DEFSTRUCT-CONSTRUCTOR
+ |(FAST-READER-METHOD SLOT-OBJECT SOURCE)|
+ |(FAST-READER-METHOD DEFINITION-SOURCE-MIXIN SOURCE)|
+ METHOD-FAST-FUNCTION |(SETF GENERIC-FUNCTION-METHODS)|
+ |(SETF GF-PRETTY-ARGLIST)|
+ |(FAST-READER-METHOD SLOT-OBJECT INITIALIZE-INFO)|
+ |(FAST-READER-METHOD SLOT-CLASS INITIALIZE-INFO)|
+ |(FAST-READER-METHOD SLOT-OBJECT ARG-INFO)|
+ |(FAST-READER-METHOD STANDARD-GENERIC-FUNCTION ARG-INFO)|
+ SPECIALIZERP EXACT-CLASS-SPECIALIZER-P
+ |(FAST-READER-METHOD SLOT-OBJECT WRAPPER)|
+ |(FAST-READER-METHOD PCL-CLASS WRAPPER)|
+ |(FAST-READER-METHOD SLOT-OBJECT INITARGS)|
+ |(FAST-READER-METHOD SLOT-DEFINITION INITARGS)|
+ |(FAST-READER-METHOD SHORT-METHOD-COMBINATION OPERATOR)|
+ |(FAST-READER-METHOD SLOT-OBJECT OPERATOR)|
+ |(FAST-READER-METHOD SLOT-OBJECT DEFSTRUCT-CONSTRUCTOR)|
+ |(FAST-READER-METHOD STRUCTURE-CLASS DEFSTRUCT-CONSTRUCTOR)|
+ |LISP::CHARACTER class predicate|
+ COMPATIBLE-META-CLASS-CHANGE-P
+ |LISP::SEQUENCE class predicate|
+ |(FAST-READER-METHOD SLOT-OBJECT CLASS-EQ-SPECIALIZER)|
+ |(FAST-READER-METHOD CLASS CLASS-EQ-SPECIALIZER)|
+ |(BOUNDP READER-FUNCTION)| |(BOUNDP PREDICATE-NAME)|
+ |(BOUNDP READERS)| UPDATE-GF-DFUN
+ |(BOUNDP CLASS-PRECEDENCE-LIST)|
+ |(BOUNDP ACCESSOR-FLAGS)| |(BOUNDP LOCATION)|
+ |(BOUNDP DOCUMENTATION)| SPECIALIZER-OBJECT
+ |(BOUNDP INCOMPATIBLE-SUPERCLASS-LIST)|
+ ACCESSOR-METHOD-SLOT-NAME |(BOUNDP SPECIALIZERS)|
+ |(BOUNDP IDENTITY-WITH-ONE-ARGUMENT)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DEFSTRUCT-ACCESSOR-SYMBOL)|
+ SPECIALIZER-CLASS |(BOUNDP PRETTY-ARGLIST)|
+ |PCL::PCL-CLASS class predicate|
+ |PCL::STD-CLASS class predicate|
+ |(BOUNDP DEFSTRUCT-FORM)|
+ |(SETF SLOT-DEFINITION-DEFSTRUCT-ACCESSOR-SYMBOL)|
+ CLASS-EQ-SPECIALIZER-P
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT SOURCE)| SLOTS-FETCHER
+ |(SETF SLOT-ACCESSOR-STD-P)| REMOVE-WRITER-METHOD
+ |(BOUNDP WRITER-FUNCTION)| |(BOUNDP INITFUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT INITIALIZE-INFO)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT ARG-INFO)|
+ STRUCTURE-CLASS-P |(BOUNDP WRITERS)|
+ |(BOUNDP INITFORM)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT WRAPPER)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT INITARGS)|
+ |LISP::BIT-VECTOR class predicate|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DEFSTRUCT-CONSTRUCTOR)|
+ UPDATE-CONSTRUCTORS |(BOUNDP SLOT-NAME)|
+ |(SETF SLOT-DEFINITION-INITARGS)| |(BOUNDP ALLOCATION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT CLASS-EQ-SPECIALIZER)|
+ DOCUMENTATION |(BOUNDP FUNCTION)|
+ |(BOUNDP GENERIC-FUNCTION)| |(BOUNDP LAMBDA-LIST)|
+ METHOD-PRETTY-ARGLIST |(BOUNDP SLOT-DEFINITION)|
+ |LISP::ARRAY class predicate|
+ |(BOUNDP CAN-PRECEDE-LIST)| |(BOUNDP PROTOTYPE)|
+ CLASS-EQ-SPECIALIZER INFORM-TYPE-SYSTEM-ABOUT-CLASS
+ |PCL::DEFINITION-SOURCE-MIXIN class predicate|
+ |(BOUNDP DFUN-STATE)| |(BOUNDP FROM-DEFCLASS-P)|
+ |(READER METHOD)|
+ |(CALL STANDARD-COMPUTE-EFFECTIVE-METHOD)|
+ |(BOUNDP FAST-FUNCTION)|
+ |LISP::COMPLEX class predicate| |(BOUNDP METHOD-CLASS)|
+ |(READER SOURCE)| |(BOUNDP INTERNAL-WRITER-FUNCTION)|
+ |(BOUNDP INTERNAL-READER-FUNCTION)|
+ |(BOUNDP METHOD-COMBINATION)| ACCESSOR-METHOD-CLASS
+ |(BOUNDP DIRECT-SLOTS)| |(BOUNDP DIRECT-METHODS)|
+ |(BOUNDP BOUNDP-FUNCTION)| |(BOUNDP DIRECT-SUBCLASSES)|
+ |(BOUNDP DIRECT-SUPERCLASSES)| |(BOUNDP METHODS)|
+ |(BOUNDP OPTIONS)| |(WRITER METHOD)|
+ |PCL::DEPENDENT-UPDATE-MIXIN class predicate|
+ GENERIC-FUNCTION-PRETTY-ARGLIST |(WRITER SOURCE)|
+ |(FAST-METHOD SLOTS-TO-INSPECT (SLOT-CLASS SLOT-OBJECT))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-GENERIC-FUNCTIONS (SPECIALIZER-WITH-OBJECT))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-METHODS (SPECIALIZER-WITH-OBJECT))|
+ |(FAST-METHOD UPDATE-INSTANCE-FOR-DIFFERENT-CLASS (STANDARD-OBJECT STANDARD-OBJECT))|
+ |(FAST-METHOD REINITIALIZE-INSTANCE (SLOT-OBJECT))|
+ |(FAST-METHOD INITIALIZE-INSTANCE (SLOT-OBJECT))|
+ |(FAST-METHOD SPECIALIZER-CLASS (EQL-SPECIALIZER))|
+ |(FAST-METHOD SAME-SPECIALIZER-P (EQL-SPECIALIZER EQL-SPECIALIZER))|
+ |(FAST-METHOD SAME-SPECIALIZER-P (CLASS-EQ-SPECIALIZER CLASS-EQ-SPECIALIZER))|
+ |(FAST-METHOD SAME-SPECIALIZER-P (SPECIALIZER SPECIALIZER))|
+ |(FAST-METHOD SPECIALIZER-METHOD-TABLE (CLASS-EQ-SPECIALIZER))|
+ |(FAST-METHOD SPECIALIZER-METHOD-TABLE (EQL-SPECIALIZER))|
+ MAKE-BOUNDP-METHOD-FUNCTION
+ |LISP::STRING class predicate|
+ |(FAST-METHOD (SETF DOCUMENTATION) (T DOCUMENTATION-MIXIN))|
+ |(FAST-METHOD DOCUMENTATION (DOCUMENTATION-MIXIN))|
+ |PCL::METAOBJECT class predicate|
+ |(FAST-METHOD ACCESSOR-METHOD-SLOT-NAME (TRACED-METHOD))|
+ |(FAST-METHOD METHOD-QUALIFIERS (TRACED-METHOD))|
+ |(FAST-METHOD METHOD-SPECIALIZERS (TRACED-METHOD))|
+ |(FAST-METHOD METHOD-LAMBDA-LIST (TRACED-METHOD))|
+ |(FAST-METHOD METHOD-PRETTY-ARGLIST (STANDARD-METHOD))|
+ |(FAST-METHOD GENERIC-FUNCTION-PRETTY-ARGLIST (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD FUNCTION-KEYWORDS (STANDARD-METHOD))|
+ |(FAST-METHOD COMPUTE-DISCRIMINATING-FUNCTION (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD REINITIALIZE-INSTANCE :AFTER (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD INITIALIZE-INSTANCE :AFTER (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD GF-FAST-METHOD-FUNCTION-P (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD GENERIC-FUNCTION-LAMBDA-LIST (GENERIC-FUNCTION))|
+ |(FAST-METHOD COMPUTE-DISCRIMINATING-FUNCTION-ARGLIST-INFO (STANDARD-GENERIC-FUNCTION))|
+ |(FAST-METHOD METHOD-QUALIFIERS (STANDARD-METHOD))|
+ |(FAST-METHOD REINITIALIZE-INSTANCE (STANDARD-METHOD))|
+ |(FAST-METHOD ACCESSOR-METHOD-CLASS (STANDARD-WRITER-METHOD))|
+ |(FAST-METHOD ACCESSOR-METHOD-CLASS (STANDARD-ACCESSOR-METHOD))|
+ |(FAST-METHOD METHOD-FUNCTION (STANDARD-METHOD))|
+ |(FAST-METHOD CHANGE-CLASS (T SYMBOL))|
+ |(FAST-METHOD MAKE-INSTANCES-OBSOLETE (SYMBOL))|
+ |(FAST-METHOD REMOVE-DIRECT-METHOD (SPECIALIZER-WITH-OBJECT METHOD))|
+ |(FAST-METHOD ADD-DIRECT-METHOD (SPECIALIZER-WITH-OBJECT METHOD))|
+ |(FAST-METHOD REMOVE-DIRECT-METHOD (CLASS METHOD))|
+ |(FAST-METHOD ADD-DIRECT-METHOD (CLASS METHOD))|
+ |(FAST-METHOD (SETF DOCUMENTATION) (T STANDARD-SLOT-DEFINITION))|
+ |(FAST-METHOD DOCUMENTATION (STANDARD-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-DEFINITION-ALLOCATION (STRUCTURE-SLOT-DEFINITION))|
+ |(FAST-METHOD INITIALIZE-INTERNAL-SLOT-FUNCTIONS (EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD MAKE-INSTANCE (SYMBOL))|
+ |(FAST-METHOD SLOT-MAKUNBOUND-USING-CLASS (STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-BOUNDP-USING-CLASS (STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD (SETF SLOT-VALUE-USING-CLASS) (T STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-VALUE-USING-CLASS (STRUCTURE-CLASS STRUCTURE-OBJECT STRUCTURE-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-MAKUNBOUND-USING-CLASS (STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-BOUNDP-USING-CLASS (STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD (SETF SLOT-VALUE-USING-CLASS) (T STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SLOT-VALUE-USING-CLASS (STD-CLASS STANDARD-OBJECT STANDARD-EFFECTIVE-SLOT-DEFINITION))|
+ |(FAST-METHOD SPECIALIZER-CLASS (CLASS))|
+ |(FAST-METHOD SAME-SPECIALIZER-P (CLASS CLASS))|
+ |(FAST-METHOD ALLOCATE-INSTANCE (FUNCALLABLE-STANDARD-CLASS))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (FUNCALLABLE-STANDARD-CLASS STANDARD-CLASS))|
+ |(FAST-METHOD RAW-INSTANCE-ALLOCATOR (FUNCALLABLE-STANDARD-CLASS))|
+ |(FAST-METHOD SLOTS-FETCHER (FUNCALLABLE-STANDARD-CLASS))|
+ |(FAST-METHOD WRAPPER-FETCHER (FUNCALLABLE-STANDARD-CLASS))|
+ |(FAST-METHOD COMPUTE-CLASS-PRECEDENCE-LIST (SLOT-CLASS))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (SLOT-CLASS FORWARD-REFERENCED-CLASS))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (CLASS BUILT-IN-CLASS))|
+ |(FAST-METHOD CLASS-DEFAULT-INITARGS (BUILT-IN-CLASS))|
+ |(FAST-METHOD CLASS-DIRECT-DEFAULT-INITARGS (BUILT-IN-CLASS))|
+ |(FAST-METHOD CLASS-SLOTS (BUILT-IN-CLASS))|
+ |(FAST-METHOD CLASS-DIRECT-SLOTS (BUILT-IN-CLASS))|
+ |(FAST-METHOD CHANGE-CLASS (STANDARD-OBJECT FUNCALLABLE-STANDARD-CLASS))|
+ |(FAST-METHOD CHANGE-CLASS (STANDARD-OBJECT STANDARD-CLASS))|
+ |(FAST-METHOD MAKE-INSTANCES-OBSOLETE (STD-CLASS))|
+ |(FAST-METHOD VALIDATE-SUPERCLASS (CLASS CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS :AROUND (STRUCTURE-CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS (STRUCTURE-CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS :AROUND (STD-CLASS))|
+ |(FAST-METHOD COMPUTE-SLOTS (STD-CLASS))|
+ |(FAST-METHOD COMPUTE-DEFAULT-INITARGS (SLOT-CLASS))|
+ |(FAST-METHOD FINALIZE-INHERITANCE (STD-CLASS))|
+ |(FAST-METHOD FINALIZE-INHERITANCE (STRUCTURE-CLASS))|
+ |(FAST-METHOD REINITIALIZE-INSTANCE :AFTER (SLOT-CLASS))|
+ |(FAST-METHOD REINITIALIZE-INSTANCE :BEFORE (SLOT-CLASS))|
+ |(FAST-METHOD ENSURE-CLASS-USING-CLASS (T PCL-CLASS))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-GENERIC-FUNCTIONS (CLASS))|
+ |(FAST-METHOD SPECIALIZER-DIRECT-METHODS (CLASS))|
+ |(FAST-METHOD REMOVE-DIRECT-SUBCLASS (CLASS CLASS))|
+ |(FAST-METHOD ADD-DIRECT-SUBCLASS (CLASS CLASS))|
+ |(FAST-METHOD CLASS-SLOT-CELLS (STD-CLASS))|
+ |(FAST-METHOD CLASS-CONSTRUCTORS (SLOT-CLASS))|
+ |(FAST-METHOD CLASS-DEFAULT-INITARGS (SLOT-CLASS))|
+ |(FAST-METHOD CLASS-DIRECT-DEFAULT-INITARGS (SLOT-CLASS))|
+ |(FAST-METHOD CLASS-PROTOTYPE (STRUCTURE-CLASS))|
+ |(FAST-METHOD CLASS-PROTOTYPE (STD-CLASS))|
+ |(FAST-METHOD CLASS-FINALIZED-P (PCL-CLASS))|
+ |(FAST-METHOD MAKE-INSTANCE (CLASS))|
+ |(FAST-METHOD ALLOCATE-INSTANCE (STRUCTURE-CLASS))|
+ |(FAST-METHOD ALLOCATE-INSTANCE (STANDARD-CLASS))|
+ |(FAST-METHOD RAW-INSTANCE-ALLOCATOR (STANDARD-CLASS))|
+ |(FAST-METHOD SLOTS-FETCHER (STANDARD-CLASS))|
+ |(FAST-METHOD WRAPPER-FETCHER (STANDARD-CLASS))|
+ CLASS-PREDICATE-NAME
+ |PCL::STRUCTURE-OBJECT class predicate|
+ |PCL::STRUCTURE-SLOT-DEFINITION class predicate|
+ |PCL::STRUCTURE-DIRECT-SLOT-DEFINITION class predicate|
+ |PCL::STRUCTURE-EFFECTIVE-SLOT-DEFINITION class predicate|
+ |LISP::SYMBOL class predicate| CLASSP
+ |PCL::EFFECTIVE-SLOT-DEFINITION class predicate|
+ |(COMBINED-METHOD SHARED-INITIALIZE)|
+ LEGAL-QUALIFIERS-P ADD-BOUNDP-METHOD
+ LEGAL-LAMBDA-LIST-P |LISP::VECTOR class predicate|
+ |SETF PCL GENERIC-FUNCTION-NAME|
+ |(READER READER-FUNCTION)| |(READER PREDICATE-NAME)|
+ |(READER READERS)| DESCRIBE-OBJECT
+ |(READER CLASS-PRECEDENCE-LIST)|
+ |(READER ACCESSOR-FLAGS)| |(READER LOCATION)|
+ |(READER DOCUMENTATION)| CLASS-INITIALIZE-INFO
+ |(SETF CLASS-SLOT-VALUE)| MAKE-WRITER-METHOD-FUNCTION
+ |SETF PCL GF-DFUN-STATE|
+ |(READER INCOMPATIBLE-SUPERCLASS-LIST)|
+ |(READER SPECIALIZERS)|
+ |(READER IDENTITY-WITH-ONE-ARGUMENT)|
+ |(SETF CLASS-INITIALIZE-INFO)|
+ |(READER PRETTY-ARGLIST)| |(READER DEFSTRUCT-FORM)|
+ |SETF PCL SLOT-DEFINITION-NAME| |SETF PCL CLASS-NAME|
+ |(WRITER READER-FUNCTION)|
+ |(SETF CLASS-DEFSTRUCT-CONSTRUCTOR)|
+ |(WRITER PREDICATE-NAME)| |(WRITER READERS)|
+ |(READER WRITER-FUNCTION)| |(READER INITFUNCTION)|
+ INITIALIZE-INTERNAL-SLOT-FUNCTIONS
+ |SETF PCL SLOT-DEFINITION-TYPE|
+ |(WRITER CLASS-PRECEDENCE-LIST)| |(READER WRITERS)|
+ |(WRITER ACCESSOR-FLAGS)| |(READER INITFORM)|
+ METHOD-COMBINATION-P |(WRITER LOCATION)|
+ |(WRITER DOCUMENTATION)|
+ |(CALL REAL-ENSURE-GF-USING-CLASS--GENERIC-FUNCTION)|
+ |SETF PCL GENERIC-FUNCTION-METHODS|
+ |SETF PCL GENERIC-FUNCTION-METHOD-COMBINATION|
+ |SETF PCL METHOD-GENERIC-FUNCTION| |(READER SLOT-NAME)|
+ |(WRITER INCOMPATIBLE-SUPERCLASS-LIST)|
+ |SETF PCL SLOT-ACCESSOR-STD-P|
+ |(CALL REAL-MAKE-METHOD-INITARGS-FORM)|
+ |(READER ALLOCATION)| |(WRITER SPECIALIZERS)|
+ |(CALL REAL-ENSURE-GF-USING-CLASS--NULL)|
+ |(WRITER IDENTITY-WITH-ONE-ARGUMENT)|
+ |(SETF METHOD-GENERIC-FUNCTION)|
+ |(WRITER PRETTY-ARGLIST)| LEGAL-SPECIALIZERS-P
+ |SETF PCL OBJECT-PLIST| |LISP::FLOAT class predicate|
+ |(WRITER DEFSTRUCT-FORM)| |(READER FUNCTION)|
+ |(READER GENERIC-FUNCTION)| |(READER LAMBDA-LIST)|
+ |(READER SLOT-DEFINITION)|
+ |PCL::CLASS-PROTOTYPE-SPECIALIZER class predicate|
+ |SETF PCL SLOT-DEFINITION-INITFORM|
+ |SETF PCL CLASS-DEFSTRUCT-FORM|
+ |(READER CAN-PRECEDE-LIST)|
+ |SETF PCL GENERIC-FUNCTION-METHOD-CLASS|
+ |(READER PROTOTYPE)| |(WRITER WRITER-FUNCTION)|
+ |(WRITER INITFUNCTION)| |(WRITER WRITERS)|
+ SLOT-ACCESSOR-STD-P |(WRITER INITFORM)|
+ |(READER DFUN-STATE)| |(READER FROM-DEFCLASS-P)|
+ |SETF PCL GF-PRETTY-ARGLIST|
+ |SETF PCL SLOT-ACCESSOR-FUNCTION|
+ |SETF PCL SLOT-DEFINITION-LOCATION|
+ |SETF PCL SLOT-DEFINITION-READER-FUNCTION|
+ |SETF PCL SLOT-DEFINITION-WRITER-FUNCTION|
+ |SETF PCL SLOT-DEFINITION-BOUNDP-FUNCTION|
+ |SETF PCL SLOT-DEFINITION-INTERNAL-READER-FUNCTION|
+ |SETF PCL SLOT-DEFINITION-INTERNAL-WRITER-FUNCTION|
+ |SETF PCL SLOT-DEFINITION-ALLOCATION|
+ |SETF PCL SLOT-DEFINITION-INITFUNCTION|
+ |(WRITER SLOT-NAME)| |(BOUNDP NAME)|
+ |(WRITER ALLOCATION)| |(READER FAST-FUNCTION)|
+ |(READER METHOD-CLASS)| |(SETF OBJECT-PLIST)|
+ |(READER INTERNAL-WRITER-FUNCTION)|
+ |(READER INTERNAL-READER-FUNCTION)|
+ |(READER METHOD-COMBINATION)|
+ METHOD-COMBINATION-OPTIONS |(READER DIRECT-SLOTS)|
+ |(READER DIRECT-METHODS)|
+ |SETF PCL SLOT-DEFINITION-READERS|
+ |(READER BOUNDP-FUNCTION)| |(WRITER FUNCTION)|
+ |(WRITER GENERIC-FUNCTION)|
+ |(READER DIRECT-SUBCLASSES)|
+ |(READER DIRECT-SUPERCLASSES)| |SETF PCL DOCUMENTATION|
+ |(WRITER LAMBDA-LIST)| |LISP::LIST class predicate|
+ FUNCALLABLE-STANDARD-CLASS-P
+ |(FAST-WRITER-METHOD SLOT-OBJECT METHOD)|
+ |(BOUNDP CLASS)| |(WRITER SLOT-DEFINITION)|
+ |(READER METHODS)| |(READER OPTIONS)|
+ |(WRITER CAN-PRECEDE-LIST)|
+ |SETF PCL SLOT-DEFINITION-CLASS|
+ |SETF PCL SLOT-VALUE-USING-CLASS|
+ |(FAST-WRITER-METHOD SLOT-OBJECT DEFSTRUCT-ACCESSOR-SYMBOL)|
+ |(FAST-WRITER-METHOD STRUCTURE-SLOT-DEFINITION DEFSTRUCT-ACCESSOR-SYMBOL)|
+ |(WRITER PROTOTYPE)| |(BOUNDP OBJECT)| |(BOUNDP TYPE)|
+ CLASS-CAN-PRECEDE-LIST |SETF PCL CLASS-DIRECT-SLOTS|
+ |SETF PCL CLASS-SLOTS| SLOT-ACCESSOR-FUNCTION
+ |(BOUNDP PLIST)|
+ |SETF PCL CLASS-INCOMPATIBLE-SUPERCLASS-LIST|
+ |SETF PCL SLOT-DEFINITION-WRITERS|
+ |(FAST-WRITER-METHOD SLOT-OBJECT SOURCE)|
+ |(WRITER DFUN-STATE)| |(WRITER FROM-DEFCLASS-P)|
+ |(BOUNDP SLOTS)| SLOT-CLASS-P
+ MAKE-READER-METHOD-FUNCTION LEGAL-METHOD-FUNCTION-P
+ |(FAST-WRITER-METHOD SLOT-OBJECT INITIALIZE-INFO)|
+ |(FAST-WRITER-METHOD SLOT-CLASS INITIALIZE-INFO)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT ARG-INFO)|
+ |PCL::PLIST-MIXIN class predicate|
+ |(WRITER FAST-FUNCTION)| |(WRITER METHOD-CLASS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT WRAPPER)|
+ |(WRITER INTERNAL-WRITER-FUNCTION)|
+ |(WRITER INTERNAL-READER-FUNCTION)|
+ |(WRITER METHOD-COMBINATION)| GET-METHOD
+ |(WRITER DIRECT-SLOTS)| |(WRITER DIRECT-METHODS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT INITARGS)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION INITARGS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT OPERATOR)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT DEFSTRUCT-CONSTRUCTOR)|
+ |(FAST-WRITER-METHOD STRUCTURE-CLASS DEFSTRUCT-CONSTRUCTOR)|
+ |(WRITER BOUNDP-FUNCTION)| |(WRITER DIRECT-SUBCLASSES)|
+ |(WRITER DIRECT-SUPERCLASSES)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT CLASS-EQ-SPECIALIZER)|
+ |(WRITER METHODS)| |(WRITER OPTIONS)|
+ SHORT-METHOD-COMBINATION-P GF-ARG-INFO
+ SPECIALIZER-METHOD-TABLE MAKE-METHOD-INITARGS-FORM
+ CLASS-DEFSTRUCT-FORM |LISP::INTEGER class predicate|
+ |(FAST-READER-METHOD SLOT-OBJECT PREDICATE-NAME)|
+ |(FAST-READER-METHOD CLASS PREDICATE-NAME)|
+ |(FAST-READER-METHOD CLASS NAME)|
+ |(FAST-READER-METHOD SLOT-DEFINITION NAME)|
+ |(FAST-READER-METHOD SLOT-OBJECT SLOT-NAME)|
+ |(FAST-READER-METHOD STANDARD-ACCESSOR-METHOD SLOT-NAME)|
+ |(FAST-READER-METHOD SLOT-OBJECT DFUN-STATE)|
+ |(FAST-READER-METHOD STANDARD-GENERIC-FUNCTION DFUN-STATE)|
+ |(FAST-READER-METHOD SLOT-OBJECT NAME)|
+ |(FAST-READER-METHOD STANDARD-GENERIC-FUNCTION NAME)|
+ GF-PRETTY-ARGLIST SAME-SPECIALIZER-P
+ SLOT-DEFINITION-BOUNDP-FUNCTION
+ SLOT-DEFINITION-WRITER-FUNCTION
+ SLOT-DEFINITION-READER-FUNCTION
+ SLOT-DEFINITION-INTERNAL-WRITER-FUNCTION
+ SLOT-DEFINITION-INTERNAL-READER-FUNCTION
+ |(FAST-READER-METHOD SLOT-OBJECT CLASS)|
+ |(FAST-READER-METHOD SLOT-DEFINITION CLASS)|
+ |(FAST-READER-METHOD SLOT-OBJECT ACCESSOR-FLAGS)|
+ |(FAST-READER-METHOD SLOT-OBJECT METHOD-CLASS)|
+ |(FAST-READER-METHOD STANDARD-GENERIC-FUNCTION METHOD-CLASS)|
+ |(FAST-READER-METHOD TRACED-METHOD GENERIC-FUNCTION)|
+ |(FAST-READER-METHOD TRACED-METHOD FUNCTION)|
+ |(FAST-READER-METHOD LONG-METHOD-COMBINATION FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT INITFUNCTION)|
+ |(FAST-READER-METHOD SLOT-DEFINITION INITFUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT ALLOCATION)|
+ |(FAST-READER-METHOD STANDARD-SLOT-DEFINITION ALLOCATION)|
+ |(FAST-READER-METHOD SLOT-OBJECT INTERNAL-WRITER-FUNCTION)|
+ |(FAST-READER-METHOD STRUCTURE-SLOT-DEFINITION INTERNAL-WRITER-FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT INTERNAL-READER-FUNCTION)|
+ |(FAST-READER-METHOD STRUCTURE-SLOT-DEFINITION INTERNAL-READER-FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT BOUNDP-FUNCTION)|
+ |(FAST-READER-METHOD EFFECTIVE-SLOT-DEFINITION BOUNDP-FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT WRITER-FUNCTION)|
+ |(FAST-READER-METHOD EFFECTIVE-SLOT-DEFINITION WRITER-FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT READER-FUNCTION)|
+ |(FAST-READER-METHOD EFFECTIVE-SLOT-DEFINITION READER-FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT LOCATION)|
+ |(FAST-READER-METHOD STANDARD-EFFECTIVE-SLOT-DEFINITION LOCATION)|
+ |(FAST-READER-METHOD SLOT-OBJECT FAST-FUNCTION)|
+ |(FAST-READER-METHOD STANDARD-METHOD FAST-FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT GENERIC-FUNCTION)|
+ |(FAST-READER-METHOD STANDARD-METHOD GENERIC-FUNCTION)|
+ |(FAST-READER-METHOD SLOT-OBJECT SLOT-DEFINITION)|
+ |(FAST-READER-METHOD STANDARD-ACCESSOR-METHOD SLOT-DEFINITION)|
+ |(FAST-READER-METHOD SLOT-OBJECT METHOD-COMBINATION)|
+ |(FAST-READER-METHOD STANDARD-GENERIC-FUNCTION METHOD-COMBINATION)|
+ |(FAST-READER-METHOD SLOT-OBJECT DOCUMENTATION)|
+ |(FAST-READER-METHOD STANDARD-METHOD-COMBINATION DOCUMENTATION)|
+ |(FAST-READER-METHOD SLOT-OBJECT WRITERS)|
+ |(FAST-READER-METHOD SLOT-DEFINITION WRITERS)|
+ |(FAST-READER-METHOD SLOT-OBJECT READERS)|
+ |(FAST-READER-METHOD SLOT-DEFINITION READERS)|
+ |(FAST-READER-METHOD SLOT-OBJECT SPECIALIZERS)|
+ |(FAST-READER-METHOD STANDARD-METHOD SPECIALIZERS)|
+ |(FAST-READER-METHOD SHORT-METHOD-COMBINATION IDENTITY-WITH-ONE-ARGUMENT)|
+ |(FAST-READER-METHOD SLOT-OBJECT IDENTITY-WITH-ONE-ARGUMENT)|
+ |(FAST-READER-METHOD SPECIALIZER TYPE)|
+ |(FAST-READER-METHOD SLOT-OBJECT PROTOTYPE)|
+ |(FAST-READER-METHOD PCL-CLASS PROTOTYPE)|
+ |(FAST-READER-METHOD CLASS-EQ-SPECIALIZER OBJECT)|
+ |(FAST-READER-METHOD CLASS-PROTOTYPE-SPECIALIZER OBJECT)|
+ |(FAST-READER-METHOD SLOT-OBJECT OBJECT)|
+ |(FAST-READER-METHOD EQL-SPECIALIZER OBJECT)|
+ |(FAST-READER-METHOD SLOT-DEFINITION TYPE)|
+ |(FAST-READER-METHOD SLOT-OBJECT TYPE)|
+ |(FAST-READER-METHOD STANDARD-METHOD-COMBINATION TYPE)|
+ |(FAST-READER-METHOD SLOT-OBJECT DEFSTRUCT-FORM)|
+ |(FAST-READER-METHOD STRUCTURE-CLASS DEFSTRUCT-FORM)|
+ |(FAST-READER-METHOD SLOT-OBJECT INITFORM)|
+ |(FAST-READER-METHOD SLOT-DEFINITION INITFORM)|
+ |(FAST-READER-METHOD SLOT-OBJECT PLIST)|
+ |(FAST-READER-METHOD PLIST-MIXIN PLIST)|
+ |(FAST-READER-METHOD SLOT-OBJECT INCOMPATIBLE-SUPERCLASS-LIST)|
+ |(FAST-READER-METHOD PCL-CLASS INCOMPATIBLE-SUPERCLASS-LIST)|
+ |(FAST-READER-METHOD SLOT-OBJECT CAN-PRECEDE-LIST)|
+ |(FAST-READER-METHOD PCL-CLASS CAN-PRECEDE-LIST)|
+ |(FAST-READER-METHOD SLOT-OBJECT CLASS-PRECEDENCE-LIST)|
+ |(FAST-READER-METHOD PCL-CLASS CLASS-PRECEDENCE-LIST)|
+ |(FAST-READER-METHOD SLOT-OBJECT LAMBDA-LIST)|
+ |(FAST-READER-METHOD STANDARD-METHOD LAMBDA-LIST)|
+ |(FAST-READER-METHOD SLOT-OBJECT PRETTY-ARGLIST)|
+ |(FAST-READER-METHOD STANDARD-GENERIC-FUNCTION PRETTY-ARGLIST)|
+ |(FAST-READER-METHOD SLOT-OBJECT DIRECT-METHODS)|
+ |(FAST-READER-METHOD SLOT-OBJECT SLOTS)|
+ |(FAST-READER-METHOD SLOT-CLASS SLOTS)|
+ |(FAST-READER-METHOD SLOT-OBJECT DIRECT-SLOTS)|
+ |(FAST-READER-METHOD SLOT-CLASS DIRECT-SLOTS)|
+ |(FAST-READER-METHOD SLOT-OBJECT FROM-DEFCLASS-P)|
+ |(FAST-READER-METHOD SLOT-OBJECT METHODS)|
+ |(FAST-READER-METHOD STANDARD-GENERIC-FUNCTION METHODS)|
+ |(FAST-READER-METHOD SLOT-OBJECT OPTIONS)|
+ |(FAST-READER-METHOD STANDARD-METHOD-COMBINATION OPTIONS)|
+ |(FAST-READER-METHOD SLOT-OBJECT DIRECT-SUBCLASSES)|
+ |(FAST-READER-METHOD CLASS DIRECT-SUBCLASSES)|
+ |(FAST-READER-METHOD SLOT-OBJECT DIRECT-SUPERCLASSES)|
+ |(FAST-READER-METHOD CLASS DIRECT-SUPERCLASSES)|
+ SLOT-DEFINITION-CLASS EQL-SPECIALIZER-OBJECT
+ |PCL::DIRECT-SLOT-DEFINITION class predicate|
+ CLASS-CONSTRUCTORS |(BOUNDP WRAPPER)| SLOTS-TO-INSPECT
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT PREDICATE-NAME)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT SLOT-NAME)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DFUN-STATE)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT NAME)|
+ |(BOUNDP DEFSTRUCT-ACCESSOR-SYMBOL)|
+ SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
+ |(BOUNDP CLASS-EQ-SPECIALIZER)|
+ |(SETF SLOT-DEFINITION-NAME)| ADD-WRITER-METHOD
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT CLASS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT ACCESSOR-FLAGS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT METHOD-CLASS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT INITFUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT ALLOCATION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT INTERNAL-WRITER-FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT INTERNAL-READER-FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT BOUNDP-FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT WRITER-FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT READER-FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT LOCATION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT FAST-FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT GENERIC-FUNCTION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT SLOT-DEFINITION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT METHOD-COMBINATION)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DOCUMENTATION)|
+ |(BOUNDP OPERATOR)| |(BOUNDP ARG-INFO)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT WRITERS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT READERS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT SPECIALIZERS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT PROTOTYPE)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT OBJECT)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT TYPE)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DEFSTRUCT-FORM)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT INITFORM)|
+ |(SETF SLOT-VALUE-USING-CLASS)|
+ |(SETF SLOT-DEFINITION-CLASS)|
+ |(SETF SLOT-ACCESSOR-FUNCTION)|
+ |(SETF SLOT-DEFINITION-INITFUNCTION)|
+ |(SETF SLOT-DEFINITION-ALLOCATION)|
+ |(SETF SLOT-DEFINITION-INTERNAL-WRITER-FUNCTION)|
+ |(SETF SLOT-DEFINITION-INTERNAL-READER-FUNCTION)|
+ |(SETF SLOT-DEFINITION-BOUNDP-FUNCTION)|
+ |(SETF SLOT-DEFINITION-WRITER-FUNCTION)|
+ |(SETF SLOT-DEFINITION-READER-FUNCTION)|
+ |(SETF SLOT-DEFINITION-LOCATION)|
+ |(BOUNDP DEFSTRUCT-CONSTRUCTOR)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT PLIST)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT INCOMPATIBLE-SUPERCLASS-LIST)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT CAN-PRECEDE-LIST)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT CLASS-PRECEDENCE-LIST)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT LAMBDA-LIST)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT PRETTY-ARGLIST)|
+ |(SETF SLOT-DEFINITION-WRITERS)|
+ |(SETF SLOT-DEFINITION-READERS)|
+ |(SETF SLOT-DEFINITION-TYPE)|
+ |(SETF SLOT-DEFINITION-INITFORM)|
+ |(BOUNDP INITIALIZE-INFO)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DIRECT-METHODS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT SLOTS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DIRECT-SLOTS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT FROM-DEFCLASS-P)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT METHODS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT OPTIONS)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DIRECT-SUBCLASSES)|
+ |(FAST-BOUNDP-METHOD SLOT-OBJECT DIRECT-SUPERCLASSES)|
+ |(FAST-INTERNAL-READER-METHOD STANDARD-GENERIC-FUNCTION ARG-INFO)|
+ |(BOUNDP INITARGS)| LONG-METHOD-COMBINATION-FUNCTION
+ GENERIC-FUNCTION-P
+ |PCL::SLOT-DEFINITION class predicate|
+ |LISP::NULL class predicate| |(READER NAME)|
+ |(READER CLASS)|
+ |(FAST-METHOD DESCRIBE-OBJECT (CLASS T))|
+ |(FAST-METHOD DESCRIBE-OBJECT (STANDARD-GENERIC-FUNCTION T))|
+ |(FAST-METHOD DESCRIBE-OBJECT (SLOT-OBJECT T))|
+ |(FAST-METHOD DESCRIBE-OBJECT (T T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-METHOD (GENERIC-FUNCTION LONG-METHOD-COMBINATION T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-METHOD (GENERIC-FUNCTION SHORT-METHOD-COMBINATION T))|
+ |(FAST-METHOD FIND-METHOD-COMBINATION (GENERIC-FUNCTION (EQL STANDARD) T))|
+ |(FAST-METHOD UPDATE-GF-DFUN (STD-CLASS T))|
+ |(FAST-METHOD COMPUTE-APPLICABLE-METHODS-USING-CLASSES (GENERIC-FUNCTION T))|
+ |(FAST-METHOD COMPUTE-APPLICABLE-METHODS (GENERIC-FUNCTION T))|
+ |(FAST-METHOD REMOVE-NAMED-METHOD (T T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (STANDARD-GENERIC-FUNCTION T))|
+ |(FAST-METHOD PRINT-OBJECT (GENERIC-FUNCTION T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STANDARD-ACCESSOR-METHOD T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STANDARD-METHOD T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (STANDARD-ACCESSOR-METHOD T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-SPECIALIZER-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-SPECIALIZERS-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-SLOT-NAME-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-QUALIFIER-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-QUALIFIERS-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-METHOD-FUNCTION-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-LAMBDA-LIST-P (STANDARD-METHOD T))|
+ |(FAST-METHOD LEGAL-DOCUMENTATION-P (STANDARD-METHOD T))|
+ |(FAST-METHOD PRINT-OBJECT (STANDARD-ACCESSOR-METHOD T))|
+ |(FAST-METHOD PRINT-OBJECT (STANDARD-METHOD T))|
+ |(FAST-METHOD INFORM-TYPE-SYSTEM-ABOUT-CLASS (STRUCTURE-CLASS T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STRUCTURE-SLOT-DEFINITION T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STANDARD-SLOT-DEFINITION T))|
+ |(FAST-METHOD PRINT-OBJECT (STANDARD-METHOD-COMBINATION T))|
+ |(FAST-METHOD PRINT-OBJECT (SLOT-DEFINITION T))|
+ |(FAST-METHOD PRINT-OBJECT (CLASS T))|
+ |(FAST-METHOD PRINT-OBJECT (T T))|
+ |(FAST-METHOD MAKE-WRITER-METHOD-FUNCTION (FUNCALLABLE-STANDARD-CLASS T))|
+ |(FAST-METHOD MAKE-READER-METHOD-FUNCTION (FUNCALLABLE-STANDARD-CLASS T))|
+ |(FAST-METHOD MAP-DEPENDENTS (DEPENDENT-UPDATE-MIXIN T))|
+ |(FAST-METHOD REMOVE-DEPENDENT (DEPENDENT-UPDATE-MIXIN T))|
+ |(FAST-METHOD ADD-DEPENDENT (DEPENDENT-UPDATE-MIXIN T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (BUILT-IN-CLASS T))|
+ |(FAST-METHOD COMPATIBLE-META-CLASS-CHANGE-P (T T))|
+ |(FAST-METHOD INFORM-TYPE-SYSTEM-ABOUT-CLASS (STD-CLASS T))|
+ |(FAST-METHOD MAKE-BOUNDP-METHOD-FUNCTION (SLOT-CLASS T))|
+ |(FAST-METHOD MAKE-WRITER-METHOD-FUNCTION (SLOT-CLASS T))|
+ |(FAST-METHOD MAKE-READER-METHOD-FUNCTION (SLOT-CLASS T))|
+ |(FAST-METHOD REMOVE-BOUNDP-METHOD (SLOT-CLASS T))|
+ |(FAST-METHOD REMOVE-WRITER-METHOD (SLOT-CLASS T))|
+ |(FAST-METHOD REMOVE-READER-METHOD (SLOT-CLASS T))|
+ |(FAST-METHOD ADD-BOUNDP-METHOD (SLOT-CLASS T T))|
+ |(FAST-METHOD ADD-WRITER-METHOD (SLOT-CLASS T T))|
+ |(FAST-METHOD WRITER-METHOD-CLASS (SLOT-CLASS T))|
+ |(FAST-METHOD ADD-READER-METHOD (SLOT-CLASS T T))|
+ |(FAST-METHOD READER-METHOD-CLASS (SLOT-CLASS T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS :AROUND (STRUCTURE-CLASS T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS (SLOT-CLASS T))|
+ |(FAST-METHOD EFFECTIVE-SLOT-DEFINITION-CLASS (STRUCTURE-CLASS T))|
+ |(FAST-METHOD EFFECTIVE-SLOT-DEFINITION-CLASS (STD-CLASS T))|
+ |(FAST-METHOD COMPUTE-EFFECTIVE-SLOT-DEFINITION (SLOT-CLASS T))|
+ |(FAST-METHOD DIRECT-SLOT-DEFINITION-CLASS (STD-CLASS T))|
+ |(FAST-METHOD DIRECT-SLOT-DEFINITION-CLASS (STRUCTURE-CLASS T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STRUCTURE-CLASS T))|
+ |(FAST-METHOD SHARED-INITIALIZE :BEFORE (CLASS T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (STD-CLASS T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (EQL-SPECIALIZER T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (CLASS-EQ-SPECIALIZER T))|
+ |(FAST-METHOD (SETF DOCUMENTATION) (T T))|
+ |(FAST-METHOD SHARED-INITIALIZE :AFTER (DOCUMENTATION-MIXIN T))|
+ |(FAST-METHOD COMPUTE-SLOT-ACCESSOR-INFO (EFFECTIVE-SLOT-DEFINITION T T))|
+ |(FAST-METHOD (SETF SLOT-ACCESSOR-STD-P) (T EFFECTIVE-SLOT-DEFINITION T))|
+ |(FAST-METHOD SLOT-ACCESSOR-STD-P (EFFECTIVE-SLOT-DEFINITION T))|
+ |(FAST-METHOD (SETF SLOT-ACCESSOR-FUNCTION) (T EFFECTIVE-SLOT-DEFINITION T))|
+ |(FAST-METHOD SLOT-ACCESSOR-FUNCTION (EFFECTIVE-SLOT-DEFINITION T))|
+ |(FAST-METHOD SHARED-INITIALIZE (SLOT-OBJECT T))|
+ |(FAST-METHOD UPDATE-INSTANCE-FOR-REDEFINED-CLASS (STANDARD-OBJECT T T T))|
+ |(FAST-METHOD DEFAULT-INITARGS (SLOT-CLASS T))|
+ |(FAST-METHOD SLOT-UNBOUND (T T T))|
+ |(FAST-METHOD SLOT-MISSING (T T T T))|
+ |(FAST-METHOD (SETF CLASS-SLOT-VALUE) (T STD-CLASS T))|
+ |(FAST-METHOD CLASS-SLOT-VALUE (STD-CLASS T))|
+ LEGAL-SLOT-NAME-P |(READER OBJECT)| |(READER TYPE)|
+ CLASS-WRAPPER |(READER PLIST)|
+ |(FAST-METHOD CLASS-PREDICATE-NAME (T))|
+ |(FAST-METHOD DOCUMENTATION (T))|
+ |(FAST-METHOD NO-APPLICABLE-METHOD (T))|
+ |(READER SLOTS)| |(WRITER NAME)| DEFINITION-SOURCE
+ |PCL::SLOT-OBJECT class predicate| DEFAULT-INITARGS
+ |(WRITER CLASS)| CLASS-SLOT-VALUE |(WRITER OBJECT)|
+ |(WRITER TYPE)|
+ |(FAST-METHOD ENSURE-CLASS-USING-CLASS (T NULL))|
+ |(WRITER PLIST)| |(WRITER SLOTS)|
+ |PCL::DOCUMENTATION-MIXIN class predicate|
+ FORWARD-REFERENCED-CLASS-P GF-FAST-METHOD-FUNCTION-P
+ LEGAL-QUALIFIER-P METHOD-P
+ |PCL::SPECIALIZER-WITH-OBJECT class predicate|
+ CLASS-SLOT-CELLS
+ |(COMBINED-METHOD INITIALIZE-INSTANCE)|
+ |(COMBINED-METHOD REINITIALIZE-INSTANCE)|
+ STANDARD-ACCESSOR-METHOD-P |(SETF CLASS-NAME)|
+ STANDARD-GENERIC-FUNCTION-P STANDARD-READER-METHOD-P
+ STANDARD-METHOD-P |(READER WRAPPER)|
+ |(READER DEFSTRUCT-ACCESSOR-SYMBOL)|
+ |(READER CLASS-EQ-SPECIALIZER)|
+ COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS
+ COMPUTE-DEFAULT-INITARGS |(SETF CLASS-DEFSTRUCT-FORM)|
+ |(CALL REAL-MAKE-METHOD-LAMBDA)|
+ |(SETF CLASS-INCOMPATIBLE-SUPERCLASS-LIST)|
+ |SETF PCL CLASS-SLOT-VALUE| |(SETF CLASS-SLOTS)|
+ |(SETF CLASS-DIRECT-SLOTS)| |(READER OPERATOR)|
+ |(CALL REAL-GET-METHOD)| |(CALL REAL-REMOVE-METHOD)|
+ |(CALL REAL-ADD-METHOD)| |(READER ARG-INFO)|
+ METHOD-COMBINATION-TYPE
+ |(READER DEFSTRUCT-CONSTRUCTOR)|
+ |(INTERNAL-READER-METHOD STANDARD-GENERIC-FUNCTION ARG-INFO)|
+ |(READER INITIALIZE-INFO)| |(WRITER WRAPPER)|
+ STANDARD-CLASS-P |LISP::NUMBER class predicate|
+ LEGAL-SPECIALIZER-P
+ |PCL::LONG-METHOD-COMBINATION class predicate|
+ |(WRITER DEFSTRUCT-ACCESSOR-SYMBOL)|
+ COMPUTE-SLOT-ACCESSOR-INFO |(READER INITARGS)|
+ |(WRITER CLASS-EQ-SPECIALIZER)|
+ STANDARD-BOUNDP-METHOD-P |(SETF DOCUMENTATION)|
+ RAW-INSTANCE-ALLOCATOR
+ |SETF PCL SLOT-DEFINITION-DEFSTRUCT-ACCESSOR-SYMBOL|
+ |SETF PCL CLASS-INITIALIZE-INFO| |(WRITER OPERATOR)|
+ |(WRITER ARG-INFO)|
+ COMPUTE-DISCRIMINATING-FUNCTION-ARGLIST-INFO
+ STANDARD-WRITER-METHOD-P
+ CLASS-INCOMPATIBLE-SUPERCLASS-LIST
+ |(WRITER DEFSTRUCT-CONSTRUCTOR)|
+ |PCL::TRACED-METHOD class predicate| WRAPPER-FETCHER
+ MAKE-A-METHOD |(WRITER INITIALIZE-INFO)|
+ METHOD-COMBINATION-DOCUMENTATION
+ |SETF PCL SLOT-DEFINITION-INITARGS|
+ REMOVE-BOUNDP-METHOD ADD-NAMED-METHOD
+ |LISP::CONS class predicate| |(WRITER INITARGS)|
+ |SETF PCL CLASS-DEFSTRUCT-CONSTRUCTOR|
+ |(BOUNDP METHOD)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT PREDICATE-NAME)|
+ |(FAST-WRITER-METHOD CLASS NAME)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION NAME)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT SLOT-NAME)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT DFUN-STATE)|
+ |(FAST-WRITER-METHOD STANDARD-GENERIC-FUNCTION DFUN-STATE)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT NAME)|
+ |(FAST-WRITER-METHOD STANDARD-GENERIC-FUNCTION NAME)|
+ |(BOUNDP SOURCE)| |(SETF GF-DFUN-STATE)|
+ SHORT-COMBINATION-OPERATOR
+ |(FAST-WRITER-METHOD SLOT-OBJECT CLASS)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION CLASS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT ACCESSOR-FLAGS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT METHOD-CLASS)|
+ |(FAST-WRITER-METHOD STANDARD-GENERIC-FUNCTION METHOD-CLASS)|
+ |(FAST-WRITER-METHOD TRACED-METHOD GENERIC-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT INITFUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION INITFUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT ALLOCATION)|
+ |(FAST-WRITER-METHOD STANDARD-SLOT-DEFINITION ALLOCATION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT INTERNAL-WRITER-FUNCTION)|
+ |(FAST-WRITER-METHOD STRUCTURE-SLOT-DEFINITION INTERNAL-WRITER-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT INTERNAL-READER-FUNCTION)|
+ |(FAST-WRITER-METHOD STRUCTURE-SLOT-DEFINITION INTERNAL-READER-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT BOUNDP-FUNCTION)|
+ |(FAST-WRITER-METHOD EFFECTIVE-SLOT-DEFINITION BOUNDP-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT WRITER-FUNCTION)|
+ |(FAST-WRITER-METHOD EFFECTIVE-SLOT-DEFINITION WRITER-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT READER-FUNCTION)|
+ |(FAST-WRITER-METHOD EFFECTIVE-SLOT-DEFINITION READER-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT LOCATION)|
+ |(FAST-WRITER-METHOD STANDARD-EFFECTIVE-SLOT-DEFINITION LOCATION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT FAST-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT GENERIC-FUNCTION)|
+ |(FAST-WRITER-METHOD STANDARD-METHOD GENERIC-FUNCTION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT SLOT-DEFINITION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT METHOD-COMBINATION)|
+ |(FAST-WRITER-METHOD STANDARD-GENERIC-FUNCTION METHOD-COMBINATION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT DOCUMENTATION)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT WRITERS)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION WRITERS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT READERS)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION READERS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT SPECIALIZERS)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT IDENTITY-WITH-ONE-ARGUMENT)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT PROTOTYPE)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT OBJECT)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION TYPE)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT TYPE)|
+ REMOVE-NAMED-METHOD
+ |(FAST-WRITER-METHOD SLOT-OBJECT DEFSTRUCT-FORM)|
+ |(FAST-WRITER-METHOD STRUCTURE-CLASS DEFSTRUCT-FORM)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT INITFORM)|
+ |(FAST-WRITER-METHOD SLOT-DEFINITION INITFORM)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT PLIST)|
+ |(FAST-WRITER-METHOD PLIST-MIXIN PLIST)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT INCOMPATIBLE-SUPERCLASS-LIST)|
+ |(FAST-WRITER-METHOD PCL-CLASS INCOMPATIBLE-SUPERCLASS-LIST)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT CAN-PRECEDE-LIST)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT CLASS-PRECEDENCE-LIST)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT LAMBDA-LIST)|
+ |(FAST-WRITER-METHOD SLOT-OBJECT PRETTY-ARGLIST)|
+ |(FAST-WRITER-METHOD STANDARD-GENERIC-FUNCTION PRETTY-ARGLIST)|
+ LEGAL-DOCUMENTATION-P CLASS-DIRECT-SUPERCLASSES
+ CLASS-DIRECT-SUBCLASSES CLASS-DIRECT-DEFAULT-INITARGS
+ SLOT-DEFINITION-READERS SLOT-VALUE-USING-CLASS
+ COMPUTE-APPLICABLE-METHODS CLASS-NAME CLASS-PROTOTYPE
+ READER-METHOD-CLASS REMOVE-METHOD
+ SLOT-DEFINITION-INITFORM
+ UPDATE-INSTANCE-FOR-REDEFINED-CLASS
+ UPDATE-INSTANCE-FOR-DIFFERENT-CLASS CHANGE-CLASS
+ METHOD-FUNCTION DIRECT-SLOT-DEFINITION-CLASS
+ MAKE-METHOD-LAMBDA EFFECTIVE-SLOT-DEFINITION-CLASS
+ CLASS-SLOTS COMPUTE-SLOTS SLOT-DEFINITION-NAME
+ FINALIZE-INHERITANCE GENERIC-FUNCTION-LAMBDA-LIST
+ CLASS-DIRECT-SLOTS CLASS-DEFAULT-INITARGS
+ COMPUTE-DISCRIMINATING-FUNCTION CLASS-FINALIZED-P
+ GENERIC-FUNCTION-NAME REMOVE-DEPENDENT
+ COMPUTE-CLASS-PRECEDENCE-LIST ADD-DEPENDENT
+ SLOT-BOUNDP-USING-CLASS ACCESSOR-METHOD-SLOT-DEFINITION
+ SHARED-INITIALIZE ADD-DIRECT-METHOD
+ SLOT-DEFINITION-LOCATION SLOT-DEFINITION-INITFUNCTION
+ SLOT-DEFINITION-ALLOCATION ADD-METHOD
+ GENERIC-FUNCTION-METHOD-CLASS METHOD-SPECIALIZERS
+ SLOT-DEFINITION-INITARGS WRITER-METHOD-CLASS
+ ADD-DIRECT-SUBCLASS SPECIALIZER-DIRECT-METHODS
+ GENERIC-FUNCTION-METHOD-COMBINATION ALLOCATE-INSTANCE
+ COMPUTE-EFFECTIVE-METHOD SLOT-DEFINITION-TYPE
+ SLOT-UNBOUND INITIALIZE-INSTANCE FUNCTION-KEYWORDS
+ REINITIALIZE-INSTANCE VALIDATE-SUPERCLASS
+ GENERIC-FUNCTION-METHODS REMOVE-DIRECT-METHOD
+ METHOD-LAMBDA-LIST MAKE-INSTANCE
+ COMPUTE-EFFECTIVE-SLOT-DEFINITION PRINT-OBJECT
+ METHOD-QUALIFIERS METHOD-GENERIC-FUNCTION
+ REMOVE-DIRECT-SUBCLASS MAKE-INSTANCES-OBSOLETE
+ SLOT-MAKUNBOUND-USING-CLASS
+ ENSURE-GENERIC-FUNCTION-USING-CLASS SLOT-MISSING
+ MAP-DEPENDENTS UPDATE-DEPENDENT FIND-METHOD-COMBINATION
+ ENSURE-CLASS-USING-CLASS NO-APPLICABLE-METHOD
+ SLOT-DEFINITION-WRITERS
+ COMPUTE-APPLICABLE-METHODS-USING-CLASSES
+ CLASS-PRECEDENCE-LIST))
+ (SETF (GET V 'COMPILER::PROCLAIMED-CLOSURE) T))
diff --git a/gcl/pcl/impl/gold-hill/gold-low.lisp b/gcl/pcl/impl/gold-hill/gold-low.lisp
new file mode 100644
index 000000000..ee47b6f21
--- /dev/null
+++ b/gcl/pcl/impl/gold-hill/gold-low.lisp
@@ -0,0 +1,51 @@
+;;;-*-Mode:LISP; Package:(PCL Lisp 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;;
+;;;
+
+(in-package 'pcl)
+
+;;; fix a bug in gcl macro-expander (or->cond->or->cond->...)
+(setf (get 'cond 'lisp::macro-expander) nil)
+
+;;; fix another bug in gcl3_0 case macro-expander
+(defun lisp::eqv (a b) (eql a b))
+
+(defun printing-random-thing-internal (thing stream)
+ (multiple-value-bind (offaddr baseaddr)
+ (sys:%pointer thing)
+ (princ baseaddr stream)
+ (princ ", " stream)
+ (princ offaddr stream)))
+
+;;;
+;;; This allows the compiler to compile a file with many "DEFMETHODS"
+;;; in succession.
+;;;
+(dolist (x '(defmethod defgeneric defclass precompile-random-code-segments))
+ (setf (get x 'gcl::compile-separately) t))
+
diff --git a/gcl/pcl/impl/gold-hill/gold-patches.lisp b/gcl/pcl/impl/gold-hill/gold-patches.lisp
new file mode 100644
index 000000000..9f6f4e7d8
--- /dev/null
+++ b/gcl/pcl/impl/gold-hill/gold-patches.lisp
@@ -0,0 +1,168 @@
+;;; -*- Mode:Lisp; Package:USER; Base:10; Syntax:Common-lisp -*-
+
+(in-package 'user)
+
+(setq c::optimize-speed 3)
+(setq c::optimize-safety 0)
+(setq c::optimize-space 0)
+
+(remprop 'macroexpand 'c::fdesc)
+(remprop 'macroexpand-1 'c::fdesc)
+
+
+;;; this is here to fix the printer so it will find the print
+;;; functions on structures that have 'em.
+
+(in-package 'lisp)
+
+(defun %write-structure (struct output-stream print-vars level)
+ (let* ((name (svref struct 0))
+ (pfun (or (let ((temp (get name 'structure-descriptor)))
+ (and temp (dd-print-function temp)))
+ (get name :print-function))))
+ (declare (symbol name))
+ (cond
+ (pfun
+ (funcall pfun struct output-stream level))
+ ((and (pv-level print-vars) (>= level (pv-level print-vars)))
+ (write-char #\# output-stream))
+ ((and (pv-circle print-vars)
+ (%write-circle struct output-stream (pv-circle print-vars))))
+ (t
+ (let ((pv-length (pv-length print-vars))
+ (pv-pretty (pv-pretty print-vars)))
+ (when pv-pretty
+ (pp-push-level pv-pretty))
+ (incf level)
+ (write-string "#s(" output-stream)
+ (cond
+ ((and pv-length (>= 0 pv-length))
+ (write-string "..."))
+ (t
+ (%write-symbol name output-stream print-vars)
+ (do ((i 0 (1+ i))
+ (n 0)
+ (slots (dd-slots (get name 'structure-descriptor))
+ (rest slots)))
+ ((endp slots))
+ (declare (fixnum i n) (list slots))
+ (when pv-pretty
+ (pp-insert-break pv-pretty *structure-keyword-slot-spec* t))
+ (write-char #\space output-stream)
+ (when (and pv-length (>= (incf n) pv-length))
+ (write-string "..." output-stream)
+ (return))
+ (write-char #\: output-stream)
+ (%write-symbol-name
+ (symbol-name (dsd-name (first slots))) output-stream print-vars)
+ (when pv-pretty
+ (pp-insert-break pv-pretty *structure-data-slot-spec* nil))
+ (write-char #\space output-stream)
+ (when (and pv-length (>= (incf n) pv-length))
+ (write-string "..." output-stream)
+ (return))
+ (%write-object
+ (svref struct (dsd-index (first slots)))
+ output-stream print-vars level))))
+ (write-char #\) output-stream)
+ (when pv-pretty
+ (pp-pop-level pv-pretty)))))))
+
+(eval-when (eval) (compile '%write-structure))
+
+;;;
+;;; Apparently, whoever implemented the TIME macro didn't consider that
+;;; someone might want to use it in a non-null lexical environment. Of
+;;; course this fix is a loser since it binds a whole mess of variables
+;;; around the evaluation of form, but it will do for now.
+;;;
+(in-package 'lisp)
+
+(DEFmacro TIME (FORM)
+ `(LET (IGNORE START FINISH S-HSEC F-HSEC S-SEC F-SEC S-MIN F-MIN VALS)
+ (FORMAT *trace-output* "~&Evaluating: ~A" ,form)
+ ;; read the start time.
+ (MULTIPLE-VALUE-SETQ (IGNORE IGNORE IGNORE S-MIN START)
+ (SYS::%SYSINT #X21 #X2C00 0 0 0))
+ ;; Eval the form.
+ (SETQ VALS (MULTIPLE-VALUE-LIST (progn ,form)))
+ ;; Read the end time.
+ (MULTIPLE-VALUE-SETQ (IGNORE IGNORE IGNORE F-MIN FINISH)
+ (SYS::%SYSINT #X21 #X2C00 0 0 0))
+ ;; Unpack start and end times.
+ (SETQ S-HSEC (LOGAND START #X0FF)
+ F-HSEC (LOGAND FINISH #X0FF)
+ S-SEC (LSH START -8)
+ F-SEC (LSH FINISH -8)
+ S-MIN (LOGAND #X0FF S-MIN)
+ F-MIN (LOGAND #X0FF F-MIN))
+ (SETQ F-HSEC (- F-HSEC S-HSEC)) ; calc hundreths
+ (IF (MINUSP F-HSEC)
+ (SETQ F-HSEC (+ F-HSEC 100)
+ F-SEC (1- F-SEC)))
+ (SETQ F-SEC (- F-SEC S-SEC)) ; calc seconds
+ (IF (MINUSP F-SEC)
+ (SETQ F-SEC (+ F-SEC 60)
+ F-MIN (1- F-MIN)))
+ (SETQ F-MIN (- F-MIN S-MIN)) ; calc minutes
+ (IF (MINUSP F-MIN) (INCF F-MIN 60))
+ (FORMAT *trace-output* "~&Elapsed time: ~D:~:[~D~;0~D~].~:[~D~;0~D~]~%"
+ F-MIN (< F-SEC 10.) F-SEC (< F-HSEC 10) F-HSEC)
+ (VALUES-LIST VALS)))
+
+;;;
+;;; Patch to PROGV
+;;;
+(in-package sys::*compiler-package-load*)
+
+;;; This is a fully portable (though not very efficient)
+;;; implementation of PROGV as a macro. It does its own special
+;;; binding (shallow binding) by saving the original values in a
+;;; list, and marking things that were originally unbound.
+
+(defun PORTABLE-PROGV-BIND (symbol old-vals place-holder)
+ (let ((val-to-save '#:value-to-save))
+ `(let ((,val-to-save (if (boundp ,symbol)
+ (symbol-value ,symbol)
+ ,place-holder)))
+ (if ,old-vals
+ (rplacd (last ,old-vals) (ncons ,val-to-save))
+ (setq ,old-vals (ncons ,val-to-save))))))
+
+(defun PORTABLE-PROGV-UNBIND (symbol old-vals place-holder)
+ (let ((val-to-restore '#:value-to-restore))
+ `(let ((,val-to-restore (pop ,old-vals)))
+ (if (eq ,val-to-restore ,place-holder)
+ (makunbound ,symbol)
+ (setf (symbol-value ,symbol) ,val-to-restore)))))
+
+
+(deftransform PROGV PORTABLE-PROGV-TRANSFORM
+ (symbols-form values-form &rest body)
+ (let ((symbols-lst '#:symbols-list)
+ (values-lst '#:values-list)
+ (syms '#:symbols)
+ (vals '#:values)
+ (sym '#:symbol)
+ (old-vals '#:old-values)
+ (unbound-holder ''#:unbound-holder))
+ `(let ((,symbols-lst ,symbols-form)
+ (,values-lst ,values-form)
+ (,old-vals nil))
+ (unless (and (listp ,symbols-lst) (listp ,values-lst))
+ (error "PROGV: Both symbols and values must be lists"))
+ (unwind-protect
+ (do ((,syms ,symbols-lst (cdr ,syms))
+ (,vals ,values-lst (cdr ,vals))
+ (,sym nil))
+ ((null ,syms) (progn ,@body))
+ (setq ,sym (car ,syms))
+ (if (symbolp ,sym)
+ ,(PORTABLE-PROGV-BIND sym old-vals unbound-holder)
+ (error "PROGV: Object to be bound not a symbol: ~S" ,sym))
+ (if ,vals
+ (setf (symbol-value ,sym) (first ,vals))
+ (makunbound ,sym)))
+ (dolist (,sym ,symbols-lst)
+ ,(PORTABLE-PROGV-UNBIND sym old-vals unbound-holder))))))
+
diff --git a/gcl/pcl/impl/hp/hp-low.lisp b/gcl/pcl/impl/hp/hp-low.lisp
new file mode 100644
index 000000000..d1e807f68
--- /dev/null
+++ b/gcl/pcl/impl/hp/hp-low.lisp
@@ -0,0 +1,37 @@
+;;; -*- Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the HP Common Lisp version of the file low.
+;;;
+;;;
+
+(in-package 'pcl)
+
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~O" (prim:@inf thing)))
+
+
+
diff --git a/gcl/pcl/impl/ibcl/ibcl-low.lisp b/gcl/pcl/impl/ibcl/ibcl-low.lisp
new file mode 100644
index 000000000..2ab3f77ba
--- /dev/null
+++ b/gcl/pcl/impl/ibcl/ibcl-low.lisp
@@ -0,0 +1,327 @@
+;;;-*-Mode:LISP; Package:(PCL Lisp 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; The version of low for Kyoto Common Lisp (KCL)
+(in-package 'pcl)
+
+;;;
+;;; The reason these are here is because the KCL compiler does not allow
+;;; LET to return FIXNUM values as values of (c) type int, hence the use
+;;; of LOCALLY (which expands into (LET () (DECLARE ...) ...)) forces
+;;; conversion of ints to objects.
+;;;
+(defmacro %logand (&rest args)
+ (reduce-variadic-to-binary 'logand args 0 t 'fixnum))
+
+;(defmacro %logxor (&rest args)
+; (reduce-variadic-to-binary 'logxor args 0 t 'fixnum))
+
+(defmacro %+ (&rest args)
+ (reduce-variadic-to-binary '+ args 0 t 'fixnum))
+
+;(defmacro %- (x y)
+; `(the fixnum (- (the fixnum ,x) (the fixnum ,y))))
+
+(defmacro %* (&rest args)
+ (reduce-variadic-to-binary '* args 1 t 'fixnum))
+
+(defmacro %/ (x y)
+ `(the fixnum (/ (the fixnum ,x) (the fixnum ,y))))
+
+(defmacro %1+ (x)
+ `(the fixnum (1+ (the fixnum ,x))))
+
+(defmacro %1- (x)
+ `(the fixnum (1- (the fixnum ,x))))
+
+(defmacro %svref (vector index)
+ `(svref (the simple-vector ,vector) (the fixnum ,index)))
+
+(defsetf %svref (vector index) (new-value)
+ `(setf (svref (the simple-vector ,vector) (the fixnum ,index))
+ ,new-value))
+
+
+;;;
+;;; std-instance-p
+;;;
+(si:define-compiler-macro std-instance-p (x)
+ (once-only (x)
+ `(and (si:structurep ,x)
+ (eq (si:structure-name ,x) 'std-instance))))
+
+(dolist (inline '((si:structurep
+ ((t) compiler::boolean nil nil "type_of(#0)==t_structure")
+ compiler::inline-always)
+ (si:structure-name
+ ((t) t nil nil "(#0)->str.str_name")
+ compiler::inline-unsafe)))
+ (setf (get (first inline) (third inline)) (list (second inline))))
+
+(setf (get 'cclosure-env 'compiler::inline-always)
+ (list '((t) t nil nil "(#0)->cc.cc_env")))
+
+;;;
+;;; turbo-closure patch. See the file kcl-mods.text for details.
+;;;
+#+:turbo-closure
+(progn
+(CLines
+ "object tc_cc_env_nthcdr (n,tc)"
+ "object n,tc; "
+ "{return (type_of(tc)==t_cclosure&& "
+ " tc->cc.cc_turbo!=NULL&& "
+ " type_of(n)==t_fixnum)? "
+ " tc->cc.cc_turbo[fix(n)]: " ; assume that n is in bounds
+ " Cnil; "
+ "} "
+ )
+
+(defentry tc-cclosure-env-nthcdr (object object) (object tc_cc_env_nthcdr))
+
+(setf (get 'tc-cclosure-env-nthcdr 'compiler::inline-unsafe)
+ '(((fixnum t) t nil nil "(#1)->cc.cc_turbo[#0]")))
+)
+
+
+;;;; low level stuff to hack compiled functions and compiled closures.
+;;;
+;;; The primary client for this is fsc-low, but since we make some use of
+;;; it here (e.g. to implement set-function-name-1) it all appears here.
+;;;
+
+(eval-when (compile eval)
+
+(defmacro define-cstruct-accessor (accessor structure-type field value-type
+ field-type tag-name)
+ (let ((setf (intern (concatenate 'string "SET-" (string accessor))))
+ (caccessor (format nil "pcl_get_~A_~A" structure-type field))
+ (csetf (format nil "pcl_set_~A_~A" structure-type field))
+ (vtype (intern (string-upcase value-type))))
+ `(progn
+ (CLines ,(format nil "~A ~A(~A) ~%~
+ object ~A; ~%~
+ { return ((~A) ~A->~A.~A); } ~%~
+ ~%~
+ ~A ~A(~A, new) ~%~
+ object ~A; ~%~
+ ~A new; ~%~
+ { return ((~A)(~A->~A.~A = ~Anew)); } ~%~
+ "
+ value-type caccessor structure-type
+ structure-type
+ value-type structure-type tag-name field
+ value-type csetf structure-type
+ structure-type
+ value-type
+ value-type structure-type tag-name field field-type
+ ))
+
+ (defentry ,accessor (object) (,vtype ,caccessor))
+ (defentry ,setf (object ,vtype) (,vtype ,csetf))
+
+
+ (defsetf ,accessor ,setf)
+
+ )))
+)
+;;;
+;;; struct cfun { /* compiled function header */
+;;; short t, m;
+;;; object cf_name; /* compiled function name */
+;;; int (*cf_self)(); /* entry address */
+;;; object cf_data; /* data the function uses */
+;;; /* for GBC */
+;;; char *cf_start; /* start address of the code */
+;;; int cf_size; /* code size */
+;;; };
+;;; add field-type tag-name
+(define-cstruct-accessor cfun-name "cfun" "cf_name" "object" "(object)" "cf")
+(define-cstruct-accessor cfun-self "cfun" "cf_self" "int" "(int (*)())"
+ "cf")
+(define-cstruct-accessor cfun-data "cfun" "cf_data" "object" "(object)" "cf")
+(define-cstruct-accessor cfun-start "cfun" "cf_start" "int" "(char *)" "cf")
+(define-cstruct-accessor cfun-size "cfun" "cf_size" "int" "(int)" "cf")
+
+(CLines
+ "object pcl_cfunp (x) "
+ "object x; "
+ "{if(x->c.t == (int) t_cfun) "
+ " return (Ct); "
+ " else "
+ " return (Cnil); "
+ " } "
+ )
+
+(defentry cfunp (object) (object pcl_cfunp))
+
+;;;
+;;; struct cclosure { /* compiled closure header */
+;;; short t, m;
+;;; object cc_name; /* compiled closure name */
+;;; int (*cc_self)(); /* entry address */
+;;; object cc_env; /* environment */
+;;; object cc_data; /* data the closure uses */
+;;; /* for GBC */
+;;; char *cc_start; /* start address of the code */
+;;; int cc_size; /* code size */
+;;; };
+;;;
+(define-cstruct-accessor cclosure-name "cclosure" "cc_name" "object"
+ "(object)" "cc")
+(define-cstruct-accessor cclosure-self "cclosure" "cc_self" "int"
+ "(int (*)())" "cc")
+(define-cstruct-accessor cclosure-data "cclosure" "cc_data" "object"
+ "(object)" "cc")
+(define-cstruct-accessor cclosure-start "cclosure" "cc_start" "int"
+ "(char *)" "cc")
+(define-cstruct-accessor cclosure-size "cclosure" "cc_size" "int"
+ "(int)" "cc")
+(define-cstruct-accessor cclosure-env "cclosure" "cc_env" "object"
+ "(object)" "cc")
+
+
+(CLines
+ "object pcl_cclosurep (x) "
+ "object x; "
+ "{if(x->c.t == (int) t_cclosure) "
+ " return (Ct); "
+ " else "
+ " return (Cnil); "
+ " } "
+ )
+
+(defentry cclosurep (object) (object pcl_cclosurep))
+
+ ;;
+;;;;;; Load Time Eval
+ ;;
+;;;
+
+;;; This doesn't work because it looks at a global variable to see if it is
+;;; in the compiler rather than looking at the macroexpansion environment.
+;;;
+;;; The result is that if in the process of compiling a file, we evaluate a
+;;; form that has a call to load-time-eval, we will get faked into thinking
+;;; that we are compiling that form.
+;;;
+;;; THIS NEEDS TO BE DONE RIGHT!!!
+;;;
+;(defmacro load-time-eval (form)
+; ;; In KCL there is no compile-to-core case. For things that we are
+; ;; "compiling to core" we just expand the same way as if were are
+; ;; compiling a file since the form will be evaluated in just a little
+; ;; bit when gazonk.o is loaded.
+; (if (and (boundp 'compiler::*compiler-input*) ;Hack to see of we are
+; compiler::*compiler-input*) ;in the compiler!
+; `'(si:|#,| . ,form)
+; `(progn ,form)))
+
+(defmacro load-time-eval (form)
+ (read-from-string (format nil "'#,~S" form)))
+
+(defmacro memory-block-ref (block offset)
+ `(svref (the simple-vector ,block) (the fixnum ,offset)))
+
+ ;;
+;;;;;; Generating CACHE numbers
+ ;;
+;;; This needs more work to be sure it is going as fast as possible.
+;;; - The calls to si:address should be open-coded.
+;;; - The logand should be open coded.
+;;;
+
+;(defmacro symbol-cache-no (symbol mask)
+; (if (and (constantp symbol)
+; (constantp mask))
+; `(load-time-eval (logand (ash (si:address ,symbol) -2) ,mask))
+; `(logand (ash (the fixnum (si:address ,symbol)) -2) ,mask)))
+
+(defmacro object-cache-no (object mask)
+ `(logand (the fixnum (si:address ,object)) ,mask))
+
+ ;;
+;;;;;; printing-random-thing-internal
+ ;;
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~O" (si:address thing)))
+
+
+(defun set-function-name-1 (fn new-name ignore)
+ (cond ((cclosurep fn)
+ (setf (cclosure-name fn) new-name))
+ ((cfunp fn)
+ (setf (cfun-name fn) new-name))
+ ((and (listp fn)
+ (eq (car fn) 'lambda-block))
+ (setf (cadr fn) new-name))
+ ((and (listp fn)
+ (eq (car fn) 'lambda))
+ (setf (car fn) 'lambda-block
+ (cdr fn) (cons new-name (cdr fn)))))
+ fn)
+
+
+
+
+#|
+(defconstant most-positive-small-fixnum 1024) /* should be supplied */
+(defconstant most-negative-small-fixnum -1024) /* by ibuki */
+
+(defmacro symbol-cache-no (symbol mask)
+ (if (constantp mask)
+ (if (and (> mask 0)
+ (< mask most-positive-small-fixnum))
+ (if (constantp symbol)
+ `(load-time-eval (coffset ,symbol ,mask 2))
+ `(coffset ,symbol ,mask 2))
+ (if (constantp symbol)
+ `(load-time-eval
+ (logand (ash (the fixnum (si:address ,symbol)) -2) ,mask))
+ `(logand (ash (the fixnum (si:address ,symbol)) -2) ,mask)))
+ `(logand (ash (the fixnum (si:address ,symbol)) -2) ,mask)))
+
+
+(defmacro object-cache-no (object mask)
+ (if (and (constantp mask)
+ (> mask 0)
+ (< mask most-positive-small-fixnum))
+ `(coffset ,object ,mask 4)
+ `(logand (ash (the fixnum (si:address ,object)) -4) ,mask)))
+
+(CLines
+ "object pcl_coffset (sym,mask,lshift)"
+ "object sym,mask,lshift;"
+ "{"
+ " return(small_fixnum(((int)sym >> fix(lshift)) & fix(mask)));"
+ "}"
+ )
+
+(defentry coffset (object object object) (object pcl_coffset))
+
+
+|#
+
diff --git a/gcl/pcl/impl/ibcl/ibcl-patches.lisp b/gcl/pcl/impl/ibcl/ibcl-patches.lisp
new file mode 100644
index 000000000..68e071cef
--- /dev/null
+++ b/gcl/pcl/impl/ibcl/ibcl-patches.lisp
@@ -0,0 +1,129 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package 'system)
+
+;;; This makes DEFMACRO take &WHOLE and &ENVIRONMENT args anywhere
+;;; in the lambda-list. The former allows deviation from the CL spec,
+;;; but what the heck.
+
+(eval-when (compile) (proclaim '(optimize (safety 2) (space 3))))
+
+(defvar *old-defmacro*)
+
+(defun new-defmacro (whole env)
+ (flet ((call-old-definition (new-whole)
+ (funcall *old-defmacro* new-whole env)))
+ (if (not (and (consp whole)
+ (consp (cdr whole))
+ (consp (cddr whole))
+ (consp (cdddr whole))))
+ (call-old-definition whole)
+ (let* ((ll (caddr whole))
+ (env-tail (do ((tail ll (cdr tail)))
+ ((not (consp tail)) nil)
+ (when (eq '&environment (car tail))
+ (return tail)))))
+ (if env-tail
+ (call-old-definition (list* (car whole)
+ (cadr whole)
+ (append (list '&environment
+ (cadr env-tail))
+ (ldiff ll env-tail)
+ (cddr env-tail))
+ (cdddr whole)))
+ (call-old-definition whole))))))
+
+(eval-when (load eval)
+ (unless (boundp '*old-defmacro*)
+ (setq *old-defmacro* (macro-function 'defmacro))
+ (setf (macro-function 'defmacro) #'new-defmacro)))
+
+;;;
+;;; setf patches
+;;;
+
+(in-package 'system)
+
+(defun get-setf-method (form)
+ (multiple-value-bind (vars vals stores store-form access-form)
+ (get-setf-method-multiple-value form)
+ (unless (listp vars)
+ (error
+ "The temporary variables component, ~s,
+ of the setf-method for ~s is not a list."
+ vars form))
+ (unless (listp vals)
+ (error
+ "The values forms component, ~s,
+ of the setf-method for ~s is not a list."
+ vals form))
+ (unless (listp stores)
+ (error
+ "The store variables component, ~s,
+ of the setf-method for ~s is not a list."
+ stores form))
+ (unless (= (list-length stores) 1)
+ (error "Multiple store-variables are not allowed."))
+ (values vars vals stores store-form access-form)))
+
+(defun get-setf-method-multiple-value (form)
+ (cond ((symbolp form)
+ (let ((store (gensym)))
+ (values nil nil (list store) `(setq ,form ,store) form)))
+ ((or (not (consp form)) (not (symbolp (car form))))
+ (error "Cannot get the setf-method of ~S." form))
+ ((get (car form) 'setf-method)
+ (apply (get (car form) 'setf-method) (cdr form)))
+ ((get (car form) 'setf-update-fn)
+ (let ((vars (mapcar #'(lambda (x)
+ (declare (ignore x))
+ (gensym))
+ (cdr form)))
+ (store (gensym)))
+ (values vars (cdr form) (list store)
+ `(,(get (car form) 'setf-update-fn)
+ ,@vars ,store)
+ (cons (car form) vars))))
+ ((get (car form) 'setf-lambda)
+ (let* ((vars (mapcar #'(lambda (x)
+ (declare (ignore x))
+ (gensym))
+ (cdr form)))
+ (store (gensym))
+ (l (get (car form) 'setf-lambda))
+ (f `(lambda ,(car l)
+ (funcall #'(lambda ,(cadr l) ,@(cddr l))
+ ',store))))
+ (values vars (cdr form) (list store)
+ (apply f vars)
+ (cons (car form) vars))))
+ ((macro-function (car form))
+ (get-setf-method-multiple-value (macroexpand-1 form)))
+ (t
+ (error "Cannot expand the SETF form ~S." form))))
+
diff --git a/gcl/pcl/impl/kcl/kcl-low.lisp b/gcl/pcl/impl/kcl/kcl-low.lisp
new file mode 100644
index 000000000..77cb4f569
--- /dev/null
+++ b/gcl/pcl/impl/kcl/kcl-low.lisp
@@ -0,0 +1,438 @@
+;;;-*-Mode:LISP; Package:(PCL Lisp 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; The version of low for Kyoto Common Lisp (KCL)
+(in-package "SI")
+(export '(%structure-name
+ %compiled-function-name
+ %set-compiled-function-name
+ %instance-ref
+ %set-instance-ref))
+(in-package 'pcl)
+
+(shadow 'lisp:dotimes)
+
+(defmacro dotimes ((var form &optional (val nil)) &rest body &environment env)
+ (multiple-value-bind (doc decls bod)
+ (extract-declarations body env)
+ (declare (ignore doc))
+ (let ((limit (gensym))
+ (label (gensym)))
+ `(let ((,limit ,form)
+ (,var 0))
+ (declare (fixnum ,limit ,var))
+ ,@decls
+ (block nil
+ (tagbody
+ ,label
+ (when (>= ,var ,limit) (return-from nil ,val))
+ ,@bod
+ (setq ,var (the fixnum (1+ ,var)))
+ (go ,label)))))))
+
+(defun memq (item list) (member item list :test #'eq))
+(defun assq (item list) (assoc item list :test #'eq))
+(defun posq (item list) (position item list :test #'eq))
+
+(si:define-compiler-macro memq (item list)
+ (let ((var (gensym)))
+ (once-only (item)
+ `(let ((,var ,list))
+ (loop (unless ,var (return nil))
+ (when (eq ,item (car ,var))
+ (return ,var))
+ (setq ,var (cdr ,var)))))))
+
+(si:define-compiler-macro assq (item list)
+ (let ((var (gensym)))
+ (once-only (item)
+ `(dolist (,var ,list nil)
+ (when (eq ,item (car ,var))
+ (return ,var))))))
+
+(si:define-compiler-macro posq (item list)
+ (let ((var (gensym)) (index (gensym)))
+ (once-only (item)
+ `(let ((,var ,list) (,index 0))
+ (declare (fixnum ,index))
+ (dolist (,var ,list nil)
+ (when (eq ,item ,var)
+ (return ,index))
+ (incf ,index))))))
+
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~X" (si:address thing)))
+
+(defmacro %svref (vector index)
+ `(svref (the simple-vector ,vector) (the fixnum ,index)))
+
+(defsetf %svref (vector index) (new-value)
+ `(setf (svref (the simple-vector ,vector) (the fixnum ,index))
+ ,new-value))
+
+
+;;;
+;;; std-instance-p
+;;;
+#-akcl
+(si:define-compiler-macro std-instance-p (x)
+ (once-only (x)
+ `(and (si:structurep ,x)
+ (eq (si:%structure-name ,x) 'std-instance))))
+
+#+akcl
+(progn
+
+#-new-kcl-wrapper
+;; declare that std-instance-p may be computed simply, and will not change.
+(si::freeze-defstruct 'std-instance)
+
+(si::freeze-defstruct 'method-call)
+(si::freeze-defstruct 'fast-method-call)
+
+(defvar *pcl-funcall*
+ `(lambda (loc)
+ (compiler::wt-nl
+ "{object _funobj = " loc ";"
+ "if(Rset&&type_of(_funobj)!=t_symbol)funcall_no_event(_funobj);
+ else super_funcall(_funobj);}")))
+
+(setq compiler::*super-funcall* *pcl-funcall*)
+
+(defmacro fmc-funcall (fn pv-cell next-method-call &rest args)
+ `(funcall ,fn ,pv-cell ,next-method-call ,@args))
+
+)
+
+;;;
+;;; turbo-closure patch. See the file kcl-mods.text for details.
+;;;
+#-turbo-closure-env-size
+(clines "
+object cclosure_env_nthcdr (n,cc)
+int n; object cc;
+{ object env;
+ if(n<0)return Cnil;
+ if(type_of(cc)!=t_cclosure)return Cnil;
+ env=cc->cc.cc_env;
+ while(n-->0)
+ {if(type_of(env)!=t_cons)return Cnil;
+ env=env->c.c_cdr;}
+ return env;
+}")
+
+#+turbo-closure-env-size
+(clines "
+object cclosure_env_nthcdr (n,cc)
+int n; object cc;
+{ object env,*turbo;
+ if(n<0)return Cnil;
+ if(type_of(cc)!=t_cclosure)return Cnil;
+ if((turbo=cc->cc.cc_turbo)==NULL)
+ {env=cc->cc.cc_env;
+ while(n-->0)
+ {if(type_of(env)!=t_cons)return Cnil;
+ env=env->c.c_cdr;}
+ return env;}
+ else
+ {if(n>=fix(*(turbo-1)))return Cnil;
+ return turbo[n];}
+}")
+
+;; This is the completely safe version.
+(defentry cclosure-env-nthcdr (int object) (object cclosure_env_nthcdr))
+;; This is the unsafe but fast version.
+(defentry %cclosure-env-nthcdr (int object) (object cclosure_env_nthcdr))
+
+;;; #+akcl means this is an AKCL newer than 5/11/89 (structures changed)
+(eval-when (compile load eval)
+
+#+new-kcl-wrapper
+(progn
+
+(defun instance-ref (slots index)
+ (si:structure-ref1 slots index))
+
+(defun set-instance-ref (slots index value)
+ (si:structure-set1 slots index value))
+
+(defsetf instance-ref set-instance-ref)
+(defsetf %instance-ref %set-instance-ref)
+)
+
+(defsetf structure-def set-structure-def)
+
+;;((name args-type result-type side-effect-p new-object-p c-expression) ...)
+(defparameter *kcl-function-inlines*
+ '((%fboundp (t) compiler::boolean nil nil "(#0)->s.s_gfdef!=OBJNULL")
+ (%symbol-function (t) t nil nil "(#0)->s.s_gfdef")
+ #-akcl (si:structurep (t) compiler::boolean nil nil "type_of(#0)==t_structure")
+ #-akcl (si:%structure-name (t) t nil nil "(#0)->str.str_name")
+ #+akcl (si:%structure-name (t) t nil nil "(#0)->str.str_def->str.str_self[0]")
+ #+new-kcl-wrapper
+ (si:%instance-ref (t t) t nil nil "(#0)->str.str_self[fix(#1)]")
+ #+new-kcl-wrapper
+ (si:%set-instance-ref (t t t) t t nil "(#0)->str.str_self[fix(#1)]=(#2)")
+ (si:%compiled-function-name (t) t nil nil "(#0)->cf.cf_name")
+ (si:%set-compiled-function-name (t t) t t nil "((#0)->cf.cf_name)=(#1)")
+ (cclosurep (t) compiler::boolean nil nil "type_of(#0)==t_cclosure")
+ #+akcl (sfun-p (t) compiler::boolean nil nil "type_of(#0)==t_sfun")
+ (%cclosure-env (t) t nil nil "(#0)->cc.cc_env")
+ (%set-cclosure-env (t t) t t nil "((#0)->cc.cc_env)=(#1)")
+ #+turbo-closure
+ (%cclosure-env-nthcdr (fixnum t) t nil nil "(#1)->cc.cc_turbo[#0]")
+
+ (logxor (fixnum fixnum) fixnum nil nil "((#0) ^ (#1))")))
+
+(defun make-function-inline (inline)
+ (setf (get (car inline) 'compiler::inline-always)
+ (list (if (fboundp 'compiler::flags)
+ (let ((opt (cdr inline)))
+ (list (first opt) (second opt)
+ (logior (if (fourth opt) 1 0) ; allocates-new-storage
+ (if (third opt) 2 0) ; side-effect
+ (if nil 4 0) ; constantp
+ (if (eq (car inline) 'logxor)
+ 8 0)) ;result type from args
+ (fifth opt)))
+ (cdr inline)))))
+
+(defmacro define-inlines ()
+ `(progn
+ ,@(mapcan #'(lambda (inline)
+ (let* ((*package* *the-pcl-package*)
+ (name (intern (format nil "~S inline" (car inline))))
+ (vars (mapcar #'(lambda (type)
+ (declare (ignore type))
+ (gensym))
+ (cadr inline))))
+ `((make-function-inline ',(cons name (cdr inline)))
+ ,@(when (or (every #'(lambda (type) (eq type 't))
+ (cadr inline))
+ (char= #\% (aref (symbol-name (car inline)) 0)))
+ `((defun ,(car inline) ,vars
+ ,@(mapcan #'(lambda (var var-type)
+ (unless (eq var-type 't)
+ `((declare (type ,var-type ,var)))))
+ vars (cadr inline))
+ (,name ,@vars))
+ (make-function-inline ',inline))))))
+ *kcl-function-inlines*)))
+
+(define-inlines)
+)
+
+(defsetf si:%compiled-function-name si:%set-compiled-function-name)
+(defsetf %cclosure-env %set-cclosure-env)
+
+(defun set-function-name-1 (fn new-name ignore)
+ (declare (ignore ignore))
+ (cond ((compiled-function-p fn)
+ (si::turbo-closure fn)
+ ;;(when (symbolp new-name) (proclaim-defgeneric new-name nil))
+ (setf (si:%compiled-function-name fn) new-name))
+ ((and (listp fn)
+ (eq (car fn) 'lambda-block))
+ (setf (cadr fn) new-name))
+ ((and (listp fn)
+ (eq (car fn) 'lambda))
+ (setf (car fn) 'lambda-block
+ (cdr fn) (cons new-name (cdr fn)))))
+ fn)
+
+
+#+akcl (clines "#define AKCL206")
+
+(clines "
+#ifdef AKCL206
+use_fast_links();
+#endif
+
+object set_cclosure (result_cc,value_cc,available_size)
+ object result_cc,value_cc; int available_size;
+{
+ object result_env_tail,value_env_tail; int i;
+#ifdef AKCL206
+ /* If we are currently using fast linking, */
+ /* make sure to remove the link for result_cc. */
+ use_fast_links(3,Cnil,result_cc);
+#endif
+ result_env_tail=result_cc->cc.cc_env;
+ value_env_tail=value_cc->cc.cc_env;
+ for(i=available_size;
+ result_env_tail!=Cnil && i>0;
+ result_env_tail=CMPcdr(result_env_tail), value_env_tail=CMPcdr(value_env_tail))
+ CMPcar(result_env_tail)=CMPcar(value_env_tail), i--;
+ result_cc->cc.cc_self=value_cc->cc.cc_self;
+ result_cc->cc.cc_data=value_cc->cc.cc_data;
+#ifndef AKCL206
+ result_cc->cc.cc_start=value_cc->cc.cc_start;
+ result_cc->cc.cc_size=value_cc->cc.cc_size;
+#endif
+ return result_cc;
+}")
+
+(defentry %set-cclosure (object object int) (object set_cclosure))
+
+
+(defun structure-functions-exist-p ()
+ t)
+
+(si:define-compiler-macro structure-instance-p (x)
+ (once-only (x)
+ `(and (si:structurep ,x)
+ (not (eq (si:%structure-name ,x) 'std-instance)))))
+
+(defun structure-type (x)
+ (and (si:structurep x)
+ (si:%structure-name x)))
+
+(si:define-compiler-macro structure-type (x)
+ (once-only (x)
+ `(and (si:structurep ,x)
+ (si:%structure-name ,x))))
+
+(defun structure-type-p (type)
+ (or (not (null (gethash type *structure-table*)))
+ (let (#+akcl(s-data nil))
+ (and (symbolp type)
+ #+akcl (setq s-data (get type 'si::s-data))
+ #-akcl (get type 'si::is-a-structure)
+ (null #+akcl (si::s-data-type s-data)
+ #-akcl (get type 'si::structure-type))))))
+
+(defun structure-type-included-type-name (type)
+ (or (car (gethash type *structure-table*))
+ #+akcl (let ((includes (si::s-data-includes (get type 'si::s-data))))
+ (when includes
+ (si::s-data-name includes)))
+ #-akcl (get type 'si::structure-include)))
+
+(defun structure-type-internal-slotds (type)
+ #+akcl (si::s-data-slot-descriptions (get type 'si::s-data))
+ #-akcl (get type 'si::structure-slot-descriptions))
+
+(defun structure-type-slot-description-list (type)
+ (or (cdr (gethash type *structure-table*))
+ (mapcan #'(lambda (slotd)
+ #-new-kcl-wrapper
+ (when (and slotd (car slotd))
+ (let ((offset (fifth slotd)))
+ (let ((reader #'(lambda (x)
+ #+akcl (si:structure-ref1 x offset)
+ #-akcl (si:structure-ref x type offset)))
+ (writer #'(lambda (v x)
+ (si:structure-set x type offset v))))
+ #+turbo-closure (si:turbo-closure reader)
+ #+turbo-closure (si:turbo-closure writer)
+ (let* ((reader-sym
+ (let ((*package* *the-pcl-package*))
+ (intern (format nil "~s SLOT~D" type offset))))
+ (writer-sym (get-setf-function-name reader-sym))
+ (slot-name (first slotd))
+ (read-only-p (fourth slotd)))
+ (setf (symbol-function reader-sym) reader)
+ (setf (symbol-function writer-sym) writer)
+ (do-standard-defsetf-1 reader-sym)
+ (list (list slot-name
+ reader-sym
+ reader
+ (and (not read-only-p) writer)))))))
+ #+new-kcl-wrapper
+ (list slotd))
+ (let ((slotds (structure-type-internal-slotds type))
+ (inc (structure-type-included-type-name type)))
+ (if inc
+ (nthcdr (length (structure-type-internal-slotds inc))
+ slotds)
+ slotds)))))
+
+#+new-kcl-wrapper
+(defun si::slot-reader-function (slot)
+ (let ((offset (si::slot-offset slot)))
+ (si:turbo-closure #'(lambda (x)
+ (si::structure-ref1 x offset)))))
+
+#+new-kcl-wrapper
+(defun si::slot-writer-function (slot)
+ (let ((offset (si::slot-offset slot)))
+ (si:turbo-closure #'(lambda (x)
+ (si::structure-set1 x offset)))))
+
+(mapcar #'(lambda (fname value)
+ (setf (symbol-function fname) (symbol-function value)))
+ '(structure-slotd-name
+ structure-slotd-accessor-symbol
+ structure-slotd-reader-function
+ structure-slotd-writer-function
+ structure-slotd-type
+ structure-slotd-init-form)
+ #-new-kcl-wrapper
+ '(first second third fourth function-returning-nil function-returning-nil)
+ #+new-kcl-wrapper
+ '(si::slot-name si::slot-accessor-name
+ si::slot-reader-function si::slot-writer-function
+ si::slot-type si::slot-default-init))
+
+
+;; Construct files sys-proclaim.lisp and sys-package.lisp
+;; The file sys-package.lisp must be loaded first, since the
+;; package sys-proclaim.lisp will refer to symbols and they must
+;; be in the right packages. sys-proclaim.lisp contains function
+;; declarations and declarations that certain things are closures.
+
+(defun renew-sys-files()
+ ;; packages:
+ (compiler::get-packages "sys-package.lisp")
+ (with-open-file (st "sys-package.lisp"
+ :direction :output
+ :if-exists :append)
+ (format st "(in-package 'SI)
+(export '(%structure-name
+ %compiled-function-name
+ %set-compiled-function-name))
+(in-package 'pcl)
+"))
+
+ ;; proclaims
+ (compiler::make-all-proclaims "*.fn")
+ (let ((*package* (find-package 'user)))
+ (with-open-file (st "sys-proclaim.lisp"
+ :direction :output
+ :if-exists :append)
+ ;;(format st "~%(IN-PACKAGE \"PCL\")~%")
+ (print
+ `(dolist (v ',
+
+ (sloop::sloop for v in-package "PCL"
+ when (get v 'compiler::proclaimed-closure)
+ collect v))
+ (setf (get v 'compiler::proclaimed-closure) t))
+ st)
+ (format st "~%")
+ )))
+
+
diff --git a/gcl/pcl/impl/kcl/kcl-mods.text b/gcl/pcl/impl/kcl/kcl-mods.text
new file mode 100644
index 000000000..741e41ac6
--- /dev/null
+++ b/gcl/pcl/impl/kcl/kcl-mods.text
@@ -0,0 +1,224 @@
+If you have akcl version 604 or newer, do not make these patches.
+
+
+(1) Turbo closure patch
+
+To make the turbo closure stuff work, make the following changes to KCL.
+These changes can also work for an IBCL.
+
+The three patches in this file add two features (reflected in the
+value of *features*) to your KCL or IBCL:
+ a feature named :TURBO-CLOSURE which increases the speed of the
+ code generated by FUNCALLABLE-INSTANCE-DATA-1
+ (previous versions of the file kcl-mods.text had this feature only),
+and
+ a feature named :TURBO-CLOSURE-ENV-SIZE which increases the speed
+ of the function FUNCALLABLE-INSTANCE-P.
+
+(This file comprises two features rather than just one to allow the
+PCL system to be work in KCL systems that do not have this patch,
+or that have the old version of this patch.)
+
+
+The first of these patches changes the turbo_closure function to
+store the size of the environment in the turbo structure.
+
+The second of patch fixes a garbage-collector bug in which
+the turbo structure was sometimes ignored, AND also adapts
+the garbage-collector to conform to the change made in the
+first patch. The bug has been fixed in newer versions of
+AKCL, but it is still necessary to apply this patch, if the
+first and third patches are applied.
+
+The third change pushes :turbo-closure and :turbo-closure-env-size
+on the *features* list so that PCL will know that turbo closures
+are enabled.
+
+
+Note that these changes have to be made before PCL is compiled, and a
+PCL which is compiled in a KCL/IBCL with these changes can only be run
+in a KCL/IBCL with these changes.
+
+(1-1) edit the function turbo_closure in the file kcl/c/cfun.c,
+change the lines
+----------
+turbo_closure(fun)
+object fun;
+{
+ object l;
+ int n;
+
+ for (n = 0, l = fun->cc.cc_env; !endp(l); n++, l = l->c.c_cdr)
+ ;
+ fun->cc.cc_turbo = (object *)alloc_contblock(n*sizeof(object));
+ for (n = 0, l = fun->cc.cc_env; !endp(l); n++, l = l->c.c_cdr)
+ fun->cc.cc_turbo[n] = l;
+}
+----------
+to
+----------
+turbo_closure(fun)
+object fun;
+{
+ object l,*block;
+ int n;
+
+ if(fun->cc.cc_turbo==NULL)
+ {for (n = 0, l = fun->cc.cc_env; !endp(l); n++, l = l->c.c_cdr);
+ block=(object *)alloc_contblock((1+n)*sizeof(object));
+ *block=make_fixnum(n);
+ fun->cc.cc_turbo = block+1; /* equivalent to &block[1] */
+ for (n = 0, l = fun->cc.cc_env; !endp(l); n++, l = l->c.c_cdr)
+ fun->cc.cc_turbo[n] = l;}
+}
+----------
+
+
+(1-2) edit the function mark_object in the file kcl/c/gbc.c,
+Find the lines following case t_cclosure: in mark_object.
+If they look like the ones between the lines marked (KCL),
+make the first change, but if the look like the lines marked
+(AKCL), apply the second change instead, and if the file
+sgbc.c exists, apply the third change to it.
+(1-2-1) Change:
+(KCL)----------
+ case t_cclosure:
+ mark_object(x->cc.cc_name);
+ mark_object(x->cc.cc_env);
+ mark_object(x->cc.cc_data);
+ if (x->cc.cc_start == NULL)
+ break;
+ if (what_to_collect == t_contiguous) {
+ if (get_mark_bit((int *)(x->cc.cc_start)))
+ break;
+ mark_contblock(x->cc.cc_start, x->cc.cc_size);
+ if (x->cc.cc_turbo != NULL) {
+ for (i = 0, y = x->cc.cc_env;
+ type_of(y) == t_cons;
+ i++, y = y->c.c_cdr);
+ mark_contblock((char *)(x->cc.cc_turbo),
+ i*sizeof(object));
+ }
+ }
+ break;
+(KCL)----------
+to
+(KCL new)----------
+ case t_cclosure:
+ mark_object(x->cc.cc_name);
+ mark_object(x->cc.cc_env);
+ mark_object(x->cc.cc_data);
+ if (what_to_collect == t_contiguous)
+ if (x->cc.cc_turbo != NULL) {
+ mark_contblock((char *)(x->cc.cc_turbo-1),
+ (1+fix(*(x->cc.cc_turbo-1)))*sizeof(object));
+ }
+ if (x->cc.cc_start == NULL)
+ break;
+ if (what_to_collect == t_contiguous) {
+ if (get_mark_bit((int *)(x->cc.cc_start)))
+ break;
+ mark_contblock(x->cc.cc_start, x->cc.cc_size);
+ }
+ break;
+(KCL new)----------
+(1-2-2) Or, Change:
+(AKCL)----------
+ case t_cclosure:
+ mark_object(x->cc.cc_name);
+ mark_object(x->cc.cc_env);
+ mark_object(x->cc.cc_data);
+ if (what_to_collect == t_contiguous) {
+ if (x->cc.cc_turbo != NULL) {
+ for (i = 0, y = x->cc.cc_env;
+ type_of(y) == t_cons;
+ i++, y = y->c.c_cdr);
+ mark_contblock((char *)(x->cc.cc_turbo),
+ i*sizeof(object));
+ }
+ }
+ break;
+(AKCL)----------
+To:
+(AKCL new)----------
+ case t_cclosure:
+ mark_object(x->cc.cc_name);
+ mark_object(x->cc.cc_env);
+ mark_object(x->cc.cc_data);
+ if (what_to_collect == t_contiguous) {
+ if (x->cc.cc_turbo != NULL)
+ mark_contblock((char *)(x->cc.cc_turbo-1),
+ (1+fix(*(x->cc.cc_turbo-1)))*sizeof(object));
+ }
+ break;
+(AKCL new)----------
+(1-2-3) In sgbc.c (if it exists), Change:
+(AKCL)----------
+ case t_cclosure:
+ sgc_mark_object(x->cc.cc_name);
+ sgc_mark_object(x->cc.cc_env);
+ sgc_mark_object(x->cc.cc_data);
+ if (what_to_collect == t_contiguous) {
+ if (x->cc.cc_turbo != NULL) {
+ for (i = 0, y = x->cc.cc_env;
+ type_of(y) == t_cons;
+ i++, y = y->c.c_cdr);
+ mark_contblock((char *)(x->cc.cc_turbo),
+ i*sizeof(object));
+ }
+ }
+ break;
+(AKCL)----------
+To:
+(AKCL new)----------
+ case t_cclosure:
+ sgc_mark_object(x->cc.cc_name);
+ sgc_mark_object(x->cc.cc_env);
+ sgc_mark_object(x->cc.cc_data);
+ if (what_to_collect == t_contiguous) {
+ if (x->cc.cc_turbo != NULL)
+ mark_contblock((char *)(x->cc.cc_turbo-1),
+ (1+fix(*(x->cc.cc_turbo-1)))*sizeof(object));
+ }
+ break;
+(AKCL new)----------
+
+
+(1-3) edit the function init_main in the file kcl/c/main.c,
+change the lines where setting the value of *features* to add a :turbo-closure
+and a :turbo-closure-env-size into the list in your KCL/IBCL.
+
+For example, in Sun4(SunOS) version of IBCL
+changing the lines:
+----------
+ make_special("*FEATURES*",
+ make_cons(make_ordinary("SUN4"),
+ make_cons(make_ordinary("SPARC"),
+ make_cons(make_ordinary("IEEE-FLOATING-POINT"),
+ make_cons(make_ordinary("UNIX"),
+ make_cons(make_ordinary("BSD"),
+ make_cons(make_ordinary("COMMON"),
+ make_cons(make_ordinary("IBCL"), Cnil))))))));
+----------
+to
+----------
+ make_special("*FEATURES*",
+ make_cons(make_ordinary("SUN4"),
+ make_cons(make_ordinary("SPARC"),
+ make_cons(make_ordinary("IEEE-FLOATING-POINT"),
+ make_cons(make_ordinary("UNIX"),
+ make_cons(make_ordinary("BSD"),
+ make_cons(make_ordinary("COMMON"),
+ make_cons(make_ordinary("IBCL"),
+ make_cons(make_keyword("TURBO-CLOSURE"),
+ make_cons(make_keyword("TURBO-CLOSURE-ENV-SIZE"),
+ Cnil))))))))));
+----------
+But, if the C macro ADD_FEATURE is defined at the end of main.c,
+use it instead.
+Insert the lines:
+ ADD_FEATURE("TURBO-CLOSURE");
+ ADD_FEATURE("TURBO-CLOSURE-ENV-SIZE");
+After the line:
+ ADD_FEATURE("AKCL");
+
diff --git a/gcl/pcl/impl/kcl/kcl-notes.text b/gcl/pcl/impl/kcl/kcl-notes.text
new file mode 100644
index 000000000..fc8a6831e
--- /dev/null
+++ b/gcl/pcl/impl/kcl/kcl-notes.text
@@ -0,0 +1,39 @@
+
+Some notes on using "5/1/90 May Day PCL (REV 4b)" with KCL and AKCL.
+
+1. KCL will try to load the PCL file "init" when it starts up,
+ if you rename the files as is mentioned in defsys.lisp and the
+ currect directory is the one containing PCL. I suggest that
+ you do not rename any file except maybe "defsys", and also
+ that you change the (files-renamed-p t) to (files-renamed-p nil)
+ in defsys.lisp.
+
+2. Do not comment out the file kcl-patches.lisp, even if you are
+ using AKCL. It contins a patch to make compiler messages more
+ informative for AKCL, and also sets compiler::*compile-ordinaries*
+ to T, so that methods will get compiled.
+
+3. While fixup.lisp compiles, there will be a pause, because
+ KCL's compiler is not reentrant, and some uncompiled
+ code is run. If you want, you can change the form
+ (fix-early-generic-functions) to (fix-early-generic-functions t)
+ in fixup.lisp to see what is happening.
+
+4. (If you are using AKCL 605 or newer, skip this step.)
+ If you want, you can apply the changes in kcl-mods.text
+ to your KCL or AKCL to make PCL run faster. The file kcl-mods.text
+ is different from what it was in versions of PCL earlier than
+ May Day PCL. If you do not make these changes, or if you made
+ the old changes, things will still work.
+
+5. If you are using AKCL, and you previously used the kcl-low.lisp
+ file from rascal.ics.utexas.edu, you should not use it this time.
+ The kcl-low.lisp that comes with May Day PCL works fine. (If you
+ insist on using an old version of kcl-low.lisp, you will need to
+ use an old version of the KCL part of fin.lisp as well: this is
+ what is done for IBCL, by the way.)
+
+6. I recommend that you use AKCL version 457 or newer rather than using
+ KCL or an older version of AKCL, because there are some bugs in KCL
+ that cause problems for May Day PCL.
+
diff --git a/gcl/pcl/impl/kcl/kcl-patches.lisp b/gcl/pcl/impl/kcl/kcl-patches.lisp
new file mode 100644
index 000000000..c051d9be3
--- /dev/null
+++ b/gcl/pcl/impl/kcl/kcl-patches.lisp
@@ -0,0 +1,362 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+
+(in-package "COMPILER")
+
+#+akcl
+(eval-when (compile load eval)
+
+(when (<= system::*akcl-version* 609)
+ (pushnew :pre_akcl_610 *features*))
+
+(if (and (boundp 'si::*akcl-version*)
+ (>= si::*akcl-version* 604))
+ (progn
+ (pushnew :turbo-closure *features*)
+ (pushnew :turbo-closure-env-size *features*))
+ (when (fboundp 'si::allocate-growth)
+ (pushnew :turbo-closure *features*)))
+
+;; patch around compiler bug.
+(when (<= si::*akcl-version* 609)
+ (let ((vcs "static int Vcs;
+"))
+ (unless (search vcs compiler::*cmpinclude-string*)
+ (setq compiler::*cmpinclude-string*
+ (concatenate 'string vcs compiler::*cmpinclude-string*)))))
+
+(let ((rset "int Rset;
+"))
+ (unless (search rset compiler::*cmpinclude-string*)
+ (setq compiler::*cmpinclude-string*
+ (concatenate 'string rset compiler::*cmpinclude-string*))))
+
+(when (get 'si::basic-wrapper 'si::s-data)
+ (pushnew :new-kcl-wrapper *features*)
+ (pushnew :structure-wrapper *features*))
+
+)
+
+
+#+akcl
+(progn
+
+(unless (fboundp 'real-c2lambda-expr-with-key)
+ (setf (symbol-function 'real-c2lambda-expr-with-key)
+ (symbol-function 'c2lambda-expr-with-key)))
+
+(defun c2lambda-expr-with-key (lambda-list body)
+ (declare (special *sup-used*))
+ (setq *sup-used* t)
+ (real-c2lambda-expr-with-key lambda-list body))
+
+
+;There is a bug in the implementation of *print-circle* that
+;causes some akcl debugging commands (including :bt and :bl)
+;to cause the following error when PCL is being used:
+;Unrecoverable error: value stack overflow.
+
+;When a CLOS object is printed, travel_push_object ends up
+;traversing almost the whole class structure, thereby overflowing
+;the value-stack.
+
+;from lsp/debug.lsp.
+;*print-circle* is badly implemented in kcl.
+;it has two separate problems that should be fixed:
+; 1. it traverses the printed object putting all objects found
+; on the value stack (rather than in a hash table or some
+; other structure; this is a problem because the size of the value stack
+; is fixed, and a potentially unbounded number of objects
+; need to be traversed), and
+; 2. it blindly traverses all slots of any
+; kind of structure including std-object structures.
+; This is safe, but not always necessary, and is very time-consuming
+; for CLOS objects (because it will always traverse every class).
+
+;For now, avoid using *print-circle* T when it will cause problems.
+
+(eval-when (compile eval)
+(defmacro si::f (op &rest args)
+ `(the fixnum (,op ,@ (mapcar #'(lambda (x) `(the fixnum ,x)) args) )))
+
+(defmacro si::fb (op &rest args)
+ `(,op ,@ (mapcar #'(lambda (x) `(the fixnum ,x)) args) ))
+)
+
+(defun si::display-env (n env)
+ (do ((v (reverse env) (cdr v)))
+ ((or (not (consp v)) (si::fb > (fill-pointer si::*display-string*) n)))
+ (or (and (consp (car v))
+ (listp (cdar v)))
+ (return))
+ (let ((*print-circle* (can-use-print-circle-p (cadar v))))
+ (format si::*display-string* "~s=~s~@[,~]" (caar v) (cadar v) (cdr v)))))
+
+(defun si::display-compiled-env ( plength ihs &aux
+ (base (si::ihs-vs ihs))
+ (end (min (si::ihs-vs (1+ ihs)) (si::vs-top))))
+ (format si::*display-string* "")
+ (do ((i base )
+ (v (get (si::ihs-fname ihs) 'si::debug) (cdr v)))
+ ((or (si::fb >= i end)(si::fb > (fill-pointer si::*display-string*) plength)))
+ (let ((*print-circle* (can-use-print-circle-p (si::vs i))))
+ (format si::*display-string* "~a~@[~d~]=~s~@[,~]"
+ (or (car v) 'si::loc) (if (not (car v)) (si::f - i base)) (si::vs i)
+ (si::fb < (setq i (si::f + i 1)) end)))))
+
+(clines "#define objnull_p(x) ((x==OBJNULL)?Ct:Cnil)")
+(defentry objnull-p (object) (object "objnull_p"))
+
+(defun can-use-print-circle-p (x)
+ (catch 'can-use-print-circle-p
+ (can-use-print-circle-p1 x nil)))
+
+(defun can-use-print-circle-p1 (x so-far)
+ (and (not (objnull-p x)) ; because of deficiencies in the compiler, maybe?
+ (if (member x so-far)
+ (throw 'can-use-print-circle-p t)
+ (let ((so-far (cons x so-far)))
+ (flet ((can-use-print-circle-p (x)
+ (can-use-print-circle-p1 x so-far)))
+ (typecase x
+ (vector (or (not (eq 't (array-element-type x)))
+ (every #'can-use-print-circle-p x)))
+ (cons (and (can-use-print-circle-p (car x))
+ (can-use-print-circle-p (cdr x))))
+ (array (or (not (eq 't (array-element-type x)))
+ (let* ((rank (array-rank x))
+ (dimensions (make-list rank)))
+ (dotimes (i rank)
+ (setf (nth i dimensions) (array-dimension x i)))
+ (or (member 0 dimensions)
+ (do ((cursor (make-list rank :initial-element 0)))
+ (nil)
+ (declare (:dynamic-extent cursor))
+ (unless (can-use-print-circle-p
+ (apply #'aref x cursor))
+ (return nil))
+ (when (si::increment-cursor cursor dimensions)
+ (return t)))))))
+ (t (or (not (si:structurep x))
+ (let* ((def (si:structure-def x))
+ (name (si::s-data-name def))
+ (len (si::s-data-length def))
+ (pfun (si::s-data-print-function def)))
+ (and (null pfun)
+ (dotimes (i len t)
+ (unless (can-use-print-circle-p
+ (si:structure-ref x name i))
+ (return nil)))))))))))))
+
+(defun si::apply-display-fun (display-fun n lis)
+ (let ((*print-length* si::*debug-print-level*)
+ (*print-level* si::*debug-print-level*)
+ (*print-pretty* nil)
+ (*PRINT-CASE* :downcase)
+ (*print-circle* nil)
+ )
+ (setf (fill-pointer si::*display-string*) 0)
+ (format si::*display-string* "{")
+ (funcall display-fun n lis)
+ (when (si::fb > (fill-pointer si::*display-string*) n)
+ (setf (fill-pointer si::*display-string*) n)
+ (format si::*display-string* "..."))
+
+ (format si::*display-string* "}")
+ )
+ si::*display-string*
+ )
+
+;The old definition of this had a bug:
+;sometimes it returned without calling mv-values.
+(defun si::next-stack-frame (ihs &aux line-info li i k na)
+ (cond ((si::fb < ihs si::*ihs-base*)
+ (si::mv-values nil nil nil nil nil))
+ ((let (fun)
+ ;; next lower visible ihs
+ (si::mv-setq (fun i) (si::get-next-visible-fun ihs))
+ (setq na fun)
+ (cond ((and (setq line-info (get fun 'si::line-info))
+ (do ((j (si::f + ihs 1) (si::f - j 1))
+ (form ))
+ ((<= j i) nil)
+ (setq form (si::ihs-fun j))
+ (cond ((setq li (si::get-line-of-form form line-info))
+ (return-from si::next-stack-frame
+ (si::mv-values
+ i fun li
+ ;; filename
+ (car (aref line-info 0))
+ ;;environment
+ (list (si::vs (setq k (si::ihs-vs j)))
+ (si::vs (1+ k))
+ (si::vs (+ k 2)))))))))))))
+ ((and (not (special-form-p na))
+ (not (get na 'si::dbl-invisible))
+ (fboundp na))
+ (si::mv-values i na nil nil
+ (if (si::ihs-not-interpreted-env i)
+ nil
+ (let ((i (si::ihs-vs i)))
+ (list (si::vs i) (si::vs (1+ i)) (si::vs (si::f + i 2)))))))
+ (t (si::mv-values nil nil nil nil nil))))
+)
+
+#+pre_akcl_610
+(progn
+
+;(proclaim '(optimize (safety 0) (speed 3) (space 1)))
+
+;Not needed... make-top-level-form generates defuns now.
+;(setq compiler::*compile-ordinaries* t)
+
+(eval-when (compile load eval)
+(unless (fboundp 'original-co1typep)
+ (setf (symbol-function 'original-co1typep) #'co1typep))
+)
+
+(defun new-co1typep (f args)
+ (or (original-co1typep f args)
+ (let ((x (car args))
+ (type (cadr args)))
+ (when (constantp type)
+ (let ((ntype (si::normalize-type (eval type))))
+ (when (and (eq (car ntype) 'satisfies)
+ (cadr ntype)
+ (symbolp (cadr ntype))
+ (symbol-package (cadr ntype)))
+ (c1expr `(the boolean (,(cadr ntype) ,x)))))))))
+
+(setf (symbol-function 'co1typep) #'new-co1typep)
+
+)
+
+#-(or akcl xkcl)
+(progn
+(in-package 'system)
+
+;;; This makes DEFMACRO take &WHOLE and &ENVIRONMENT args anywhere
+;;; in the lambda-list. The former allows deviation from the CL spec,
+;;; but what the heck.
+
+(eval-when (compile) (proclaim '(optimize (safety 2) (space 3))))
+
+(defvar *old-defmacro*)
+
+(defun new-defmacro (whole env)
+ (flet ((call-old-definition (new-whole)
+ (funcall *old-defmacro* new-whole env)))
+ (if (not (and (consp whole)
+ (consp (cdr whole))
+ (consp (cddr whole))
+ (consp (cdddr whole))))
+ (call-old-definition whole)
+ (let* ((ll (caddr whole))
+ (env-tail (do ((tail ll (cdr tail)))
+ ((not (consp tail)) nil)
+ (when (eq '&environment (car tail))
+ (return tail)))))
+ (if env-tail
+ (call-old-definition (list* (car whole)
+ (cadr whole)
+ (append (list '&environment
+ (cadr env-tail))
+ (ldiff ll env-tail)
+ (cddr env-tail))
+ (cdddr whole)))
+ (call-old-definition whole))))))
+
+(eval-when (load eval)
+ (unless (boundp '*old-defmacro*)
+ (setq *old-defmacro* (macro-function 'defmacro))
+ (setf (macro-function 'defmacro) #'new-defmacro)))
+
+;;;
+;;; setf patches
+;;;
+
+(defun get-setf-method (form)
+ (multiple-value-bind (vars vals stores store-form access-form)
+ (get-setf-method-multiple-value form)
+ (unless (listp vars)
+ (error
+ "The temporary variables component, ~s,
+ of the setf-method for ~s is not a list."
+ vars form))
+ (unless (listp vals)
+ (error
+ "The values forms component, ~s,
+ of the setf-method for ~s is not a list."
+ vals form))
+ (unless (listp stores)
+ (error
+ "The store variables component, ~s,
+ of the setf-method for ~s is not a list."
+ stores form))
+ (unless (= (list-length stores) 1)
+ (error "Multiple store-variables are not allowed."))
+ (values vars vals stores store-form access-form)))
+
+(defun get-setf-method-multiple-value (form)
+ (cond ((symbolp form)
+ (let ((store (gensym)))
+ (values nil nil (list store) `(setq ,form ,store) form)))
+ ((or (not (consp form)) (not (symbolp (car form))))
+ (error "Cannot get the setf-method of ~S." form))
+ ((get (car form) 'setf-method)
+ (apply (get (car form) 'setf-method) (cdr form)))
+ ((get (car form) 'setf-update-fn)
+ (let ((vars (mapcar #'(lambda (x)
+ (declare (ignore x))
+ (gensym))
+ (cdr form)))
+ (store (gensym)))
+ (values vars (cdr form) (list store)
+ `(,(get (car form) 'setf-update-fn)
+ ,@vars ,store)
+ (cons (car form) vars))))
+ ((get (car form) 'setf-lambda)
+ (let* ((vars (mapcar #'(lambda (x)
+ (declare (ignore x))
+ (gensym))
+ (cdr form)))
+ (store (gensym))
+ (l (get (car form) 'setf-lambda))
+ (f `(lambda ,(car l)
+ (funcall #'(lambda ,(cadr l) ,@(cddr l))
+ ',store))))
+ (values vars (cdr form) (list store)
+ (apply f vars)
+ (cons (car form) vars))))
+ ((macro-function (car form))
+ (get-setf-method-multiple-value (macroexpand-1 form)))
+ (t
+ (error "Cannot expand the SETF form ~S." form))))
+
+)
+
diff --git a/gcl/pcl/impl/kcl/makefile.akcl b/gcl/pcl/impl/kcl/makefile.akcl
new file mode 100644
index 000000000..057a3f9de
--- /dev/null
+++ b/gcl/pcl/impl/kcl/makefile.akcl
@@ -0,0 +1,32 @@
+# makefile for making pcl -- W. Schelter.
+
+# Directions:
+# make -f makefile.akcl compile
+# make -f makefile.akcl saved_pcl
+
+SHELL=/bin/sh
+
+LISP=akcl
+
+
+SETUP='(load "pkg.lisp")(load "defsys.lisp")' \
+ '(setq pcl::*default-pathname-extensions* (cons "lisp" "o"))' \
+ '(setq pcl::*pathname-extensions* (cons "lisp" "o"))' \
+ '(load "sys-proclaim.lisp")(compiler::emit-fn t)'
+
+compile:
+ echo ${SETUP} '(pcl::compile-pcl)' | ${LISP}
+
+saved_pcl:
+ echo ${SETUP} '(pcl::load-pcl)(si::save-system "saved_pcl")' | ${LISP}
+
+
+# remake the sys-package.lisp and sys-proclaim.lisp files
+# Those files may be empty on a first build.
+remake-sys-files:
+ echo ${SETUP} '(pcl::load-pcl)(in-package "PCL")(renew-sys-files)' | ${LISP}
+ cp sys-proclaim.lisp xxx
+ cat xxx | sed -e "s/COMPILER::CMP-ANON//g" > sys-proclaim.lisp
+
+clean:
+ rm -f *.o
diff --git a/gcl/pcl/impl/kcl/misc-kcl-patches.text b/gcl/pcl/impl/kcl/misc-kcl-patches.text
new file mode 100644
index 000000000..54bb9c718
--- /dev/null
+++ b/gcl/pcl/impl/kcl/misc-kcl-patches.text
@@ -0,0 +1,340 @@
+c/cmpaux.c
+*** c/cmpaux.c Mon Jul 6 00:14:55 1992
+--- ../akcl-1-615/c/cmpaux.c Thu Jun 18 20:01:07 1992
+***************
+*** 229,239 ****
+ if (leng > 0 && leng < x->st.st_dim && x->st.st_self[leng]==0)
+ return x->st.st_self;
+ if (x->st.st_dim == leng
+ && ( leng % sizeof(object))
+ )
+! { x->st.st_self[leng] = 0;
+ return x->st.st_self;
+ }
+ else
+ {char *res=malloc(leng+1);
+ bcopy(x->st.st_self,res,leng);
+--- 229,240 ----
+ if (leng > 0 && leng < x->st.st_dim && x->st.st_self[leng]==0)
+ return x->st.st_self;
+ if (x->st.st_dim == leng
+ && ( leng % sizeof(object))
+ )
+! { if(x->st.st_self[leng] != 0)
+! x->st.st_self[leng] = 0;
+ return x->st.st_self;
+ }
+ else
+ {char *res=malloc(leng+1);
+ bcopy(x->st.st_self,res,leng);
+c/main.c
+*** c/main.c Mon Jul 6 00:14:59 1992
+--- ../akcl-1-615/c/main.c Fri Jul 3 02:19:37 1992
+***************
+*** 611,621 ****
+ {catch_fatal = -1;
+ if (sgc_enabled)
+ { sgc_quit();}
+ if (sgc_enabled==0)
+ { install_segmentation_catcher() ;}
+! FEerror("Caught fatal error [memory may be damaged]"); }
+ printf("\nUnrecoverable error: %s.\n", s);
+ fflush(stdout);
+ #ifdef UNIX
+ abort();
+ #endif
+--- 611,621 ----
+ {catch_fatal = -1;
+ if (sgc_enabled)
+ { sgc_quit();}
+ if (sgc_enabled==0)
+ { install_segmentation_catcher() ;}
+! FEerror("Caught fatal error [memory may be damaged] ~A",1,make_simple_string(s)); }
+ printf("\nUnrecoverable error: %s.\n", s);
+ fflush(stdout);
+ #ifdef UNIX
+ abort();
+ #endif
+***************
+*** 853,872 ****
+
+ siLsave_system()
+ {
+ int i;
+
+- #ifdef HAVE_YP_UNBIND
+- extern object truename(),namestring();
+ check_arg(1);
+! /* prevent subsequent consultation of yp by getting
+! truename now*/
+! vs_base[0]=namestring(truename(vs_base[0]));
+! {char name[200];
+! char *dom = name;
+! if (0== getdomainname(dom,sizeof(name)))
+! yp_unbind(dom);}
+ #endif
+
+ saving_system = TRUE;
+ GBC(t_contiguous);
+
+--- 853,867 ----
+
+ siLsave_system()
+ {
+ int i;
+
+ check_arg(1);
+! #ifdef HAVE_YP_UNBIND
+! /* see unixsave.c */
+! {char *dname;
+! yp_get_default_domain(&dname);}
+ #endif
+
+ saving_system = TRUE;
+ GBC(t_contiguous);
+
+c/num_log.c
+*** c/num_log.c Mon Jul 6 00:15:00 1992
+--- ../akcl-1-615/c/num_log.c Mon Jun 15 21:15:59 1992
+***************
+*** 266,286 ****
+ return(~j);
+ }
+
+ int
+ big_bitp(x, p)
+! object x;
+! int p;
+ { GEN u = MP(x);
+ int ans ;
+ int i = p /32;
+ if (signe(u) < 0)
+ { save_avma;
+ u = complementi(u);
+ restore_avma;
+ }
+! if (i < lgef(u))
+ { ans = ((MP_ITH_WORD(u,i,lgef(u))) & (1 << p%32));}
+ else if (big_sign(x) < 0) ans = 1;
+ else ans = 0;
+ return ans;
+ }
+--- 266,286 ----
+ return(~j);
+ }
+
+ int
+ big_bitp(x, p)
+! object x;
+! int p;
+ { GEN u = MP(x);
+ int ans ;
+ int i = p /32;
+ if (signe(u) < 0)
+ { save_avma;
+ u = complementi(u);
+ restore_avma;
+ }
+! if (i < lgef(u) -MP_CODE_WORDS)
+ { ans = ((MP_ITH_WORD(u,i,lgef(u))) & (1 << p%32));}
+ else if (big_sign(x) < 0) ans = 1;
+ else ans = 0;
+ return ans;
+ }
+c/unixsave.c
+*** c/unixsave.c Mon Jul 6 00:15:07 1992
+--- ../akcl-1-615/c/unixsave.c Fri Jul 3 02:52:36 1992
+***************
+*** 71,81 ****
+--- 71,160 ----
+ break;
+ } else
+ break;
+ }
+
++ #include "page.h"
+
++ /* string is aligned on a word boundary */
++ int
++ find_string_in_memory(string,length,other_p,function)
++ char *string;
++ int length,other_p;
++ int *function();
++ {
++ int *imem_first,*imem_last,*imem,word;
++ char *mem;
++ int len,page_first,page_last,i;
++ int maxpage = page(heap_end);
++ if(((int)string & 3) == 0 && length >= 4) /* just to be safe */
++ {word=*(int *)string;
++ for (page_first = 0; page_first < maxpage; page_first++)
++ if ((enum type)type_map[page_first] != t_other)
++ break;
++ for (; page_first < maxpage; page_first++)
++ if (((enum type)type_map[page_first] == t_other)?other_p:!other_p)
++ {for (page_last = page_first+1; page_last < maxpage; page_last++)
++ if ( !(((enum type)type_map[page_last] == t_other)?other_p:!other_p) )
++ break;
++ imem_first=(int *)pagetochar(page_first);
++ imem_last=(int *)( ( ((int)pagetochar(page_last)) - length) &~3 );
++ for (imem = imem_first; imem <= imem_last; imem++)
++ if (*imem == word)
++ {mem=(char *)imem;
++ for(i=4; i<length && mem[i]==string[i]; i++);
++ if(i>=length)
++ if((*function)(mem))
++ return TRUE;}}}
++ return FALSE;
++ }
++
++ int
++ fsim_first(address)
++ char *address;
++ {
++ return TRUE;
++ }
++
++ int
++ fsim_reset_pointer(address)
++ char **address;
++ {
++ *address = NULL;
++ return FALSE;
++ }
++
++ #define t_other_PAGES TRUE
++ #define NOT_t_other_PAGES FALSE
++
++ int
++ reset_other_pointers(address)
++ char *address;
++ {
++ int word=(int)address;
++ find_string_in_memory(&word,4,t_other_PAGES,fsim_reset_pointer);
++ }
++
++ int
++ maybe_reset_pointers(address)
++ char *address;
++ {
++ int word=(int)address;
++ if(!find_string_in_memory(&word,4,NOT_t_other_PAGES,fsim_first))
++ reset_other_pointers(address);
++ return FALSE;
++ }
++
++ reset_other_pointers_to_string(string)
++ char *string;
++ {
++ int length=strlen(string)+1;
++ find_string_in_memory(string,length,t_other_PAGES,maybe_reset_pointers);
++ }
++
++ bool saving_system;
++
+ memory_save(original_file, save_file)
+ char *original_file, *save_file;
+ { MEM_SAVE_LOCALS;
+ char *data_begin, *data_end;
+ int original_data;
+***************
+*** 100,110 ****
+--- 179,206 ----
+ n = open(save_file, O_CREAT|O_WRONLY, 0777);
+ if (n != 1 || (save = fdopen(n, "w")) != stdout) {
+ fprintf(stderr, "Can't open the save file.\n");
+ exit(1);
+ }
++
+ setbuf(save, stdout_buf);
++
++ #ifdef HAVE_YP_UNBIND
++ /* yp_get_default_domain() caches the result of getdomainname() in
++ a malloc'ed block of memory; and gethostbyname saves the result of
++ yp_get_default_domain() in yet another chunk of memory. These
++ cached values will cause problems if the saved image is run on a
++ machine having a different local domainname. [When getdomainname
++ is called (by CLX, for example) KCL will wait forever.] There doesn't
++ seem to be any way to uncache these things (apparently yp_unbind does
++ not do this), nor any good way to find these blocks of memory. */
++
++ if(saving_system)
++ {char *dname;
++ yp_get_default_domain(&dname);
++ reset_other_pointers(dname);}
++ #endif
+
+ READ_HEADER;
+ FILECPY_HEADER;
+
+ for (n = header.a_data, p = data_begin; ; n -= BUFSIZ, p += BUFSIZ)
+cmpnew/cmpcall.lsp
+*** cmpnew/cmpcall.lsp Mon Jul 6 00:15:13 1992
+--- ../akcl-1-615/cmpnew/cmpcall.lsp Thu Jun 18 21:43:24 1992
+***************
+*** 118,127 ****
+--- 118,128 ----
+ ;;; responsible for maintaining this condition.
+ (let ((*vs* *vs*) (form (caddr funob)))
+ (declare (object form))
+ (cond ((and (listp args)
+ *use-sfuncall*
++ (<= (length (cdr args)) 10)
+ ;;Determine if only one value at most is required:
+ (or
+ (eq *value-to-go* 'trash)
+ (and (consp *value-to-go*)
+ (eq (car *value-to-go*) 'var))
+lsp/autoload.lsp
+*** lsp/autoload.lsp Mon Jul 6 00:15:27 1992
+--- ../akcl-1-615/lsp/autoload.lsp Tue Jun 16 02:36:45 1992
+***************
+*** 430,440 ****
+ '(cons
+ fixnum bignum ratio short-float long-float complex
+ character symbol package hash-table
+ array vector string bit-vector
+ structure stream random-state readtable pathname
+! cfun cclosure sfun gfun cfdata spice fat-string ))
+
+ (defun room (&optional x)
+ (let ((l (multiple-value-list (si:room-report)))
+ maxpage leftpage ncbpage maxcbpage ncb cbgbccount npage
+ rbused rbfree nrbpage
+--- 430,440 ----
+ '(cons
+ fixnum bignum ratio short-float long-float complex
+ character symbol package hash-table
+ array vector string bit-vector
+ structure stream random-state readtable pathname
+! cfun cclosure sfun gfun vfun cfdata spice fat-string dclosure))
+
+ (defun room (&optional x)
+ (let ((l (multiple-value-list (si:room-report)))
+ maxpage leftpage ncbpage maxcbpage ncb cbgbccount npage
+ rbused rbfree nrbpage
+lsp/cmpinit.lsp
+*** lsp/cmpinit.lsp Mon Jul 6 00:15:28 1992
+--- ../akcl-1-615/lsp/cmpinit.lsp Mon Jun 22 17:11:11 1992
+***************
+*** 4,12 ****
+ (setq compiler::*eval-when-defaults* '(compile eval load))
+ (or (fboundp 'si::get-&environment) (load "defmacro.lsp"))
+ ;(or (get 'si::s-data 'si::s-data)
+ ; (progn (load "../lsp/setf.lsp") (load "../lsp/defstruct.lsp")))
+ (if (probe-file "sys-proclaim.lisp")(load "sys-proclaim.lisp"))
+!
+!
+
+ ;;;;;
+--- 4,13 ----
+ (setq compiler::*eval-when-defaults* '(compile eval load))
+ (or (fboundp 'si::get-&environment) (load "defmacro.lsp"))
+ ;(or (get 'si::s-data 'si::s-data)
+ ; (progn (load "../lsp/setf.lsp") (load "../lsp/defstruct.lsp")))
+ (if (probe-file "sys-proclaim.lisp")(load "sys-proclaim.lisp"))
+! (unless (get 'si::basic-wrapper 'si::s-data)
+! (setf (get 'si::s-data 'si::s-data) nil)
+! (load "../lsp/defstruct.lsp"))
+
+ ;;;;;
diff --git a/gcl/pcl/impl/kcl/new-kcl-wrapper.text b/gcl/pcl/impl/kcl/new-kcl-wrapper.text
new file mode 100644
index 000000000..7f161a6c5
--- /dev/null
+++ b/gcl/pcl/impl/kcl/new-kcl-wrapper.text
@@ -0,0 +1,2157 @@
+The new-kcl-wrapper modifications make the storage of standard-objects
+and structure objects much more similar than before. These changes should
+greatly speed up WRAPPER-OF for structure objects and should speed up
+WRAPPER-OF for standard-instances also (but not funcallable instances).
+
+Look first at the defstructs defined here (scan this file for "(defstruct (").
+Then look at cache.lisp, at the "#+structure-wrapper" for the new definition of
+the wrapper structure. Finally, look in low.lisp, at the
+"#+new-structure-wrapper" for the definition of %allocate-instance--class.
+
+You need to have akcl-1-615 to use this file.
+
+This file contains new versions of the files V/c/structure.c and
+V/lsp/defstruct.lsp, as well as small changes to the files c/gbc.c, c/sgbc.c,
+cmpnew/cmpinit.lsp, lsp/cmpinit.lsp, and lsp/describe.lsp.
+
+-- The gbc changes allow the garbage collector to work correctly even when
+structures which define other structures (ones which can be the value of
+STRUCTURE-DEF) are not allocated in static storage.
+
+
+c/gbc.c
+*** c/gbc.c Tue Jun 30 04:11:00 1992
+--- ../akcl-1-615/c/gbc.c Tue Jun 30 02:48:04 1992
+***************
+*** 427,453 ****
+ break;
+ goto COPY_STRING;
+
+ case t_structure:
+ mark_object(x->str.str_def);
+ p = x->str.str_self;
+ if (p == NULL)
+! break;
+! {object def=x->str.str_def;
+! unsigned char * s_type = &SLOT_TYPE(def,0);
+! unsigned short *s_pos= & SLOT_POS(def,0);
+! for (i = 0, j = S_DATA(def)->length; i < j; i++)
+ if (s_type[i]==0) mark_object(STREF(object,x,s_pos[i]));
+ if ((int)what_to_collect >= (int)t_contiguous) {
+ if (inheap(x->str.str_self)) {
+ if (what_to_collect == t_contiguous)
+ mark_contblock((char *)p,
+! S_DATA(def)->size);
+
+ } else
+! x->str.str_self = (object *)
+! copy_relblock((char *)p, S_DATA(def)->size);
+ }}
+ break;
+
+ case t_stream:
+ switch (x->sm.sm_mode) {
+--- 427,461 ----
+ break;
+ goto COPY_STRING;
+
+ case t_structure:
++ x->d.m = 2;
+ mark_object(x->str.str_def);
+ p = x->str.str_self;
+ if (p == NULL)
+! {x->d.m = TRUE; break;}
+! {object def=x->str.str_def;
+! struct s_data *sdef=S_DATA(def);
+! unsigned char *s_type;
+! unsigned short *s_pos;
+! if((int)what_to_collect >= (int)t_contiguous &&
+! !inheap(sdef) && def->d.m==TRUE)
+! sdef=(struct s_data *)(((char *)sdef)+(rb_start1-rb_start));
+! s_type = sdef->raw->ust.ust_self;
+! s_pos = &USHORT(sdef->slot_position,0);
+! for (i = 0, j = sdef->length; i < j; i++)
+ if (s_type[i]==0) mark_object(STREF(object,x,s_pos[i]));
+ if ((int)what_to_collect >= (int)t_contiguous) {
+ if (inheap(x->str.str_self)) {
+ if (what_to_collect == t_contiguous)
+ mark_contblock((char *)p,
+! sdef->size);
+
+ } else
+! x->str.str_self = (object *)
+! copy_relblock((char *)p, sdef->size);
+ }}
++ x->d.m = TRUE;
+ break;
+
+ case t_stream:
+ switch (x->sm.sm_mode) {
+*** c/sgbc.c Mon Jun 15 21:16:01 1992
+--- akcl-1-615/c/sgbc.c Wed Jul 1 18:37:24 1992
+***************
+*** 355,386 ****
+ if (cp == NULL)
+ break;
+ goto COPY_STRING;
+
+ case t_structure:
+ sgc_mark_object(x->str.str_def);
+ p = x->str.str_self;
+ if (p == NULL)
+! break;
+! {object def=x->str.str_def;
+! unsigned char * s_type = &SLOT_TYPE(def,0);
+! unsigned short *s_pos= & SLOT_POS(def,0);
+! for (i = 0, j = S_DATA(def)->length; i < j; i++)
+ if (s_type[i]==0 &&
+ ON_WRITABLE_PAGE(& STREF(object,x,s_pos[i]))
+ )
+ sgc_mark_object(STREF(object,x,s_pos[i]));
+ if ((int)what_to_collect >= (int)t_contiguous) {
+ if (inheap(x->str.str_self)) {
+ if (what_to_collect == t_contiguous)
+ mark_contblock((char *)p,
+! S_DATA(def)->size);
+
+ } else if(SGC_RELBLOCK_P(p))
+ x->str.str_self = (object *)
+! copy_relblock((char *)p, S_DATA(def)->size);
+ }}
+ break;
+
+ case t_stream:
+ switch (x->sm.sm_mode) {
+ case smm_input:
+--- 355,394 ----
+ if (cp == NULL)
+ break;
+ goto COPY_STRING;
+
+ case t_structure:
++ x->d.m = 2;
+ sgc_mark_object(x->str.str_def);
+ p = x->str.str_self;
+ if (p == NULL)
+! {x->d.m = TRUE; break;}
+! {object def=x->str.str_def;
+! struct s_data *sdef=S_DATA(def);
+! unsigned char *s_type;
+! unsigned short *s_pos;
+! if((int)what_to_collect >= (int)t_contiguous &&
+! !inheap(sdef) && def->d.m==TRUE)
+! sdef=(struct s_data *)(((char *)sdef)+(rb_start1-rb_start));
+! s_type = sdef->raw->ust.ust_self;
+! s_pos = &USHORT(sdef->slot_position,0);
+! for (i = 0, j = sdef->length; i < j; i++)
+ if (s_type[i]==0 &&
+ ON_WRITABLE_PAGE(& STREF(object,x,s_pos[i]))
+ )
+ sgc_mark_object(STREF(object,x,s_pos[i]));
+ if ((int)what_to_collect >= (int)t_contiguous) {
+ if (inheap(x->str.str_self)) {
+ if (what_to_collect == t_contiguous)
+ mark_contblock((char *)p,
+! sdef->size);
+
+ } else if(SGC_RELBLOCK_P(p))
+ x->str.str_self = (object *)
+! copy_relblock((char *)p, sdef->size);
+ }}
++ x->d.m = TRUE;
+ break;
+
+ case t_stream:
+ switch (x->sm.sm_mode) {
+ case smm_input:
+cmpnew/cmpinit.lsp
+*** cmpnew/cmpinit.lsp Tue Jun 30 04:11:13 1992
+--- ../akcl-1-615/cmpnew/cmpinit.lsp Mon Jun 22 18:41:51 1992
+***************
+*** 4,7 ****
+--- 4,10 ----
+ (load "sys-proclaim.lisp")
+ (setq compiler::*eval-when-defaults* '(compile eval load))
+
+ ;(dolist (v '( cmpeval cmpopt cmptype cmpbind cmpinline cmploc cmpvar cmptop cmplet cmpcall cmpmulti cmplam cmplabel cmpeval)) (load (format nil "~(~a~).lsp" v)))
++ (unless (get 'si::basic-wrapper 'si::s-data)
++ (setf (get 'si::s-data 'si::s-data) nil)
++ (load "../lsp/defstruct.lsp"))
+lsp/cmpinit.lsp
+*** lsp/cmpinit.lsp Tue Jun 30 04:11:26 1992
+--- ../akcl-1-615/lsp/cmpinit.lsp Mon Jun 22 17:11:11 1992
+***************
+*** 5,12 ****
+ (or (fboundp 'si::get-&environment) (load "defmacro.lsp"))
+ ;(or (get 'si::s-data 'si::s-data)
+ ; (progn (load "../lsp/setf.lsp") (load "../lsp/defstruct.lsp")))
+ (if (probe-file "sys-proclaim.lisp")(load "sys-proclaim.lisp"))
+!
+!
+
+ ;;;;;
+--- 5,13 ----
+ (or (fboundp 'si::get-&environment) (load "defmacro.lsp"))
+ ;(or (get 'si::s-data 'si::s-data)
+ ; (progn (load "../lsp/setf.lsp") (load "../lsp/defstruct.lsp")))
+ (if (probe-file "sys-proclaim.lisp")(load "sys-proclaim.lisp"))
+! (unless (get 'si::basic-wrapper 'si::s-data)
+! (setf (get 'si::s-data 'si::s-data) nil)
+! (load "../lsp/defstruct.lsp"))
+
+ ;;;;;
+lsp/describe.lsp
+*** lsp/describe.lsp Tue Jun 30 04:11:27 1992
+--- ../akcl-1-615/lsp/describe.lsp Tue Jun 23 16:39:07 1992
+***************
+*** 266,282 ****
+
+ (defun inspect-structure (x &aux name)
+ (format t "Structure of type ~a ~%Byte:[Slot Type]Slot Name :Slot Value"
+ (setq name (type-of x)))
+! (let* ((sd (get name 'si::s-data))
+ (spos (s-data-slot-position sd)))
+ (dolist (v (s-data-slot-descriptions sd))
+ (format t "~%~4d:~@[[~s] ~]~20a:~s"
+! (aref spos (nth 4 v))
+! (let ((type (nth 2 v)))
+ (if (eq t type) nil type))
+! (car v)
+! (structure-ref1 x (nth 4 v))))))
+
+
+ (defun inspect-object (object &aux (*inspect-level* *inspect-level*))
+ (inspect-indent)
+--- 266,282 ----
+
+ (defun inspect-structure (x &aux name)
+ (format t "Structure of type ~a ~%Byte:[Slot Type]Slot Name :Slot Value"
+ (setq name (type-of x)))
+! (let* ((sd (structure-def x))
+ (spos (s-data-slot-position sd)))
+ (dolist (v (s-data-slot-descriptions sd))
+ (format t "~%~4d:~@[[~s] ~]~20a:~s"
+! (aref spos (slot-offset v))
+! (let ((type (slot-type v)))
+ (if (eq t type) nil type))
+! (slot-name v)
+! (structure-ref1 x (slot-offset v))))))
+
+
+ (defun inspect-object (object &aux (*inspect-level* *inspect-level*))
+ (inspect-indent)
+==============================================================================
+=============================== c/structure.c ================================
+Changes file for /kcl/c/structure.c
+Usage \n@s[Original text\n@s|Replacement Text\n@s]
+See the file rascal.ics.utexas.edu:/usr2/ftp/merge.c
+for a program to merge change files. Anything not between
+ "\n@s[" and "\n@s]" is a simply a comment.
+This file was constructed using emacs and merge.el
+ by (Bill Schelter) wfs@carl.ma.utexas.edu
+
+
+****Change:(orig (15 17 d))
+@s[object siSstructure_print_function;
+object siSstructure_slot_descriptions;
+object siSstructure_include;
+
+@s|
+@s]
+
+
+****Change:(orig (18 18 a))
+@s[
+
+@s|
+#define COERCE_DEF(x) if (type_of(x)==t_symbol) \
+ x=getf(x->s.s_plist,siLs_data,Cnil)
+
+#define check_type_structure(x) \
+ if(type_of((x))!=t_structure) \
+ FEwrong_type_argument(Sstructure,(x))
+
+
+
+@s]
+
+
+****Change:(orig (22 31 c))
+@s[{
+ do {
+ if (type_of(x) != t_symbol)
+ return(FALSE);
+
+@s, } while (x != Cnil);
+ return(FALSE);
+}
+
+@s|{ if (x==y) return 1;
+ if (type_of(x)!= t_structure
+ || type_of(y)!=t_structure)
+ FEerror("bad call to structure_subtypep",0);
+ {if (S_DATA(y)->included == Cnil) return 0;
+ while ((x=S_DATA(x)->includes) != Cnil)
+ { if (x==y) return 1;}
+ return 0;
+ }}
+
+@s]
+
+
+****Change:(orig (32 32 a))
+@s[
+
+@s|
+static
+bad_raw_type()
+{ FEerror("Bad raw struct type",0);}
+
+
+
+@s]
+
+
+****Change:(orig (34 34 c))
+@s[structure_ref(x, name, n)
+
+@s|structure_ref(x, name, i)
+
+@s]
+
+
+****Change:(orig (36 38 c))
+@s[object x, name;
+int n;
+{
+ int i;
+
+@s|object x, name;
+int i;
+{unsigned short *s_pos;
+ COERCE_DEF(name);
+ if (type_of(x) != t_structure ||
+ (type_of(name)!=t_structure) ||
+ !structure_subtypep(x->str.str_def, name))
+ FEwrong_type_argument((type_of(name)==t_structure ?
+ S_DATA(name)->name : name),
+ x);
+ s_pos = &SLOT_POS(x->str.str_def,0);
+ switch((SLOT_TYPE(x->str.str_def,i)))
+ {
+ case aet_object: return(STREF(object,x,s_pos[i]));
+ case aet_fix: return(make_fixnum((STREF(int,x,s_pos[i]))));
+ case aet_ch: return(code_char(STREF(char,x,s_pos[i])));
+ case aet_bit:
+ case aet_char: return(make_fixnum(STREF(char,x,s_pos[i])));
+ case aet_sf: return(make_shortfloat(STREF(shortfloat,x,s_pos[i])));
+ case aet_lf: return(make_longfloat(STREF(longfloat,x,s_pos[i])));
+ case aet_uchar: return(make_fixnum(STREF(unsigned char,x,s_pos[i])));
+ case aet_ushort: return(make_fixnum(STREF(unsigned short,x,s_pos[i])));
+ case aet_short: return(make_fixnum(STREF(short,x,s_pos[i])));
+ default:
+ bad_raw_type();
+ return 0;
+ }}
+
+@s]
+
+
+****Change:(orig (40 43 c))
+@s[ if (type_of(x) != t_structure ||
+ !structure_subtypep(x->str.str_name, name))
+ FEwrong_type_argument(name, x);
+ return(x->str.str_self[n]);
+
+@s|
+void
+siLstructure_ref1()
+{object x=vs_base[0];
+ int n=fix(vs_base[1]);
+ object def;
+ check_type_structure(x);
+ def=x->str.str_def;
+ if(n>= S_DATA(def)->length)
+ FEerror("Structure ref out of bounds",0);
+ vs_base[0]=structure_ref(x,x->str.str_def,n);
+ vs_top=vs_base+1;
+
+@s]
+
+
+****Change:(orig (45 45 a))
+@s[}
+
+
+@s|}
+
+void
+siLstructure_set1()
+{object x=vs_base[0];
+ int n=fix(vs_base[1]);
+ object v=vs_base[2];
+ object def;
+ check_type_structure(x);
+ def=x->str.str_def;
+ if(n>= S_DATA(def)->length)
+ FEerror("Structure ref out of bounds",0);
+ vs_base[0]=structure_set(x,x->str.str_def,n,v);
+ vs_top=vs_base+1;
+}
+
+
+
+@s]
+
+
+****Change:(orig (47 47 c))
+@s[structure_set(x, name, n, v)
+
+@s|structure_set(x, name, i, v)
+
+@s]
+
+
+****Change:(orig (49 51 c))
+@s[object x, name, v;
+int n;
+{
+ int i;
+
+@s|object x, name, v;
+int i;
+{unsigned short *s_pos;
+
+ COERCE_DEF(name);
+ if (type_of(x) != t_structure ||
+ type_of(name) != t_structure ||
+ !structure_subtypep(x->str.str_def, name))
+ FEwrong_type_argument((type_of(name)==t_structure ?
+ S_DATA(name)->name : name)
+ , x);
+
+@s]
+
+
+****Change:(orig (53 57 c))
+@s[ if (type_of(x) != t_structure ||
+ !structure_subtypep(x->str.str_name, name))
+ FEwrong_type_argument(name, x);
+ x->str.str_self[n] = v;
+
+@s, return(v);
+
+@s|#ifdef SGC
+ /* make sure the structure header is on a writable page */
+ if (x->d.m) FEerror("bad gc field",0); else x->d.m = 0;
+#endif
+
+ s_pos= & SLOT_POS(x->str.str_def,0);
+ switch(SLOT_TYPE(x->str.str_def,i)){
+
+ case aet_object: STREF(object,x,s_pos[i])=v; break;
+ case aet_fix: (STREF(int,x,s_pos[i]))=fix(v); break;
+ case aet_ch: STREF(char,x,s_pos[i])=char_code(v); break;
+ case aet_bit:
+ case aet_char: STREF(char,x,s_pos[i])=fix(v); break;
+ case aet_sf: STREF(shortfloat,x,s_pos[i])=sf(v); break;
+ case aet_lf: STREF(longfloat,x,s_pos[i])=lf(v); break;
+ case aet_uchar: STREF(unsigned char,x,s_pos[i])=fix(v); break;
+ case aet_ushort: STREF(unsigned short,x,s_pos[i])=fix(v); break;
+ case aet_short: STREF(short,x,s_pos[i])=fix(v); break;
+ default:
+ bad_raw_type();
+
+ }
+ return(v);
+
+@s]
+
+
+****Change:(orig (59 59 a))
+@s[}
+
+
+@s|}
+
+void
+siLstructure_subtype_p()
+{object x,y;
+ check_arg(2);
+ x=vs_base[0];
+ y=vs_base[1];
+ if (type_of(x)!=t_structure)
+ {vs_base[0]=Cnil; goto BOTTOM;}
+ x=x->str.str_def;
+ COERCE_DEF(y);
+ if (structure_subtypep(x,y)) vs_base[0]=Ct;
+ else vs_base[0]=Cnil;
+ BOTTOM:
+ vs_top=vs_base+1;
+}
+
+static object
+slot_name(x)
+ object x;
+{
+ if(type_of(x)==t_cons)
+ return car(x);
+ if(type_of(x)==t_structure)
+ return x->str.str_self[0];
+ return Cnil;
+}
+
+
+@s]
+
+
+****Change:(orig (64 64 a))
+@s[object x;
+{
+ object *p, s;
+
+@s|object x;
+{
+ object *p, s;
+ struct s_data *def=S_DATA(x->str.str_def);
+
+@s]
+
+
+****Change:(orig (66 69 c))
+@s[
+ s = getf(x->str.str_name->s.s_plist,
+ siSstructure_slot_descriptions, Cnil);
+ vs_push(x->str.str_name);
+
+@s|
+ s = def->slot_descriptions;
+ vs_push(def->name);
+
+@s]
+
+
+****Change:(orig (72 73 c))
+@s[ for (i=0, n=x->str.str_length; !endp(s)&&i<n; s=s->c.c_cdr, i++) {
+ *p = make_cons(car(s->c.c_car), Cnil);
+
+@s| for (i=0, n=def->length; !endp(s)&&i<n; s=s->c.c_cdr, i++) {
+ *p = make_cons(slot_name(s->c.c_car), Cnil);
+
+@s]
+
+
+****Change:(orig (75 75 c))
+@s[ *p = make_cons(x->str.str_self[i], Cnil);
+
+@s| *p = make_cons(structure_ref(x,x->str.str_def,i), Cnil);
+
+@s]
+
+
+****Change:(orig (81 81 a))
+@s[ stack_cons();
+ return(vs_pop);
+}
+
+
+@s| stack_cons();
+ return(vs_pop);
+}
+
+void
+
+@s]
+
+
+****Change:(orig (84 85 c))
+@s[ object x;
+ int narg, i;
+
+@s| object x,name,*base;
+ struct s_data *def;
+ int narg, i,size;
+ base=vs_base;
+ if ((narg = vs_top - base) == 0)
+ too_few_arguments();
+ x = alloc_object(t_structure);
+ name=base[0];
+ COERCE_DEF(name);
+ if (type_of(name)!=t_structure ||
+ (def=S_DATA(name))->length != --narg)
+ FEerror("Bad make_structure args for type ~a",1,
+ base[0]);
+ x->str.str_def = name;
+ x->str.str_self = NULL;
+ size=S_DATA(name)->size;
+ base[0] = x;
+ x->str.str_self = (object *)
+ (def->staticp == Cnil ? alloc_relblock(size)
+ : alloc_contblock(size));
+ /* There may be holes in the structure.
+ We want them zero, so that equal can work better.
+ */
+ if (S_DATA(name)->has_holes != Cnil)
+ bzero(x->str.str_self,size);
+ {unsigned char *s_type;
+ unsigned short *s_pos;
+ s_pos= (&SLOT_POS(x->str.str_def,0));
+ s_type = (&(SLOT_TYPE(x->str.str_def,0)));
+ base=base+1;
+ for (i = 0; i < narg; i++)
+ {object v=base[i];
+ switch(s_type[i]){
+
+ case aet_object: STREF(object,x,s_pos[i])=v; break;
+ case aet_fix: (STREF(int,x,s_pos[i]))=fix(v); break;
+ case aet_ch: STREF(char,x,s_pos[i])=char_code(v); break;
+ case aet_bit:
+ case aet_char: STREF(char,x,s_pos[i])=fix(v); break;
+ case aet_sf: STREF(shortfloat,x,s_pos[i])=sf(v); break;
+ case aet_lf: STREF(longfloat,x,s_pos[i])=lf(v); break;
+ case aet_uchar: STREF(unsigned char,x,s_pos[i])=fix(v); break;
+ case aet_ushort: STREF(unsigned short,x,s_pos[i])=fix(v); break;
+ case aet_short: STREF(short,x,s_pos[i])=fix(v); break;
+ default:
+ bad_raw_type();
+
+@s]
+
+
+****Change:(orig (87 97 c))
+@s[ if ((narg = vs_top - vs_base) == 0)
+ too_few_arguments();
+ x = alloc_object(t_structure);
+ x->str.str_name = vs_base[0];
+
+@s, x->str.str_self[i] = vs_top[i];
+
+@s| }}
+ vs_top = base;
+ vs_base=base-1;
+
+ }
+
+@s]
+
+
+****Change:(orig (99 99 a))
+@s[}
+
+
+@s|}
+
+void
+
+@s]
+
+
+****Change:(orig (103 103 c))
+@s[ object x, y;
+ int i, j;
+
+@s| object x, y;
+ struct s_data *def;
+
+@s]
+
+
+****Change:(orig (105 105 c))
+@s[
+ check_arg(2);
+
+@s|
+ if (vs_top-vs_base < 1) too_few_arguments();
+
+@s]
+
+
+****Change:(orig (107 110 c))
+@s[ if (type_of(x) != t_structure || x->str.str_name != vs_base[1])
+ FEwrong_type_argument(vs_base[1], x);
+ vs_base[1] = y = alloc_object(t_structure);
+ y->str.str_name = x->str.str_name;
+
+@s| check_type_structure(x);
+ vs_base[0] = y = alloc_object(t_structure);
+ def=S_DATA(y->str.str_def = x->str.str_def);
+
+@s]
+
+
+****Change:(orig (112 116 c))
+@s[ y->str.str_length = j = x->str.str_length;
+ y->str.str_self = (object *)alloc_relblock(sizeof(object)*j);
+ for (i = 0; i < j; i++)
+ y->str.str_self[i] = x->str.str_self[i];
+
+@s, vs_base++;
+
+@s| y->str.str_self = (object *)alloc_relblock(def->size);
+ bcopy(x->str.str_self,y->str.str_self,def->size);
+ vs_top=vs_base+1;
+
+@s]
+
+
+****Change:(orig (118 118 a))
+@s[}
+
+
+@s|}
+
+void
+siLcopy_structure_header()
+{
+ object x, y;
+
+ if (vs_top-vs_base < 1) too_few_arguments();
+ x = vs_base[0];
+ check_type_structure(x);
+ vs_base[0] = y = alloc_object(t_structure);
+ y->str.str_def = x->str.str_def;
+ y->str.str_self = x->str.str_self;
+ vs_top=vs_base+1;
+}
+
+
+void
+
+@s]
+
+
+****Change:(orig (122 124 c))
+@s[ if (type_of(vs_base[0]) != t_structure)
+ FEwrong_type_argument(Sstructure, vs_base[0]);
+ vs_base[0] = vs_base[0]->str.str_name;
+
+@s| check_type_structure(vs_base[0]);
+ vs_base[0] = S_DATA(vs_base[0]->str.str_def)->name;
+
+@s]
+
+
+****Change:(orig (127 127 c))
+@s[}
+
+siLstructure_ref()
+
+@s|}
+
+#define FIND_SLOT(str,name) ((type_of(name)==t_fixnum)?fix(name): \
+ structure_slot_position(str,name))
+
+object
+structure_ref_new(x, name, i)
+ object x,name,i;
+
+@s]
+
+
+****Change:(orig (129 131 c))
+@s[ object x;
+ int i;
+ check_arg(3);
+
+@s| return structure_ref(x,name,FIND_SLOT(x,i));
+}
+
+@s]
+
+
+****Change:(orig (133 144 c))
+@s[ x = vs_base[0];
+ if (type_of(x) != t_structure ||
+ !structure_subtypep(x->str.str_name, vs_base[1]))
+ FEwrong_type_argument(vs_base[1], x);
+
+@s, vs_base[0] = x->str.str_self[i];
+ vs_top = vs_base+1;
+
+@s|object
+structure_set_new(x, name, i, v)
+ object x,name,i,v;
+{
+ return structure_set(x,name,FIND_SLOT(x,i),v);
+
+@s]
+
+
+****Change:(orig (146 146 a))
+@s[}
+
+
+@s|}
+
+void
+siLstructure_ref()
+{
+ check_arg(3);
+ vs_base[0]=structure_ref_new(vs_base[0],vs_base[1],vs_base[2]);
+ vs_top=vs_base+1;
+}
+
+void
+
+@s]
+
+
+****Change:(orig (149 150 d))
+@s[siLstructure_set()
+{
+ object x;
+ int i;
+
+@s|siLstructure_set()
+{
+
+@s]
+
+
+****Change:(orig (152 163 c))
+@s[
+ x = vs_base[0];
+ if (type_of(x) != t_structure ||
+ !structure_subtypep(x->str.str_name, vs_base[1]))
+
+@s, x->str.str_self[i] = vs_base[3];
+
+@s| structure_set_new(vs_base[0],vs_base[1],vs_base[2],vs_base[3]);
+
+@s]
+
+
+****Change:(orig (166 166 a))
+@s[ vs_base = vs_top-1;
+}
+
+
+@s| vs_base = vs_top-1;
+}
+
+void
+
+@s]
+
+
+****Change:(orig (228 228 c))
+@s[init_structure_function()
+
+@s|void
+siLmake_s_data_structure()
+{object x,y,raw,*base;
+ int i;
+ check_arg(5);
+ x=vs_base[0];
+ base=vs_base;
+ raw=vs_base[1];
+ y=alloc_object(t_structure);
+ y->str.str_def=y;
+ y->str.str_self = (object *)( x->v.v_self);
+ S_DATA(y)->name =siLs_data;
+ S_DATA(y)->length=(raw->v.v_dim);
+ S_DATA(y)->raw =raw;
+ for(i=3; i<raw->v.v_dim; i++)
+ y->str.str_self[i]=Cnil;
+ S_DATA(y)->slot_position=base[2];
+ S_DATA(y)->slot_descriptions=base[3];
+ S_DATA(y)->staticp=base[4];
+ S_DATA(y)->size = (raw->v.v_dim)*sizeof(object);
+ vs_base[0]=y;
+ vs_top=vs_base+1;
+}
+
+object siSstructure_init,siSstructure_init_named;
+object siSname,siSdefault_init;
+object siSraw,siSslot_position,siSsize,siSstaticp,siSslot_descriptions;
+
+static object
+slot_value(str,name)
+ object str,name;
+
+@s]
+
+
+****Change:(orig (230 237 c))
+@s[ siSstructure_print_function
+ = make_si_ordinary("STRUCTURE-PRINT-FUNCTION");
+ enter_mark_origin(&siSstructure_print_function);
+ siSstructure_slot_descriptions
+
+@s, enter_mark_origin(&siSstructure_include);
+
+@s| top:
+ if(type_of(str)==t_structure)
+ return structure_ref_new(str,str->str.str_def,name);
+ if(str->c.c_car==siSstructure_init_named)
+ {object new=get(str->c.c_cdr,siLs_data);
+ str->c.c_car=siSstructure_init;
+ str->c.c_cdr=(type_of(new)==t_structure)?new:cdr(new);}
+ if(siSstructure_init!=car(str))
+ FEerror("Illegal call to SI:MAKE-STRUCTURES 1",0);
+ {object key=intern(coerce_to_string(name),keyword_package);
+ object value=getf(cdddr(str),key,NULL);
+ if(value!=NULL)
+ return value;
+ else
+ {object slots;
+ if(str==caddr(str)&&name==siSslot_descriptions)
+ FEerror("Illegal call to SI:MAKE-STRUCTURES 2",0);
+ slots=slot_value(caddr(str),siSslot_descriptions);
+ for(;!endp(slots);slots=cdr(slots))
+ if(name==slot_value(car(slots),siSname))
+ {object result,form=slot_value(car(slots),siSdefault_init);
+ object *old_vs_base=vs_base,*old_vs_top=vs_top;
+ vs_base=vs_top;vs_push(form);Leval();result=vs_base[0];
+ vs_base=old_vs_base; vs_top=old_vs_top;
+ return result;}
+ FEerror("Illegal call to SI:MAKE-STRUCTURES 3",0);}}
+ return Cnil;
+}
+
+@s]
+
+
+****Change:(orig (238 238 a))
+@s[
+
+@s|
+int
+structure_slot_position(str,name)
+ object str,name;
+{
+ if(type_of(name)==t_fixnum)
+ return fix(name);
+ else
+ {object slotd_list;
+ int pos;
+ check_type_structure(str);
+ slotd_list=S_DATA(str->str.str_def)->slot_descriptions;
+ for(pos=0; type_of(slotd_list)==t_cons; pos++,slotd_list=cdr(slotd_list))
+ {object slotd=car(slotd_list);
+ if(name==((type_of(slotd)==t_structure)?
+ slotd->str.str_self[0]:slot_value(slotd,siSname)))
+ return pos;}
+ FEerror("Slot ~S not found in structure ~S",2,name,str);
+ return 0;}
+}
+
+static object
+make_structures_internal(value)
+ object value;
+{
+ object str,def;
+ int def_index,i,ind;
+
+ switch(type_of(value))
+ {case t_cons:
+ if(value->c.c_car==siSstructure_init_named)
+ {object new=get(value->c.c_cdr,siLs_data);
+ value->c.c_car=siSstructure_init;
+ value->c.c_cdr=(type_of(new)==t_structure)?new:cdr(new);}
+ if(car(value)!=siSstructure_init)
+ {value->c.c_car=make_structures_internal(value->c.c_car);
+ value->c.c_cdr=make_structures_internal(value->c.c_cdr);
+ break;}
+ if(type_of(cadr(value))==t_structure)
+ {value=value->c.c_cdr->c.c_car;
+ break;}
+ {object def=caddr(value),plist=cdddr(value),result;
+ object slots,slots_tail;
+ int size,staticp,len,i;
+ if(def!=value)def=make_structures_internal(def);
+ result=alloc_object(t_structure);
+ result->str.str_def=(def==value)?result:def;
+ result->str.str_self=NULL;
+ value->c.c_cdr->c.c_car=result;
+ size=fixint(slot_value(def,siSsize));
+ staticp=Cnil!=slot_value(def,siSstaticp);
+ slots=slot_value(def,siSslot_descriptions);
+ len=length(slots);
+ result->str.str_self=(object *)(staticp?alloc_contblock(size):
+ alloc_relblock(size));
+ bzero(result->str.str_self,size);
+ if(def==value)
+ {S_DATA(result)->raw=slot_value(def,siSraw);
+ S_DATA(result)->slot_position=slot_value(def,siSslot_position);}
+ for(i=0,slots_tail=slots; i<len; i++,slots_tail=cdr(slots_tail))
+ {object svalue=slot_value(value,slot_value(car(slots_tail),siSname));
+ structure_set(result,result->str.str_def,i,svalue);}
+ for(i=0,slots_tail=slots; i<len; i++,slots_tail=cdr(slots_tail))
+ {object svalue=structure_ref(result,result->str.str_def,i);
+ svalue=make_structures_internal(svalue);
+ structure_set(result,result->str.str_def,i,svalue);}
+ value=result;
+ break;}
+ case t_vector:
+ if ((enum aelttype)value->v.v_elttype == aet_object)
+ {int i,len=value->v.v_dim;
+ for(i=0; i<len; i++)
+ value->v.v_self[i]=make_structures_internal(value->v.v_self[i]);}
+ break;
+ case t_symbol:
+ {object plist=value->s.s_plist,next;
+ for(;!endp(plist);plist=cddr(plist))
+ {next=plist->c.c_cdr;
+ if(plist->c.c_car==siLs_data&&
+ type_of(next->c.c_car)==t_cons)
+ next->c.c_car=make_structures_internal(next->c.c_car);}
+ break;}}
+ return value;
+}
+
+void
+siLmake_structures()
+{
+ check_arg(1);
+ vs_base[0]=make_structures_internal(vs_base[0]);
+}
+
+void
+siLstructure_def()
+{check_arg(1);
+ check_type_structure(vs_base[0]);
+ vs_base[0]=vs_base[0]->str.str_def;
+}
+
+short aet_sizes [] = {
+sizeof(object), /* aet_object t */
+sizeof(char), /* aet_ch string-char */
+sizeof(char), /* aet_bit bit */
+sizeof(fixnum), /* aet_fix fixnum */
+sizeof(float), /* aet_sf short-float */
+sizeof(double), /* aet_lf long-float */
+sizeof(char), /* aet_char signed char */
+sizeof(char), /* aet_uchar unsigned char */
+sizeof(short), /* aet_short signed short */
+sizeof(short) /* aet_ushort unsigned short */
+};
+
+
+
+
+
+void
+siLsize_of()
+{ object x= vs_base[0];
+ int i;
+ i= aet_sizes[get_aelttype(x)];
+ vs_base[0]=make_fixnum(i);
+}
+
+void
+siLaet_type()
+{vs_base[0]=make_fixnum(get_aelttype(vs_base[0]));}
+
+
+/* Return N such that something of type ARG can be aligned on
+ an address which is a multiple of N */
+
+
+void
+siLalignment()
+{struct {double x; int y; double z;
+ float x1; int y1; float z1;}
+ joe;
+ joe.z=3.0;
+
+ if (vs_base[0]==Slong_float)
+ {vs_base[0]=make_fixnum((int)&joe.z- (int)&joe.y); return;}
+ else
+ if (vs_base[0]==Sshort_float)
+ {vs_base[0]=make_fixnum((int)&(joe.z1)-(int)&(joe.y1)); return;}
+ else
+ {siLsize_of();}
+}
+
+void
+swap_structure_contents(str1,str2)
+ object str1,str2;
+{
+ object def1,*self1;
+ check_type_structure(str1);
+ check_type_structure(str2);
+ def1=str1->str.str_def;
+ self1=str1->str.str_self;
+ str1->str.str_def=str2->str.str_def;
+ str1->str.str_self=str2->str.str_self;
+ str2->str.str_def=def1;
+ str2->str.str_self=self1;
+}
+
+void
+siLswap_structure_contents()
+{
+ check_arg(2);
+ swap_structure_contents(vs_base[0],vs_base[1]);
+ vs_base[0]=Cnil;
+ vs_top=vs_base+1;
+}
+
+void
+siLset_structure_def()
+{check_arg(2);
+ check_type_structure(vs_base[0]);
+ check_type_structure(vs_base[1]);
+ vs_base[0]->str.str_def=vs_base[1];
+ vs_base[0]=vs_base[1];
+ vs_top=vs_base+1;
+}
+
+init_structure_function()
+{
+ siLs_data=make_si_ordinary("S-DATA");
+ siSstructure_init=make_si_ordinary("STRUCTURE-INIT");
+ siSstructure_init_named=make_si_ordinary("STRUCTURE-INIT-NAMED");
+ siSname=make_si_ordinary("NAME");
+ siSdefault_init=make_si_ordinary("DEFAULT-INIT");
+ siSraw=make_si_ordinary("RAW");
+ siSslot_position=make_si_ordinary("SLOT-POSITION");
+ siSsize=make_si_ordinary("SIZE");
+ siSstaticp=make_si_ordinary("STATICP");
+ siSslot_descriptions=make_si_ordinary("SLOT-DESCRIPTIONS");
+
+@s]
+
+
+****Change:(orig (239 239 a))
+@s[ make_si_function("MAKE-STRUCTURE", siLmake_structure);
+
+@s| make_si_function("MAKE-STRUCTURE", siLmake_structure);
+ make_si_function("MAKE-S-DATA-STRUCTURE",siLmake_s_data_structure);
+
+@s]
+
+
+****Change:(orig (240 240 a))
+@s[ make_si_function("COPY-STRUCTURE", siLcopy_structure);
+
+@s| make_si_function("COPY-STRUCTURE", siLcopy_structure);
+ make_si_function("COPY-STRUCTURE-HEADER", siLcopy_structure_header);
+
+@s]
+
+
+****Change:(orig (242 242 a))
+@s[ make_si_function("STRUCTURE-REF", siLstructure_ref);
+
+@s| make_si_function("STRUCTURE-REF", siLstructure_ref);
+ make_si_function("STRUCTURE-DEF", siLstructure_def);
+ make_si_function("STRUCTURE-REF1", siLstructure_ref1);
+ make_si_function("STRUCTURE-SET1", siLstructure_set1);
+
+@s]
+
+
+****Change:(orig (245 245 c))
+@s[ make_si_function("STRUCTUREP", siLstructurep);
+
+
+@s| make_si_function("STRUCTUREP", siLstructurep);
+ make_si_function("SIZE-OF", siLsize_of);
+ make_si_function("ALIGNMENT",siLalignment);
+ make_si_function("STRUCTURE-SUBTYPE-P",siLstructure_subtype_p);
+
+@s]
+
+
+****Change:(orig (247 247 a))
+@s[ make_si_function("LIST-NTH", siLlist_nth);
+
+@s| make_si_function("LIST-NTH", siLlist_nth);
+ make_si_function("AET-TYPE",siLaet_type);
+ make_si_function("SWAP-STRUCTURE-CONTENTS",siLswap_structure_contents);
+ make_si_function("SET-STRUCTURE-DEF", siLset_structure_def);
+ make_si_function("MAKE-STRUCTURES", siLmake_structures);
+
+
+@s]
+
+==============================================================================
+============================== V/lsp/defstruct.lsp =============================
+Changes file for /kcl/lsp/defstruct.lsp
+Usage \n@s[Original text\n@s|Replacement Text\n@s]
+See the file rascal.ics.utexas.edu:/usr2/ftp/merge.c
+for a program to merge change files. Anything not between
+ "\n@s[" and "\n@s]" is a simply a comment.
+This file was constructed using emacs and merge.el
+ by (Bill Schelter) wfs@carl.ma.utexas.edu
+
+
+****Change:(orig (20 71 c))
+@s[(defun make-access-function (name conc-name type named
+ slot-name default-init slot-type read-only
+ offset)
+ (declare (ignore named default-init slot-type))
+
+@s, ((error "~S is an illegal structure type." type)))))
+
+@s|(defvar *accessors* (make-array 10 :adjustable t))
+(defvar *list-accessors* (make-array 2 :adjustable t))
+(defvar *vector-accessors* (make-array 2 :adjustable t))
+
+@s]
+
+
+****Change:(orig (72 72 a))
+@s[
+
+@s|
+(or (fboundp 'record-fn) (setf (symbol-function 'record-fn)
+ #'(lambda (&rest l) l nil)))
+
+@s]
+
+
+****Change:(orig (73 73 a))
+@s[
+
+@s|
+(defun boot-slot-value (str name)
+ (if (structurep str)
+ (structure-ref str (structure-def str) name)
+ (getf (cdddr str) (intern (string name) :keyword))))
+
+(defun boot-set-slot-value (str name new-value)
+ (if (structurep str)
+ (structure-set str (structure-def str) name new-value)
+ (setf (getf (cdddr str) (intern (string name) :keyword)) new-value)))
+
+(defun boot-subtypep (type1 type2)
+ (or (eq type1 type2)
+ (let* ((s-data (get type1 's-data))
+ (include (boot-s-data-name (boot-slot-value s-data 'includes))))
+ (boot-subtypep include type2))))
+
+(defun make-slot-boot (&rest args)
+ (if (get 's-data 's-data)
+ (apply #'make-slot args)
+ (list* 'structure-init
+ nil
+ '(structure-init-named . slot)
+ args)))
+
+(defun make-s-data-boot (&rest args)
+ (if (get 's-data 's-data)
+ (apply #'make-s-data args)
+ (list* 'structure-init
+ nil
+ '(structure-init-named . s-data)
+ args)))
+
+(defun make-boot-accessor (slot accessor)
+ (setf (symbol-function accessor)
+ #'(lambda (object)
+ (boot-slot-value object slot)))
+ (let ((writer (intern (format nil "SET ~A" accessor))))
+ (setf (symbol-function writer)
+ #'(lambda (object value)
+ (boot-set-slot-value object slot value)))
+ (eval `(defsetf ,accessor ,writer))))
+
+(defmacro defstructboot (name &rest slots)
+ (let ((conc-name (if (listp name)
+ (string (second (assoc :conc-name (cdr name))))
+ (format nil "~A-" name))))
+ `(progn
+ ,@(mapcar #'(lambda (slot)
+ (let ((fname (intern (format nil "~A~A" conc-name slot))))
+ `(make-boot-accessor ',slot ',fname)))
+ slots))))
+
+(defstructboot (slot (:conc-name boot-slot-))
+ name default-init type read-only offset accessor-name type-changed)
+
+(defstructboot (s-data-internal (:conc-name boot-s-data-))
+ name length raw included includes staticp print-function
+ slot-descriptions slot-position size has-holes)
+
+(defstructboot (basic-wrapper (:conc-name boot-wrapper-))
+ cache-number-vector state class)
+
+(defstructboot (s-data (:conc-name boot-s-data-))
+ frozen documentation constructors offset
+ named type conc-name)
+
+(defun make-access-function (name conc-name type named include no-fun slot)
+ (declare (ignore named))
+
+ (let* ((slot-name (boot-slot-name slot))
+ (slot-type (boot-slot-type slot))
+ (read-only (boot-slot-read-only slot))
+ (offset (boot-slot-offset slot))
+ (access-function
+ (intern (si:string-concatenate (string conc-name)
+ (string slot-name))))
+ accsrs dont-overwrite)
+ (unless (boot-slot-accessor-name slot)
+ (setf (boot-slot-accessor-name slot) access-function))
+ (ecase type
+ ((nil)
+ (setf accsrs *accessors*))
+ (list
+ (setf accsrs *list-accessors*))
+ (vector
+ (setf accsrs *vector-accessors*)))
+ (or (> (length accsrs) offset)
+ (adjust-array accsrs (+ offset 10)))
+ (unless
+ dont-overwrite
+ (record-fn access-function 'defun '(t) slot-type)
+ (or no-fun
+ (and (fboundp access-function)
+ (eq (aref accsrs offset) (symbol-function access-function)))
+ (setf (symbol-function access-function)
+ (or (aref accsrs offset)
+ (setf (aref accsrs offset)
+ (cond ((eq accsrs *accessors*)
+ #'(lambda (x)
+ (or (structurep x)
+ (error "~a is not a structure" x))
+ (structure-ref1 x offset)))
+ ((eq accsrs *list-accessors*)
+ #'(lambda(x)
+ (si:list-nth offset x)))
+ ((eq accsrs *vector-accessors*)
+ #'(lambda(x)
+ (aref x offset)))))))))
+ (cond (read-only
+ (remprop access-function 'structure-access)
+ (setf (get access-function 'struct-read-only) t))
+ (t (remprop access-function 'setf-update-fn)
+ (remprop access-function 'setf-lambda)
+ (remprop access-function 'setf-documentation)
+ (let ((tem (get access-function 'structure-access)))
+ (cond ((and (consp tem) include
+ (if (consp (get include 's-data))
+ (boot-subtypep include (car tem))
+ (subtypep include (car tem)))
+ (eql (cdr tem) offset))
+ ;; don't change overwrite accessor of subtype.
+ (setq dont-overwrite t)
+ )
+ (t (setf (get access-function 'structure-access)
+ (cons (if type type name) offset)))))))
+ nil))
+
+
+@s]
+
+
+****Change:(orig (80 89 c))
+@s[ (cond ((null x)
+ ;; If the slot-description is NIL,
+ ;; it is in the padding of initial-offset.
+ nil)
+
+@s, (t (car x))))
+
+@s| (or (boot-slot-name x)
+ (and (boot-slot-default-init x)
+ ;; If the slot name is NIL,
+ ;; it is the structure name.
+ ;; This is for typed structures with names.
+ (list 'quote (boot-slot-default-init x)))))
+
+@s]
+
+
+****Change:(orig (94 97 c))
+@s[ (cond ((null x) nil)
+ ((null (car x)) nil)
+ ((null (cadr x)) (list (car x)))
+ (t (list (list (car x) (cadr x))))))
+
+@s| (when (boot-slot-name x)
+ (if (boot-slot-default-init x)
+ (list (list (boot-slot-name x) (boot-slot-default-init x)))
+ (list (boot-slot-name x)))))
+
+@s]
+
+
+****Change:(orig (248 248 d))
+@s[ ((error "~S is an illegal structure type" type)))))
+
+
+
+@s| ((error "~S is an illegal structure type" type)))))
+
+
+@s]
+
+
+****Change:(orig (252 265 d))
+@s[
+(defun make-copier (name copier type named)
+ (declare (ignore named))
+ (cond ((null type)
+
+@s, ((error "~S is an illegal structure type." type))))
+
+
+
+@s|
+@s]
+
+
+****Change:(orig (267 275 c))
+@s[ (cond ((null type)
+ ;; If TYPE is NIL, the predicate searches the link
+ ;; of structure-include, until there is no included structure.
+ `(defun ,predicate (x)
+
+@s, (setq n (get n 'structure-include))))))
+
+@s| (cond ((null type))
+ ; done in define-structure
+
+@s]
+
+
+****Change:(orig (282 283 c))
+@s[ (> (length x) ,name-offset)
+ (eq (elt x ,name-offset) ',name))))
+
+@s| (> (the fixnum (length x)) ,name-offset)
+ (eq (aref (the (vector t) x) ,name-offset) ',name))))
+
+@s]
+
+
+****Change:(orig (294 294 a))
+@s[ ((= i 0) (and (consp y) (eq (car y) ',name)))
+
+@s| ((= i 0) (and (consp y) (eq (car y) ',name)))
+ (declare (fixnum i))
+
+@s]
+
+
+****Change:(orig (300 301 c))
+@s[;;; and returns a list of the form:
+;;; (slot-name default-init slot-type read-only offset)
+
+@s|;;; and returns a slot.
+
+@s]
+
+
+****Change:(orig (325 325 c))
+@s[ (list slot-name default-init slot-type read-only offset)))
+
+@s| (make-slot-boot :name slot-name
+ :default-init default-init
+ :type slot-type
+ :read-only read-only
+ :offset offset)))
+
+@s]
+
+
+****Change:(orig (335 335 c))
+@s[ (let ((sds (member (caar olds) news :key #'car)))
+
+@s| (let* ((old (car olds))
+ (sds (member (boot-slot-name old) news :key #'slot-name))
+ (new (car sds)))
+
+@s]
+
+
+****Change:(orig (337 348 c))
+@s[ (when (and (null (cadddr (car sds)))
+ (cadddr (car olds)))
+ ;; If read-only is true in the old
+ ;; and false in the new, signal an error.
+
+@s, (car (cddddr (car olds))))
+
+@s| (when (and (null (boot-slot-read-only new))
+ (boot-slot-read-only old))
+ ;; If read-only is true in the old
+ ;; and false in the new, signal an error.
+ (error "~S is an illegal include slot-description."
+ new))
+ ;; If
+ (setf (boot-slot-type new)
+ (best-array-element-type (boot-slot-type new)))
+ (when (not (equal (normalize-type (or (boot-slot-type new) t))
+ (normalize-type (or (boot-slot-type old) t))))
+ (error "Type mismmatch for included slot ~a" new))
+ (cons (make-slot :name (boot-slot-name new)
+ :default-init (boot-slot-default-init new)
+ :type (boot-slot-type new)
+ :read-only (boot-slot-read-only new)
+ :offset (boot-slot-offset old))
+
+@s]
+
+
+****Change:(orig (353 353 a))
+@s[ (overwrite-slot-descriptions news (cdr olds))))))))
+
+
+@s| (overwrite-slot-descriptions news (cdr olds))))))))
+
+(defvar *all-t-s-type* (make-array 50 :element-type 'unsigned-char :static t))
+
+@s]
+
+
+****Change:(orig (355 355 c))
+@s[;;; The DEFSTRUCT macro.
+
+@s|(defun make-t-type (n include slot-descriptions &aux i)
+ (let ((res (make-array n :element-type 'unsigned-char :static t)))
+ (when include
+ (let ((tem (get include 's-data))raw)
+ (or tem (error "Included structure undefined ~a" include))
+ (setq raw (boot-s-data-raw tem))
+ (dotimes (i (min n (length raw)))
+ (setf (aref res i) (aref raw i)))))
+ (dolist (v slot-descriptions)
+ (setq i (boot-slot-offset v))
+ (let ((type (boot-slot-type v)))
+ (cond ((<= (the fixnum (alignment type)) #. (alignment t))
+ (setf (aref res i) (aet-type type))))))
+ (cond ((< n (length *all-t-s-type*))
+ (dotimes (i n)
+ (cond ((not (eql (the fixnum (aref res i)) 0))
+ (return-from make-t-type res))))
+ *all-t-s-type*)
+ (t res))))
+
+@s]
+
+
+****Change:(orig (356 356 a))
+@s[
+
+@s|
+(defvar *standard-slot-positions*
+ (let ((ar (make-array 50 :element-type 'unsigned-short
+ :static t)))
+ (dotimes (i 50)
+ (declare (fixnum i))
+ (setf (aref ar i)(* #. (size-of t) i)))
+ ar))
+
+(eval-when (compile )
+(proclaim '(function round-up (fixnum fixnum ) fixnum))
+)
+
+(defun round-up (a b)
+ (declare (fixnum a b))
+ (setq a (ceiling a b))
+ (the fixnum (* a b)))
+
+
+(defun get-slot-pos (leng include slot-descriptions &aux type small-types
+ has-holes)
+ (declare (special *standard-slot-positions*)) include
+ (dolist (v slot-descriptions)
+ (when (boot-slot-name v)
+ (setf type (best-array-element-type (boot-slot-type v))
+ (boot-slot-type v) type)
+ (let ((val (boot-slot-default-init v)))
+ (unless (typep val type)
+ (if (and (symbolp val)
+ (constantp val))
+ (setf val (symbol-value val)))
+ (and (constantp val)
+ (setf (boot-slot-default-init v) (coerce val type)))))
+ (cond ((memq type '(signed-char unsigned-char
+ short unsigned-short
+ long-float
+ bit))
+ (setq small-types t)))))
+ (cond ((and (null small-types)
+ (< leng (length *standard-slot-positions*))
+ (list *standard-slot-positions* (* leng #. (size-of t)) nil)))
+ (t (let ((ar (make-array leng :element-type 'unsigned-short
+ :static t))
+ (pos 0)(i 0)(align 0)type (next-pos 0))
+ (declare (fixnum pos i align next-pos))
+ ;; A default array.
+
+ (dolist (v slot-descriptions)
+ (setq type (boot-slot-type v))
+ (setq align (alignment type))
+ (unless (<= align #. (alignment t))
+ (setq type t)
+ (setf (boot-slot-type v) t)
+ (setq align #. (alignment t))
+ (setf (boot-slot-type-changed v) t))
+ (setq next-pos (round-up pos align))
+ (or (eql pos next-pos) (setq has-holes t))
+ (setq pos next-pos)
+ (setf (aref ar i) pos)
+ (incf pos (size-of type))
+ (incf i))
+ (list ar (round-up pos (size-of t)) has-holes)
+ ))))
+
+
+(defun define-structure (name conc-name type named slot-descriptions copier
+ static include print-function constructors
+ offset predicate &optional documentation no-funs
+ &aux leng)
+ (and (consp type) (eq (car type) 'vector)(setq type 'vector))
+ (setq leng (length slot-descriptions))
+ (setq slot-descriptions
+ (mapcar #'(lambda (info)
+ (make-slot-boot :name (first info)
+ :default-init (second info)
+ :type (third info)
+ :read-only (fourth info)
+ :offset (fifth info)
+ :accessor-name (sixth info)
+ :type-changed (seventh info)))
+ slot-descriptions))
+ (dolist (x slot-descriptions)
+ (when (boot-slot-name x)
+ (make-access-function name conc-name type named include no-funs x)))
+ (when (and copier (not no-funs))
+ (setf (symbol-function copier)
+ (ecase type
+ ((nil) #'si::copy-structure)
+ (list #'copy-list)
+ (vector #'copy-seq))))
+ (let ((include-str (and include (get include 's-data))))
+ (when (and (eq include 's-data-internal)
+ (not (eq name 'basic-wrapper)))
+ (error "only ~s can include ~s" 'basic-wrapper 's-data-internal))
+ (when include-str
+ (cond ((and (not (consp include-str))
+ (s-data-frozen include-str)
+ (or (not (s-data-included include-str))
+ (not (let ((te (get name 's-data)))
+ (and te
+ (eq (s-data-includes te)
+ include-str))))))
+ (warn " ~a was frozen but now included"
+ include)))
+ (let ((old-included (boot-slot-value include-str 'included)))
+ (unless (member name old-included)
+ (boot-set-slot-value include-str 'included (cons name old-included)))))
+ (let* ((tem (get name 's-data))
+ (g-s-p (and (null type)
+ (get-slot-pos leng include slot-descriptions)))
+ (slot-position (car g-s-p))
+ (size (if g-s-p (cadr g-s-p) 0))
+ (has-holes (caddr g-s-p))
+ (def (make-s-data-boot :name name
+ :length leng
+ :raw
+ (and (null type)
+ (make-t-type leng include
+ slot-descriptions))
+ :slot-position slot-position
+ :size size
+ :has-holes has-holes
+ :staticp static
+ :includes include-str
+ :print-function print-function
+ :slot-descriptions slot-descriptions
+ :constructors constructors
+ :offset offset
+ :type type
+ :named named
+ :documentation documentation
+ :conc-name conc-name)))
+ (check-s-data tem def name)
+ (when (and (consp def) (eq name 's-data))
+ (make-structures def))))
+ (when documentation
+ (setf (get name 'structure-documentation)
+ documentation))
+ (when (and (null type) predicate)
+ (record-fn predicate 'defun '(t) t)
+ (or no-funs
+ (setf (symbol-function predicate)
+ #'(lambda (x)
+ (si::structure-subtype-p x name))))
+ (setf (get predicate 'compiler::co1)
+ 'compiler::co1structure-predicate)
+ (setf (get predicate 'struct-predicate) name))
+ nil)
+
+(defun check-s-data (old new name)
+ (unless (and old (member name '(slot s-data-internal basic-wrapper s-data)))
+ (when (and old (eq (structure-def old) (get 's-data 's-data)))
+ (boot-set-slot-value new 'included (boot-slot-value old 'included))
+ (boot-set-slot-value new 'frozen (boot-slot-value old 'frozen)))
+ (unless (and old
+ (eq (structure-def old) (get 's-data 's-data))
+ (let ((new-cnv (boot-slot-value new 'cache-number-vector))
+ (old-cnv (boot-slot-value old 'cache-number-vector)))
+ (boot-set-slot-value new 'cache-number-vector old-cnv)
+ (prog1 (equalp new old)
+ (boot-set-slot-value new 'cache-number-vector new-cnv))))
+ (when old
+ (warn "structure ~a is changing" name)
+ (when (eq (structure-def old) (get 's-data 's-data))
+ (boot-set-slot-value old 'state (list ':obsolete new))))
+ (setf (get name 's-data) new))))
+
+
+@s]
+
+
+****Change:(orig (364 364 c))
+@s[ predicate predicate-specified
+ include
+
+@s| predicate predicate-specified
+ include include-s-data
+
+@s]
+
+
+****Change:(orig (367 367 c))
+@s[ offset name-offset
+ documentation)
+
+@s| offset name-offset
+ documentation
+ static)
+
+@s]
+
+
+****Change:(orig (370 370 c))
+@s[ ;; The defstruct options are supplied.
+
+@s| ;; The defstruct options are supplied.
+
+@s]
+
+
+****Change:(orig (390 425 c))
+@s[ (cond ((and (consp (car os)) (not (endp (cdar os))))
+ (setq o (caar os) v (cadar os))
+ (case o
+ (:conc-name
+
+@s, (t (error "~S is an illegal defstruct option." o))))))
+
+@s| (cond ((and (consp (car os)) (not (endp (cdar os))))
+ (setq o (caar os) v (cadar os))
+ (case o
+ (:conc-name
+ (if (null v)
+ (setq conc-name "")
+ (setq conc-name v)))
+ (:constructor
+ (if (null v)
+ (setq no-constructor t)
+ (if (endp (cddar os))
+ (setq constructors (cons v constructors))
+ (setq constructors (cons (cdar os) constructors)))))
+ (:copier (setq copier v))
+ (:static (setq static v))
+ (:predicate
+ (setq predicate v)
+ (setq predicate-specified t))
+ (:include
+ (setq include (cdar os))
+ (unless (setq include-s-data (get v 's-data))
+ (error "~S is an illegal included structure." v)))
+ (:print-function
+ (and (consp v) (eq (car v) 'function)
+ (setq v (second v)))
+ (setq print-function v))
+ (:type (setq type v))
+ (:initial-offset (setq initial-offset v))
+ (t (error "~S is an illegal defstruct option." o))))
+ (t
+ (if (consp (car os))
+ (setq o (caar os))
+ (setq o (car os)))
+ (case o
+ (:constructor
+ (setq constructors
+ (cons default-constructor constructors)))
+ ((:conc-name :copier :predicate :print-function))
+ (:named (setq named t))
+ (t (error "~S is an illegal defstruct option." o))))))
+
+@s]
+
+
+****Change:(orig (426 426 a))
+@s[
+
+@s|
+ (setq conc-name (intern (string conc-name)))
+
+ (and include-s-data (not print-function)
+ (setq print-function (boot-s-data-print-function include-s-data)))
+
+
+@s]
+
+
+****Change:(orig (434 435 c))
+@s[ (when include
+ (unless (equal type (get (car include) 'structure-type))
+
+@s| (when include-s-data
+ (unless (equal type (boot-s-data-type include-s-data))
+
+@s]
+
+
+****Change:(orig (442 443 c))
+@s[ (t
+ (setq offset (get (car include) 'structure-offset))))
+
+@s| (t
+ (setq offset (boot-s-data-offset include-s-data))))
+
+@s]
+
+
+****Change:(orig (457 458 c))
+@s[ (setq sds (cons (parse-slot-description (car ds) offset) sds))
+ (setq offset (1+ offset)))
+
+@s| (setq sds (cons (parse-slot-description (car ds) offset) sds))
+ (setq offset (1+ offset)))
+
+@s]
+
+
+****Change:(orig (464 464 c))
+@s[ (cons (list nil name) slot-descriptions)))
+
+@s| (cons (make-slot :default-init name) slot-descriptions)))
+
+@s]
+
+
+****Change:(orig (469 469 c))
+@s[ (append (make-list initial-offset) slot-descriptions)))
+
+@s| (append (mapcar #'make-named-slot (make-list initial-offset))
+ slot-descriptions)))
+
+@s]
+
+
+****Change:(orig (473 486 c))
+@s[ (cond ((null include))
+ ((endp (cdr include))
+ (setq slot-descriptions
+ (append (get (car include) 'structure-slot-descriptions)
+
+@s, slot-descriptions))))
+
+@s| (let ((include-slot-descriptions
+ (and include
+ (boot-s-data-slot-descriptions include-s-data))))
+ (cond ((null include))
+ ((endp (cdr include))
+ (setq slot-descriptions
+ (append include-slot-descriptions
+ slot-descriptions)))
+ (t
+ (setq slot-descriptions
+ (append (overwrite-slot-descriptions
+ (mapcar #'(lambda (sd)
+ (parse-slot-description sd 0))
+ (cdr include))
+ include-slot-descriptions)
+ slot-descriptions)))))
+
+@s]
+
+
+****Change:(orig (489 492 c))
+@s[ ;; If a constructor option is NIL,
+ ;; no constructor should have been specified.
+ (when constructors
+ (error "Contradictory constructor options.")))
+
+@s| ;; If a constructor option is NIL,
+ ;; no constructor should have been specified.
+ (when constructors
+ (error "Contradictory constructor options.")))
+
+@s]
+
+
+****Change:(orig (494 495 c))
+@s[ ;; If no constructor is specified,
+ ;; the default-constructor is made.
+
+@s| ;; If no constructor is specified,
+ ;; the default-constructor is made.
+
+@s]
+
+
+****Change:(orig (497 497 a))
+@s[ (setq constructors (list default-constructor))))
+
+
+@s| (setq constructors (list default-constructor))))
+
+ ;; We need a default constructor for the sharp-s-reader
+ (or (member t (mapcar 'symbolp constructors))
+ (push (intern (string-concatenate "__si::" default-constructor))
+ constructors))
+
+
+@s]
+
+
+****Change:(orig (509 509 c))
+@s[ (error "An print function is supplied to a typed structure."))
+
+@s| (error "A print function is supplied to a typed structure."))
+
+ `(progn
+ (define-structure ',name ',conc-name ',type ',named
+ ',(mapcar #'(lambda (slotd)
+ (list (boot-slot-name slotd)
+ (boot-slot-default-init slotd)
+ (boot-slot-type slotd)
+ (boot-slot-read-only slotd)
+ (boot-slot-offset slotd)
+ (boot-slot-accessor-name slotd)
+ (boot-slot-type-changed slotd)))
+ slot-descriptions)
+ ',copier ',static ',include ',print-function ',constructors
+ ',offset ',predicate ',documentation)
+
+@s]
+
+
+****Change:(orig (511 542 c))
+@s[ `(progn (si:putprop ',name
+ '(defstruct ,name ,@slots)
+ 'defstruct-form)
+ (si:putprop ',name t 'is-a-structure)
+
+@s, (si:putprop ',name ,documentation 'structure-documentation)
+ ',name)))
+
+@s| ,@(mapcar #'(lambda (constructor)
+ (make-constructor name constructor type named
+ slot-descriptions))
+ constructors)
+ ,@(if (and type predicate)
+ (list (make-predicate name predicate type named
+ name-offset)))
+ ',name
+ )))
+
+@s]
+
+
+****Change:(orig (544 544 a))
+@s[
+
+
+@s|
+
+(eval-when (compile load eval)
+
+(defconstant wrapper-cache-number-adds-ok 4)
+
+(defconstant wrapper-cache-number-length
+ (- (integer-length most-positive-fixnum)
+ wrapper-cache-number-adds-ok))
+
+(defconstant wrapper-cache-number-mask
+ (1- (expt 2 wrapper-cache-number-length)))
+
+
+(defvar *get-wrapper-cache-number* (make-random-state))
+
+(defun get-wrapper-cache-number ()
+ (let ((n 0))
+ (declare (fixnum n))
+ (loop
+ (setq n
+ (logand wrapper-cache-number-mask
+ (random most-positive-fixnum *get-wrapper-cache-number*)))
+ (unless (zerop n) (return n)))))
+
+)
+
+(eval-when (compile load eval)
+
+(defconstant wrapper-cache-number-vector-length 8)
+
+(deftype cache-number-vector ()
+ `(simple-array fixnum (8)))
+
+(defconstant wrapper-layout (make-list wrapper-cache-number-vector-length
+ :initial-element 'number))
+
+)
+
+(defun make-wrapper-cache-number-vector ()
+ (let ((cnv (make-array #.wrapper-cache-number-vector-length
+ :element-type 'fixnum)))
+ (dotimes (i #.wrapper-cache-number-vector-length)
+ (setf (aref cnv i) (get-wrapper-cache-number)))
+ cnv))
+
+(defstruct (slot
+ (:static t)
+ (:constructor make-slot)
+ (:constructor make-named-slot (name)))
+ name
+ default-init
+ (type t)
+ read-only
+ offset
+ accessor-name
+ type-changed)
+
+;; All of the fields of s-data-internal must coincide with
+;; the C structure s_data (see object.h).
+(defstruct (s-data-internal
+ (:conc-name s-data-)
+ (:constructor nil)
+ (:static t))
+ ;; all of these slots are used by c code
+ name ; a symbol
+ (length 0 :type fixnum) ; length of slot-descriptions
+ raw ; a static array of unsigned-short (enum aelttype)
+ included ; a list of the names of structures including this one
+ includes ; nil or a s-data structure
+ staticp ; t or nil
+ print-function ; nil, a symbol, or a lambda expression
+ slot-descriptions ; a list of slots
+ slot-position ; a static array of unsigned-short
+ (size 0 :type fixnum) ; total size to allocate
+ has-holes) ; t or nil
+
+(defstruct (basic-wrapper (:include s-data-internal)
+ (:conc-name wrapper-)
+ (:constructor nil)
+ (:static t))
+ (cache-number-vector (make-wrapper-cache-number-vector))
+ (state t) ; either t or a list (state-sym new-wrapper)
+ ;; where state-sym is either :flush or :obsolete
+ (class nil))
+
+;(get name 'si::s-data) ;returns one of these:
+(defstruct (s-data (:include basic-wrapper)
+ (:static t))
+ ;; these slots are used only from lisp
+ frozen ; t or nil ; t means won't include this
+ documentation
+ constructors ; a list of either a symbol or a list symbol, arglist
+ offset ; the total number of slots and placeholders
+ named ; t or nil
+ type ; one of: nil, list, or vector
+ conc-name) ; an interned symbol
+
+#||
+(import '(si::wrapper-state si::wrapper-class si::basic-wrapper))
+
+(defstruct (wrapper (:include basic-wrapper)
+ (:print-function print-wrapper)
+ (:constructor make-wrapper-internal)
+ (:predicate wrapper-p)
+ (:conc-name wrapper-))
+ (class-slots nil :type list))
+
+(defun print-wrapper (instance stream depth)
+ (printing-random-thing (wrapper stream)
+ (format stream "Wrapper ~S" (wrapper-class wrapper))))
+||#
+
+(defun update-wrapper-state (old new same-p)
+ (unless (consp old)
+ (setf (wrapper-state old)
+ (list (if same-p ':flush ':obsolete) new))))
+
+(defun freeze-defstruct (name)
+ (let ((tem (and (symbolp name) (get name 's-data))))
+ (if tem (setf (s-data-frozen tem) t))))
+
+
+
+@s]
+
+
+****Change:(orig (551 553 c))
+@s[ (let ((l (read stream)))
+ (unless (get (car l) 'is-a-structure)
+ (error "~S is not a structure." (car l)))
+
+@s| (let* ((l (prog1 (read stream t nil t)
+ (if *read-suppress*
+ (return-from sharp-s-reader nil))))
+ (sd
+ (or (get (car l) 's-data)
+
+ (error "~S is not a structure." (car l)))))
+
+
+@s]
+
+
+****Change:(orig (558 558 c))
+@s[ (do ((cs (get (car l) 'structure-constructors) (cdr cs)))
+
+@s| (do ((cs (s-data-constructors sd) (cdr cs)))
+
+@s]
+
+
+****Change:(orig (571 571 d))
+@s[(set-dispatch-macro-character #\# #\S 'sharp-s-reader)
+
+
+
+@s|(set-dispatch-macro-character #\# #\S 'sharp-s-reader)
+
+
+@s]
+
+
+****Change:(orig (582 582 c))
+@s[(defstruct person name age sex)
+
+@s|(defstruct person name (age 20 :type signed-char) (eyes 2 :type signed-char)
+ sex)
+(defstruct person name (age 20 :type signed-char) (eyes 2 :type signed-char)
+ sex)
+(defstruct person1 name (age 20 :type fixnum)
+ sex)
+
+@s]
+
+
+****Change:(orig (584 584 c))
+@s[(defstruct (astronaut (:include person (age 45))
+
+@s|(defstruct joe a (a1 0 :type (mod 30)) (a2 0 :type (mod 30))
+ (a3 0 :type (mod 30)) (a4 0 :type (mod 30)) )
+
+;(defstruct person name age sex)
+
+(defstruct (astronaut (:include person (age 45 :type fixnum))
+
+@s]
+
+
+****Change:(orig (605 605 a))
+@s[ associative
+ identity)
+
+@s| associative
+ identity)
+
+
+@s]
+
+==============================================================================
diff --git a/gcl/pcl/impl/kcl/sys-package.lisp b/gcl/pcl/impl/kcl/sys-package.lisp
new file mode 100644
index 000000000..427813bad
--- /dev/null
+++ b/gcl/pcl/impl/kcl/sys-package.lisp
@@ -0,0 +1,149 @@
+
+
+;;; Definitions for package SLOT-ACCESSOR-NAME of type ESTABLISH
+(LISP::IN-PACKAGE "SLOT-ACCESSOR-NAME" :USE LISP::NIL :NICKNAMES
+ '("S-A-N"))
+
+;;; Definitions for package PCL of type ESTABLISH
+(LISP::IN-PACKAGE "PCL" :USE LISP::NIL)
+
+;;; Definitions for package ITERATE of type ESTABLISH
+(LISP::IN-PACKAGE "ITERATE" :USE LISP::NIL)
+
+;;; Definitions for package WALKER of type ESTABLISH
+(LISP::IN-PACKAGE "WALKER" :USE LISP::NIL)
+
+;;; Definitions for package SLOT-ACCESSOR-NAME of type EXPORT
+(LISP::IN-PACKAGE "SLOT-ACCESSOR-NAME" :USE 'LISP::NIL :NICKNAMES
+ '("S-A-N"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT 'LISP::NIL)
+
+;;; Definitions for package PCL of type EXPORT
+(LISP::IN-PACKAGE "PCL" :USE '("LISP" "ITERATE" "WALKER"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT
+ '(PCL::CLASS-PRECEDENCE-LIST PCL::SLOT-DEFINITION
+ PCL::COMPUTE-APPLICABLE-METHODS-USING-CLASSES
+ PCL::SLOT-DEFINITION-WRITERS PCL::CLASS-OF
+ PCL::NO-APPLICABLE-METHOD PCL::STANDARD-WRITER-METHOD
+ PCL::ENSURE-CLASS-USING-CLASS PCL::ENSURE-GENERIC-FUNCTION
+ PCL::FIND-METHOD-COMBINATION PCL::UPDATE-DEPENDENT
+ PCL::MAP-DEPENDENTS PCL::SLOT-MISSING PCL::SPECIALIZER
+ PCL::CALL-NEXT-METHOD PCL::ENSURE-GENERIC-FUNCTION-USING-CLASS
+ PCL::SLOT-MAKUNBOUND-USING-CLASS PCL::MAKE-INSTANCES-OBSOLETE
+ PCL::INTERN-EQL-SPECIALIZER PCL::REMOVE-DIRECT-SUBCLASS
+ PCL::METHOD-GENERIC-FUNCTION PCL::METHOD-QUALIFIERS
+ PCL::FUNCALLABLE-STANDARD-CLASS PCL::EXTRACT-LAMBDA-LIST
+ PCL::STANDARD-CLASS PCL::PRINT-OBJECT PCL::STRUCTURE-CLASS
+ PCL::COMPUTE-EFFECTIVE-SLOT-DEFINITION
+ PCL::GENERIC-FUNCTION-DECLARATIONS PCL::MAKE-INSTANCE
+ PCL::METHOD-LAMBDA-LIST PCL::DEFGENERIC
+ PCL::REMOVE-DIRECT-METHOD PCL::STANDARD-DIRECT-SLOT-DEFINITION
+ PCL::GENERIC-FUNCTION-METHODS PCL::VALIDATE-SUPERCLASS
+ PCL::REINITIALIZE-INSTANCE PCL::STANDARD-METHOD
+ PCL::STANDARD-ACCESSOR-METHOD
+ PCL::FUNCALLABLE-STANDARD-INSTANCE PCL::FUNCTION-KEYWORDS
+ PCL::STANDARD PCL::FIND-METHOD PCL::EXTRACT-SPECIALIZER-NAMES
+ PCL::INITIALIZE-INSTANCE PCL::GENERIC-FLET PCL::SLOT-UNBOUND
+ PCL::STANDARD-INSTANCE PCL::SLOT-DEFINITION-TYPE
+ PCL::COMPUTE-EFFECTIVE-METHOD PCL::ALLOCATE-INSTANCE
+ PCL::SYMBOL-MACROLET PCL::GENERIC-FUNCTION
+ PCL::GENERIC-FUNCTION-METHOD-COMBINATION
+ PCL::SPECIALIZER-DIRECT-METHODS PCL::ADD-DIRECT-SUBCLASS
+ PCL::WRITER-METHOD-CLASS PCL::SLOT-DEFINITION-INITARGS
+ PCL::METHOD-SPECIALIZERS PCL::GENERIC-FUNCTION-METHOD-CLASS
+ PCL::ADD-METHOD PCL::WITH-ACCESSORS
+ PCL::SLOT-DEFINITION-ALLOCATION
+ PCL::SLOT-DEFINITION-INITFUNCTION
+ PCL::SLOT-DEFINITION-LOCATION PCL::ADD-DIRECT-METHOD
+ PCL::SLOT-BOUNDP PCL::EQL-SPECIALIZER PCL::SHARED-INITIALIZE
+ PCL::STANDARD-GENERIC-FUNCTION
+ PCL::ACCESSOR-METHOD-SLOT-DEFINITION
+ PCL::SLOT-BOUNDP-USING-CLASS PCL::ADD-DEPENDENT
+ PCL::SPECIALIZER-DIRECT-GENERIC-FUNCTION
+ PCL::WITH-ADDED-METHODS PCL::COMPUTE-CLASS-PRECEDENCE-LIST
+ PCL::REMOVE-DEPENDENT PCL::NEXT-METHOD-P
+ PCL::GENERIC-FUNCTION-NAME PCL::SLOT-VALUE
+ PCL::EFFECTIVE-SLOT-DEFINITION PCL::CLASS-FINALIZED-P
+ PCL::COMPUTE-DISCRIMINATING-FUNCTION PCL::STANDARD-OBJECT
+ PCL::CLASS-DEFAULT-INITARGS PCL::CLASS-DIRECT-SLOTS
+ PCL::FUNCALLABLE-STANDARD-INSTANCE-ACCESS PCL::BUILT-IN-CLASS
+ PCL::NO-NEXT-METHOD PCL::SLOT-MAKUNBOUND
+ PCL::STANDARD-READER-METHOD PCL::GENERIC-FUNCTION-LAMBDA-LIST
+ PCL::GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER
+ PCL::INVALID-METHOD-ERROR PCL::METHOD-COMBINATION-ERROR
+ PCL::SLOT-EXISTS-P PCL::FINALIZE-INHERITANCE
+ PCL::SLOT-DEFINITION-NAME
+ PCL::STANDARD-EFFECTIVE-SLOT-DEFINITION PCL::COMPUTE-SLOTS
+ PCL::CLASS-SLOTS PCL::EFFECTIVE-SLOT-DEFINITION-CLASS
+ PCL::STANDARD-INSTANCE-ACCESS PCL::WITH-SLOTS
+ PCL::DIRECT-SLOT-DEFINITION PCL::DEFINE-METHOD-COMBINATION
+ PCL::MAKE-METHOD-LAMBDA PCL::ENSURE-CLASS
+ PCL::DIRECT-SLOT-DEFINITION-CLASS PCL::METHOD-FUNCTION
+ PCL::STANDARD-SLOT-DEFINITION PCL::CHANGE-CLASS PCL::DEFMETHOD
+ PCL::UPDATE-INSTANCE-FOR-DIFFERENT-CLASS
+ PCL::UPDATE-INSTANCE-FOR-REDEFINED-CLASS
+ PCL::FORWARD-REFERENCED-CLASS PCL::SLOT-DEFINITION-INITFORM
+ PCL::REMOVE-METHOD PCL::READER-METHOD-CLASS PCL::CALL-METHOD
+ PCL::CLASS-PROTOTYPE PCL::CLASS-NAME PCL::FIND-CLASS
+ PCL::DEFCLASS PCL::COMPUTE-APPLICABLE-METHODS
+ PCL::SLOT-VALUE-USING-CLASS PCL::METHOD-COMBINATION
+ PCL::EQL-SPECIALIZER-INSTANCE PCL::GENERIC-LABELS PCL::METHOD
+ PCL::SLOT-DEFINITION-READERS
+ PCL::CLASS-DIRECT-DEFAULT-INITARGS
+ PCL::CLASS-DIRECT-SUBCLASSES PCL::CLASS-DIRECT-SUPERCLASSES
+ PCL::SET-FUNCALLABLE-INSTANCE-FUNCTION))
+
+;;; Definitions for package ITERATE of type EXPORT
+(LISP::IN-PACKAGE "ITERATE" :USE '("WALKER" "LISP"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT
+ '(ITERATE::SUMMING ITERATE::MINIMIZING ITERATE::PLIST-ELEMENTS
+ ITERATE::ITERATE* ITERATE::MAXIMIZING ITERATE::LIST-TAILS
+ ITERATE::*ITERATE-WARNINGS* ITERATE::GATHERING
+ ITERATE::EACHTIME ITERATE::ELEMENTS ITERATE::GATHER
+ ITERATE::LIST-ELEMENTS ITERATE::WHILE ITERATE::ITERATE
+ ITERATE::UNTIL ITERATE::JOINING ITERATE::COLLECTING
+ ITERATE::WITH-GATHERING ITERATE::INTERVAL))
+
+;;; Definitions for package WALKER of type EXPORT
+(LISP::IN-PACKAGE "WALKER" :USE '("LISP"))
+(LISP::IMPORT 'LISP::NIL)
+(LISP::EXPORT
+ '(WALKER::DEFINE-WALKER-TEMPLATE WALKER::*VARIABLE-DECLARATIONS*
+ WALKER::NESTED-WALK-FORM WALKER::VARIABLE-DECLARATION
+ WALKER::WALK-FORM-EXPAND-MACROS-P WALKER::VARIABLE-LEXICAL-P
+ WALKER::VARIABLE-SPECIAL-P WALKER::WALK-FORM
+ WALKER::MACROEXPAND-ALL WALKER::VARIABLE-GLOBALLY-SPECIAL-P))
+
+;;; Definitions for package SLOT-ACCESSOR-NAME of type SHADOW
+(LISP::IN-PACKAGE "SLOT-ACCESSOR-NAME")
+(LISP::SHADOW 'LISP::NIL)
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT 'LISP::NIL)
+
+;;; Definitions for package PCL of type SHADOW
+(LISP::IN-PACKAGE "PCL")
+(LISP::SHADOW '(PCL::DOTIMES PCL::DOCUMENTATION))
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT
+ '(SYSTEM::STRUCTURE-REF SYSTEM::STRUCTURE-DEF SYSTEM::STRUCTUREP))
+
+;;; Definitions for package ITERATE of type SHADOW
+(LISP::IN-PACKAGE "ITERATE")
+(LISP::SHADOW 'LISP::NIL)
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT 'LISP::NIL)
+
+;;; Definitions for package WALKER of type SHADOW
+(LISP::IN-PACKAGE "WALKER")
+(LISP::SHADOW 'LISP::NIL)
+(LISP::SHADOWING-IMPORT 'LISP::NIL)
+(LISP::IMPORT 'LISP::NIL)
+
+(lisp::in-package 'SI)
+(export '(%structure-name
+ %compiled-function-name
+ %set-compiled-function-name))
+(in-package 'pcl)
diff --git a/gcl/pcl/impl/kcl/sys-proclaim.lisp b/gcl/pcl/impl/kcl/sys-proclaim.lisp
new file mode 100644
index 000000000..c1d1f92f6
--- /dev/null
+++ b/gcl/pcl/impl/kcl/sys-proclaim.lisp
@@ -0,0 +1,818 @@
+
+(IN-PACKAGE "USER")
+(PROCLAIM '(FTYPE (FUNCTION (*) FIXNUM) PCL::ZERO))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T FIXNUM *) FIXNUM)
+ PCL::COMPUTE-PRIMARY-CACHE-LOCATION-FROM-LOCATION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) FIXNUM) PCL::FAST-INSTANCE-BOUNDP-INDEX
+ PCL::ONE-INDEX-LIMIT-FN PCL::N-N-ACCESSORS-LIMIT-FN
+ PCL::CHECKING-LIMIT-FN PCL::PV-CACHE-LIMIT-FN
+ PCL::CACHE-NLINES PCL::CACHE-MAX-LOCATION PCL::CACHE-SIZE
+ PCL::CACHE-MASK PCL::ARG-INFO-NUMBER-REQUIRED
+ PCL::DEFAULT-LIMIT-FN PCL::CACHE-COUNT
+ PCL::CACHING-LIMIT-FN PCL::PV-TABLE-PV-SIZE
+ PCL::EARLY-CLASS-SIZE))
+(PROCLAIM '(FTYPE (FUNCTION (FIXNUM) T) PCL::POWER-OF-TWO-CEILING))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) FUNCTION) PCL::CACHE-LIMIT-FN
+ PCL::METHOD-CALL-FUNCTION PCL::FAST-METHOD-CALL-FUNCTION))
+(PROCLAIM '(FTYPE (FUNCTION (T) PCL::FIELD-TYPE) PCL::CACHE-FIELD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) LIST) PCL::CACHE-OVERFLOW
+ PCL::PV-TABLE-SLOT-NAME-LISTS PCL::PV-TABLE-CALL-LIST))
+(PROCLAIM '(FTYPE (FUNCTION (T) (MEMBER NIL T)) PCL::CACHE-VALUEP))
+(PROCLAIM '(FTYPE (FUNCTION (T) SIMPLE-VECTOR) PCL::CACHE-VECTOR))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) (VALUES T T)) PCL::MAKE-CLASS-PREDICATE-NAME
+ PCL::MAKE-KEYWORD))
+(PROCLAIM '(FTYPE (FUNCTION (FIXNUM T) T) PCL::%CCLOSURE-ENV-NTHCDR))
+(PROCLAIM
+ '(FTYPE (FUNCTION (FIXNUM FIXNUM T) FIXNUM)
+ PCL::COMPUTE-PRIMARY-CACHE-LOCATION))
+(PROCLAIM '(FTYPE (FUNCTION (T) (INTEGER 1 512)) PCL::CACHE-LINE-SIZE))
+(PROCLAIM '(FTYPE (FUNCTION (T) (INTEGER 1 256)) PCL::CACHE-NKEYS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) (OR PCL::CACHE NULL)) PCL::PV-TABLE-CACHE))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T) *) PCL::MEMF-CODE-CONVERTER
+ PCL::REAL-LOAD-DEFCLASS PCL::CACHE-MISS-VALUES-INTERNAL
+ PCL::GENERATE-DISCRIMINATION-NET-INTERNAL
+ PCL::MAKE-LONG-METHOD-COMBINATION-FUNCTION
+ PCL::DO-SHORT-METHOD-COMBINATION
+ WALKER::WALK-TEMPLATE-HANDLE-REPEAT-1))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T) *)
+ PCL::GET-OPTIMIZED-STD-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ ITERATE::WALK-GATHERING-BODY
+ PCL::CACHE-MISS-VALUES
+ PCL::MAKE-OPTIMIZED-STD-READER-METHOD-FUNCTION
+ PCL::OPTIMIZE-SLOT-VALUE-BY-CLASS-P PCL::ACCESSOR-VALUES1
+ PCL::EMIT-READER/WRITER
+ PCL::EMIT-ONE-OR-N-INDEX-READER/WRITER
+ WALKER::WALK-MULTIPLE-VALUE-SETQ PCL::GENERATING-LISP
+ PCL::EMIT-READER/WRITER-FUNCTION
+ PCL::EMIT-ONE-OR-N-INDEX-READER/WRITER-FUNCTION
+ WALKER::WALK-LET-IF PCL::SET-SLOT-VALUE
+ PCL::CONVERT-METHODS PCL::SLOT-VALUE-USING-CLASS-DFUN
+ PCL::SLOT-BOUNDP-USING-CLASS-DFUN
+ PCL::CHECK-METHOD-ARG-INFO PCL::LOAD-LONG-DEFCOMBIN
+ PCL::MAKE-FINAL-N-N-ACCESSOR-DFUN
+ PCL::MAKE-FINAL-CACHING-DFUN
+ PCL::MAKE-FINAL-CONSTANT-VALUE-DFUN
+ PCL::GET-CLASS-SLOT-VALUE-1 PCL::ACCESSOR-VALUES-INTERNAL
+ PCL::MAKE-OPTIMIZED-STD-WRITER-METHOD-FUNCTION
+ PCL::MAKE-OPTIMIZED-STD-BOUNDP-METHOD-FUNCTION
+ ITERATE::EXPAND-INTO-LET WALKER::WALK-FORM-INTERNAL
+ ITERATE::RENAME-VARIABLES
+ PCL::CONSTANT-VALUE-MISS PCL::CACHING-MISS
+ PCL::CHECKING-MISS
+ PCL::GET-OPTIMIZED-STD-ACCESSOR-METHOD-FUNCTION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T) *)
+ PCL::COMPUTE-DISCRIMINATING-FUNCTION-ARGLIST-INFO-INTERNAL
+ PCL::ADD-METHOD-DECLARATIONS PCL::WALK-METHOD-LAMBDA
+ PCL::MAKE-TWO-CLASS-ACCESSOR-DFUN
+ WALKER::WALK-TEMPLATE-HANDLE-REPEAT))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T) *)
+ PCL::GET-ACCESSOR-FROM-SVUC-METHOD-FUNCTION
+ PCL::BOOTSTRAP-ACCESSOR-DEFINITION
+ PCL::GET-ACCESSOR-METHOD-FUNCTION
+ PCL::EMIT-CHECKING-OR-CACHING
+ PCL::EMIT-CHECKING-OR-CACHING-FUNCTION
+ PCL::SETF-SLOT-VALUE-USING-CLASS-DFUN
+ PCL::LOAD-SHORT-DEFCOMBIN
+ PCL::INITIALIZE-INSTANCE-SIMPLE-FUNCTION
+ PCL::MAKE-SHARED-INITIALIZE-FORM-LIST
+ PCL::MAKE-ONE-CLASS-ACCESSOR-DFUN
+ PCL::MAKE-FINAL-ONE-INDEX-ACCESSOR-DFUN
+ PCL::MAKE-FINAL-CHECKING-DFUN PCL::ACCESSOR-VALUES
+ PCL::SET-CLASS-SLOT-VALUE-1
+ PCL::GENERATE-DISCRIMINATION-NET
+ PCL::REAL-MAKE-METHOD-LAMBDA
+ PCL::ORDER-SPECIALIZERS WALKER::WALK-TEMPLATE
+ PCL::ACCESSOR-MISS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T) *)
+ ITERATE::ITERATE-TRANSFORM-BODY))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T *) *) PCL::SLOT-VALUE-OR-DEFAULT
+ PCL::MAKE-EFFECTIVE-METHOD-FUNCTION
+ PCL::GET-EFFECTIVE-METHOD-FUNCTION
+ PCL::MAKE-N-N-ACCESSOR-DFUN WALKER:NESTED-WALK-FORM
+ PCL::MAKE-CHECKING-DFUN PCL::LOAD-DEFGENERIC
+ PCL::TYPES-FROM-ARGUMENTS
+ PCL::MAKE-DEFAULT-INITARGS-FORM-LIST
+ PCL::MAKE-FINAL-ACCESSOR-DFUN PCL::MAKE-ACCESSOR-TABLE
+ PCL::GET-SIMPLE-INITIALIZATION-FUNCTION
+ PCL::GET-COMPLEX-INITIALIZATION-FUNCTIONS
+ PCL::COMPUTE-SECONDARY-DISPATCH-FUNCTION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T *) *)
+ PCL::MAKE-EFFECTIVE-METHOD-FUNCTION-SIMPLE1
+ ITERATE::RENAME-LET-BINDINGS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T *) *) PCL::MAKE-ONE-INDEX-ACCESSOR-DFUN
+ WALKER::WALK-DECLARATIONS
+ PCL::GET-SECONDARY-DISPATCH-FUNCTION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T *) *) PCL::REAL-MAKE-A-METHOD))
+(PROCLAIM '(FTYPE (FUNCTION (T STREAM T) T) PCL::PRINT-DFUN-INFO))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T) T) ITERATE::SIMPLE-EXPAND-GATHERING-FORM
+ ITERATE::RENAME-AND-CAPTURE-VARIABLES
+ ITERATE::VARIABLE-SAME-P
+ PCL::GET-FUNCTION-GENERATOR
+ WALKER:VARIABLE-DECLARATION PCL::GET-NEW-FUNCTION-GENERATOR
+ PCL::TRACE-METHOD-INTERNAL PCL::ONE-INDEX-DFUN-INFO
+ PCL::ONE-CLASS-DFUN-INFO
+ PCL::MAP-ALL-ORDERS SYSTEM::APPLY-DISPLAY-FUN
+ PCL::NOTE-PV-TABLE-REFERENCE
+ WALKER::RELIST-INTERNAL
+ PCL::MAKE-DFUN-CALL
+ WALKER::WALK-TAGBODY-1 WALKER::WALK-LAMBDA
+ PCL::OPTIMIZE-GF-CALL-INTERNAL
+ PCL::SKIP-OPTIMIZE-SLOT-VALUE-BY-CLASS-P
+ WALKER::WALK-COMPILER-LET PCL::SKIP-FAST-SLOT-ACCESS-P
+ WALKER::WALK-UNEXPECTED-DECLARE WALKER::WALK-FLET
+ WALKER::WALK-IF
+ WALKER::WALK-LABELS WALKER::WALK-LET WALKER::WALK-LET*
+ WALKER::WALK-LOCALLY
+ WALKER::WALK-MACROLET
+ PCL::FIX-SLOT-ACCESSORS WALKER::WALK-MULTIPLE-VALUE-BIND
+ PCL:COMPUTE-EFFECTIVE-METHOD WALKER::WALK-SETQ
+ WALKER::WALK-SYMBOL-MACROLET PCL::EMIT-SLOT-READ-FORM
+ WALKER::WALK-TAGBODY PCL::EMIT-BOUNDP-CHECK WALKER::WALK-DO
+ WALKER::WALK-DO* WALKER::WALK-PROG
+ WALKER::WALK-NAMED-LAMBDA WALKER::WALK-PROG*
+ PCL::EXPAND-DEFGENERIC PCL::EMIT-GREATER-THAN-1-DLAP
+ PCL::EMIT-1-T-DLAP
+ PCL::MAKE-METHOD-INITARGS-FORM-INTERNAL
+ PCL::ENTRY-IN-CACHE-P PCL::CONVERT-TABLE
+ PCL::MAKE-METHOD-SPEC PCL::TRACE-EMF-CALL-INTERNAL
+ PCL::FLUSH-CACHE-TRAP PCL::SET-FUNCTION-NAME-1
+ PCL::OBSOLETE-INSTANCE-TRAP
+ PCL::COMPUTE-PRECEDENCE PCL::PRINT-STD-INSTANCE
+ PCL::|SETF PCL METHOD-FUNCTION-GET|
+ PCL::|SETF PCL PLIST-VALUE|
+ WALKER::WITH-AUGMENTED-ENVIRONMENT-INTERNAL
+ PCL::CAN-OPTIMIZE-ACCESS PCL::OPTIMIZE-SLOT-VALUE
+ PCL::OPTIMIZE-SET-SLOT-VALUE PCL::DECLARE-STRUCTURE
+ PCL::OPTIMIZE-SLOT-BOUNDP
+ PCL::PRINT-CACHE PCL::COMPUTE-STD-CPL-PHASE-3
+ PCL::FIRST-FORM-TO-LISP
+ ITERATE::OPTIMIZE-ITERATE-FORM
+ PCL::WRAP-METHOD-GROUP-SPECIFIER-BINDINGS
+ PCL::MAKE-TOP-LEVEL-FORM PCL::INVALIDATE-WRAPPER
+ PCL::STANDARD-COMPUTE-EFFECTIVE-METHOD
+ PCL::MAKE-OPTIMIZED-STD-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ PCL::MAKE-OPTIMIZED-STD-SETF-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ PCL::MAKE-OPTIMIZED-STD-SLOT-BOUNDP-USING-CLASS-METHOD-FUNCTION
+ WALKER::RECONS ITERATE::OPTIMIZE-GATHERING-FORM))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T) T) PCL::MAKE-EFFECTIVE-METHOD-FUNCTION1
+ PCL::MAKE-EFFECTIVE-METHOD-FUNCTION-INTERNAL
+ PCL::MAKE-EFFECTIVE-METHOD-FUNCTION-TYPE
+ PCL::MEMF-TEST-CONVERTER
+ PCL::LOAD-PRECOMPILED-DFUN-CONSTRUCTOR
+ PCL::TWO-CLASS-DFUN-INFO
+ WALKER::WALK-LET/LET* WALKER::WALK-PROG/PROG*
+ WALKER::WALK-DO/DO*
+ WALKER::WALK-BINDINGS-2 PCL::OPTIMIZE-READER
+ PCL::OPTIMIZE-WRITER
+ PCL::EMIT-CHECKING-OR-CACHING-FUNCTION-PRELIMINARY
+ PCL::MAYBE-EXPAND-ACCESSOR-FORM
+ PCL::INITIALIZE-INSTANCE-SIMPLE
+ PCL::GET-WRAPPERS-FROM-CLASSES
+ PCL::LOAD-PRECOMPILED-IIS-ENTRY
+ PCL::FILL-CACHE-P
+ PCL::ADJUST-CACHE
+ PCL::EXPAND-CACHE
+ PCL::EXPAND-SYMBOL-MACROLET-INTERNAL
+ PCL::BOOTSTRAP-SET-SLOT PCL::EXPAND-DEFCLASS PCL::GET-CACHE
+ ))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T) T) PCL::LOAD-FUNCTION-GENERATOR
+ PCL::EXPAND-EMF-CALL-METHOD PCL::MAKE-FGEN
+ PCL::BOOTSTRAP-MAKE-SLOT-DEFINITIONS
+ PCL::BOOTSTRAP-ACCESSOR-DEFINITIONS1
+ PCL::MAKE-FINAL-ORDINARY-DFUN-INTERNAL PCL::COMPUTE-PV-SLOT
+ WALKER::WALK-BINDINGS-1
+ PCL::OPTIMIZE-INSTANCE-ACCESS
+ PCL::OPTIMIZE-ACCESSOR-CALL
+ PCL::MAKE-METHOD-INITARGS-FORM-INTERNAL1
+ PCL::UPDATE-SLOTS-IN-PV
+ PCL::MAKE-PARAMETER-REFERENCES
+ PCL::MAKE-EMF-CACHE
+ PCL::GET-MAKE-INSTANCE-FUNCTION-INTERNAL
+ PCL::MAKE-INSTANCE-FUNCTION-COMPLEX
+ PCL::MAKE-INSTANCE-FUNCTION-SIMPLE
+ PCL::OPTIMIZE-GENERIC-FUNCTION-CALL
+ PCL::REAL-MAKE-METHOD-INITARGS-FORM
+ ))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T *) T)
+ PCL::MAKE-EFFECTIVE-METHOD-FUNCTION-SIMPLE
+ PCL::MAKE-EMF-FROM-METHOD
+ PCL::EXPAND-EFFECTIVE-METHOD-FUNCTION
+ PCL::NAMED-OBJECT-PRINT-FUNCTION PCL::FIND-CLASS-FROM-CELL
+ PCL::FIND-CLASS-PREDICATE-FROM-CELL PCL::INITIALIZE-INFO
+ PCL::GET-EFFECTIVE-METHOD-FUNCTION1 PCL::GET-DECLARATION
+ PCL::GET-METHOD-FUNCTION-PV-CELL
+ PCL:ENSURE-GENERIC-FUNCTION-USING-CLASS PCL::EMIT-MISS
+ PCL::METHOD-FUNCTION-GET PCL::PROBE-CACHE PCL::MAP-CACHE
+ PCL::GET-CACHE-FROM-CACHE PCL::PRECOMPUTE-EFFECTIVE-METHODS
+ PCL::RECORD-DEFINITION WALKER::CONVERT-MACRO-TO-LAMBDA
+ PCL::CPL-ERROR PCL::REAL-ADD-METHOD
+ PCL::REAL-ENSURE-GF-USING-CLASS--GENERIC-FUNCTION
+ PCL::REAL-ENSURE-GF-USING-CLASS--NULL
+ PCL::COMPUTE-SECONDARY-DISPATCH-FUNCTION1))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T T) T)
+ PCL::GET-SECONDARY-DISPATCH-FUNCTION2))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T) T)
+ PCL::BOOTSTRAP-MAKE-SLOT-DEFINITION PCL::EMIT-SLOT-ACCESS
+ PCL::OPTIMIZE-GF-CALL PCL::SET-ARG-INFO1 PCL::LOAD-DEFCLASS
+ PCL::MAKE-EARLY-CLASS-DEFINITION))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T *) T) PCL::FILL-DFUN-CACHE
+ PCL::EARLY-ADD-NAMED-METHOD PCL::REAL-ADD-NAMED-METHOD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T *) T) PCL::LOAD-DEFMETHOD
+ PCL::MAKE-DEFMETHOD-FORM PCL::MAKE-DEFMETHOD-FORM-INTERNAL
+ PCL::EARLY-MAKE-A-METHOD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T *) T) PCL::CHECK-INITARGS-2-PLIST
+ PCL::CHECK-INITARGS-2-LIST WALKER::WALK-ARGLIST
+ PCL::MAKE-EMF-CALL PCL::CAN-OPTIMIZE-ACCESS1
+ PCL::EMIT-FETCH-WRAPPER PCL::FILL-CACHE
+ PCL::REAL-GET-METHOD PCL::CHECK-INITARGS-1 PCL::GET-METHOD))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T *) T) PCL::EMIT-DLAP
+ PCL::GET-SECONDARY-DISPATCH-FUNCTION1))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T FIXNUM) T) PCL::FILL-CACHE-FROM-CACHE-P))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T) T) PCL::EXPAND-DEFMETHOD
+ PCL::LOAD-DEFMETHOD-INTERNAL
+ ))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T T T T T T T *) T)
+ PCL::BOOTSTRAP-INITIALIZE-CLASS))
+(PROCLAIM
+ '(FTYPE (FUNCTION NIL *) PCL::COUNT-ALL-DFUNS PCL::RENEW-SYS-FILES
+ PCL::EMIT-N-N-READERS PCL::EMIT-N-N-WRITERS))
+(PROCLAIM
+ '(FTYPE (FUNCTION NIL T) PCL::GET-EFFECTIVE-METHOD-GENSYM
+ PCL::SHOW-EMF-CALL-TRACE PCL::BOOTSTRAP-META-BRAID
+ PCL::BOOTSTRAP-BUILT-IN-CLASSES PCL::LIST-ALL-DFUNS
+ PCL::DEFAULT-METHOD-ONLY-DFUN-INFO
+ PCL::INITIALIZE-CHECKING-OR-CACHING-FUNCTION-LIST
+ PCL::CACHES-TO-ALLOCATE PCL::UPDATE-DISPATCH-DFUNS
+ PCL::MAKE-CACHE PCL::RESET-PCL-PACKAGE
+ PCL::IN-THE-COMPILER-P PCL::STRUCTURE-FUNCTIONS-EXIST-P
+ PCL::ALLOCATE-FUNCALLABLE-INSTANCE-2
+ PCL::%%ALLOCATE-INSTANCE--CLASS
+ PCL::ALLOCATE-FUNCALLABLE-INSTANCE-1
+ PCL::DISPATCH-DFUN-INFO PCL::INITIAL-DISPATCH-DFUN-INFO
+ PCL::INITIAL-DFUN-INFO PCL::NO-METHODS-DFUN-INFO
+ PCL::SHOW-FREE-CACHE-VECTORS PCL::MAKE-CPD
+ PCL::MAKE-ARG-INFO PCL::SHOW-DFUN-CONSTRUCTORS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (*) *) PCL::UNTRACE-METHOD
+ PCL:INVALID-METHOD-ERROR PCL:METHOD-COMBINATION-ERROR
+ PCL::LIST-LARGE-CACHES
+ PCL::UPDATE-MAKE-INSTANCE-FUNCTION-TABLE))
+(PROCLAIM '(FTYPE (FUNCTION (FIXNUM T *) *) PCL::FIND-FREE-CACHE-LINE))
+(PROCLAIM
+ '(FTYPE (FUNCTION (FIXNUM T T) *) PCL::COMPUTE-CACHE-PARAMETERS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (*) T) PCL::|__si::MAKE-DFUN-INFO|
+ PCL::|__si::MAKE-NO-METHODS| PCL::|__si::MAKE-INITIAL|
+ PCL::|__si::MAKE-INITIAL-DISPATCH|
+ PCL::|__si::MAKE-DISPATCH|
+ PCL::|__si::MAKE-DEFAULT-METHOD-ONLY|
+ PCL::|__si::MAKE-ACCESSOR-DFUN-INFO|
+ PCL::|__si::MAKE-ONE-INDEX-DFUN-INFO|
+ PCL::MAKE-FAST-METHOD-CALL PCL::|__si::MAKE-N-N|
+ PCL::MAKE-FAST-INSTANCE-BOUNDP PCL::|__si::MAKE-ONE-CLASS|
+ PCL::|__si::MAKE-TWO-CLASS| PCL::|__si::MAKE-ONE-INDEX|
+ PCL::|__si::MAKE-CHECKING| PCL::|__si::MAKE-ARG-INFO|
+ PCL::FIX-EARLY-GENERIC-FUNCTIONS PCL::STRING-APPEND
+ PCL::|__si::MAKE-CACHING| PCL::|__si::MAKE-CONSTANT-VALUE|
+ PCL::FALSE PCL::|STRUCTURE-OBJECT class constructor|
+ PCL::PV-WRAPPERS-FROM-PV-ARGS PCL::MAKE-PV-TABLE
+ PCL::|__si::MAKE-PV-TABLE| PCL::INTERN-PV-TABLE
+ PCL::CALLED-FIN-WITHOUT-FUNCTION
+ PCL::|__si::MAKE-STD-INSTANCE| PCL::TRUE
+ PCL::MAKE-INITIALIZE-INFO PCL::|__si::MAKE-CACHE|
+ PCL::MAKE-PROGN WALKER::UNBOUND-LEXICAL-FUNCTION
+ PCL::|__si::MAKE-CLASS-PRECEDENCE-DESCRIPTION|
+ PCL::MAKE-METHOD-CALL))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) *) PCL::TYPE-FROM-SPECIALIZER
+ PCL::*NORMALIZE-TYPE PCL::UNPARSE-TYPE
+ PCL::DEFAULT-CODE-CONVERTER PCL::CONVERT-TO-SYSTEM-TYPE
+ PCL::EMIT-CONSTANT-VALUE PCL::SFUN-P PCL::PCL-DESCRIBE
+ PCL::GET-GENERIC-FUNCTION-INFO PCL::EARLY-METHOD-FUNCTION
+ PCL::EARLY-METHOD-STANDARD-ACCESSOR-SLOT-NAME
+ PCL::SPECIALIZER-FROM-TYPE PCL::CLASS-EQ-TYPE
+ COMPILER::CAN-USE-PRINT-CIRCLE-P PCL::STRUCTURE-WRAPPER
+ PCL::FIND-STRUCTURE-CLASS PCL::MAKE-DISPATCH-DFUN
+ PCL::FIND-WRAPPER PCL::PARSE-DEFMETHOD
+ PCL::PROTOTYPES-FOR-MAKE-METHOD-LAMBDA
+ PCL::FORCE-CACHE-FLUSHES PCL::EMIT-ONE-CLASS-READER
+ PCL::EMIT-ONE-CLASS-WRITER PCL::EMIT-TWO-CLASS-READER
+ PCL::EMIT-TWO-CLASS-WRITER PCL::EMIT-ONE-INDEX-READERS
+ PCL::EMIT-ONE-INDEX-WRITERS PCL::NET-CODE-CONVERTER
+ PCL::EMIT-IN-CHECKING-CACHE-P PCL::COMPILE-IIS-FUNCTIONS
+ PCL::ANALYZE-LAMBDA-LIST
+ PCL::COMPUTE-APPLICABLE-METHODS-EMF
+ PCL::GET-DISPATCH-FUNCTION PCL::INSURE-CACHING-DFUN
+ PCL::%FBOUNDP PCL::CCLOSUREP PCL::GENERIC-FUNCTION-NAME-P
+ PCL::MAKE-FINAL-DISPATCH-DFUN
+ PCL::STRUCTURE-SLOTD-INIT-FORM
+ PCL::PARSE-METHOD-GROUP-SPECIFIER
+ PCL::METHOD-PROTOTYPE-FOR-GF
+ PCL::EARLY-COLLECT-INHERITANCE))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T) T) PCL::UNENCAPSULATED-FDEFINITION
+ PCL::DFUN-INFO-P PCL::NO-METHODS-P
+ PCL::MAKE-TYPE-PREDICATE
+ PCL::DEFAULT-TEST-CONVERTER PCL::INITIAL-P
+ PCL::UNPARSE-TYPE-LIST PCL::MAKE-CALL-METHODS
+ PCL::DEFAULT-CONSTANT-CONVERTER PCL::INITIAL-DISPATCH-P
+ PCL::DISPATCH-P PCL::GBOUNDP PCL::GMAKUNBOUND
+ PCL::DEFAULT-CONSTANTP PCL::DEFAULT-METHOD-ONLY-P
+ PCL::FGEN-TEST PCL::LOOKUP-FGEN PCL::ACCESSOR-DFUN-INFO-P
+ PCL::FGEN-GENERATOR PCL::FGEN-SYSTEM
+ PCL::ONE-INDEX-DFUN-INFO-P PCL::FAST-METHOD-CALL-P
+ PCL::N-N-P PCL::FAST-INSTANCE-BOUNDP-P
+ PCL::METHOD-FUNCTION-PV-TABLE PCL::METHOD-FUNCTION-METHOD
+ PCL::STORE-FGEN PCL::ONE-CLASS-P
+ PCL::METHOD-FUNCTION-NEEDS-NEXT-METHODS-P
+ PCL::FTYPE-DECLARATION-FROM-LAMBDA-LIST PCL::FGEN-GENSYMS
+ PCL::TWO-CLASS-P PCL::ARG-INFO-LAMBDA-LIST
+ PCL::ARG-INFO-PRECEDENCE PCL::ARG-INFO-METATYPES
+ PCL::FGEN-GENERATOR-LAMBDA SYSTEM:%STRUCTURE-NAME
+ PCL::ARG-INFO-NUMBER-OPTIONAL
+ SYSTEM:%COMPILED-FUNCTION-NAME PCL::ARG-INFO-KEY/REST-P
+ PCL::ONE-INDEX-P PCL::ARG-INFO-KEYWORDS
+ PCL::GF-INFO-SIMPLE-ACCESSOR-TYPE
+ PCL::GF-PRECOMPUTE-DFUN-AND-EMF-P
+ PCL::GF-INFO-STATIC-C-A-M-EMF PCL::CHECKING-P
+ PCL::GF-INFO-C-A-M-EMF-STD-P PCL::GF-INFO-FAST-MF-P
+ PCL::UNDEFMETHOD-1 PCL::ARG-INFO-P
+ PCL::FAST-METHOD-CALL-ARG-INFO PCL::ARG-INFO-NKEYS
+ PCL::GF-DFUN-CACHE PCL:CLASS-OF PCL::GF-DFUN-INFO
+ PCL::FUNCTION-RETURNING-NIL
+ PCL::ACCESSOR-DFUN-INFO-ACCESSOR-TYPE PCL::EVAL-FORM
+ PCL::ONE-INDEX-DFUN-INFO-INDEX
+ PCL::SLOT-INITARGS-FROM-STRUCTURE-SLOTD PCL::TYPE-CLASS
+ PCL::ONE-CLASS-WRAPPER0 PCL::EXTRACT-PARAMETERS
+ PCL::CLASS-PREDICATE PCL::EXTRACT-REQUIRED-PARAMETERS
+ PCL::MAKE-CLASS-EQ-PREDICATE PCL::TWO-CLASS-WRAPPER1
+ PCL::MAKE-EQL-PREDICATE PCL::CHECKING-FUNCTION
+ PCL::BOOTSTRAP-ACCESSOR-DEFINITIONS
+ PCL::INITIALIZE-INFO-KEY PCL::BOOTSTRAP-CLASS-PREDICATES
+ PCL::GET-BUILT-IN-CLASS-SYMBOL PCL::INITIALIZE-INFO-WRAPPER
+ PCL::GET-BUILT-IN-WRAPPER-SYMBOL PCL::DO-STANDARD-DEFSETF-1
+ PCL::CACHING-P PCL::GFS-OF-TYPE PCL::LEGAL-CLASS-NAME-P
+ PCL::STRUCTURE-TYPE-P PCL::CONSTANT-VALUE-P
+ PCL::USE-DEFAULT-METHOD-ONLY-DFUN-P
+ SYSTEM::NEXT-STACK-FRAME PCL::WRAPPER-FIELD
+ PCL::NEXT-WRAPPER-FIELD PCL::SETFBOUNDP
+ PCL::GET-SETF-FUNCTION-NAME PCL::USE-CACHING-DFUN-P
+ PCL::MAKE-PV-TYPE-DECLARATION
+ PCL::MAKE-CALLS-TYPE-DECLARATION PCL::MAP-SPECIALIZERS
+ WALKER:VARIABLE-GLOBALLY-SPECIAL-P PCL::SLOT-VECTOR-SYMBOL
+ PCL::MAKE-PERMUTATION-VECTOR PCL::STRUCTURE-OBJECT-P
+ PCL::EXPAND-MAKE-INSTANCE-FORM PCL::MAKE-CONSTANT-FUNCTION
+ PCL::FUNCTION-RETURNING-T PCL::SORT-SLOTS PCL::SORT-CALLS
+ PCL::SYMBOL-PKG-NAME
+ PCL::CLASS-HAS-A-FORWARD-REFERENCED-SUPERCLASS-P
+ PCL::INITIALIZE-INFO-BOUND-SLOTS
+ PCL::INITIALIZE-INFO-CACHED-VALID-P
+ PCL::GET-MAKE-INSTANCE-FUNCTIONS
+ PCL::INITIALIZE-INFO-CACHED-RI-VALID-P
+ PCL::INITIALIZE-INFO-CACHED-INITARGS-FORM-LIST
+ PCL::INITIALIZE-INFO-CACHED-NEW-KEYS
+ PCL::UPDATE-C-A-M-GF-INFO
+ PCL::INITIALIZE-INFO-CACHED-DEFAULT-INITARGS-FUNCTION
+ PCL::UPDATE-GF-SIMPLE-ACCESSOR-TYPE
+ PCL::UPDATE-GFS-OF-CLASS
+ PCL::INITIALIZE-INFO-CACHED-SHARED-INITIALIZE-T-FUNCTION
+ PCL::DO-STANDARD-DEFSETFS-FOR-DEFCLASS
+ PCL::STANDARD-SVUC-METHOD
+ PCL::INITIALIZE-INFO-CACHED-SHARED-INITIALIZE-NIL-FUNCTION
+ PCL:EXTRACT-LAMBDA-LIST PCL::%CCLOSURE-ENV
+ PCL::STRUCTURE-SVUC-METHOD
+ PCL::INITIALIZE-INFO-CACHED-CONSTANTS
+ PCL:EXTRACT-SPECIALIZER-NAMES PCL::METHOD-FUNCTION-PLIST
+ PCL::INITIALIZE-INFO-CACHED-COMBINED-INITIALIZE-FUNCTION
+ PCL::INITIALIZE-INFO-CACHED-MAKE-INSTANCE-FUNCTION
+ PCL::INITIALIZE-INFO-CACHED-MAKE-INSTANCE-FUNCTION-SYMBOL
+ PCL::INTERNED-SYMBOL-P PCL::GDEFINITION
+ PCL::UPDATE-CLASS-CAN-PRECEDE-P PCL::%STD-INSTANCE-WRAPPER
+ PCL::%STD-INSTANCE-SLOTS PCL::PV-TABLEP PCL::STD-INSTANCE-P
+ PCL::COMPUTE-MCASE-PARAMETERS PCL::COMPUTE-CLASS-SLOTS
+ PCL::MAKE-PV-TABLE-TYPE-DECLARATION PCL::NET-TEST-CONVERTER
+ PCL:INTERN-EQL-SPECIALIZER
+ PCL::MAKE-INSTANCE-FUNCTION-SYMBOL
+ PCL::UPDATE-ALL-C-A-M-GF-INFO
+ PCL::UPDATE-PV-TABLE-CACHE-INFO PCL::DFUN-INFO-CACHE
+ PCL::NO-METHODS-CACHE PCL::ARG-INFO-APPLYP
+ PCL::INITIAL-CACHE PCL::INITIAL-DISPATCH-CACHE
+ PCL::CHECK-CACHE PCL::DISPATCH-CACHE PCL::CLASS-FROM-TYPE
+ PCL::DEFAULT-METHOD-ONLY-CACHE PCL::DNET-METHODS-P
+ PCL::ACCESSOR-DFUN-INFO-CACHE
+ PCL::METHOD-FUNCTION-FROM-FAST-FUNCTION
+ PCL::ONE-INDEX-DFUN-INFO-CACHE
+ PCL::ONE-INDEX-DFUN-INFO-ACCESSOR-TYPE
+ PCL::METHOD-CALL-CALL-METHOD-ARGS PCL::KEYWORD-SPEC-NAME
+ PCL::N-N-CACHE PCL::GENERIC-CLOBBERS-FUNCTION
+ PCL::N-N-ACCESSOR-TYPE PCL::FAST-METHOD-CALL-PV-CELL
+ PCL::WRAPPER-FOR-STRUCTURE PCL::ONE-CLASS-CACHE
+ PCL::FAST-METHOD-CALL-NEXT-METHOD-CALL
+ PCL::ONE-CLASS-ACCESSOR-TYPE PCL::ONE-CLASS-INDEX
+ PCL::BUILT-IN-WRAPPER-OF PCL::TWO-CLASS-CACHE
+ PCL::BUILT-IN-OR-STRUCTURE-WRAPPER1
+ PCL::TWO-CLASS-ACCESSOR-TYPE PCL::TWO-CLASS-INDEX
+ PCL::ALLOCATE-CACHE-VECTOR PCL::TWO-CLASS-WRAPPER0
+ PCL::FLUSH-CACHE-VECTOR-INTERNAL PCL::ONE-INDEX-CACHE
+ PCL::EARLY-CLASS-NAME PCL::ONE-INDEX-ACCESSOR-TYPE
+ PCL::ONE-INDEX-INDEX PCL::INTERN-FUNCTION-NAME
+ PCL::CHECKING-CACHE PCL::COMPILE-LAMBDA-UNCOMPILED
+ PCL::GF-LAMBDA-LIST PCL::CACHING-CACHE
+ PCL::CONSTANT-VALUE-CACHE PCL::COMPILE-LAMBDA-DEFERRED
+ PCL::FUNCALLABLE-INSTANCE-P
+ PCL::RESET-CLASS-INITIALIZE-INFO PCL::GET-CACHE-VECTOR
+ PCL::CONSTANT-SYMBOL-P PCL::FREE-CACHE-VECTOR
+ PCL::EARLY-METHOD-LAMBDA-LIST PCL::ARG-INFO-VALID-P
+ PCL::DFUN-ARG-SYMBOL PCL::EARLY-METHOD-CLASS
+ PCL::EARLY-GF-P PCL::EARLY-GF-NAME PCL::CACHING-DFUN-INFO
+ PCL::COMPUTE-APPLICABLE-METHODS-EMF-STD-P
+ PCL::CONSTANT-VALUE-DFUN-INFO
+ PCL::RESET-CLASS-INITIALIZE-INFO-1 PCL::FREE-CACHE
+ PCL::PARSE-SPECIALIZERS PCL::RESET-INITIALIZE-INFO
+ PCL::EARLY-METHOD-QUALIFIERS
+ PCL::PROCLAIM-INCOMPATIBLE-SUPERCLASSES PCL::WRAPPER-OF
+ PCL::EARLY-METHOD-STANDARD-ACCESSOR-P
+ PCL::FUNCTION-PRETTY-ARGLIST
+ PCL::GET-MAKE-INSTANCE-FUNCTION PCL::CHECK-WRAPPER-VALIDITY
+ PCL::UNPARSE-SPECIALIZERS PCL::%SYMBOL-FUNCTION
+ PCL::FINAL-ACCESSOR-DFUN-TYPE
+ PCL::COMPLICATED-INSTANCE-CREATION-METHOD
+ PCL::DEFAULT-STRUCTUREP PCL::UPDATE-GF-INFO
+ PCL::CACHE-OWNER PCL::DEFAULT-STRUCTURE-INSTANCE-P
+ PCL::DEFAULT-STRUCTURE-TYPE PCL::STRUCTURE-TYPE
+ PCL::COMPUTE-STD-CPL-PHASE-2 PCL::GET-PV-CELL-FOR-CLASS
+ PCL::STRUCTURE-TYPE-INCLUDED-TYPE-NAME
+ PCL::STRUCTURE-TYPE-SLOT-DESCRIPTION-LIST PCL::CACHE-P
+ PCL::STRUCTURE-SLOTD-NAME
+ PCL::STRUCTURE-SLOTD-ACCESSOR-SYMBOL
+ PCL::DEFAULT-SECONDARY-DISPATCH-FUNCTION
+ PCL::STRUCTURE-SLOTD-WRITER-FUNCTION
+ PCL::FIND-CYCLE-REASONS PCL::EARLY-CLASS-DEFINITION
+ PCL::ECD-SOURCE PCL::STRUCTURE-SLOTD-TYPE
+ PCL::FORMAT-CYCLE-REASONS PCL::ECD-METACLASS PCL::CPD-CLASS
+ PCL::EARLY-CLASS-PRECEDENCE-LIST
+ PCL::METHODS-CONTAIN-EQL-SPECIALIZER-P PCL::CPD-SUPERS
+ PCL::EXPAND-LONG-DEFCOMBIN PCL::EARLY-CLASS-NAME-OF
+ PCL::CPD-AFTER PCL::EXPAND-SHORT-DEFCOMBIN
+ PCL::EARLY-CLASS-SLOTDS PCL::CPD-COUNT
+ PCL::EARLY-SLOT-DEFINITION-NAME PCL::SLOT-READER-SYMBOL
+ PCL::EARLY-SLOT-DEFINITION-LOCATION WALKER::ENV-LOCK
+ PCL::MAKE-INITIAL-DFUN PCL::EARLY-ACCESSOR-METHOD-SLOT-NAME
+ PCL::SLOT-WRITER-SYMBOL WALKER::ENV-DECLARATIONS
+ WALKER::ENV-LEXICAL-VARIABLES PCL::LIST-DFUN
+ PCL::SLOT-BOUNDP-SYMBOL PCL::MAP-ALL-GENERIC-FUNCTIONS
+ PCL::MAKE-STRUCTURE-SLOT-BOUNDP-FUNCTION
+ PCL::EARLY-CLASS-DIRECT-SUBCLASSES
+ PCL::MAKE-FUNCTION-INLINE PCL::LIST-LARGE-CACHE
+ PCL::CLASS-PRECEDENCE-DESCRIPTION-P
+ PCL::INFORM-TYPE-SYSTEM-ABOUT-STD-CLASS
+ PCL::MAKE-DEFAULT-METHOD-GROUP-DESCRIPTION
+ PCL::MAKE-OPTIMIZED-STRUCTURE-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ WALKER::ENV-WALK-FUNCTION
+ WALKER::GET-IMPLEMENTATION-DEPENDENT-WALKER-TEMPLATE
+ PCL::COUNT-DFUN PCL::MAKE-INITFUNCTION
+ PCL::MAKE-OPTIMIZED-STRUCTURE-SETF-SLOT-VALUE-USING-CLASS-METHOD-FUNCTION
+ ITERATE::VARIABLES-FROM-LET WALKER::ENV-WALK-FORM
+ PCL::MAKE-OPTIMIZED-STRUCTURE-SLOT-BOUNDP-USING-CLASS-METHOD-FUNCTION
+ PCL::INITIALIZE-INFO-P PCL::ECD-CLASS-NAME PCL::COPY-CACHE
+ PCL::COMPUTE-LINE-SIZE PCL::CANONICAL-SLOT-NAME
+ WALKER::GET-WALKER-TEMPLATE PCL::EARLY-CLASS-SLOTS
+ PCL::STRUCTURE-TYPE-INTERNAL-SLOTDS PCL::EARLY-COLLECT-CPL
+ PCL::EARLY-COLLECT-SLOTS
+ PCL::METHOD-LL->GENERIC-FUNCTION-LL
+ PCL::EARLY-COLLECT-DEFAULT-INITARGS
+ PCL::ECD-SUPERCLASS-NAMES PCL::METHOD-CALL-P
+ PCL::STRUCTURE-SLOT-BOUNDP ITERATE::SEQUENCE-ACCESSOR
+ PCL::ECD-CANONICAL-SLOTS PCL::ECD-OTHER-INITARGS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T *) *) PCL::COERCE-TO-CLASS
+ PCL::GET-METHOD-FUNCTION WALKER:MACROEXPAND-ALL
+ PCL::GET-FUNCTION PCL::GET-FUNCTION1
+ PCL:ENSURE-GENERIC-FUNCTION PCL::PARSE-METHOD-OR-SPEC
+ PCL::EXTRACT-DECLARATIONS PCL::GET-DFUN-CONSTRUCTOR
+ PCL::MAP-ALL-CLASSES PCL::MAKE-CACHING-DFUN
+ WALKER:WALK-FORM PCL:ENSURE-CLASS
+ PCL::MAKE-METHOD-FUNCTION-INTERNAL
+ PCL::PARSE-SPECIALIZED-LAMBDA-LIST
+ PCL::MAKE-METHOD-LAMBDA-INTERNAL
+ PCL::MAKE-CONSTANT-VALUE-DFUN PCL::MAKE-FINAL-DFUN-INTERNAL
+ PCL::COMPILE-LAMBDA))
+(PROCLAIM '(FTYPE (FUNCTION (T T *) (VALUES T T)) PCL::SYMBOL-APPEND))
+(PROCLAIM '(FTYPE (FUNCTION (T *) STRING) PCL::CAPITALIZE-WORDS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T) *) PCL::SAUT-CLASS
+ PCL::SPECIALIZER-APPLICABLE-USING-TYPE-P PCL::*TYPEP
+ PCL::COMPUTE-TEST PCL::GET-NEW-FUNCTION-GENERATOR-INTERNAL
+ PCL::COMPUTE-CODE PCL::CLASS-APPLICABLE-USING-CLASS-P
+ PCL::SAUT-AND PCL::SAUT-NOT PCL::SAUT-PROTOTYPE
+ COMPILER::CAN-USE-PRINT-CIRCLE-P1 PCL:SLOT-BOUNDP
+ PCL::DESTRUCTURE PCL:SLOT-MAKUNBOUND PCL:SLOT-VALUE
+ PCL::ENSURE-CLASS-VALUES PCL::MAKE-DIRECT-SLOTD
+ PCL::GENERATE-FAST-CLASS-SLOT-ACCESS-P
+ PCL::MUTATE-SLOTS-AND-CALLS PCL::INVOKE-EMF
+ PCL::EMIT-DEFAULT-ONLY-FUNCTION PCL::SPLIT-DECLARATIONS
+ PCL::EMIT-DEFAULT-ONLY COMPILER::C2LAMBDA-EXPR-WITH-KEY
+ PCL::SLOT-NAME-LISTS-FROM-SLOTS PCL::EMIT-CHECKING
+ PCL::UPDATE-SLOT-VALUE-GF-INFO PCL::EMIT-CACHING
+ PCL::SDFUN-FOR-CACHING PCL::SLOT-UNBOUND-INTERNAL
+ PCL::MAKE-INSTANCE-1 PCL::SET-FUNCTION-NAME
+ PCL::COMPUTE-STD-CPL-PHASE-1 PCL::FORM-LIST-TO-LISP
+ PCL::FIND-SUPERCLASS-CHAIN PCL::SAUT-CLASS-EQ
+ PCL::COMPUTE-APPLICABLE-METHODS-USING-TYPES
+ PCL::CHECK-INITARGS-VALUES PCL::SAUT-EQL PCL::*SUBTYPEP
+ ITERATE::PARSE-DECLARATIONS PCL::INITIAL-DFUN))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T *) T) PCL::MAKE-TYPE-PREDICATE-NAME
+ PCL::SET-DFUN PCL:FIND-CLASS PCL::TRACE-METHOD
+ PCL::FIND-CLASS-CELL PCL::MAKE-FINAL-DFUN
+ PCL::PV-TABLE-LOOKUP-PV-ARGS PCL::USE-DISPATCH-DFUN-P
+ WALKER::RELIST* WALKER::RELIST PCL::FIND-CLASS-PREDICATE
+ PCL::EARLY-METHOD-SPECIALIZERS
+ PCL::USE-CONSTANT-VALUE-DFUN-P PCL::MAKE-EARLY-GF
+ PCL::ALLOCATE-FUNCALLABLE-INSTANCE PCL::SET-ARG-INFO
+ PCL::INITIALIZE-METHOD-FUNCTION PCL::UPDATE-DFUN
+ PCL::MAKE-SPECIALIZABLE PCL::ALLOCATE-STRUCTURE-INSTANCE
+ PCL::ALLOCATE-STANDARD-INSTANCE
+ WALKER::WALKER-ENVIRONMENT-BIND-1
+ ITERATE::FUNCTION-LAMBDA-P ITERATE::MAYBE-WARN
+ PCL::MAKE-WRAPPER))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T T) (*)) PCL::SORT-APPLICABLE-METHODS
+ PCL::SORT-METHODS))
+(PROCLAIM
+ '(FTYPE (FUNCTION (T T) T) PCL::FDEFINE-CAREFULLY
+ PCL::MAKE-INTERNAL-READER-METHOD-FUNCTION
+ PCL::MAKE-STD-READER-METHOD-FUNCTION
+ PCL::MAKE-STD-WRITER-METHOD-FUNCTION
+ ITERATE::SIMPLE-EXPAND-ITERATE-FORM
+ PCL::MAKE-STD-BOUNDP-METHOD-FUNCTION
+ PCL::DO-SATISFIES-DEFTYPE PCL::MEMF-CONSTANT-CONVERTER
+ PCL::COMPUTE-CONSTANTS PCL::CLASS-CAN-PRECEDE-P
+ PCL::SAUT-NOT-CLASS PCL::SAUT-NOT-CLASS-EQ
+ PCL::SAUT-NOT-PROTOTYPE PCL::GF-MAKE-FUNCTION-FROM-EMF
+ PCL::SAUT-NOT-EQL PCL::SUPERCLASSES-COMPATIBLE-P
+ PCL::CLASSES-HAVE-COMMON-SUBCLASS-P
+ SYSTEM:%SET-COMPILED-FUNCTION-NAME PCL:ADD-METHOD
+ SYSTEM::DISPLAY-ENV PCL::DESCRIBE-PACKAGE
+ SYSTEM::DISPLAY-COMPILED-ENV
+ PCL::PRINTING-RANDOM-THING-INTERNAL
+ PCL::MAKE-CLASS-PREDICATE
+ PCL::METHOD-FUNCTION-RETURNING-NIL
+ PCL::METHOD-FUNCTION-RETURNING-T PCL::VARIABLE-CLASS
+ PCL::MAKE-PLIST PCL::REMTAIL PCL:REMOVE-METHOD
+ PCL:SLOT-EXISTS-P PCL::DESTRUCTURE-INTERNAL
+ PCL::ACCESSOR-MISS-FUNCTION
+ PCL::UPDATE-INITIALIZE-INFO-INTERNAL PCL::N-N-DFUN-INFO
+ PCL::MAKE-CAXR PCL::MAKE-CDXR WALKER:VARIABLE-LEXICAL-P
+ WALKER:VARIABLE-SPECIAL-P PCL::CHECKING-DFUN-INFO
+ PCL::MAKE-PV-TABLE-INTERNAL PCL::FIND-SLOT-DEFINITION
+ WALKER::WALK-REPEAT-EVAL WALKER::NOTE-DECLARATION
+ PCL::MAKE-DFUN-LAMBDA-LIST WALKER::NOTE-LEXICAL-BINDING
+ PCL::MAKE-DLAP-LAMBDA-LIST PCL::ADD-DIRECT-SUBCLASSES
+ PCL::COMPUTE-PV PCL::MAKE-DFUN-ARG-LIST PCL::COMPUTE-CALLS
+ PCL::MAKE-FAST-METHOD-CALL-LAMBDA-LIST
+ PCL::UPDATE-ALL-PV-TABLE-CACHES PCL::UPDATE-CLASS
+ PCL::MAP-PV-TABLE-REFERENCES-OF PCL::ADD-SLOT-ACCESSORS
+ WALKER::ENVIRONMENT-FUNCTION PCL::REMOVE-DIRECT-SUBCLASSES
+ PCL::REMOVE-SLOT-ACCESSORS PCL::SYMBOL-LESSP
+ PCL::SYMBOL-OR-CONS-LESSP PCL::|SETF PCL FIND-CLASS|
+ PCL::|SETF PCL FIND-CLASS-PREDICATE|
+ PCL::PV-WRAPPERS-FROM-ALL-ARGS PCL::PV-TABLE-LOOKUP
+ PCL::PROCLAIM-DEFGENERIC PCL::UPDATE-CPL PCL::LIST-EQ
+ PCL::UPDATE-SLOTS PCL::COMPUTE-APPLICABLE-METHODS-FUNCTION
+ PCL::COMPUTE-EMF-FROM-WRAPPERS PCL::UPDATE-INITS
+ PCL::UPDATE-STD-OR-STR-METHODS
+ PCL::SET-STANDARD-SVUC-METHOD PCL::EMIT-1-NIL-DLAP
+ PCL::PLIST-VALUE PCL::SET-STRUCTURE-SVUC-METHOD
+ PCL::EMIT-1-WRAPPER-COMPUTE-PRIMARY-CACHE-LOCATION
+ PCL:FUNCALLABLE-STANDARD-INSTANCE-ACCESS
+ PCL::MEC-ALL-CLASSES-INTERNAL
+ PCL::EMIT-N-WRAPPER-COMPUTE-PRIMARY-CACHE-LOCATION
+ PCL::MEC-ALL-CLASSES PCL::%SET-CCLOSURE-ENV
+ PCL::MEC-ALL-CLASS-LISTS PCL::REDEFINE-FUNCTION
+ PCL::METHODS-CONVERTER PCL::COMPUTE-LAYOUT PCL::NO-SLOT
+ PCL::PV-WRAPPERS-FROM-ALL-WRAPPERS
+ PCL::NET-CONSTANT-CONVERTER PCL::AUGMENT-TYPE
+ PCL::CHANGE-CLASS-INTERNAL
+ PCL:SET-FUNCALLABLE-INSTANCE-FUNCTION
+ PCL::VALUE-FOR-CACHING PCL:STANDARD-INSTANCE-ACCESS
+ PCL::|SETF PCL METHOD-FUNCTION-PLIST| PCL::GET-KEY-ARG
+ PCL::GET-KEY-ARG1 PCL::SET-METHODS
+ PCL::SET-FUNCTION-PRETTY-ARGLIST
+ PCL::FIND-STANDARD-II-METHOD PCL::MAKE-EARLY-ACCESSOR
+ PCL::DOCTOR-DFUN-FOR-THE-DEBUGGER PCL::COMPUTE-STD-CPL
+ PCL::|SETF PCL GDEFINITION|
+ PCL::MAKE-DISCRIMINATING-FUNCTION-ARGLIST PCL::ADD-FORMS
+ PCL::CPL-INCONSISTENT-ERROR
+ PCL::REDIRECT-EARLY-FUNCTION-INTERNAL PCL::ADD-TO-CVECTOR
+ PCL::BOOTSTRAP-SLOT-INDEX PCL::QUALIFIER-CHECK-RUNTIME
+ PCL::CPL-FORWARD-REFERENCED-CLASS-ERROR
+ PCL::REAL-REMOVE-METHOD WALKER::ENVIRONMENT-MACRO
+ PCL::CANONICALIZE-SLOT-SPECIFICATION
+ PCL::CANONICALIZE-DEFCLASS-OPTION PCL::SET-WRAPPER
+ PCL::DEAL-WITH-ARGUMENTS-OPTION
+ PCL::PARSE-QUALIFIER-PATTERN PCL::SWAP-WRAPPERS-AND-SLOTS
+ ITERATE::MV-SETQ PCL::MAKE-UNORDERED-METHODS-EMF
+ PCL::CLASS-MIGHT-PRECEDE-P
+ ITERATE::EXTRACT-SPECIAL-BINDINGS
+ WALKER::VARIABLE-SYMBOL-MACRO-P PCL::RAISE-METATYPE))
+(PROCLAIM '(FTYPE (FUNCTION NIL FIXNUM) PCL::GET-WRAPPER-CACHE-NUMBER))
+(DOLIST (PCL::V '(PCL::ADD-READER-METHOD
+ PCL::SHORT-COMBINATION-IDENTITY-WITH-ONE-ARGUMENT
+ PCL::REMOVE-READER-METHOD PCL::EQL-SPECIALIZER-P
+ PCL::OBJECT-PLIST
+ PCL::SLOT-DEFINITION-DEFSTRUCT-ACCESSOR-SYMBOL
+ PCL::SPECIALIZER-TYPE PCL::GF-DFUN-STATE
+ PCL::CLASS-DEFSTRUCT-CONSTRUCTOR
+ PCL::METHOD-FAST-FUNCTION PCL::SPECIALIZERP
+ PCL::EXACT-CLASS-SPECIALIZER-P
+ PCL::COMPATIBLE-META-CLASS-CHANGE-P
+ PCL::UPDATE-GF-DFUN PCL::SPECIALIZER-OBJECT
+ PCL::ACCESSOR-METHOD-SLOT-NAME
+ PCL::SPECIALIZER-CLASS PCL::CLASS-EQ-SPECIALIZER-P
+ PCL::SLOTS-FETCHER PCL::REMOVE-WRITER-METHOD
+ PCL::STRUCTURE-CLASS-P PCL::UPDATE-CONSTRUCTORS
+ PCL::DOCUMENTATION PCL::METHOD-PRETTY-ARGLIST
+ PCL::CLASS-EQ-SPECIALIZER
+ PCL::INFORM-TYPE-SYSTEM-ABOUT-CLASS
+ PCL::ACCESSOR-METHOD-CLASS
+ PCL::GENERIC-FUNCTION-PRETTY-ARGLIST
+ PCL::MAKE-BOUNDP-METHOD-FUNCTION
+ PCL::CLASS-PREDICATE-NAME PCL::CLASSP
+ PCL::LEGAL-QUALIFIERS-P PCL::ADD-BOUNDP-METHOD
+ PCL::LEGAL-LAMBDA-LIST-P
+ PCL::|SETF PCL GENERIC-FUNCTION-NAME|
+ PCL::DESCRIBE-OBJECT PCL::CLASS-INITIALIZE-INFO
+ PCL::MAKE-WRITER-METHOD-FUNCTION
+ PCL::|SETF PCL GF-DFUN-STATE|
+ PCL::|SETF PCL SLOT-DEFINITION-NAME|
+ PCL::|SETF PCL CLASS-NAME|
+ PCL::INITIALIZE-INTERNAL-SLOT-FUNCTIONS
+ PCL::|SETF PCL SLOT-DEFINITION-TYPE|
+ PCL::METHOD-COMBINATION-P
+ PCL::|SETF PCL GENERIC-FUNCTION-METHODS|
+ PCL::|SETF PCL GENERIC-FUNCTION-METHOD-COMBINATION|
+ PCL::|SETF PCL METHOD-GENERIC-FUNCTION|
+ PCL::|SETF PCL SLOT-ACCESSOR-STD-P|
+ PCL::LEGAL-SPECIALIZERS-P
+ PCL::|SETF PCL OBJECT-PLIST|
+ PCL::|SETF PCL SLOT-DEFINITION-INITFORM|
+ PCL::|SETF PCL CLASS-DEFSTRUCT-FORM|
+ PCL::|SETF PCL GENERIC-FUNCTION-METHOD-CLASS|
+ PCL::SLOT-ACCESSOR-STD-P
+ PCL::|SETF PCL GF-PRETTY-ARGLIST|
+ PCL::|SETF PCL SLOT-ACCESSOR-FUNCTION|
+ PCL::|SETF PCL SLOT-DEFINITION-LOCATION|
+ PCL::|SETF PCL SLOT-DEFINITION-READER-FUNCTION|
+ PCL::|SETF PCL SLOT-DEFINITION-WRITER-FUNCTION|
+ PCL::|SETF PCL SLOT-DEFINITION-BOUNDP-FUNCTION|
+ PCL::|SETF PCL SLOT-DEFINITION-INTERNAL-READER-FUNCTION|
+ PCL::|SETF PCL SLOT-DEFINITION-INTERNAL-WRITER-FUNCTION|
+ PCL::|SETF PCL SLOT-DEFINITION-ALLOCATION|
+ PCL::|SETF PCL SLOT-DEFINITION-INITFUNCTION|
+ PCL::METHOD-COMBINATION-OPTIONS
+ PCL::|SETF PCL SLOT-DEFINITION-READERS|
+ PCL::|SETF PCL DOCUMENTATION|
+ PCL::FUNCALLABLE-STANDARD-CLASS-P
+ PCL::|SETF PCL SLOT-DEFINITION-CLASS|
+ PCL::|SETF PCL SLOT-VALUE-USING-CLASS|
+ PCL::CLASS-CAN-PRECEDE-LIST
+ PCL::|SETF PCL CLASS-DIRECT-SLOTS|
+ PCL::|SETF PCL CLASS-SLOTS|
+ PCL::SLOT-ACCESSOR-FUNCTION
+ PCL::|SETF PCL CLASS-INCOMPATIBLE-SUPERCLASS-LIST|
+ PCL::|SETF PCL SLOT-DEFINITION-WRITERS|
+ PCL::SLOT-CLASS-P PCL::MAKE-READER-METHOD-FUNCTION
+ PCL::LEGAL-METHOD-FUNCTION-P PCL::GET-METHOD
+ PCL::SHORT-METHOD-COMBINATION-P PCL::GF-ARG-INFO
+ PCL::SPECIALIZER-METHOD-TABLE
+ PCL::MAKE-METHOD-INITARGS-FORM
+ PCL::CLASS-DEFSTRUCT-FORM PCL::GF-PRETTY-ARGLIST
+ PCL::SAME-SPECIALIZER-P
+ PCL::SLOT-DEFINITION-BOUNDP-FUNCTION
+ PCL::SLOT-DEFINITION-WRITER-FUNCTION
+ PCL::SLOT-DEFINITION-READER-FUNCTION
+ PCL::SLOT-DEFINITION-INTERNAL-WRITER-FUNCTION
+ PCL::SLOT-DEFINITION-INTERNAL-READER-FUNCTION
+ PCL::SLOT-DEFINITION-CLASS
+ PCL::EQL-SPECIALIZER-OBJECT
+ PCL::CLASS-CONSTRUCTORS PCL::SLOTS-TO-INSPECT
+ PCL::SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
+ PCL::ADD-WRITER-METHOD
+ PCL::LONG-METHOD-COMBINATION-FUNCTION
+ PCL::GENERIC-FUNCTION-P PCL::LEGAL-SLOT-NAME-P
+ PCL::CLASS-WRAPPER PCL::DEFINITION-SOURCE
+ PCL::DEFAULT-INITARGS PCL::CLASS-SLOT-VALUE
+ PCL::FORWARD-REFERENCED-CLASS-P
+ PCL::GF-FAST-METHOD-FUNCTION-P
+ PCL::LEGAL-QUALIFIER-P PCL::METHOD-P
+ PCL::CLASS-SLOT-CELLS
+ PCL::STANDARD-ACCESSOR-METHOD-P
+ PCL::STANDARD-GENERIC-FUNCTION-P
+ PCL::STANDARD-READER-METHOD-P
+ PCL::STANDARD-METHOD-P
+ PCL::COMPUTE-EFFECTIVE-SLOT-DEFINITION-INITARGS
+ PCL::COMPUTE-DEFAULT-INITARGS
+ PCL::|SETF PCL CLASS-SLOT-VALUE|
+ PCL::METHOD-COMBINATION-TYPE PCL::STANDARD-CLASS-P
+ PCL::LEGAL-SPECIALIZER-P
+ PCL::COMPUTE-SLOT-ACCESSOR-INFO
+ PCL::STANDARD-BOUNDP-METHOD-P
+ PCL::RAW-INSTANCE-ALLOCATOR
+ PCL::|SETF PCL SLOT-DEFINITION-DEFSTRUCT-ACCESSOR-SYMBOL|
+ PCL::|SETF PCL CLASS-INITIALIZE-INFO|
+ PCL::COMPUTE-DISCRIMINATING-FUNCTION-ARGLIST-INFO
+ PCL::STANDARD-WRITER-METHOD-P
+ PCL::CLASS-INCOMPATIBLE-SUPERCLASS-LIST
+ PCL::WRAPPER-FETCHER
+ PCL::METHOD-COMBINATION-DOCUMENTATION
+ PCL::|SETF PCL SLOT-DEFINITION-INITARGS|
+ PCL::REMOVE-BOUNDP-METHOD
+ PCL::|SETF PCL CLASS-DEFSTRUCT-CONSTRUCTOR|
+ PCL::SHORT-COMBINATION-OPERATOR
+ PCL::REMOVE-NAMED-METHOD
+ PCL::LEGAL-DOCUMENTATION-P
+ PCL:CLASS-DIRECT-SUPERCLASSES
+ PCL:CLASS-DIRECT-SUBCLASSES
+ PCL:CLASS-DIRECT-DEFAULT-INITARGS
+ PCL:SLOT-DEFINITION-READERS
+ PCL:SLOT-VALUE-USING-CLASS
+ PCL:COMPUTE-APPLICABLE-METHODS PCL:CLASS-NAME
+ PCL:CLASS-PROTOTYPE PCL:READER-METHOD-CLASS
+ PCL:REMOVE-METHOD PCL:SLOT-DEFINITION-INITFORM
+ PCL:UPDATE-INSTANCE-FOR-REDEFINED-CLASS
+ PCL:UPDATE-INSTANCE-FOR-DIFFERENT-CLASS
+ PCL:CHANGE-CLASS PCL:METHOD-FUNCTION
+ PCL:DIRECT-SLOT-DEFINITION-CLASS
+ PCL:MAKE-METHOD-LAMBDA
+ PCL:EFFECTIVE-SLOT-DEFINITION-CLASS
+ PCL:CLASS-SLOTS PCL:COMPUTE-SLOTS
+ PCL:SLOT-DEFINITION-NAME PCL:FINALIZE-INHERITANCE
+ PCL:GENERIC-FUNCTION-LAMBDA-LIST
+ PCL:CLASS-DIRECT-SLOTS PCL:CLASS-DEFAULT-INITARGS
+ PCL:COMPUTE-DISCRIMINATING-FUNCTION
+ PCL:CLASS-FINALIZED-P PCL:GENERIC-FUNCTION-NAME
+ PCL:REMOVE-DEPENDENT
+ PCL:COMPUTE-CLASS-PRECEDENCE-LIST
+ PCL:ADD-DEPENDENT PCL:SLOT-BOUNDP-USING-CLASS
+ PCL:ACCESSOR-METHOD-SLOT-DEFINITION
+ PCL:SHARED-INITIALIZE PCL:ADD-DIRECT-METHOD
+ PCL:SLOT-DEFINITION-LOCATION
+ PCL:SLOT-DEFINITION-INITFUNCTION
+ PCL:SLOT-DEFINITION-ALLOCATION PCL:ADD-METHOD
+ PCL:GENERIC-FUNCTION-METHOD-CLASS
+ PCL:METHOD-SPECIALIZERS
+ PCL:SLOT-DEFINITION-INITARGS
+ PCL:WRITER-METHOD-CLASS PCL:ADD-DIRECT-SUBCLASS
+ PCL:SPECIALIZER-DIRECT-METHODS
+ PCL:GENERIC-FUNCTION-METHOD-COMBINATION
+ PCL:ALLOCATE-INSTANCE PCL:COMPUTE-EFFECTIVE-METHOD
+ PCL:SLOT-DEFINITION-TYPE PCL:SLOT-UNBOUND
+ PCL:INITIALIZE-INSTANCE PCL:FUNCTION-KEYWORDS
+ PCL:REINITIALIZE-INSTANCE PCL:VALIDATE-SUPERCLASS
+ PCL:GENERIC-FUNCTION-METHODS
+ PCL:REMOVE-DIRECT-METHOD PCL:METHOD-LAMBDA-LIST
+ PCL:MAKE-INSTANCE
+ PCL:COMPUTE-EFFECTIVE-SLOT-DEFINITION
+ PCL:PRINT-OBJECT PCL:METHOD-QUALIFIERS
+ PCL:METHOD-GENERIC-FUNCTION
+ PCL:REMOVE-DIRECT-SUBCLASS
+ PCL:MAKE-INSTANCES-OBSOLETE
+ PCL:SLOT-MAKUNBOUND-USING-CLASS
+ PCL:ENSURE-GENERIC-FUNCTION-USING-CLASS
+ PCL:SLOT-MISSING PCL:MAP-DEPENDENTS
+ PCL:FIND-METHOD-COMBINATION
+ PCL:ENSURE-CLASS-USING-CLASS
+ PCL:NO-APPLICABLE-METHOD
+ PCL:SLOT-DEFINITION-WRITERS
+ PCL:COMPUTE-APPLICABLE-METHODS-USING-CLASSES
+ PCL:CLASS-PRECEDENCE-LIST))
+ (SETF (GET PCL::V 'COMPILER::PROCLAIMED-CLOSURE) T))
diff --git a/gcl/pcl/impl/kcl/sysdef.lisp b/gcl/pcl/impl/kcl/sysdef.lisp
new file mode 100644
index 000000000..9da68cd54
--- /dev/null
+++ b/gcl/pcl/impl/kcl/sysdef.lisp
@@ -0,0 +1,121 @@
+;;; -*- Mode: Lisp; Base: 10; Syntax: Common-Lisp; Package: DSYS -*-
+;;; File: sysdef.lisp
+;;; Author: Richard Harris
+
+(in-package "DSYS")
+
+(defvar *pcl-compiled-p* nil)
+(defvar *pcl-loaded-p* nil)
+
+(unless (boundp 'pcl::*redefined-functions*)
+ (setq pcl::*redefined-functions* nil))
+
+(defun reset-pcl-package ()
+ (pcl::reset-pcl-package)
+ (let ((defsys (subfile '("pcl") :name "defsys")))
+ (setq pcl::*pcl-directory* defsys)
+ (load-file defsys))
+ (mapc #'(lambda (path)
+ (setf (lfi-fwd (get-loaded-file-info path)) 0))
+ (pcl-binary-files)))
+
+(defun pcl-binary-files ()
+ (pcl::system-binary-files 'pcl::pcl))
+
+(defun maybe-load-defsys (&optional compile-defsys-p)
+ (let ((defsys (subfile '("pcl") :name "defsys"))
+ (*use-default-pathname-type* nil)
+ (*skip-load-if-loaded-p* t)
+ (*skip-compile-file-fwd* 0))
+ (set 'pcl::*pcl-directory* defsys)
+ (when compile-defsys-p
+ (compile-file defsys))
+ (let ((b-s 'pcl::*boot-state*))
+ (when (and (boundp b-s) (symbol-value b-s))
+ #+ignore (reset-pcl-package)))
+ (load-file defsys)))
+
+(defun maybe-load-pcl (&optional force-p)
+ (unless (and (null force-p)
+ (fboundp 'pcl::system-binary-files)
+ (every #'(lambda (path)
+ (let* ((path-fwd (file-write-date path))
+ (lfi (get-loaded-file-info path)))
+ (and lfi path-fwd (= path-fwd (lfi-fwd lfi)))))
+ (pcl-binary-files)))
+ (let ((b-s 'pcl::*boot-state*))
+ (when (and (boundp b-s) (symbol-value b-s))
+ (reset-pcl-package)))
+ (pcl::load-pcl)))
+
+(defsystem pcl
+ (:pretty-name "PCL")
+ #+akcl
+ (:forms
+ :compile (let ((cfn (subfile '("pcl") :name "collectfn" :type "lisp")))
+ (unless (probe-file cfn)
+ (run-unix-command
+ (format nil "ln -s ~A ~A"
+ (namestring (merge-pathnames "../cmpnew/collectfn.lsp"
+ si::*system-directory*))
+ (namestring cfn))))))
+
+ #+akcl
+ "collectfn"
+ (:forms
+ :compile
+ (progn
+ (maybe-load-defsys t)
+ (if (and (fboundp 'pcl::operation-transformations)
+ (or (null (probe-file (subfile '("pcl") :name "defsys" :type "lisp")))
+ (every #'(lambda (trans)
+ (eq (car trans) :load))
+ (pcl::operation-transformations 'pcl::pcl :compile))))
+ (maybe-load-pcl)
+ (let ((b-s 'pcl::*boot-state*))
+ (when (and (boundp b-s) (symbol-value b-s))
+ (reset-pcl-package))
+ #+akcl (compiler::emit-fn t)
+ #+akcl (load (merge-pathnames "../lsp/sys-proclaim.lisp"
+ si::*system-directory*))
+ (#+cmu with-compilation-unit #-cmu progn
+ #+cmu (:optimize
+ '(optimize (user::debug-info #+(and small (not testing)) .5
+ #-(and small (not testing)) 2)
+ (speed #+testing 1 #-testing 2)
+ (safety #+testing 3 #-testing 0)
+ #+ignore (user::inhibit-warnings 2))
+ :context-declarations
+ '(#+ignore
+ (:external (declare (user::optimize-interface
+ (safety 2) (debug-info 1))))))
+ (proclaim #+testing *testing-declaration*
+ #-testing *fast-declaration*)
+ (pcl::compile-pcl))
+ (reset-pcl-package)
+ (maybe-load-pcl t)))
+ #+cmu (purify))
+ :load
+ (progn
+ (maybe-load-pcl)
+ #+cmu (purify))))
+
+(defparameter *pcl-files*
+ '((("systems") "lisp"
+ "pcl")
+ (("pcl") "lisp"
+ "sysdef"
+ "boot" "braid" "cache" "cloe-low" "cmu-low" "combin" "compat"
+ "construct" "coral-low" "cpatch" "cpl" "ctypes" "defclass" "defcombin"
+ "defs" "defsys" "dfun" "dlap" "env" "excl-low" "fin" "fixup" "fngen" "fsc"
+ "gcl-patches" "genera-low" "gold-low" "hp-low" "ibcl-low" "ibcl-patches"
+ "init" "iterate" "kcl-low" "kcl-patches" "lap" "low" "lucid-low" "macros"
+ "methods" "pcl-env-internal" "pcl-env" "pkg" "plap" "precom1" "precom2"
+ "precom4" "pyr-low" "pyr-patches" "quadlap" "rel-7-2-patches" "rel-8-patches"
+ "slots" "std-class" "sys-proclaim" "ti-low" "ti-patches" "vaxl-low" "vector" "walk"
+ "xerox-low" "xerox-patches")
+ (("pcl") "text"
+ "12-7-88-notes" "3-17-88-notes" "3-19-87-notes" "4-21-87-notes"
+ "4-29-87-notes" "5-22-87-notes" "5-22-89-notes" "8-28-88-notes"
+ "get-pcl" "kcl-mods" "kcl-notes" "lap" "notes" "pcl-env" "readme")))
+
diff --git a/gcl/pcl/impl/lucid/lucid-low.lisp b/gcl/pcl/impl/lucid/lucid-low.lisp
new file mode 100644
index 000000000..ec473574e
--- /dev/null
+++ b/gcl/pcl/impl/lucid/lucid-low.lisp
@@ -0,0 +1,384 @@
+;;; -*- Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the Lucid lisp version of the file portable-low.
+;;;
+;;; Lucid: (415)329-8400
+;;;
+
+(in-package 'pcl)
+
+;;; First, import some necessary "internal" or Lucid-specific symbols
+
+(eval-when (eval compile load)
+
+(#-LCL3.0 progn #+LCL3.0 lcl:handler-bind
+ #+LCL3.0 ((lcl:warning #'(lambda (condition)
+ (declare (ignore condition))
+ (lcl:muffle-warning))))
+(let ((importer
+ #+LCL3.0 #'sys:import-from-lucid-pkg
+ #-LCL3.0 (let ((x (find-symbol "IMPORT-FROM-LUCID-PKG" "LUCID")))
+ (if (and x (fboundp x))
+ (symbol-function x)
+ ;; Only the #'(lambda (x) ...) below is really needed,
+ ;; but when available, the "internal" function
+ ;; 'import-from-lucid-pkg' provides better checking.
+ #'(lambda (name)
+ (import (intern name "LUCID")))))))
+ ;;
+ ;; We need the following "internal", undocumented Lucid goodies:
+ (mapc importer '("%POINTER" "DEFSTRUCT-SIMPLE-PREDICATE"
+ #-LCL3.0 "LOGAND&" "%LOGAND&" #+VAX "LOGAND&-VARIABLE"))
+
+ ;;
+ ;; For without-interrupts.
+ ;;
+ #+LCL3.0
+ (mapc importer '("*SCHEDULER-WAKEUP*" "MAYBE-CALL-SCHEDULER"))
+
+ ;;
+ ;; We import the following symbols, because in 2.1 Lisps they have to be
+ ;; accessed as SYS:<foo>, whereas in 3.0 lisps, they are homed in the
+ ;; LUCID-COMMON-LISP package.
+ (mapc importer '("ARGLIST" "NAMED-LAMBDA" "*PRINT-STRUCTURE*"))
+ ;;
+ ;; We import the following symbols, because in 2.1 Lisps they have to be
+ ;; accessed as LUCID::<foo>, whereas in 3.0 lisps, they have to be
+ ;; accessed as SYS:<foo>
+ (mapc importer '(
+ "NEW-STRUCTURE" "STRUCTURE-REF"
+ "STRUCTUREP" "STRUCTURE-TYPE" "STRUCTURE-LENGTH"
+ "PROCEDUREP" "PROCEDURE-SYMBOL"
+ "PROCEDURE-REF" "SET-PROCEDURE-REF"
+ ))
+; ;;
+; ;; The following is for the "patch" to the general defstruct printer.
+; (mapc importer '(
+; "OUTPUT-STRUCTURE" "DEFSTRUCT-INFO"
+; "OUTPUT-TERSE-OBJECT" "DEFAULT-STRUCTURE-PRINT"
+; "STRUCTURE-TYPE" "*PRINT-OUTPUT*"
+; ))
+ ;;
+ ;; The following is for a "patch" affecting compilation of %logand&.
+ ;; On APOLLO, Domain/CommonLISP 2.10 does not include %logand& whereas
+ ;; Domain/CommonLISP 2.20 does; Domain/CommonLISP 2.20 includes :DOMAIN/OS
+ ;; on *FEATURES*, so this conditionalizes correctly for APOLLO.
+ #-(or (and APOLLO DOMAIN/OS) LCL3.0 VAX)
+ (mapc importer '("COPY-STRUCTURE" "GET-FDESC" "SET-FDESC"))
+
+ nil))
+
+;; end of eval-when
+
+)
+
+
+;;;
+;;; Patch up for the fact that the PCL package creation in defsys.lisp
+;;; will probably have an explicit :use list ??
+;;;
+;;; #+LCL3.0 (use-package *default-make-package-use-list*)
+
+
+
+
+#+lcl3.0
+(progn
+
+(defvar *saved-compilation-speed* 3)
+
+; the production compiler sometimes
+; screws up vars within labels
+
+(defmacro dont-use-production-compiler ()
+ '(eval-when (compile)
+ (setq *saved-compilation-speed* (if LUCID:*USE-SFC* 3 0))
+ (proclaim '(optimize (compilation-speed 3)))))
+
+(defmacro use-previous-compiler ()
+ `(eval-when (compile)
+ (proclaim '(optimize (compilation-speed ,*saved-compilation-speed*)))))
+
+)
+
+(defmacro %logand (x y)
+ #-VAX `(%logand& ,x ,y)
+ #+VAX `(logand&-variable ,x ,y))
+
+;;; Fix for VAX LCL
+#+VAX
+(defun logand&-variable (x y)
+ (logand&-variable x y))
+
+;;; Fix for other LCLs
+#-(or (and APOLLO DOMAIN/OS) LCL3.0 VAX)
+(eval-when (compile load eval)
+
+(let* ((logand&-fdesc (get-fdesc 'logand&))
+ (%logand&-fdesc (copy-structure logand&-fdesc)))
+ (setf (structure-ref %logand&-fdesc 0 t) '%logand&)
+ (setf (structure-ref %logand&-fdesc 7 t) nil)
+ (setf (structure-ref %logand&-fdesc 8 t) nil)
+ (set-fdesc '%logand& %logand&-fdesc))
+
+(eval-when (load)
+ (defun %logand& (x y) (%logand& x y)))
+
+(eval-when (eval)
+ (compile '%logand& '(lambda (x y) (%logand& x y))))
+
+);#-(or LCL3.0 (and APOLLO DOMAIN/OS) VAX)
+
+;;;
+;;; From: JonL
+;;; Date: November 28th, 1988
+;;;
+;;; Here's a better attempt to do the without-interrupts macro for LCL3.0.
+;;; For the 2.1 release, maybe you should just ignore it (i.e, turn it
+;;; into a PROGN and "take your chances") since there isn't a uniform way
+;;; to do inhibition. 2.1 has interrupts, but no multiprocessing.
+;;;
+;;; The best bet for protecting the cache is merely to inhibit the
+;;; scheduler, since asynchronous interrupts are only run when "scheduled".
+;;; Of course, there may be other interrupts, which can cons and which
+;;; could cause a GC; but at least they wouldn't be running PCL type code.
+;;;
+;;; Note that INTERRUPTS-ON shouldn't arbitrarily enable scheduling again,
+;;; but rather simply restore it to the state outside the scope of the call
+;;; to WITHOUT-INTERRUPTS. Note also that an explicit call to
+;;; MAYBE-CALL-SHEDULER must be done when "turning interrupts back on", if
+;;; there are any interrupts/schedulings pending; at least the test to see
+;;; if any are pending is very fast.
+
+#+LCL3.0
+(defmacro without-interrupts (&body body)
+ `(macrolet ((interrupts-on ()
+ `(when (null outer-scheduling-state)
+ (setq lcl:*inhibit-scheduling* nil)
+ (when *scheduler-wakeup* (maybe-call-scheduler))))
+ (interrupts-off ()
+ '(setq lcl:*inhibit-scheduling* t)))
+ (let ((outer-scheduling-state lcl:*inhibit-scheduling*))
+ (prog1 (let ((lcl:*inhibit-scheduling* t)) . ,body)
+ (when (and (null outer-scheduling-state) *scheduler-wakeup*)
+ (maybe-call-scheduler))))))
+
+
+;;; The following should override the definitions provided by lucid-low.
+;;;
+#+(or LCL3.0 (and APOLLO DOMAIN/OS))
+(progn
+(defstruct-simple-predicate std-instance std-instance-p)
+(defstruct-simple-predicate fast-method-call fast-method-call-p)
+(defstruct-simple-predicate method-call method-call-p)
+)
+
+
+
+(defun set-function-name-1 (fn new-name ignore)
+ (declare (ignore ignore))
+ (if (not (procedurep fn))
+ (error "~S is not a procedure." fn)
+ (if (compiled-function-p fn)
+ ;; This is one of:
+ ;; compiled-function, funcallable-instance, compiled-closure
+ ;; or a macro.
+ ;; So just go ahead and set its name.
+ ;; Only change the name when necessary: maybe it is read-only.
+ (unless (eq new-name (procedure-ref fn procedure-symbol))
+ (set-procedure-ref fn procedure-symbol new-name))
+ ;; This is an interpreted function.
+ ;; Seems like any number of different things can happen depending
+ ;; vaguely on what release you are running. Try to do something
+ ;; reasonable.
+ (let ((symbol (procedure-ref fn procedure-symbol)))
+ (cond ((symbolp symbol)
+ ;; In fact, this is the name of the procedure.
+ ;; Just set it.
+ (set-procedure-ref fn procedure-symbol new-name))
+ ((and (listp symbol)
+ (eq (car symbol) 'lambda))
+ (setf (car symbol) 'named-lambda
+ (cdr symbol) (cons new-name (cdr symbol))))
+ ((eq (car symbol) 'named-lambda)
+ (setf (cadr symbol) new-name))))))
+ fn)
+
+(defun function-arglist (fn)
+ (arglist fn))
+
+ ;;
+;;;;;; printing-random-thing-internal
+ ;;
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~O" (%pointer thing)))
+
+
+;;;
+;;; 16-Feb-90 Jon L White
+;;;
+;;; A Patch provide specifically for the benefit of PCL, in the Lucid 3.0
+;;; release environment. This adds type optimizers for FUNCALL so that
+;;; forms such as:
+;;;
+;;; (FUNCALL (THE PROCEDURE F) ...)
+;;;
+;;; and:
+;;;
+;;; (LET ((F (Frobulate)))
+;;; (DECLARE (TYPE COMPILED-FUNCTION F))
+;;; (FUNCALL F ...))
+;;;
+;;; will just jump directly to the procedure code, rather than waste time
+;;; trying to coerce the functional argument into a procedure.
+;;;
+
+
+(in-package "LUCID")
+
+
+;;; (DECLARE-MACHINE-CLASS COMMON)
+(set-up-compiler-target 'common)
+
+
+(set-function-descriptor 'FUNCALL
+ :TYPE 'LISP
+ :PREDS 'NIL
+ :EFFECTS 'T
+ :OPTIMIZER #'(lambda (form &optional environment)
+ (declare (ignore form environment))
+ (let* ((fun (second form))
+ (lambdap (and (consp fun)
+ (eq (car fun) 'function)
+ (consp (second fun))
+ (memq (car (second fun))
+ '(lambda internal-lambda)))))
+ (if (not lambdap)
+ form
+ (alphatize
+ (cons (second fun) (cddr form)) environment))))
+ :FUNCTIONTYPE '(function (function &rest t) (values &rest t))
+ :TYPE-DISPATCH `(((PROCEDURE &REST T) (VALUES &REST T)
+ ,#'(lambda (anode fun &rest args)
+ (declare (ignore anode fun args))
+ `(FAST-FUNCALL ,fun ,@args)))
+ ((COMPILED-FUNCTION &REST T) (VALUES &REST T)
+ ,#'(lambda (anode fun &rest args)
+ (declare (ignore anode fun args))
+ `(FAST-FUNCALL ,fun ,@args))))
+ :LAMBDALIST '(FN &REST ARGUMENTS)
+ :ARGS '(1 NIL)
+ :VALUES '(0 NIL)
+ )
+
+(def-compiler-macro fast-funcall (&rest args &environment env)
+ (if (COMPILER-OPTION-SET-P :READ-SAFETY ENV)
+ `(FUNCALL-SUBR . ,args)
+ `(&FUNCALL . ,args)))
+
+
+
+(setf (symbol-function 'funcall-subr) #'funcall)
+
+
+;;; (UNDECLARE-MACHINE-CLASS)
+(restore-compiler-params)
+
+
+(in-package 'pcl)
+
+(pushnew :structure-wrapper *features*)
+
+(defun structure-functions-exist-p ()
+ t)
+
+(defun structure-instance-p (x)
+ (and (structurep x)
+ (not (eq 'std-instance (structure-type x)))))
+
+(defvar *structure-type* nil)
+(defvar *structure-length* nil)
+
+(defun structure-type-p (type)
+ (declare (special lucid::*defstructs*))
+ (let ((s-data (gethash type lucid::*defstructs*)))
+ (or (and s-data
+ (eq 'structure (structure-ref s-data 1 'defstruct))) ; type - Fix this
+ (and type (eq *structure-type* type)))))
+
+(defun structure-type-included-type-name (type)
+ (declare (special lucid::*defstructs*))
+ (let ((s-data (gethash type lucid::*defstructs*)))
+ (and s-data (structure-ref s-data 6 'defstruct)))) ; include - Fix this
+
+(defun structure-type-slot-description-list (type)
+ (declare (special lucid::*defstructs*))
+ (let ((s-data (gethash type lucid::*defstructs*)))
+ (if s-data
+ (nthcdr (let ((include (structure-ref s-data 6 'defstruct)))
+ (if include
+ (let ((inc-s-data (gethash include lucid::*defstructs*)))
+ (if inc-s-data
+ (length (structure-ref inc-s-data 7 'defstruct))
+ 0))
+ 0))
+ (map 'list
+ #'(lambda (slotd)
+ (let* ((ds 'lucid::defstruct-slot)
+ (slot-name (system:structure-ref slotd 0 ds))
+ (position (system:structure-ref slotd 1 ds))
+ (accessor (system:structure-ref slotd 2 ds))
+ (read-only-p (system:structure-ref slotd 5 ds)))
+ (list slot-name accessor
+ #'(lambda (x)
+ (system:structure-ref x position type))
+ (unless read-only-p
+ #'(lambda (v x)
+ (setf (system:structure-ref x position type)
+ v))))))
+ (structure-ref s-data 7 'defstruct))) ; slots - Fix this
+ (let ((result (make-list *structure-length*)))
+ (dotimes (i *structure-length* result)
+ (let* ((name (format nil "SLOT~D" i))
+ (slot-name (intern name (or (symbol-package type) *package*)))
+ (i i))
+ (setf (elt result i) (list slot-name nil
+ #'(lambda (x)
+ (system:structure-ref x i type))
+ nil))))))))
+
+(defun structure-slotd-name (slotd)
+ (first slotd))
+
+(defun structure-slotd-accessor-symbol (slotd)
+ (second slotd))
+
+(defun structure-slotd-reader-function (slotd)
+ (third slotd))
+
+(defun structure-slotd-writer-function (slotd)
+ (fourth slotd))
diff --git a/gcl/pcl/impl/pyramid/pyr-low.lisp b/gcl/pcl/impl/pyramid/pyr-low.lisp
new file mode 100644
index 000000000..935a7d343
--- /dev/null
+++ b/gcl/pcl/impl/pyramid/pyr-low.lisp
@@ -0,0 +1,50 @@
+;;; -*- Mode:LISP; Package:PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the Pyramid version of low.lisp -- it runs with versions 1.1
+;;; and newer -- Created by David Bein Mon May 4 11:22:30 1987
+;;;
+(in-package 'pcl)
+
+ ;;
+;;;;;; Cache No's
+ ;;
+
+;;; The purpose behind the shift is that the bottom 2 bits are always 0
+;;; We use the same scheme for symbols and objects although a good
+;;; case may be made for shifting objects more since they will
+;;; be aligned differently...
+
+;(defmacro symbol-cache-no (symbol mask)
+; `(logand (the fixnum (ash (lisp::%sp-make-fixnum ,symbol) -2))
+; (the fixnum ,mask)))
+
+(defmacro object-cache-no (symbol mask)
+ `(logand (the fixnum (ash (lisp::%sp-make-fixnum ,symbol) -2))
+ (the fixnum ,mask)))
+
+
+
diff --git a/gcl/pcl/impl/pyramid/pyr-patches.lisp b/gcl/pcl/impl/pyramid/pyr-patches.lisp
new file mode 100644
index 000000000..32647fe97
--- /dev/null
+++ b/gcl/pcl/impl/pyramid/pyr-patches.lisp
@@ -0,0 +1,9 @@
+(in-package 'pcl)
+
+;;; This next kludge disables macro memoization (the default) since somewhere
+;;; in PCL, the memoization is getting in the way.
+
+(eval-when (load eval)
+ (format t "~&;;; Resetting *MACROEXPAND-HOOK* to #'FUNCALL~%")
+ (setq lisp::*macroexpand-hook* #'funcall))
+
diff --git a/gcl/pcl/impl/symbolics/cloe-low.lisp b/gcl/pcl/impl/symbolics/cloe-low.lisp
new file mode 100644
index 000000000..af7459de3
--- /dev/null
+++ b/gcl/pcl/impl/symbolics/cloe-low.lisp
@@ -0,0 +1,32 @@
+;;;-*-Mode:LISP; Package: PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+(defmacro object-cache-no (object mask)
+ `(logand (sys::address-of ,object) ,mask))
+
diff --git a/gcl/pcl/impl/symbolics/genera-low.lisp b/gcl/pcl/impl/symbolics/genera-low.lisp
new file mode 100644
index 000000000..71c939d13
--- /dev/null
+++ b/gcl/pcl/impl/symbolics/genera-low.lisp
@@ -0,0 +1,423 @@
+;;; -*- Mode:LISP; Package:(PCL Lisp 1000); Base:10.; Syntax:Common-lisp; Patch-File: Yes -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the 3600 version of the file portable-low.
+;;;
+
+(in-package 'pcl)
+
+(pushnew ':pcl-internals dbg:*all-invisible-frame-types*)
+
+#+IMach ;On the I-Machine these are
+(eval-when (compile load eval) ;faster than the versions
+ ;that use :test #'eq.
+(defmacro memq (item list) `(member ,item ,list))
+(defmacro assq (item list) `(assoc ,item ,list))
+(defmacro rassq (item list) `(rassoc ,item ,list))
+(defmacro delq (item list) `(delete ,item ,list))
+(defmacro posq (item list) `(position ,item ,list))
+
+)
+
+compiler::
+(defoptimizer (cl:the the-just-gets-in-the-way-of-optimizers) (form)
+ (matchp form
+ (('cl:the type subform)
+ (ignore type)
+ subform)
+ (* form)))
+
+(defmacro %ash (x count)
+ (if (and (constantp count) (zerop (eval count)))
+ x
+ `(the fixnum (ash (the fixnum ,x ) ,count))))
+
+;;;
+;;;
+;;;
+
+(defmacro without-interrupts (&body body)
+ `(let ((outer-scheduling-state si:inhibit-scheduling-flag)
+ (si:inhibit-scheduling-flag t))
+ (macrolet ((interrupts-on ()
+ '(when (null outer-scheduling-state)
+ (setq si:inhibit-scheduling-flag nil)))
+ (interrupts-off ()
+ '(setq si:inhibit-scheduling-flag t)))
+ (progn outer-scheduling-state)
+ ,.body)))
+
+;;;
+;;; It would appear that #, does not work properly in Genera. At least I can't get it
+;;; to work when I use it inside of std-instance-p (defined later in this file). So,
+;;; all of this is just to support that.
+;;;
+;;; WHEN EXPANDS-TO
+;;; compile to a file (#:EVAL-AT-LOAD-TIME-MARKER . <form>)
+;;; compile to core '<result of evaluating form>
+;;; not in compiler at all (progn <form>)
+;;;
+;;; Believe me when I tell you that I don't know why it is I need both a
+;;; transformer and an optimizer to get this to work. Believe me when I
+;;; tell you that I don't really care why either.
+;;;
+(defmacro load-time-eval (form)
+ ;; The interpreted definition of load-time-eval. This definition
+ ;; never gets compiled.
+ (let ((value (gensym)))
+ `(multiple-value-bind (,value)
+ (progn ,form)
+ ,value)))
+
+(compiler:deftransformer (load-time-eval optimize-load-time-eval) (form)
+ (compiler-is-a-loser-internal form))
+
+(compiler:defoptimizer (load-time-eval transform-load-time-eval) (form)
+ (compiler-is-a-loser-internal form))
+
+(defun compiler-is-a-loser-internal (form)
+ ;; When compiling a call to load-time-eval the compiler will call
+ ;; this optimizer before the macro expansion.
+ (if zl:compiler:(and (boundp '*compile-function*) ;Probably don't need
+ ;this boundp check
+ ;but it can't hurt.
+ (funcall *compile-function* :to-core-p))
+ ;; Compiling to core.
+ ;; Evaluate the form now, and expand into a constant
+ ;; (the result of evaluating the form).
+ `',(eval (cadr form))
+ ;; Compiling to a file.
+ ;; Generate the magic which causes the dumper compiler and loader
+ ;; to do magic and evaluate the form at load time.
+ `',(cons compiler:eval-at-load-time-marker (cadr form))))
+
+;;
+;;;;;; Memory Block primitives. ***
+ ;;
+
+
+(defmacro make-memory-block (size &optional area)
+ `(make-array ,size :area ,area))
+
+(defmacro memory-block-ref (block offset) ;Don't want to go faster yet.
+ `(aref ,block ,offset))
+
+(defvar class-wrapper-area)
+(eval-when (load eval)
+ (si:make-area :name 'class-wrapper-area
+ :room t
+ :gc :static))
+
+(eval-when (compile load eval)
+ (remprop '%%allocate-instance--class 'inline))
+
+(eval-when (compile load eval)
+
+(scl:defflavor std-instance
+ ((wrapper nil)
+ (slots nil))
+ ()
+ (:constructor %%allocate-instance--class())
+ :ordered-instance-variables)
+
+(defvar *std-instance-flavor* (flavor:find-flavor 'std-instance))
+
+)
+
+#-imach
+(scl:defsubst pcl-%instance-flavor (instance)
+ (declare (compiler:do-not-record-macroexpansions))
+ (sys::%make-pointer sys:dtp-array
+ (sys:%p-contents-as-locative
+ (sys:follow-structure-forwarding instance))))
+
+#+imach
+(scl:defsubst pcl-%instance-flavor (instance)
+ (sys:%instance-flavor instance))
+
+(scl::defsubst std-instance-p (x)
+ (and (sys:instancep x)
+ (eq (pcl-%instance-flavor x) (load-time-eval *std-instance-flavor*))))
+
+(scl:defmethod (:print-self std-instance) (stream depth slashify)
+ (declare (ignore slashify))
+ (print-std-instance scl:self stream depth))
+
+(scl:defmethod (:describe std-instance) ()
+ (describe-object scl:self *standard-output*))
+
+(defmacro %std-instance-wrapper (std-instance)
+ `(sys:%instance-ref ,std-instance 1))
+
+(defmacro %std-instance-slots (std-instance)
+ `(sys:%instance-ref ,std-instance 2))
+
+(scl:compile-flavor-methods std-instance)
+
+
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~\\si:address\\" (si:%pointer thing)))
+
+;;;
+;;; This is hard, I am sweating.
+;;;
+(defun function-arglist (function) (zl:arglist function t))
+
+(defun function-pretty-arglist (function) (zl:arglist function))
+
+
+;; New (& complete) fspec handler.
+;; 1. uses a single #'equal htable where stored elements are (fn . plist)
+;; (maybe we should store the method object instead)
+;; 2. also implements the fspec-plist operators here.
+;; 3. fdefine not only stores the method, but actually does the loading here!
+;;
+
+;;;
+;;; genera-low.lisp (replaces old method-function-spec-handler)
+;;;
+
+;; New (& complete) fspec handler.
+;; 1. uses a single #'equal htable where stored elements are (fn . plist)
+;; (maybe we should store the method object instead)
+;; 2. also implements the fspec-plist operators here.
+;; 3. fdefine not only stores the method, but actually does the loading here!
+;;
+
+(defvar *method-htable* (make-hash-table :test #'equal :size 500))
+(sys:define-function-spec-handler method (op spec &optional arg1 arg2)
+ (if (eq op 'sys:validate-function-spec)
+ (and (let ((gspec (cadr spec)))
+ (or (symbolp gspec)
+ (and (listp gspec)
+ (eq (car gspec) 'setf)
+ (symbolp (cadr gspec))
+ (null (cddr gspec)))))
+ (let ((tail (cddr spec)))
+ (loop (cond ((null tail) (return nil))
+ ((listp (car tail)) (return t))
+ ((atom (pop tail)))
+ (t (return nil))))))
+ (let ((table *method-htable*)
+ (key spec))
+ (case op
+ ((si:fdefinedp si:fdefinition)
+ (car (gethash key table nil)))
+ (si:fundefine
+ (remhash key table))
+ (si:fdefine
+ (let ((old (gethash key table nil))
+ (quals nil)
+ (specs nil)
+ (ptr (cddr spec)))
+ (setq specs
+ (loop (cond ((null ptr) (return nil))
+ ((listp (car ptr)) (return (car ptr)))
+ (t (push (pop ptr) quals)))))
+ (setf (gethash key table) (cons arg1 (cdr old)))))
+ (si:get
+ (let ((old (gethash key table nil)))
+ (getf (cdr old) arg1)))
+ (si:plist
+ (let ((old (gethash key table nil)))
+ (cdr old)))
+ (si:putprop
+ (let ((old (gethash key table nil)))
+ (unless old
+ (setf old (cons nil nil))
+ (setf (gethash key table) old))
+ (setf (getf (cdr old) arg2) arg1)))
+ (si:remprop
+ (let ((old (gethash key table nil)))
+ (when old
+ (remf (cdr old) arg1))))
+ (otherwise
+ (si:function-spec-default-handler op spec arg1 arg2))))))
+
+
+#||
+;; this guy is just a stub to make the fspec handler simpler (and so I could trace it
+;; easier).
+(defun pcl-fdefine-helper (gspec qualifiers specializers fn)
+ (let* ((dlist (scl:debugging-info fn))
+ (class (cadr (assoc 'pcl-method-class dlist)))
+ (lambda-list (let ((ll-stuff (assoc 'pcl-lambda-list dlist)))
+ (if ll-stuff (cadr ll-stuff) (arglist fn))))
+ (doc (cadr (assoc 'pcl-documentation dlist)))
+ (plist (cadr (assoc 'pcl-plist dlist))))
+ (load-defmethod (or class 'standard-method)
+ gspec
+ qualifiers
+ specializers
+ lambda-list
+ doc
+ (getf plist :pv-table-cache-symbol)
+ plist
+ fn)))
+||#
+
+;; define a few special declarations to get pushed onto the function's debug-info
+;; list... note that we do not need to do a (proclaim (declarations ...)) here.
+;;
+(eval-when (compile load eval)
+ (setf (get 'pcl-plist 'si:debug-info) t)
+ (setf (get 'pcl-documentation 'si:debug-info) t)
+ (setf (get 'pcl-method-class 'si:debug-info) t)
+ (setf (get 'pcl-lambda-list 'si:debug-info) t)
+)
+
+(eval-when (load eval)
+ (setf
+ (get 'defmethod 'zwei:definition-function-spec-type) 'defun
+ (get 'defmethod-setf 'zwei:definition-function-spec-type) 'defun
+ (get 'method 'si:definition-type-name) "method"
+ (get 'method 'si:definition-type-name) "method"
+
+ (get 'declass 'zwei:definition-function-spec-type) 'defclass
+ (get 'defclass 'si:definition-type-name) "Class"
+ (get 'defclass 'zwei:definition-function-spec-finder-template) '(0 1))
+ )
+
+
+
+(defun (:property defmethod zwei::definition-function-spec-parser) (bp)
+ (zwei:parse-pcl-defmethod-for-zwei bp nil))
+
+;;;
+;;; Previously, if a source file in a PCL-based package contained what looks
+;;; like flavor defmethod forms (i.e. an (IN-PACKAGE 'non-pcl-package) form
+;;; appears at top level, and then a flavor-style defmethod form) appear, the
+;;; parser would break.
+;;;
+;;; Now, if we can't parse the defmethod form, we send it to the flavor
+;;; defmethod parser instead.
+;;;
+;;; Also now supports multi-line arglist sectionizing.
+;;;
+zwei:
+(defun parse-pcl-defmethod-for-zwei (bp-after-defmethod setfp)
+ (block parser
+ (flet ((barf (&optional (error t))
+ (return-from parser
+ (cond ((eq error :flavor)
+ (funcall (get 'flavor:defmethod
+ 'zwei::definition-function-spec-parser)
+ bp-after-defmethod))
+ (t
+ (values nil nil nil error))))))
+ (let ((bp-after-generic (forward-sexp bp-after-defmethod))
+ (qualifiers ())
+ (specializers ())
+ (spec nil)
+ (ignore1 nil)
+ (ignore2 nil))
+ (when bp-after-generic
+ (multiple-value-bind (generic error-p)
+ (read-fspec-item-from-interval bp-after-defmethod
+ bp-after-generic)
+ (if error-p
+ (barf) ; error here is really bad.... BARF!
+ (progn
+ (when (listp generic)
+ (if (and (symbolp (car generic))
+ (string-equal (cl:symbol-name (car generic)) "SETF"))
+ (setq generic (second generic) ; is a (setf xxx) form
+ setfp t)
+ (barf :flavor))) ; make a last-ditch-effort with flavor parser
+ (let* ((bp1 bp-after-generic)
+ (bp2 (forward-sexp bp1)))
+ (cl:loop
+ (if (null bp2)
+ (barf :more) ; item not closed - need another line!
+ (multiple-value-bind (item error-p)
+ (read-fspec-item-from-interval bp1 bp2)
+ (cond (error-p (barf)) ;
+ ((listp item)
+ (setq qualifiers (nreverse qualifiers))
+ (cl:multiple-value-setq (ignore1
+ ignore2
+ specializers)
+ (pcl::parse-specialized-lambda-list item))
+ (setq spec (pcl::make-method-spec
+ (if setfp
+ `(cl:setf ,generic)
+ generic)
+ qualifiers
+ specializers))
+ (return (values spec
+ 'defun
+ (string-interval
+ bp-after-defmethod
+ bp2))))
+ (t (push item qualifiers)
+ (setq bp1 bp2
+ bp2 (forward-sexp bp2))))))))))))))))
+
+zwei:
+(progn
+ (defun indent-clos-defmethod (ignore bp defmethod-paren &rest ignore)
+ (let ((here
+ (forward-over *whitespace-chars* (forward-word defmethod-paren))))
+ (loop until (char-equal (bp-char here) #\()
+ do (setf here
+ (forward-over *whitespace-chars* (forward-sexp here))))
+ (if (bp-< here bp)
+ (values defmethod-paren nil 2)
+ (values defmethod-paren nil 4))))
+
+ (defindentation (pcl::defmethod . indent-clos-defmethod)))
+
+;;;
+;;; Teach zwei that when it gets the name of a generic function as an argument
+;;; it should edit all the methods of that generic function. This works for
+;;; ED as well as meta-point.
+;;;
+(zl:advise (flavor:method :SETUP-FUNCTION-SPECS-TO-EDIT zwei:ZMACS-EDITOR)
+ :around
+ setup-function-specs-to-edit-advice
+ ()
+ (let ((old-definitions (cadddr arglist))
+ (new-definitions ())
+ (new nil))
+ (dolist (old old-definitions)
+ (setq new (setup-function-specs-to-edit-advice-1 old))
+ (push (or new (list old)) new-definitions))
+ (setf (cadddr arglist) (apply #'append (reverse new-definitions)))
+ :do-it))
+
+(defun setup-function-specs-to-edit-advice-1 (spec)
+ (and (or (symbolp spec)
+ (and (listp spec) (eq (car spec) 'setf)))
+ (gboundp spec)
+ (generic-function-p (gdefinition spec))
+ (mapcar #'(lambda (m)
+ (make-method-spec spec
+ (method-qualifiers m)
+ (unparse-specializers
+ (method-specializers m))))
+ (generic-function-methods (gdefinition spec)))))
+
+
diff --git a/gcl/pcl/impl/symbolics/rel-7-2-patches.lisp b/gcl/pcl/impl/symbolics/rel-7-2-patches.lisp
new file mode 100644
index 000000000..9c9587bd6
--- /dev/null
+++ b/gcl/pcl/impl/symbolics/rel-7-2-patches.lisp
@@ -0,0 +1,387 @@
+;;; -*- Mode: LISP; Syntax: Common-lisp; Package: ZL-USER; Base: 10; Patch-File: T -*-
+
+;=====================================
+(SYSTEM-INTERNALS:BEGIN-PATCH-SECTION)
+(SYSTEM-INTERNALS:PATCH-SECTION-SOURCE-FILE "SYS:l-COMPILER;OPTIMIZE.LISP.179")
+(SYSTEM-INTERNALS:PATCH-SECTION-ATTRIBUTES
+ "-*- Mode: Lisp; Package: Compiler; Lowercase: T; Base: 8 -*-")
+
+;;; Does simple constant folding. This works for everything that doesn't have
+;;; side-effects.
+;;; ALL operands must be constant.
+;;; Note that commutative-constant-folder can hack this case perfectly well
+;;; by himself for the functions he handles.
+(defun constant-fold-optimizer (form)
+ (let ((eval-when-load-p nil))
+ (flet ((constant-form-p (x)
+ (when (constant-form-p x)
+ (cond ((and (listp x)
+ (eq (car x) 'quote)
+ (listp (cadr x))
+ (eq (caadr x) eval-at-load-time-marker))
+ (setq eval-when-load-p t)
+ (cdadr x))
+ (t x)))))
+ (if (every (cdr form) #'constant-form-p)
+ (if eval-when-load-p
+ (list 'quote
+ (list* eval-at-load-time-marker
+ (car form)
+ (mapcar #'constant-form-p (cdr form))))
+ (condition-case (error-object)
+ (multiple-value-call #'(lambda (&rest values)
+ (if (= (length values) 1)
+ `',(first values)
+ `(values ,@(mapcar #'(lambda (x) `',x)
+ values))))
+ (eval form))
+ (error
+ (phase-1-warning "Constant form left unoptimized: ~S~%because: ~~A~"
+ form error-object)
+ form)))
+ form))))
+
+
+;=====================================
+(SYSTEM-INTERNALS:BEGIN-PATCH-SECTION)
+(SYSTEM-INTERNALS:PATCH-SECTION-SOURCE-FILE "SYS:L-COMPILER;COMFILE.LISP.85")
+(SYSTEM-INTERNALS:PATCH-SECTION-ATTRIBUTES
+ "-*- Mode: Lisp; Package: Compiler; Lowercase: T; Base: 8 -*-")
+
+;;;
+;;; The damn compiler doesn't compile random forms that appear at top level.
+;;; Its difficult to do because you have to get an associated function spec
+;;; to go with those forms. This handles that by defining a special form,
+;;; top-level-form that compiles its body. It takes a list of eval-when
+;;; times just like eval when does. It also takes a name which it uses
+;;; to construct a function spec for the top-level-form function it has
+;;; to create.
+;;;
+;
+;si::
+;(defvar *top-level-form-fdefinitions* (cl:make-hash-table :test #'equal))
+;
+;si::
+;(define-function-spec-handler pcl::top-level-form
+; (operation fspec &optional arg1 arg2)
+; (let ((name (cadr fspec)))
+; (selectq operation
+; (validate-function-spec (and (= (length fspec) 2)
+; (or (symbolp name)
+; (listp name))))
+; (fdefine
+; (setf (gethash name *top-level-form-fdefinitions*) arg1))
+; ((fdefinition fdefinedp)
+; (gethash name *top-level-form-fdefinitions*))
+; (fdefinition-location
+; (ferror "It is not possible to get the fdefinition-location of ~s."
+; fspec))
+; (fundefine (remhash name *top-level-form-fdefinitions*))
+; (otherwise (function-spec-default-handler operation fspec arg1 arg2)))))
+;
+;;;
+;;; This is basically stolen from PROGN (surprised?)
+;;;
+;(si:define-special-form pcl::top-level-form (name times
+; &body body
+; &environment env)
+; (declare lt:(arg-template . body) (ignore name))
+; (si:check-eval-when-times times)
+; (when (member 'eval times) (si:eval-body body env)))
+;
+;(defun (:property pcl::top-level-form lt:mapforms) (original-form form usage)
+; (lt::mapforms-list original-form form (cddr form) 'eval usage))
+
+;;; This is the normal function for looking at each form read from the file and calling
+;;; *COMPILE-FORM-FUNCTION* on the sub-forms of it.
+;;; COMPILE-TIME-TOO means override the normal cases that eval at compile time. It is
+;;; used for recursive calls under (EVAL-WHEN (COMPILE LOAD) ...).
+;(DEFUN COMPILE-FROM-STREAM-1 (FORM &OPTIONAL (COMPILE-TIME-TOO NIL))
+; (CATCH-ERROR-RESTART
+; (SYS:ERROR "Skip compiling form ~2,2\COMPILER:SHORT-S-FORMAT\" FORM)
+; (LET ((DEFAULT-CONS-AREA (FUNCALL *COMPILE-FUNCTION* ':CONS-AREA)))
+; (LET ((ERROR-MESSAGE-HOOK
+; #'(LAMBDA ()
+; (DECLARE (SYS:DOWNWARD-FUNCTION))
+; (FORMAT T "~&While processing ~V,V\COMPILER:SHORT-S-FORMAT\"
+; DBG:*ERROR-MESSAGE-PRINLEVEL*
+; DBG:*ERROR-MESSAGE-PRINLENGTH*
+; FORM))))
+; (SETQ FORM (FUNCALL *COMPILE-FUNCTION* ':MACRO-EXPAND FORM)))
+; (WHEN (LISTP FORM) ;Ignore atoms at top-level
+; (LET ((FUNCTION (FIRST FORM)))
+; (SELECTQ FUNCTION
+; ((QUOTE)) ;and quoted constants e.g. 'COMPILE
+; ((PROGN)
+; (DOLIST (FORM (CDR FORM))
+; (COMPILE-FROM-STREAM-1 FORM COMPILE-TIME-TOO)))
+; ((EVAL-WHEN)
+; (SI:CHECK-EVAL-WHEN-TIMES (CADR FORM))
+; (LET ((COMPILE-P (OR (MEMQ 'COMPILE (CADR FORM))
+; (AND COMPILE-TIME-TOO (MEMQ 'EVAL (CADR FORM)))))
+; (LOAD-P (OR (MEMQ 'LOAD (CADR FORM)) (MEMQ 'CL:LOAD (CADR FORM))))
+; (FORMS (CDDR FORM)))
+; (COND (LOAD-P
+; (DOLIST (FORM FORMS)
+; (COMPILE-FROM-STREAM-1 FORM (AND COMPILE-P ':FORCE))))
+; (COMPILE-P
+; (DOLIST (FORM FORMS)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM ':FORCE NIL))))))
+; ((DEFUN)
+; (LET ((TEM (DEFUN-COMPATIBILITY (CDR FORM) :WARN-IF-OBSOLETE T)))
+; (IF (EQ (CDR TEM) (CDR FORM))
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM COMPILE-TIME-TOO T)
+; (COMPILE-FROM-STREAM-1 TEM COMPILE-TIME-TOO))))
+; ((MACRO)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM (OR COMPILE-TIME-TOO T) T))
+; ((DECLARE)
+; (DOLIST (FORM (CDR FORM))
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM (OR COMPILE-TIME-TOO T)
+; ;; (DECLARE (SPECIAL ... has load-time action as well.
+; ;; All other DECLARE's do not.
+; (MEMQ (CAR FORM) '(SPECIAL ZL:UNSPECIAL)))))
+; ((COMPILER-LET)
+; (COMPILER-LET-INTERNAL (CADR FORM) (CDDR FORM)
+; #'COMPILE-FROM-STREAM-1 COMPILE-TIME-TOO))
+; ((SI:DEFINE-SPECIAL-FORM)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM COMPILE-TIME-TOO T))
+; ((MULTIPLE-DEFINITION)
+; (DESTRUCTURING-BIND (NAME TYPE . BODY) (CDR FORM)
+; (LET ((NAME-VALID (AND (NOT (NULL NAME))
+; (OR (SYMBOLP NAME)
+; (AND (LISTP NAME) (NEQ (CAR NAME) 'QUOTE)))))
+; (TYPE-VALID (AND (NOT (NULL TYPE)) (SYMBOLP TYPE))))
+; (UNLESS (AND NAME-VALID TYPE-VALID)
+; (WARN "(~S ~S ~S ...) is invalid because~@
+; ~:[~S is not valid as a definition name~;~*~]~
+; ~:[~&~S is not valid as a definition type~;~*~]"
+; 'MULTIPLE-DEFINITION NAME TYPE NAME-VALID NAME TYPE-VALID TYPE)))
+; (LET* ((COMPILED-BODY NIL)
+; (COMPILE-FUNCTION *COMPILE-FUNCTION*)
+; (*COMPILE-FUNCTION*
+; (LAMBDA (OPERATION &REST ARGS)
+; (DECLARE (SYS:DOWNWARD-FUNCTION))
+; (SELECTQ OPERATION
+; (:DUMP-FORM
+; (PUSH (FUNCALL COMPILE-FUNCTION :OPTIMIZE-TOP-LEVEL-FORM
+; (FIRST ARGS))
+; COMPILED-BODY))
+; (:INSTALL-DEFINITION
+; (PUSH (FORM-FOR-DEFINE *COMPILER* (FIRST ARGS) (SECOND ARGS))
+; COMPILED-BODY))
+; (OTHERWISE (CL:APPLY COMPILE-FUNCTION OPERATION ARGS)))))
+; (LOCAL-DECLARATIONS `((FUNCTION-PARENT ,NAME ,TYPE)
+; ,@LOCAL-DECLARATIONS)))
+; (DOLIST (FORM BODY)
+; (COMPILE-FROM-STREAM-1 FORM COMPILE-TIME-TOO))
+; (FUNCALL COMPILE-FUNCTION :DUMP-FORM
+; `(LOAD-MULTIPLE-DEFINITION
+; ',NAME ',TYPE ',(NREVERSE COMPILED-BODY) NIL)))))
+; ((pcl::top-level-form)
+; (destructuring-bind (name times . body)
+; (cdr form)
+; (si:check-eval-when-times times)
+; (let ((compile-p (or (memq 'compile times)
+; (and compile-time-too (memq 'eval times))))
+; (load-p (or (memq 'load times)
+; (memq 'cl:load times)))
+; (fspec `(pcl::top-level-form ,name)))
+; (cond (load-p
+; (compile-from-stream-1
+; `(progn (defun ,fspec () . ,body)
+; (funcall (function ,fspec)))
+; (and compile-p ':force)))
+; (compile-p
+; (dolist (b body)
+; (funcall *compile-form-function* form ':force nil)))))))
+; (OTHERWISE
+; (LET ((TEM (AND (SYMBOLP FUNCTION) (GET FUNCTION 'TOP-LEVEL-FORM))))
+; (IF TEM
+; (FUNCALL *COMPILE-FORM-FUNCTION* (FUNCALL TEM FORM) COMPILE-TIME-TOO T)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM COMPILE-TIME-TOO T))))))))))
+;
+;
+
+
+dw::
+(defun symbol-flavor-or-cl-type (symbol)
+ (declare (values flavor defstruct-p deftype-fun typep-fun atomic-subtype-parent
+ non-atomic-deftype))
+ (multiple-value-bind (result foundp)
+ (gethash symbol *flavor-or-cl-type-cache*)
+ (let ((frob
+ (if foundp result
+ (setf (gethash symbol *flavor-or-cl-type-cache*)
+ (or (get symbol 'flavor:flavor)
+ (not (null (defstruct-type-p symbol)))
+ (let* ((deftype (get symbol 'deftype))
+ (descriptor (symbol-presentation-type-descriptor symbol))
+ (typep
+ (unless (and descriptor
+ (presentation-type-explicit-type-function
+ descriptor))
+ ;; Don't override the one defined in the presentation-type.
+ (get symbol 'typep)))
+ (atomic-subtype-parent (find-atomic-subtype-parent symbol))
+ (non-atomic-deftype
+ (when (and (not descriptor) deftype)
+ (not (member (first (type-arglist symbol))
+ '(&rest &key &optional))))))
+ (if (or typep (not (atom deftype))
+ non-atomic-deftype
+ ;; deftype overrides atomic-subtype-parent.
+ (and (not deftype) atomic-subtype-parent))
+ (list-in-area *handler-dynamic-area*
+ deftype typep atomic-subtype-parent
+ non-atomic-deftype)
+ deftype)))))))
+ (locally (declare (inline compiled-function-p))
+ (etypecase frob
+ (array (values frob))
+ (null (values nil))
+ ((member t) (values nil t))
+ (compiled-function (values nil nil frob))
+ (lexical-closure (values nil nil frob))
+ (list (destructuring-bind (deftype typep atomic-subtype-parent non-atomic-deftype)
+ frob
+ (values nil nil deftype typep atomic-subtype-parent non-atomic-deftype)))
+ (symbol (values nil nil nil nil frob)))))))
+
+;;;
+;;; The variable zwei::*sectionize-line-lookahead* controls how many lines the parser
+;;; is willing to look ahead while trying to parse a definition. Even 2 lines is enough
+;;; for just about all cases, but there isn't much overhead, and 10 should be enough
+;;; to satisfy pretty much everyone... but feel free to change it.
+;;; - MT 880921
+;;;
+
+zwei:
+(defvar *sectionize-line-lookahead* 3)
+
+zwei:
+(DEFMETHOD (:SECTIONIZE-BUFFER MAJOR-MODE :DEFAULT)
+ (FIRST-BP LAST-BP BUFFER STREAM INT-STREAM ADDED-COMPLETIONS)
+ ADDED-COMPLETIONS ;ignored, obsolete
+ (WHEN STREAM
+ (SEND-IF-HANDLES STREAM :SET-RETURN-DIAGRAMS-AS-LINES T))
+ (INCF *SECTIONIZE-BUFFER*)
+ (LET ((BUFFER-TICK (OR (SEND-IF-HANDLES BUFFER :SAVE-TICK) *TICK*))
+ OLD-CHANGED-SECTIONS)
+ (TICK)
+ ;; Flush old section nodes. Also collect the names of those that are modified, they are
+ ;; the ones that will be modified again after a revert buffer.
+ (DOLIST (NODE (NODE-INFERIORS BUFFER))
+ (AND (> (NODE-TICK NODE) BUFFER-TICK)
+ (PUSH (LIST (SECTION-NODE-FUNCTION-SPEC NODE)
+ (SECTION-NODE-DEFINITION-TYPE NODE))
+ OLD-CHANGED-SECTIONS))
+ (FLUSH-BP (INTERVAL-FIRST-BP NODE))
+ (FLUSH-BP (INTERVAL-LAST-BP NODE)))
+ (DO ((LINE (BP-LINE FIRST-BP) (LINE-NEXT INT-LINE))
+ (LIMIT (BP-LINE LAST-BP))
+ (EOFFLG)
+ (ABNORMAL T)
+ (DEFINITION-LIST NIL)
+ (BP (COPY-BP FIRST-BP))
+ (FUNCTION-SPEC)
+ (DEFINITION-TYPE)
+ (STR)
+ (INT-LINE)
+ (first-time t)
+ (future-line) ; we actually read into future line
+ (future-int-line)
+ (PREV-NODE-START-BP FIRST-BP)
+ (PREV-NODE-DEFINITION-LINE NIL)
+ (PREV-NODE-FUNCTION-SPEC NIL)
+ (PREV-NODE-TYPE 'HEADER)
+ (PREVIOUS-NODE NIL)
+ (NODE-LIST NIL)
+ (STATE (SEND SELF :INITIAL-SECTIONIZATION-STATE)))
+ (NIL)
+ ;; If we have a stream, read another line.
+ (when (AND STREAM (NOT EOFFLG))
+ (let ((lookahead (if future-line 1 *sectionize-line-lookahead*)))
+ (dotimes (i lookahead) ; startup lookahead
+ (MULTIPLE-VALUE (future-LINE EOFFLG)
+ (LET ((DEFAULT-CONS-AREA *LINE-AREA*))
+ (SEND STREAM ':LINE-IN LINE-LEADER-SIZE)))
+ (IF future-LINE (SETQ future-INT-LINE (FUNCALL INT-STREAM ':LINE-OUT future-LINE)))
+ (when first-time
+ (setq first-time nil)
+ (setq line future-line)
+ (setq int-line future-int-line))
+ (when eofflg
+ (return)))))
+
+ (SETQ INT-LINE LINE)
+
+ (when int-line
+ (MOVE-BP BP INT-LINE 0)) ;Record as potentially start-bp for a section
+
+ ;; See if the line is the start of a defun.
+ (WHEN (AND LINE
+ (LET (ERR)
+ (MULTIPLE-VALUE (FUNCTION-SPEC DEFINITION-TYPE STR ERR STATE)
+ (SEND SELF ':SECTION-NAME INT-LINE BP STATE))
+ (NOT ERR)))
+ (PUSH (LIST FUNCTION-SPEC DEFINITION-TYPE) DEFINITION-LIST)
+ (SECTION-COMPLETION FUNCTION-SPEC STR NIL)
+ ;; List methods under both names for user ease.
+ (LET ((OTHER-COMPLETION (SEND SELF ':OTHER-SECTION-NAME-COMPLETION
+ FUNCTION-SPEC INT-LINE)))
+ (WHEN OTHER-COMPLETION
+ (SECTION-COMPLETION FUNCTION-SPEC OTHER-COMPLETION NIL)))
+ (LET ((PREV-NODE-END-BP (BACKWARD-OVER-COMMENT-LINES BP ':FORM-AS-BLANK)))
+ ;; Don't make a section node if it's completely empty. This avoids making
+ ;; a useless Buffer Header section node. Just set all the PREV variables
+ ;; so that the next definition provokes the *right thing*
+ (UNLESS (BP-= PREV-NODE-END-BP PREV-NODE-START-BP)
+ (SETQ PREVIOUS-NODE
+ (ADD-SECTION-NODE PREV-NODE-START-BP
+ (SETQ PREV-NODE-START-BP PREV-NODE-END-BP)
+ PREV-NODE-FUNCTION-SPEC PREV-NODE-TYPE
+ PREV-NODE-DEFINITION-LINE BUFFER PREVIOUS-NODE
+ (IF (LOOP FOR (FSPEC TYPE) IN OLD-CHANGED-SECTIONS
+ THEREIS (AND (EQ PREV-NODE-FUNCTION-SPEC FSPEC)
+ (EQ PREV-NODE-TYPE TYPE)))
+ *TICK* BUFFER-TICK)
+ BUFFER-TICK))
+ (PUSH PREVIOUS-NODE NODE-LIST)))
+ (SETQ PREV-NODE-FUNCTION-SPEC FUNCTION-SPEC
+ PREV-NODE-TYPE DEFINITION-TYPE
+ PREV-NODE-DEFINITION-LINE INT-LINE))
+ ;; After processing the last line, exit.
+ (WHEN (OR #+ignore EOFFLG (null line) (AND (NULL STREAM) (EQ LINE LIMIT)))
+ ;; If reading a stream, we should not have inserted a CR
+ ;; after the eof line.
+ (WHEN STREAM
+ (DELETE-INTERVAL (FORWARD-CHAR LAST-BP -1 T) LAST-BP T))
+ ;; The rest of the buffer is part of the last node
+ (UNLESS (SEND SELF ':SECTION-NAME-TRIVIAL-P)
+ ;; ---oh dear, what sort of section will this be? A non-empty HEADER
+ ;; ---node. Well, ok for now.
+ (PUSH (ADD-SECTION-NODE PREV-NODE-START-BP LAST-BP
+ PREV-NODE-FUNCTION-SPEC PREV-NODE-TYPE
+ PREV-NODE-DEFINITION-LINE BUFFER PREVIOUS-NODE
+ (IF (LOOP FOR (FSPEC TYPE) IN OLD-CHANGED-SECTIONS
+ THEREIS (AND (EQ PREV-NODE-FUNCTION-SPEC FSPEC)
+ (EQ PREV-NODE-TYPE TYPE)))
+ *TICK* BUFFER-TICK)
+ BUFFER-TICK)
+ NODE-LIST)
+ (SETF (LINE-NODE (BP-LINE LAST-BP)) (CAR NODE-LIST)))
+ (SETF (NODE-INFERIORS BUFFER) (NREVERSE NODE-LIST))
+ (SETF (NAMED-BUFFER-WITH-SECTIONS-FIRST-SECTION BUFFER) (CAR (NODE-INFERIORS BUFFER)))
+ (SETQ ABNORMAL NIL) ;timing windows here
+ ;; Speed up completion if enabled.
+ (WHEN SI:*ENABLE-AARRAY-SORTING-AFTER-LOADS*
+ (SI:SORT-AARRAY *ZMACS-COMPLETION-AARRAY*))
+ (SETQ *ZMACS-COMPLETION-AARRAY*
+ (FOLLOW-STRUCTURE-FORWARDING *ZMACS-COMPLETION-AARRAY*))
+ (RETURN
+ (VALUES
+ (CL:SETF (ZMACS-SECTION-LIST BUFFER)
+ (NREVERSE DEFINITION-LIST))
+ ABNORMAL))))))
+
+
diff --git a/gcl/pcl/impl/symbolics/rel-8-patches.lisp b/gcl/pcl/impl/symbolics/rel-8-patches.lisp
new file mode 100644
index 000000000..99b85b25e
--- /dev/null
+++ b/gcl/pcl/impl/symbolics/rel-8-patches.lisp
@@ -0,0 +1,255 @@
+;;; -*- Mode: LISP; Syntax: Common-lisp; Package: ZL-USER; Base: 10; Patch-File: T -*-
+
+;=====================================
+(SYSTEM-INTERNALS:BEGIN-PATCH-SECTION)
+(SYSTEM-INTERNALS:PATCH-SECTION-SOURCE-FILE "SYS:l-COMPILER;OPTIMIZE.LISP.179")
+(SYSTEM-INTERNALS:PATCH-SECTION-ATTRIBUTES
+ "-*- Mode: Lisp; Package: Compiler; Lowercase: T; Base: 8 -*-")
+
+;;; Does simple constant folding. This works for everything that doesn't have
+;;; side-effects.
+;;; ALL operands must be constant.
+;;; Note that commutative-constant-folder can hack this case perfectly well
+;;; by himself for the functions he handles.
+(defun constant-fold-optimizer (form)
+ (let ((eval-when-load-p nil))
+ (flet ((constant-form-p (x)
+ (when (constant-form-p x)
+ (cond ((and (listp x)
+ (eq (car x) 'quote)
+ (listp (cadr x))
+ (eq (caadr x) eval-at-load-time-marker))
+ (setq eval-when-load-p t)
+ (cdadr x))
+ (t x)))))
+ (if (every (cdr form) #'constant-form-p)
+ (if eval-when-load-p
+ (list 'quote
+ (list* eval-at-load-time-marker
+ (car form)
+ (mapcar #'constant-form-p (cdr form))))
+ (condition-case (error-object)
+ (multiple-value-call #'(lambda (&rest values)
+ (if (= (length values) 1)
+ `',(first values)
+ `(values ,@(mapcar #'(lambda (x) `',x)
+ values))))
+ (eval form))
+ (error
+ (phase-1-warning "Constant form left unoptimized: ~S~%because: ~~A~"
+ form error-object)
+ form)))
+ form))))
+
+
+;=====================================
+(SYSTEM-INTERNALS:BEGIN-PATCH-SECTION)
+(SYSTEM-INTERNALS:PATCH-SECTION-SOURCE-FILE "SYS:L-COMPILER;COMFILE.LISP.85")
+(SYSTEM-INTERNALS:PATCH-SECTION-ATTRIBUTES
+ "-*- Mode: Lisp; Package: Compiler; Lowercase: T; Base: 8 -*-")
+
+;;;
+;;; The damn compiler doesn't compile random forms that appear at top level.
+;;; Its difficult to do because you have to get an associated function spec
+;;; to go with those forms. This handles that by defining a special form,
+;;; top-level-form that compiles its body. It takes a list of eval-when
+;;; times just like eval when does. It also takes a name which it uses
+;;; to construct a function spec for the top-level-form function it has
+;;; to create.
+;;;
+;
+;si::
+;(defvar *top-level-form-fdefinitions* (cl:make-hash-table :test #'equal))
+;
+;si::
+;(define-function-spec-handler pcl::top-level-form
+; (operation fspec &optional arg1 arg2)
+; (let ((name (cadr fspec)))
+; (selectq operation
+; (validate-function-spec (and (= (length fspec) 2)
+; (or (symbolp name)
+; (listp name))))
+; (fdefine
+; (setf (gethash name *top-level-form-fdefinitions*) arg1))
+; ((fdefinition fdefinedp)
+; (gethash name *top-level-form-fdefinitions*))
+; (fdefinition-location
+; (ferror "It is not possible to get the fdefinition-location of ~s."
+; fspec))
+; (fundefine (remhash name *top-level-form-fdefinitions*))
+; (otherwise (function-spec-default-handler operation fspec arg1 arg2)))))
+;
+;;;
+;;; This is basically stolen from PROGN (surprised?)
+;;;
+;(si:define-special-form pcl::top-level-form (name times
+; &body body
+; &environment env)
+; (declare lt:(arg-template . body) (ignore name))
+; (si:check-eval-when-times times)
+; (when (member 'eval times) (si:eval-body body env)))
+;
+;(defun (:property pcl::top-level-form lt:mapforms) (original-form form usage)
+; (lt::mapforms-list original-form form (cddr form) 'eval usage))
+
+;;; This is the normal function for looking at each form read from the file and calling
+;;; *COMPILE-FORM-FUNCTION* on the sub-forms of it.
+;;; COMPILE-TIME-TOO means override the normal cases that eval at compile time. It is
+;;; used for recursive calls under (EVAL-WHEN (COMPILE LOAD) ...).
+;(DEFUN COMPILE-FROM-STREAM-1 (FORM &OPTIONAL (COMPILE-TIME-TOO NIL))
+; (CATCH-ERROR-RESTART
+; (SYS:ERROR "Skip compiling form ~2,2\COMPILER:SHORT-S-FORMAT\" FORM)
+; (LET ((DEFAULT-CONS-AREA (FUNCALL *COMPILE-FUNCTION* ':CONS-AREA)))
+; (LET ((ERROR-MESSAGE-HOOK
+; #'(LAMBDA ()
+; (DECLARE (SYS:DOWNWARD-FUNCTION))
+; (FORMAT T "~&While processing ~V,V\COMPILER:SHORT-S-FORMAT\"
+; DBG:*ERROR-MESSAGE-PRINLEVEL*
+; DBG:*ERROR-MESSAGE-PRINLENGTH*
+; FORM))))
+; (SETQ FORM (FUNCALL *COMPILE-FUNCTION* ':MACRO-EXPAND FORM)))
+; (WHEN (LISTP FORM) ;Ignore atoms at top-level
+; (LET ((FUNCTION (FIRST FORM)))
+; (SELECTQ FUNCTION
+; ((QUOTE)) ;and quoted constants e.g. 'COMPILE
+; ((PROGN)
+; (DOLIST (FORM (CDR FORM))
+; (COMPILE-FROM-STREAM-1 FORM COMPILE-TIME-TOO)))
+; ((EVAL-WHEN)
+; (SI:CHECK-EVAL-WHEN-TIMES (CADR FORM))
+; (LET ((COMPILE-P (OR (MEMQ 'COMPILE (CADR FORM))
+; (AND COMPILE-TIME-TOO (MEMQ 'EVAL (CADR FORM)))))
+; (LOAD-P (OR (MEMQ 'LOAD (CADR FORM)) (MEMQ 'CL:LOAD (CADR FORM))))
+; (FORMS (CDDR FORM)))
+; (COND (LOAD-P
+; (DOLIST (FORM FORMS)
+; (COMPILE-FROM-STREAM-1 FORM (AND COMPILE-P ':FORCE))))
+; (COMPILE-P
+; (DOLIST (FORM FORMS)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM ':FORCE NIL))))))
+; ((DEFUN)
+; (LET ((TEM (DEFUN-COMPATIBILITY (CDR FORM) :WARN-IF-OBSOLETE T)))
+; (IF (EQ (CDR TEM) (CDR FORM))
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM COMPILE-TIME-TOO T)
+; (COMPILE-FROM-STREAM-1 TEM COMPILE-TIME-TOO))))
+; ((MACRO)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM (OR COMPILE-TIME-TOO T) T))
+; ((DECLARE)
+; (DOLIST (FORM (CDR FORM))
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM (OR COMPILE-TIME-TOO T)
+; ;; (DECLARE (SPECIAL ... has load-time action as well.
+; ;; All other DECLARE's do not.
+; (MEMQ (CAR FORM) '(SPECIAL ZL:UNSPECIAL)))))
+; ((COMPILER-LET)
+; (COMPILER-LET-INTERNAL (CADR FORM) (CDDR FORM)
+; #'COMPILE-FROM-STREAM-1 COMPILE-TIME-TOO))
+; ((SI:DEFINE-SPECIAL-FORM)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM COMPILE-TIME-TOO T))
+; ((MULTIPLE-DEFINITION)
+; (DESTRUCTURING-BIND (NAME TYPE . BODY) (CDR FORM)
+; (LET ((NAME-VALID (AND (NOT (NULL NAME))
+; (OR (SYMBOLP NAME)
+; (AND (LISTP NAME) (NEQ (CAR NAME) 'QUOTE)))))
+; (TYPE-VALID (AND (NOT (NULL TYPE)) (SYMBOLP TYPE))))
+; (UNLESS (AND NAME-VALID TYPE-VALID)
+; (WARN "(~S ~S ~S ...) is invalid because~@
+; ~:[~S is not valid as a definition name~;~*~]~
+; ~:[~&~S is not valid as a definition type~;~*~]"
+; 'MULTIPLE-DEFINITION NAME TYPE NAME-VALID NAME TYPE-VALID TYPE)))
+; (LET* ((COMPILED-BODY NIL)
+; (COMPILE-FUNCTION *COMPILE-FUNCTION*)
+; (*COMPILE-FUNCTION*
+; (LAMBDA (OPERATION &REST ARGS)
+; (DECLARE (SYS:DOWNWARD-FUNCTION))
+; (SELECTQ OPERATION
+; (:DUMP-FORM
+; (PUSH (FUNCALL COMPILE-FUNCTION :OPTIMIZE-TOP-LEVEL-FORM
+; (FIRST ARGS))
+; COMPILED-BODY))
+; (:INSTALL-DEFINITION
+; (PUSH (FORM-FOR-DEFINE *COMPILER* (FIRST ARGS) (SECOND ARGS))
+; COMPILED-BODY))
+; (OTHERWISE (CL:APPLY COMPILE-FUNCTION OPERATION ARGS)))))
+; (LOCAL-DECLARATIONS `((FUNCTION-PARENT ,NAME ,TYPE)
+; ,@LOCAL-DECLARATIONS)))
+; (DOLIST (FORM BODY)
+; (COMPILE-FROM-STREAM-1 FORM COMPILE-TIME-TOO))
+; (FUNCALL COMPILE-FUNCTION :DUMP-FORM
+; `(LOAD-MULTIPLE-DEFINITION
+; ',NAME ',TYPE ',(NREVERSE COMPILED-BODY) NIL)))))
+; ((pcl::top-level-form)
+; (destructuring-bind (name times . body)
+; (cdr form)
+; (si:check-eval-when-times times)
+; (let ((compile-p (or (memq 'compile times)
+; (and compile-time-too (memq 'eval times))))
+; (load-p (or (memq 'load times)
+; (memq 'cl:load times)))
+; (fspec `(pcl::top-level-form ,name)))
+; (cond (load-p
+; (compile-from-stream-1
+; `(progn (defun ,fspec () . ,body)
+; (funcall (function ,fspec)))
+; (and compile-p ':force)))
+; (compile-p
+; (dolist (b body)
+; (funcall *compile-form-function* form ':force nil)))))))
+; (OTHERWISE
+; (LET ((TEM (AND (SYMBOLP FUNCTION) (GET FUNCTION 'TOP-LEVEL-FORM))))
+; (IF TEM
+; (FUNCALL *COMPILE-FORM-FUNCTION* (FUNCALL TEM FORM) COMPILE-TIME-TOO T)
+; (FUNCALL *COMPILE-FORM-FUNCTION* FORM COMPILE-TIME-TOO T))))))))))
+;
+;
+
+
+dw::
+(defun symbol-flavor-or-cl-type (symbol)
+ (declare (values flavor defstruct-p deftype-fun typep-fun atomic-subtype-parent
+ non-atomic-deftype))
+ (multiple-value-bind (result foundp)
+ (gethash symbol *flavor-or-cl-type-cache*)
+ (let ((frob
+ (if foundp result
+ (setf (gethash symbol *flavor-or-cl-type-cache*)
+ (or (get symbol 'flavor:flavor)
+ (let ((class (get symbol 'clos-internals::class-for-name)))
+ (when (and class
+ (not (typep class 'clos:built-in-class)))
+ class))
+ (not (null (defstruct-type-p symbol)))
+ (let* ((deftype (get symbol 'deftype))
+ (descriptor (symbol-presentation-type-descriptor symbol))
+ (typep
+ (unless (and descriptor
+ (presentation-type-explicit-type-function
+ descriptor))
+ ;; Don't override the one defined in the presentation-type.
+ (get symbol 'typep)))
+ (atomic-subtype-parent (find-atomic-subtype-parent symbol))
+ (non-atomic-deftype
+ (when (and (not descriptor) deftype)
+ (not (member (first (type-arglist symbol))
+ '(&rest &key &optional))))))
+ (if (or typep (not (atom deftype))
+ non-atomic-deftype
+ ;; deftype overrides atomic-subtype-parent.
+ (and (not deftype) atomic-subtype-parent))
+ (list-in-area *handler-dynamic-area*
+ deftype typep atomic-subtype-parent
+ non-atomic-deftype)
+ deftype)))))))
+ (locally (declare (inline compiled-function-p))
+ (etypecase frob
+ (array (values frob))
+ (instance (values frob))
+ (null (values nil))
+ ((member t) (values nil t))
+ (compiled-function (values nil nil frob))
+ (lexical-closure (values nil nil frob))
+ (list (destructuring-bind (deftype typep atomic-subtype-parent non-atomic-deftype)
+ frob
+ (values nil nil deftype typep atomic-subtype-parent non-atomic-deftype)))
+ (symbol (values nil nil nil nil frob)))))))
+
+
diff --git a/gcl/pcl/impl/ti/ti-low.lisp b/gcl/pcl/impl/ti/ti-low.lisp
new file mode 100644
index 000000000..95f5e842e
--- /dev/null
+++ b/gcl/pcl/impl/ti/ti-low.lisp
@@ -0,0 +1,83 @@
+;;; -*- Mode:LISP; Package:(PCL (Lisp WALKER)); Base:10.; Syntax:Common-lisp; Patch-File: Yes -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the 3600 version of the file portable-low.
+;;;
+
+(in-package 'pcl)
+
+(defmacro without-interrupts (&body body)
+ `(let ((outer-scheduling-state si:inhibit-scheduling-flag)
+ (si:inhibit-scheduling-flag t))
+ (macrolet ((interrupts-on ()
+ '(when (null outer-scheduling-state)
+ (setq si:inhibit-scheduling-flag nil)))
+ (interrupts-off ()
+ '(setq si:inhibit-scheduling-flag t)))
+ ,.body)))
+
+(si:defsubst std-instance-p (x)
+ (si:typep-structure-or-flavor x 'std-instance))
+
+ ;;
+;;;;;; printing-random-thing-internal
+ ;;
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~O" (si:%pointer thing)))
+
+(eval-when (compile load eval) ;There seems to be some bug with
+ (setq si::inhibit-displacing-flag t)) ;macrolet'd macros or something.
+ ;This gets around it but its not
+ ;really the right fix.
+
+(defun function-arglist (f)
+ (sys::arglist f t))
+
+(defun record-definition (type spec &rest ignore)
+ (if (eql type 'method)
+ (sys:record-source-file-name spec 'defun :no-query)
+ (sys:record-source-file-name spec type :no-query)))
+
+(ticl:defprop method method-function-spec-handler sys:function-spec-handler)
+(defun method-function-spec-handler
+ (function function-spec &optional arg1 arg2)
+ (let ((symbol (second function-spec)))
+ (case function
+ (sys:validate-function-spec t)
+ (otherwise
+ (sys:function-spec-default-handler
+ function function-spec arg1 arg2)))))
+
+;;;Edited by Reed Hastings 13 Aug 87 16:59
+;;;Edited by Reed Hastings 2 Nov 87 22:58
+(defun set-function-name (function new-name)
+ (when (si:get-debug-info-struct function)
+ (setf (si:get-debug-info-field (si:get-debug-info-struct function) :name)
+ new-name))
+ function)
+
+
+
diff --git a/gcl/pcl/impl/ti/ti-patches.lisp b/gcl/pcl/impl/ti/ti-patches.lisp
new file mode 100644
index 000000000..c18986109
--- /dev/null
+++ b/gcl/pcl/impl/ti/ti-patches.lisp
@@ -0,0 +1,105 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package 'pcl)
+
+;;;
+;;; This little bit of magic keeps the dumper from dumping the lexical
+;;; definition of call-next-method when it dumps method functions that
+;;; come from defmethod forms.
+;;;
+(proclaim '(notinline nil))
+
+(eval-when (load)
+ (setf (get 'function 'si:type-predicate) 'functionp))
+
+;; fix defsetf to deal with do-standard-defsetf
+
+#!C
+; From file SETF.LISP#> KERNEL; VIRGO:
+#8R SYSTEM#:
+(COMPILER-LET ((*PACKAGE* (FIND-PACKAGE "SYSTEM"))
+ (SI:*LISP-MODE* :COMMON-LISP)
+ (*READTABLE* COMMON-LISP-READTABLE)
+ (SI:*READER-SYMBOL-SUBSTITUTIONS* *COMMON-LISP-SYMBOL-SUBSTITUTIONS*))
+ (COMPILER#:PATCH-SOURCE-FILE "SYS: KERNEL; SETF.#"
+
+
+(defmacro defsetf (access-function arg1 &optional arg2 &environment env &body body)
+ "Define a SETF expander for ACCESS-FUNCTION.
+DEFSETF has two forms:
+
+The simple form (DEFSETF access-function update-function [doc-string])
+can be used as follows: After (DEFSETF GETFROB PUTFROB),
+\(SETF (GETFROB A 3) FOO) ==> (PUTFROB A 3 FOO).
+
+The complex form is like DEFMACRO:
+
+\(DEFSETF access-function access-lambda-list newvalue-lambda-list body...)
+
+except there are TWO lambda-lists.
+The first one represents the argument forms to the ACCESS-FUNCTION.
+Only &OPTIONAL and &REST are allowed here.
+The second has only one argument, representing the value to be stored.
+The body of the DEFSETF definition must then compute a
+replacement for the SETF form, just as for any other macro.
+When the body is executed, the args in the lambda-lists will not
+really contain the value-expression or parts of the form to be set;
+they will contain gensymmed variables which SETF may or may not
+eliminate by substitution."
+ ;; REF and VAL are arguments to the expansion function
+ (if (null body)
+ `(defdecl ,access-function setf-method ,arg1)
+ (multiple-value-bind (body decls doc-string)
+ (parse-body body env t)
+ (let* ((access-ll arg1)
+ (value-names arg2)
+ (expansion
+ (let (all-arg-names)
+ (dolist (x access-ll)
+ (cond ((symbolp x)
+ (if (not (member x lambda-list-keywords :test #'eq))
+ (push x all-arg-names)
+ (when (eq x '&rest) (return)))) ;;9/20/88 clm
+ (t ; it's a list after &optional
+ (push (car x) all-arg-names))))
+ (setq all-arg-names (reverse all-arg-names))
+ `(let ((tempvars (mapcar #'(lambda (ignore) (gensym)) ',all-arg-names))
+ (storevar (gensym)))
+ (values tempvars (list . ,all-arg-names) (list storevar)
+ (let ((,(car value-names) storevar)
+ . ,(loop for arg in all-arg-names
+ for i = 0 then (1+ i)
+ collect `(,arg (nth ,i tempvars))))
+ ,@decls . ,body)
+ `(,',access-function . ,tempvars))))))
+ `(define-setf-method ,access-function ,arg1
+ ,@doc-string ,expansion)
+ ))))
+))
+
+
diff --git a/gcl/pcl/impl/vaxlisp/vaxl-low.lisp b/gcl/pcl/impl/vaxlisp/vaxl-low.lisp
new file mode 100644
index 000000000..ae9383bb5
--- /dev/null
+++ b/gcl/pcl/impl/vaxlisp/vaxl-low.lisp
@@ -0,0 +1,80 @@
+;;;-*-Mode:LISP; Package:(PCL Lisp 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; The version of low for VAXLisp
+;;;
+(in-package 'pcl)
+
+(defmacro without-interrupts (&body body)
+ `(macrolet ((interrupts-on ()
+ `(when (null outer-scheduling-state)
+ (setq system::*critical-section-p* nil)
+ (when (system::%sp-interrupt-queued-p)
+ (system::interrupt-dequeuer t))))
+ (interrupts-off ()
+ `(setq system::*critical-section-p* t)))
+ (let ((outer-scheduling-state system::*critical-section-p*))
+ (prog1 (let ((system::*critical-section-p* t)) ,@body)
+ (when (and (null outer-scheduling-state)
+ (system::%sp-interrupt-queued-p))
+ (system::interrupt-dequeuer t))))))
+
+
+ ;;
+;;;;;; Load Time Eval
+ ;;
+(defmacro load-time-eval (form)
+ `(progn ,form))
+
+ ;;
+;;;;;; Generating CACHE numbers
+ ;;
+;;; How are symbols in VAXLisp actually arranged in memory?
+;;; Should we be shifting the address?
+;;; Are they relocated?
+;;; etc.
+
+;(defmacro symbol-cache-no (symbol mask)
+; `(logand (the fixnum (system::%sp-pointer->fixnum ,symbol)) ,mask))
+
+(defmacro object-cache-no (object mask)
+ `(logand (the fixnum (system::%sp-pointer->fixnum ,object)) ,mask))
+
+ ;;
+;;;;;; printing-random-thing-internal
+ ;;
+(defun printing-random-thing-internal (thing stream)
+ (format stream "~O" (system::%sp-pointer->fixnum thing)))
+
+
+(defun function-arglist (fn)
+ (system::function-lambda-vars (symbol-function fn)))
+
+(defun set-function-name-1 (fn name ignore)
+ (cond ((system::slisp-compiled-function-p fn)
+ (system::%sp-b-store fn 3 name)))
+ fn)
+
diff --git a/gcl/pcl/impl/xerox/pcl-env-internal.lisp b/gcl/pcl/impl/xerox/pcl-env-internal.lisp
new file mode 100644
index 000000000..86b947bff
--- /dev/null
+++ b/gcl/pcl/impl/xerox/pcl-env-internal.lisp
@@ -0,0 +1,261 @@
+(DEFINE-FILE-INFO PACKAGE "XCL" READTABLE "XCL")
+(il:filecreated "28-Aug-87 18:42:36" il:{phylum}<pcl>pcl-env-internal.\;1 8356
+
+ il:|changes| il:|to:| (il:vars il:pcl-env-internalcoms)
+ (il:props (il:pcl-env-internal il:makefile-environment))
+ (il:functions stack-eql stack-pointer-frame stack-frame-valid-p
+ stack-frame-fn-header stack-frame-pc fnheader-debugging-info
+ stack-frame-name compiled-closure-fnheader compiled-closure-env)
+)
+
+
+; Copyright (c) 1987 by Xerox Corporation. All rights reserved.
+
+(il:prettycomprint il:pcl-env-internalcoms)
+
+(il:rpaqq il:pcl-env-internalcoms (
+
+(il:* il:|;;;| "***************************************")
+
+
+
+(il:* il:|;;;| " Copyright (c) 1987 Xerox Corporation. All rights reserved.")
+
+
+
+(il:* il:|;;;| "")
+
+
+
+(il:* il:|;;;| "Use and copying of this software and preparation of derivative works based upon this software are permitted. Any distribution of this software or derivative works must comply with all applicable United States export control laws.")
+
+
+
+(il:* il:|;;;| " ")
+
+
+
+(il:* il:|;;;| "This software is made available AS IS, and Xerox Corporation makes no warranty about the software, its performance or its conformity to any specification.")
+
+
+
+(il:* il:|;;;| " ")
+
+
+
+(il:* il:|;;;| "Any person obtaining a copy of this software is requested to send their name and post office or electronic mail address to:")
+
+
+
+(il:* il:|;;;| " CommonLoops Coordinator")
+
+
+
+(il:* il:|;;;| " Xerox Artifical Intelligence Systems")
+
+
+
+(il:* il:|;;;| " 2400 Hanover St.")
+
+
+
+(il:* il:|;;;| " Palo Alto, CA 94303")
+
+
+
+(il:* il:|;;;| "(or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)")
+
+
+
+(il:* il:|;;;| "")
+
+
+
+(il:* il:|;;;| " Suggestions, comments and requests for improvements are also welcome.")
+
+
+
+(il:* il:|;;;| " *************************************************************************")
+
+
+
+(il:* il:|;;;| "")
+
+ (il:declare\: il:dontcopy (il:prop il:makefile-environment
+ il:pcl-env-internal))
+ (il:* il:\;
+ "We're off to hack the system...")
+
+ (il:declare\: il:eval@compile il:dontcopy (il:files pcl::abc)
+
+
+ (il:* il:|;;| "The Deltas and The East and The Freeze")
+)
+ (il:functions stack-eql stack-pointer-frame stack-frame-valid-p
+ stack-frame-fn-header stack-frame-pc
+ fnheader-debugging-info stack-frame-name
+ compiled-closure-fnheader compiled-closure-env)))
+
+
+
+(il:* il:|;;;| "***************************************")
+
+
+
+
+(il:* il:|;;;| " Copyright (c) 1987 Xerox Corporation. All rights reserved.")
+
+
+
+
+(il:* il:|;;;| "")
+
+
+
+
+(il:* il:|;;;|
+"Use and copying of this software and preparation of derivative works based upon this software are permitted. Any distribution of this software or derivative works must comply with all applicable United States export control laws."
+)
+
+
+
+
+(il:* il:|;;;| " ")
+
+
+
+
+(il:* il:|;;;|
+"This software is made available AS IS, and Xerox Corporation makes no warranty about the software, its performance or its conformity to any specification."
+)
+
+
+
+
+(il:* il:|;;;| " ")
+
+
+
+
+(il:* il:|;;;|
+"Any person obtaining a copy of this software is requested to send their name and post office or electronic mail address to:"
+)
+
+
+
+
+(il:* il:|;;;| " CommonLoops Coordinator")
+
+
+
+
+(il:* il:|;;;| " Xerox Artifical Intelligence Systems")
+
+
+
+
+(il:* il:|;;;| " 2400 Hanover St.")
+
+
+
+
+(il:* il:|;;;| " Palo Alto, CA 94303")
+
+
+
+
+(il:* il:|;;;| "(or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)")
+
+
+
+
+(il:* il:|;;;| "")
+
+
+
+
+(il:* il:|;;;| " Suggestions, comments and requests for improvements are also welcome.")
+
+
+
+
+(il:* il:|;;;| " *************************************************************************")
+
+
+
+
+(il:* il:|;;;| "")
+
+(il:declare\: il:dontcopy
+
+(il:putprops il:pcl-env-internal il:makefile-environment (:package "XCL" :readtable "XCL"))
+)
+
+
+
+(il:* il:\; "We're off to hack the system...")
+
+(il:declare\: il:eval@compile il:dontcopy
+(il:filesload pcl::abc)
+)
+
+(defun stack-eql (x y) "Test two stack pointers for equality" (and (il:stackp x)
+ (il:stackp y)
+ (eql (il:fetch (il:stackp il:edfxp
+ )
+ il:of x)
+ (il:fetch (il:stackp il:edfxp
+ )
+ il:of y))))
+
+
+(defun stack-pointer-frame (stack-pointer) (il:|fetch| (il:stackp il:edfxp) il:|of| stack-pointer))
+
+
+(defun stack-frame-valid-p (frame) (not (il:|fetch| (il:fx il:invalidp) il:|of| frame)))
+
+
+(defun stack-frame-fn-header (frame) (il:|fetch| (il:fx il:fnheader) il:|of| frame))
+
+
+(defun stack-frame-pc (frame) (il:|fetch| (il:fx il:pc) il:|of| frame))
+
+
+(defun fnheader-debugging-info (fnheader) (let* ((start-pc (il:fetch (il:fnheader il:startpc)
+ il:of fnheader))
+ (name-table-words
+ (let ((size (il:fetch (il:fnheader il:ntsize)
+ il:of fnheader)))
+ (if (zerop size)
+ il:wordsperquad
+ (* size 2))))
+ (past-name-table-in-words (+ (il:fetch (il:fnheader
+
+ il:overheadwords
+ )
+ il:of fnheader)
+ name-table-words)))
+ (and (= (- start-pc (* il:bytesperword
+ past-name-table-in-words))
+ il:bytespercell)
+
+ (il:* il:|;;| "It's got a debugging-info list.")
+
+ (il:\\getbaseptr fnheader
+ past-name-table-in-words))))
+
+
+(defun stack-frame-name (frame) (il:|fetch| (il:fx il:framename) il:|of| frame))
+
+
+(defun compiled-closure-fnheader (closure) (il:|fetch| (il:compiled-closure il:fnheader) il:|of|
+ closure))
+
+
+(defun compiled-closure-env (closure) (il:fetch (il:compiled-closure il:environment) il:of closure))
+
+(il:putprops il:pcl-env-internal il:copyright ("Xerox Corporation" 1987))
+(il:declare\: il:dontcopy
+ (il:filemap (nil)))
+il:stop
+
diff --git a/gcl/pcl/impl/xerox/pcl-env.lisp b/gcl/pcl/impl/xerox/pcl-env.lisp
new file mode 100644
index 000000000..7bf4b476e
--- /dev/null
+++ b/gcl/pcl/impl/xerox/pcl-env.lisp
@@ -0,0 +1,1629 @@
+;;;-*-Mode:LISP; Package:(PCL (LISP WALKER)); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.com)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; Xerox-Lisp specific environment hacking for PCL
+
+(in-package "PCL")
+
+;;
+;; Protect the Corporation
+;;
+(eval-when (eval load)
+ (format *terminal-io*
+ "~&;PCL-ENV Copyright (c) 1987, 1988, 1989, by ~
+ Xerox Corporation. All rights reserved.~%"))
+
+
+;;; Make funcallable instances (FINs) print by calling print-object.
+
+(eval-when (eval load)
+ (il:defprint 'il:compiled-closure 'il:print-closure))
+
+(defun il:print-closure (x &optional stream depth)
+ ;; See the IRM, section 25.3.3. Unfortunatly, that documentation is
+ ;; not correct. In particular, it makes no mention of the third argument.
+ (cond ((not (funcallable-instance-p x))
+ ;; IL:\CCLOSURE.DEFPRINT is the orginal system function for
+ ;; printing closures
+ (il:\\cclosure.defprint x stream))
+ ((streamp stream)
+ ;; Use the standard PCL printing method, then return T to tell
+ ;; the printer that we have done the printing ourselves.
+ (print-object x stream)
+ t)
+ (t
+ ;; Internal printing (again, see the IRM section 25.3.3).
+ ;; Return a list containing the string of characters that
+ ;; would be printed, if the object were being printed for
+ ;; real.
+ (with-output-to-string (stream)
+ (list (print-object x stream))))))
+
+
+;;; Naming methods
+
+(defun gf-named (gf-name)
+ (let ((spec (cond ((symbolp gf-name) gf-name)
+ ((and (consp gf-name)
+ (eq (first gf-name) 'setf)
+ (symbolp (second gf-name))
+ (null (cddr gf-name)))
+ (get-setf-function-name (second gf-name)))
+ (t nil))))
+ (if (and (fboundp spec)
+ (generic-function-p (symbol-function spec)))
+ (symbol-function spec)
+ nil)))
+
+(defun generic-function-method-names (gf-name hasdefp)
+ (if hasdefp
+ (let ((names nil))
+ (maphash #'(lambda (key value)
+ (declare (ignore value))
+ (when (and (consp key) (eql (car key) gf-name))
+ (pushnew key names)))
+ (gethash 'methods xcl:*definition-hash-table*))
+ names)
+ (let ((gf (gf-named gf-name)))
+ (when gf
+ (mapcar #'full-method-name (generic-function-methods gf))))))
+
+(defun full-method-name (method)
+ "Return the full name of the method"
+ (let ((specializers (mapcar #'(lambda (x)
+ (cond ((eq x 't) t)
+ ((consp x) x)
+ (t (class-name x))))
+ (method-type-specifiers method))))
+ ;; Now go through some hair to make sure that specializer is
+ ;; really right. Once PCL returns the right value for
+ ;; specializers this can be taken out.
+ (let* ((arglist (method-arglist method))
+ (number-required (or (position-if
+ #'(lambda (x) (member x lambda-list-keywords))
+ arglist)
+ (length arglist)))
+ (diff (- number-required (length specializers))))
+ (when (> diff 0)
+ (setq specializers (nconc (copy-list specializers)
+ (make-list diff :initial-element 't)))))
+ (make-full-method-name (generic-function-name
+ (method-generic-function method))
+ (method-qualifiers method)
+ specializers)))
+
+(defun make-full-method-name (generic-function-name qualifiers arg-types)
+ "Return the full name of a method, given the generic-function name, the method
+qualifiers, and the arg-types"
+ ;; The name of the method is:
+ ;; (<generic-function-name> <qualifier-1> ..
+ ;; (<arg-specializer-1>..))
+ (labels ((remove-trailing-ts (l)
+ (if (null l)
+ nil
+ (let ((tail (remove-trailing-ts (cdr l))))
+ (if (null tail)
+ (if (eq (car l) 't)
+ nil
+ (list (car l)))
+ (if (eq l tail)
+ l
+ (cons (car l) tail)))))))
+ `(,generic-function-name ,@qualifiers
+ ,(remove-trailing-ts arg-types))))
+
+(defun parse-full-method-name (method-name)
+ "Parse the method name, returning the gf-name, the qualifiers, and the
+arg-types."
+ (values (first method-name)
+ (butlast (rest method-name))
+ (car (last method-name))))
+
+(defun prompt-for-full-method-name (gf-name &optional has-def-p)
+ "Prompt the user for the full name of a method on the given generic function name"
+ (let ((method-names (generic-function-method-names gf-name has-def-p)))
+ (cond ((null method-names)
+ nil)
+ ((null (cdr method-names))
+ (car method-names))
+ (t (il:menu
+ (il:create
+ il:menu il:items il:_ ;If HAS-DEF-P, include only
+ ; those methods that have a
+ ; symbolic def'n that we can
+ ; find
+ (remove-if #'null
+ (mapcar #'(lambda (m)
+ (if (or (not has-def-p)
+ (il:hasdef m 'methods))
+ `(,(with-output-to-string (s)
+ (dolist (x m)
+ (format s "~A " x))
+ s)
+ ',m)
+ nil))
+ method-names))
+ il:title il:_ "Which method?"))))))
+
+
+;;; Converting generic defining macros into DEFDEFINER macros
+
+(defmacro make-defdefiner (definer-name definer-type type-description &body
+ definer-options)
+ "Make the DEFINER-NAME use DEFDEFINER, defining items of type DEFINER-TYPE"
+ (let ((old-definer-macro-name (intern (string-append definer-name
+ " old definition")
+ (symbol-package definer-name)))
+ (old-definer-macro-expander (intern (string-append definer-name
+ " old expander")
+ (symbol-package definer-name))))
+ `(progn
+ ;; First, move the current defining function off to some safe
+ ;; place
+ (unmake-defdefiner ',definer-name)
+ (cond ((not (fboundp ',definer-name))
+ (error "~A has no definition!" ',definer-name))
+ ((fboundp ',old-definer-macro-name))
+ ((macro-function ',definer-name)
+ ; We have to move the macro
+ ; expansion function as well,
+ ; so it won't get clobbered
+ ; when the original macro is
+ ; redefined. See AR 7410.
+ (let* ((expansion-function (macro-function ',definer-name)))
+ (setf (symbol-function ',old-definer-macro-expander)
+ (loop (if (symbolp expansion-function)
+ (setq expansion-function
+ (symbol-function expansion-function))
+ (return expansion-function))))
+ (setf (macro-function ',old-definer-macro-name)
+ ',old-definer-macro-expander)
+ (setf (get ',definer-name 'make-defdefiner) expansion-function)))
+ (t (error "~A does not name a macro." ',definer-name)))
+ ;; Make sure the type is defined
+ (xcl:def-define-type ,definer-type ,type-description)
+ ;; Now redefine the definer, using DEFEDFINER and the original def'n
+ (xcl:defdefiner ,(if definer-options
+ (cons definer-name definer-options)
+ definer-name)
+ ,definer-type (&body b) `(,',old-definer-macro-name ,@,'b)))))
+
+(defun unmake-defdefiner (definer-name)
+ (let ((old-expander (get definer-name 'make-defdefiner)))
+ (when old-expander
+ (setf (macro-function definer-name old-expander))
+ (remprop definer-name 'make-defdefiner))))
+
+
+;;; For tricking ED into being able to use just the generic-function-name
+;;; instead of the full method name
+
+(defun source-manager-method-edit-fn (name type source editcoms options)
+ "Edit a method of the given name"
+ (let ((full-name (if (gf-named name)
+ ;If given the name of a
+ ; generic-function, try to get
+ ; the full method name
+ (prompt-for-full-method-name name t)
+ ; Otherwise it should name the
+ ; method
+ name)))
+ (when (not (null full-name))
+ (il:default.editdef full-name type source editcoms options))
+ (or full-name name))) ;Return the name
+
+(defun source-manager-method-hasdef-fn (name type &optional source)
+ "Is there a method defined with the given name?"
+ (cond ((not (eq type 'methods)) nil)
+ ((or (symbolp name)
+ (and (consp name)
+ (eq (first name) 'setf)
+ (symbolp (second name))
+ (null (cddr name))))
+ ;; If passed in the name of a generic-function, pretend that
+ ;; there is a method by that name if there is a generic function
+ ;; by that name, and there is a method whose source we can find.
+ (if (and (not (null (gf-named name)))
+ (find-if #'(lambda (m)
+ (il:hasdef m type source))
+ (generic-function-method-names name t)))
+ name
+ nil))
+ ((and (consp name) (>= (length name) 2))
+ ;; Standard methods are named (gf-name {qualifiers}* ({specializers}*))
+ (when (il:getdef name type source '(il:nocopy il:noerror))
+ name))
+ (t
+ ;; Nothing else can name a method
+ nil)))
+
+;;; Initialize the PCL env
+
+(defun initialize-pcl-env nil
+ "Initialize the Xerox PCL environment"
+ ;; Set up SourceManager DEFDEFINERS for classes and methods.
+ ;;
+ ;; Make sure to define methods before classes, so that (IL:FILES?) will build
+ ;; filecoms that have classes before methods.
+ (unless (il:hasdef 'methods 'il:filepkgtype)
+ (make-defdefiner defmethod methods "methods"
+ (:name (lambda (form)
+ (multiple-value-bind (name qualifiers arglist)
+ (parse-defmethod (cdr form))
+ (make-full-method-name name qualifiers
+ (extract-specializer-names
+ arglist)))))
+ (:undefiner
+ (lambda (method-name)
+ (multiple-value-bind
+ (name qualifiers arg-types)
+ (parse-full-method-name method-name)
+ (let* ((gf (gf-named name))
+ (method (when gf
+ (get-method gf qualifiers
+ (mapcar #'find-class
+ arg-types)))))
+ (when method (remove-method gf method))))))))
+ ;; Include support for DEFGENERIC, if that is defined
+ (unless (or (not (fboundp 'defgeneric))
+ (il:hasdef 'generic-functions 'il:filepkgtype))
+ (make-defdefiner defgeneric generic-functions "generic-function definitions"))
+ ;; DEFCLASS FileManager stuff
+ (unless (il:hasdef 'classes 'il:filepkgtype)
+ (make-defdefiner defclass classes "class definitions"
+ (:undefiner (lambda (name)
+ (when (find-class name t)
+ (setf (find-class name) nil)))))
+ ;; CLASSES "include" TYPES.
+ (il:filepkgcom 'classes 'il:contents
+ #'(lambda (com name type &optional reason)
+ (declare (ignore name reason))
+ (if (member type '(il:types classes) :test #'eq)
+ (cdr com)
+ nil))))
+ ;; Set up the hooks so that ED can be handed the name of a generic function,
+ ;; and end up editing a method instead
+ (il:filepkgtype 'methods 'il:editdef 'source-manager-method-edit-fn
+ 'il:hasdef 'source-manager-method-hasdef-fn)
+ ;; Set up the inspect macro. The right way to do this is to
+ ;; (ENSURE-GENERIC-FUNCTION 'IL:INSPECT...), but for now...
+ (push '((il:function pcl-object-p) . \\internal-inspect-object)
+ il:inspectmacros)
+ ;; Unmark any SourceManager changes caused by this loadup
+ (dolist (com (il:filepkgchanges))
+ (dolist (name (cdr com))
+ (when (and (symbolp name)
+ (eq (symbol-package name) (find-package "PCL")))
+ (il:unmarkaschanged name (car com))))))
+
+(eval-when (eval load)
+ (initialize-pcl-env))
+
+
+;;; Inspecting PCL objects
+
+(defun pcl-object-p (x)
+ "Is the datum a PCL object?"
+ (or (std-instance-p x)
+ (fsc-instance-p x)))
+
+(defun \\internal-inspect-object (x type where)
+ (inspect-object x type where))
+
+(defun \\internal-inspect-slot-names (x)
+ (inspect-slot-names x))
+
+(defun \\internal-inspect-slot-value (x slot-name)
+ (inspect-slot-value x slot-name))
+
+(defun \\internal-inspect-setf-slot-value (x slot-name value)
+ (inspect-setf-slot-value x slot-name value))
+
+(defun \\internal-inspect-slot-name-command (slot-name x window)
+ (inspect-slot-name-command slot-name x window))
+
+(defun \\internal-inspect-title (x y)
+ (inspect-title x y))
+
+(defmethod inspect-object (x type where)
+ "Open an insect window on the object x"
+ (il:inspectw.create x '\\internal-inspect-slot-names
+ '\\internal-inspect-slot-value
+ '\\internal-inspect-setf-slot-value
+ '\\internal-inspect-slot-name-command nil nil
+ '\\internal-inspect-title nil where
+ #'(lambda (n v) ;Same effect as NIL, but avoids bug in
+ (declare (ignore v)) ; INSPECTW.CREATE
+ n)))
+
+(defmethod inspect-slot-names (x)
+ "Return a list of names of slots of the object that should be shown in the
+inspector"
+ (mapcar #'(lambda (slotd) (slot-value slotd 'name))
+ (slots-to-inspect (class-of x) x)))
+
+(defmethod inspect-slot-value (x slot-name)
+ (cond ((not (slot-exists-p x slot-name)) "** no such slot **")
+ ((not (slot-boundp x slot-name)) "** slot not bound **")
+ (t (slot-value x slot-name))))
+
+(defmethod inspect-setf-slot-value (x slot-name value)
+ "Used by the inspector to set the value fo a slot"
+ ;; Make this UNDO-able
+ (il:undosave `(inspect-setf-slot-value ,x ,slot-name
+ ,(slot-value x slot-name)))
+ ;; Then change the value
+ (setf (slot-value x slot-name) value))
+
+(defmethod inspect-slot-name-command (slot-name x window)
+ "Allows the user to select a menu item to change a slot value in an inspect
+window"
+ ;; This code is a very slightly hacked version of the system function
+ ;; DEFAULT.INSPECTW.PROPCOMMANDFN. We have to do this because the
+ ;; standard version makes some nasty assumptions about
+ ;; structure-objects that are not true for PCL objects.
+ (declare (special il:|SetPropertyMenu|))
+ (case (il:menu (cond ((typep il:|SetPropertyMenu| 'il:menu)
+ il:|SetPropertyMenu|)
+ (t (il:setq il:|SetPropertyMenu|
+ (il:|create| il:menu il:items il:_
+ '((set 'set
+ "Allows a new value to be entered"
+ )))))))
+ (set
+ ;; The user want to set the value
+ (il:ersetq (prog ((il:oldvalueitem (il:itemofpropertyvalue slot-name
+ window))
+ il:newvalue il:pwindow)
+ (il:ttydisplaystream (il:setq il:pwindow
+ (il:getpromptwindow window 3)))
+ (il:clearbuf t t)
+ (il:resetlst
+ (il:resetsave (il:\\itemw.flipitem il:oldvalueitem window)
+ (list 'il:\\itemw.flipitem
+ il:oldvalueitem window))
+ (il:resetsave (il:tty.process (il:this.process)))
+ (il:resetsave (il:printlevel 4 3))
+ (il:|printout| t "Enter the new "
+ slot-name " for " x t
+ "The expression read will be EVALuated."
+ t "> ")
+ (il:setq il:newvalue (il:lispx (il:lispxread t t)
+ '>))
+ ; clear tty buffer because it
+ ; sometimes has stuff left.
+ (il:clearbuf t t))
+ (il:closew il:pwindow)
+ (return (il:inspectw.replace window slot-name il:newvalue)))))))
+
+(defmethod inspect-title (x window)
+ "Return the title to use in an inspect window viewing x"
+ (format nil "Inspecting a ~A" (class-name (class-of x))))
+
+(defmethod inspect-title ((x standard-class) window)
+ (format nil "Inspecting the class ~A" (class-name x)))
+
+
+;;; Debugger support for PCL
+
+
+(il:filesload pcl-env-internal)
+
+;; Non-PCL specific changes to the debugger
+
+;; Redefining the standard INTERESTING-FRAME-P function. Now functions can be
+;; declared uninteresting to BT by giving them an XCL::UNINTERESTINGP
+;; property.
+
+(dolist (fn '(si::*unwind-protect* il:*env*
+ evalhook xcl::nohook xcl::undohook
+ xcl::execa0001 xcl::execa0001a0002
+ xcl::|interpret-UNDOABLY|
+ cl::|interpret-IF| cl::|interpret-FLET|
+ cl::|interpret-LET| cl::|interpret-LETA0001|
+ cl::|interpret-BLOCK| cl::|interpret-BLOCKA0001|
+ il:do-event il:eval-input
+ apply t))
+ (setf (get fn 'xcl::uninterestingp) t))
+
+(defun xcl::interesting-frame-p (xcl::pos &optional xcl::interpflg)
+ "Return TRUE iff the frame should be visible for a short backtrace."
+ (declare (special il:openfns))
+ (let ((xcl::name (if (il:stackp xcl::pos) (il:stkname xcl::pos) xcl::pos)))
+ (typecase xcl::name
+ (symbol (case xcl::name
+ (il:*env*
+ ;; *ENV* is used by ENVEVAL etc.
+ nil)
+ (il:errorset
+ (or (<= (il:stknargs xcl::pos) 1)
+ (not (eq (il:stkarg 2 xcl::pos nil)
+ 'il:internal))))
+ (il:eval
+ (or (<= (il:stknargs xcl::pos) 1)
+ (not (eq (il:stkarg 2 xcl::pos nil)
+ 'xcl::internal))))
+ (il:apply
+ (or (<= (il:stknargs xcl::pos) 2)
+ (not (il:stkarg 3 xcl::pos nil))))
+ (otherwise
+ (cond ((get xcl::name 'xcl::uninterestingp)
+ ;; Explicitly declared uninteresting.
+ nil)
+ ((eq (il:chcon1 xcl::name) (char-code #\\))
+ ;; Implicitly declared uninteresting by starting the
+ ;; name with a "\".
+ nil)
+ ((or (member xcl::name il:openfns :test #'eq)
+ (eq xcl::name 'funcall))
+ ;;The function won't be seen when compiled, so only show
+ ;;it if INTERPFLG it true
+ xcl::interpflg)
+ (t
+ ;; Interesting by default.
+ t)))))
+ (cons (case (car xcl::name)
+ (:broken t)
+ (otherwise nil)))
+ (otherwise nil))))
+
+(setq il:*short-backtrace-filter* 'xcl::interesting-frame-p)
+
+
+(eval-when (eval compile)
+ (il:record il:bkmenuitem (il:label (il:bkmenuinfo il:frame-name))))
+
+
+;; Change the frame inspector to open up lexical environments
+
+ ;; Since the DEFSTRUCT is going to build the accessors in the package that is
+ ;; current at read-time, and we want the accessors to reside in the IL
+ ;; package, we have got to make sure that the defstruct happens when the
+ ;; package is IL.
+
+(in-package "IL")
+
+(cl:defstruct (frame-prop-name (:type cl:list))
+ (label-fn 'nill)
+ (value-fn
+ (function
+ (lambda (prop-name framespec)
+ (frame-prop-name-data prop-name))))
+ (setf-fn 'nill)
+ (inspect-fn
+ (function
+ (lambda (value prop-name framespec window)
+ (default.inspectw.valuecommandfn value prop-name (car framespec) window))))
+ (data nil))
+
+(cl:in-package "PCL")
+
+(defun il:debugger-stack-frame-prop-names (il:framespec)
+ ;; Frame prop-names are structures of the form
+ ;; (LABEL-FN VALUE-FN SETF-FN EDIT-FN DATA)
+ (let ((il:pos (car il:framespec))
+ (il:backtrace-item (cadr il:framespec)))
+ (il:if (eq 'eval (il:stkname il:pos))
+ il:then
+ (let ((il:expression (il:stkarg 1 il:pos))
+ (il:environment (il:stkarg 2 il:pos)))
+ `(,(il:make-frame-prop-name :inspect-fn
+ (il:function
+ (il:lambda (il:value il:prop-name il:framespec il:window)
+ (il:inspect/as/function il:value (car il:framespec) il:window)))
+ :data il:expression)
+ ,(il:make-frame-prop-name :data "ENVIRONMENT")
+ ,@(il:for il:aspect il:in
+ `((,(and il:environment (il:environment-vars il:environment))
+ "vars")
+ (,(and il:environment (il:environment-functions il:environment))
+ "functions")
+ (,(and il:environment (il:environment-blocks il:environment))
+ "blocks")
+ (,(and il:environment (il:environment-tagbodies il:environment))
+ "tag bodies"))
+ il:bind il:group-name il:p-list
+ il:eachtime (il:setq il:group-name (cadr il:aspect))
+ (il:setq il:p-list (car il:aspect))
+ il:when (not (null il:p-list))
+ il:join
+ `(,(il:make-frame-prop-name :data il:group-name)
+ ,@(il:for il:p il:on il:p-list il:by cddr il:collect
+ (il:make-frame-prop-name :label-fn
+ (il:function (il:lambda (il:prop-name il:framespec)
+ (car (il:frame-prop-name-data il:prop-name))))
+ :value-fn
+ (il:function (il:lambda (il:prop-name il:framespec)
+ (cadr (il:frame-prop-name-data il:prop-name))))
+ :setf-fn
+ (il:function (il:lambda (il:prop-name il:framespec il:new-value)
+ (il:change (cadr (il:frame-prop-name-data
+ il:prop-name))
+ il:new-value)))
+ :data il:p))))))
+ il:else
+ (flet ((il:build-name (&key il:arg-name il:arg-number)
+ (il:make-frame-prop-name :label-fn
+ (il:function (il:lambda (il:prop-name il:framespec)
+ (car (il:frame-prop-name-data il:prop-name))))
+ :value-fn
+ (il:function (il:lambda (il:prop-name il:framespec)
+ (il:stkarg (cadr (il:frame-prop-name-data
+ il:prop-name))
+ (car il:framespec))))
+ :setf-fn
+ (il:function (il:lambda (il:prop-name il:framespec il:new-value)
+ (il:setstkarg (cadr (il:frame-prop-name-data
+ il:prop-name))
+ (car il:framespec)
+ il:new-value)))
+ :data
+ (list il:arg-name il:arg-number))))
+ (let ((il:nargs (il:stknargs il:pos t))
+ (il:nargs1 (il:stknargs il:pos))
+ (il:fnname (il:stkname il:pos))
+ il:argname
+ (il:arglist))
+ (and (il:litatom il:fnname)
+ (il:ccodep il:fnname)
+ (il:setq il:arglist (il:listp (il:smartarglist il:fnname))))
+ `(,(il:make-frame-prop-name :inspect-fn
+ (il:function (il:lambda (il:value il:prop-name il:framespec
+ il:window)
+ (il:inspect/as/function il:value
+ (car il:framespec)
+ il:window)))
+ :data
+ (il:fetch (il:bkmenuitem il:frame-name) il:of il:backtrace-item))
+ ,@(il:bind il:mode il:for il:i il:from 1 il:to il:nargs1 il:collect
+ (progn (il:while (il:fmemb (il:setq il:argname (il:pop il:arglist))
+ lambda-list-keywords)
+ il:do
+ (il:setq il:mode il:argname))
+ (il:build-name :arg-name
+ (or (il:stkargname il:i il:pos)
+ ; special
+ (if (case il:mode
+ ((nil &optional) il:argname)
+ (t nil))
+ (string il:argname)
+ (il:concat "arg " (- il:i 1))))
+ :arg-number il:i)))
+ ,@(let* ((il:novalue "No value")
+ (il:slots (il:for il:pvar il:from 0 il:as il:i il:from
+ (il:add1 il:nargs1)
+ il:to il:nargs il:by 1 il:when
+ (and (il:neq il:novalue (il:stkarg il:i il:pos
+ il:novalue))
+ (or (il:setq il:argname (il:stkargname
+ il:i il:pos))
+ (il:setq il:argname (il:concat
+ "local "
+ il:pvar)))
+ )
+ il:collect
+ (il:build-name :arg-name il:argname
+ :arg-number il:i))))
+ (and il:slots (cons (il:make-frame-prop-name :data "locals")
+ il:slots)))))))))
+
+(defun il:debugger-stack-frame-fetchfn (il:framespec il:prop-name)
+ (il:apply* (il:frame-prop-name-value-fn il:prop-name)
+ il:prop-name il:framespec))
+
+(defun il:debugger-stack-frame-storefn (il:framespec il:prop-name il:newvalue)
+ (il:apply* (il:frame-prop-name-setf-fn il:prop-name)
+ il:prop-name il:framespec il:newvalue))
+
+(defun il:debugger-stack-frame-value-command (il:datum il:prop-name
+ il:framespec il:window)
+ (il:apply* (il:frame-prop-name-inspect-fn il:prop-name)
+ il:datum il:prop-name il:framespec il:window))
+
+(defun il:debugger-stack-frame-title (il:framespec &optional il:window)
+ (declare (ignore il:window))
+ (il:concat (il:stkname (car il:framespec)) " Frame"))
+
+(defun il:debugger-stack-frame-property (il:prop-name il:framespec)
+ (il:apply* (il:frame-prop-name-label-fn il:prop-name)
+ il:prop-name il:framespec))
+
+;; Teaching the debugger that there are other file-manager types that can
+;; appear on the stack
+
+(defvar xcl::*function-types* '(il:fns il:functions)
+ "Manager types that can appear on the stack")
+
+;; Redefine a couple of system functions to use the above stuff
+
+#+Xerox-Lyric
+(progn
+
+(defun il:attach-backtrace-menu (&optional (il:ttywindow
+ (il:wfromds (il:ttydisplaystream)))
+ il:skip)
+ (let ((il:bkmenu (il:|create| il:menu
+ il:items il:_
+ (il:collect-backtrace-items il:ttywindow il:skip)
+ il:whenselectedfn il:_
+ (il:function il:backtrace-item-selected)
+ il:whenheldfn il:_
+ #'(il:lambda (il:item il:menu il:button)
+ (declare (ignore il:item il:menu))
+ (case il:button
+ (il:left (il:promptprint
+ "Open a frame inspector on this stack frame"
+ ))
+ (il:middle (il:promptprint
+ "Inspect/Edit this function"))
+ ))
+ il:menuoutlinesize il:_ 0
+ il:menufont il:_ il:backtracefont
+ il:menucolumns il:_ 1))
+ (il:ttyregion (il:windowprop il:ttywindow 'il:region))
+ il:btw)
+ (cond
+ ((il:setq il:btw (il:|for| il:atw il:|in| (il:attachedwindows il:ttywindow)
+ il:|when| (and (il:setq il:btw (il:windowprop il:atw 'il:menu))
+ (eql (il:|fetch| (il:menu il:whenselectedfn)
+ il:|of| (car il:btw))
+ (il:function il:backtrace-item-selected)))
+ il:|do|
+ (return il:atw)))
+ (il:deletemenu (car (il:windowprop il:btw 'il:menu))
+ nil il:btw)
+ (il:windowprop il:btw 'il:extent nil)
+ (il:clearw il:btw))
+ ((il:setq il:btw (il:createw (il:region-next-to (il:windowprop il:ttywindow 'il:region)
+ (il:widthifwindow (il:imin (il:|fetch| (il:menu
+ il:imagewidth
+ )
+ il:|of| il:bkmenu)
+ il:|MaxBkMenuWidth|))
+ (il:|fetch| (il:region il:height) il:|of| il:ttyregion
+ )
+ 'il:left)))
+ (il:attachwindow il:btw il:ttywindow (cond
+ ((il:igreaterp (il:|fetch| (il:region il:left)
+ il:|of| (il:windowprop
+ il:btw
+ 'il:region))
+ (il:|fetch| (il:region il:left)
+ il:|of| il:ttyregion))
+ 'il:right)
+ (t 'il:left))
+ nil
+ 'il:localclose)
+ (il:windowprop il:btw 'il:process (il:windowprop il:ttywindow 'il:process))
+
+ ))
+ (il:addmenu il:bkmenu il:btw (il:|create| il:_ il:position
+ il:xcoord il:_ 0
+ il:ycoord il:_ (il:idifference (il:windowprop
+ il:btw
+ 'il:height)
+ (il:|fetch| (il:menu il:imageheight
+ ) il:|of|
+ il:bkmenu
+ ))))))
+
+(defun il:backtrace-item-selected (il:item il:menu il:button)
+ (il:resetlst
+ (prog (il:olditem il:ttywindow il:bkpos il:pos il:positions il:framewindow
+ (il:framespecn (il:|fetch| (il:bkmenuitem il:bkmenuinfo) il:|of| il:item)
+
+ ))
+ (cond
+ ((il:setq il:olditem (il:|fetch| (il:menu il:menuuserdata) il:|of| il:menu))
+ (il:menudeselect il:olditem il:menu)
+ ))
+ (il:setq il:ttywindow (il:windowprop (il:wfrommenu il:menu)
+ 'il:mainwindow))
+ (il:setq il:bkpos (il:windowprop il:ttywindow 'il:stack-position))
+ (il:setq il:pos (il:stknth (- il:framespecn)
+ il:bkpos))
+ (let ((il:lp (il:windowprop il:ttywindow 'il:lastpos)))
+ (and il:lp (il:stknth 0 il:pos il:lp)))
+ (il:menuselect il:item il:menu)
+ (if (eq il:button 'il:middle)
+ (progn
+
+
+ (il:resetsave nil (list 'il:relstk il:pos))
+ (il:inspect/as/function (il:|fetch| (il:bkmenuitem il:frame-name)
+ il:|of| il:item)
+ il:pos il:ttywindow))
+ (progn
+
+
+ (il:setq il:framewindow
+ (xcl:with-profile (il:process.eval
+ (il:windowprop il:ttywindow 'il:process)
+ '(let ((il:profile (xcl:copy-profile (xcl:find-profile
+ "READ-PRINT"))))
+ (setf (xcl::profile-entry-value '
+ xcl:*eval-function* il:profile)
+ xcl:*eval-function*)
+ (xcl:save-profile il:profile))
+ t)
+ (il:inspectw.create (list il:pos il:item)
+ 'il:debugger-stack-frame-prop-names
+ 'il:debugger-stack-frame-fetchfn
+ 'il:debugger-stack-frame-storefn nil '
+ il:debugger-stack-frame-value-command nil '
+ il:debugger-stack-frame-title nil (
+ il:make-frame-inspect-window
+ il:ttywindow)
+ 'il:debugger-stack-frame-property)))
+ (cond
+ ((not (il:windowprop il:framewindow 'il:mainwindow))
+ (il:attachwindow il:framewindow il:ttywindow
+ (cond
+ ((il:igreaterp (il:|fetch| (il:region il:bottom)
+ il:|of| (il:windowprop il:framewindow
+ 'il:region))
+ (il:|fetch| (il:region il:bottom)
+ il:|of| (il:windowprop il:ttywindow 'il:region)))
+ 'il:top)
+ (t 'il:bottom))
+ nil
+ 'il:localclose)
+ (il:windowaddprop il:framewindow 'il:closefn (il:function il:detachwindow
+ ))))))
+ (return))))
+
+(defun il:collect-backtrace-items (xcl::tty-window xcl::skip)
+ (let* ((xcl::items (cons nil nil))
+ (xcl::items-tail xcl::items))
+ (macrolet ((xcl::collect-item (xcl::new-item)
+ `(progn (setf (rest xcl::items-tail)
+ (cons ,xcl::new-item nil))
+ (pop xcl::items-tail))))
+ (let* ((xcl::filter-fn (cond
+ ((null xcl::skip)
+ #'xcl:true)
+ ((eq xcl::skip t)
+ il:*short-backtrace-filter*)
+ (t xcl::skip)))
+ (xcl::top-frame (il:stknth 0 (il:getwindowprop xcl::tty-window '
+ il:stack-position)))
+ (xcl::next-frame xcl::top-frame)
+ (xcl::frame-number 0)
+ xcl::interesting-p xcl::last-frame-consumed xcl::use-frame xcl::label)
+ (loop (when (null xcl::next-frame)
+ (return))
+ (multiple-value-setq (xcl::interesting-p xcl::last-frame-consumed
+ xcl::use-frame xcl::label)
+ (funcall xcl::filter-fn xcl::next-frame))
+ (when (null xcl::last-frame-consumed)
+
+ (setf xcl::last-frame-consumed xcl::next-frame))
+ (when xcl::interesting-p
+ (when (null xcl::use-frame)
+ (setf xcl::use-frame xcl::last-frame-consumed))
+
+ (when (null xcl::label)
+ (setf xcl::label (il:stkname xcl::use-frame))
+ (if (member xcl::label '(eval il:eval il:apply apply)
+ :test
+ 'eq)
+ (setf xcl::label (il:stkarg 1 xcl::use-frame))))
+
+ (loop (cond
+ ((not (typep xcl::next-frame 'il:stackp))
+ (error "~%Use-frame ~S not found" xcl::use-frame))
+ ((xcl::stack-eql xcl::next-frame xcl::use-frame)
+ (return))
+ (t (incf xcl::frame-number)
+ (setf xcl::next-frame (il:stknth -1 xcl::next-frame
+ xcl::next-frame)))))
+
+ (xcl::collect-item (il:|create| il:bkmenuitem
+ il:label il:_ (let ((*print-level* 2)
+ (*print-length* 3)
+ (*print-escape* t)
+ (*print-gensym* t)
+ (*print-pretty* nil)
+ (*print-circle* nil)
+ (*print-radix* 10)
+ (*print-array* nil)
+ (il:*print-structure*
+ nil))
+ (prin1-to-string
+ xcl::label))
+ il:bkmenuinfo il:_ xcl::frame-number
+ il:frame-name il:_ xcl::label)))
+
+ (loop (cond
+ ((not (typep xcl::next-frame 'il:stackp))
+ (error "~%Last-frame-consumed ~S not found"
+ xcl::last-frame-consumed))
+ ((prog1 (xcl::stack-eql xcl::next-frame xcl::last-frame-consumed
+ )
+ (incf xcl::frame-number)
+ (setf xcl::next-frame (il:stknth -1 xcl::next-frame
+
+ xcl::next-frame)))
+ (return)))))))
+ (rest xcl::items)))
+
+)
+#+Xerox-Medley
+(progn
+
+(defun dbg::attach-backtrace-menu (&optional tty-window skip)
+ (declare (special il:\\term.ofd il:backtracefont))
+ (or tty-window (il:setq tty-window (il:wfromds (il:ttydisplaystream))))
+ (prog (btw bkmenu
+ (tty-region (il:windowprop tty-window 'il:region))
+ ;; And, for the FORMAT below...
+ (*print-level* 2)
+ (*print-length* 3)
+ (*print-escape* t)
+ (*print-gensym* t)
+ (*print-pretty* nil)
+ (*print-circle* nil)
+ (*print-radix* 10)
+ (*print-array* nil)
+ (il:*print-structure* nil))
+ (setq bkmenu
+ (il:|create| il:menu
+ il:items il:_ (dbg::collect-backtrace-items tty-window skip)
+ il:whenselectedfn il:_ 'dbg::backtrace-item-selected
+ il:menuoutlinesize il:_ 0
+ il:menufont il:_ il:backtracefont
+ il:menucolumns il:_ 1
+ il:whenheldfn il:_
+ #'(il:lambda (item menu button)
+ (declare (ignore item menu))
+ (case button
+ (il:left
+ (il:promptprint
+ "Open a frame inspector on this stack frame"))
+ (il:middle
+ (il:promptprint "Inspect/Edit this function"))))))
+ (cond ((setq btw
+ (dolist (atw (il:attachedwindows tty-window))
+ ;; Test for an attached window that has a backtrace menu in
+ ;; it.
+ (when (and (setq btw (il:windowprop atw 'il:menu))
+ (eq (il:|fetch| (il:menu il:whenselectedfn)
+ il:|of| (car btw))
+ 'dbg::backtrace-item-selected))
+ (return atw))))
+ ;; If there is alread a backtrace window, delete the old menu from
+ ;; it.
+ (il:deletemenu (car (il:windowprop btw 'il:menu)) nil btw)
+ (il:windowprop btw 'il:extent nil)
+ (il:clearw btw))
+ ((setq btw
+ (il:createw (dbg::region-next-to
+ (il:windowprop tty-window 'il:region)
+ (il:widthifwindow
+ (il:imin (il:|fetch| (il:menu il:imagewidth)
+ il:|of| bkmenu)
+ il:|MaxBkMenuWidth|))
+ (il:|fetch| (il:region il:height)
+ il:|of| tty-region)
+ :left)))
+ ; put bt window at left of TTY
+ ; window unless ttywindow is
+ ; near left edge.
+ (il:attachwindow btw tty-window
+ (if (il:igreaterp (il:|fetch| (il:region il:left)
+ il:|of|
+ (il:windowprop btw
+ 'il:region))
+ (il:|fetch| (il:region il:left)
+ il:|of| tty-region))
+ 'il:right
+ 'il:left)
+ nil
+ 'il:localclose)
+ ;; So that button clicks will switch the TTY
+ (il:windowprop btw 'il:process
+ (il:windowprop tty-window 'il:process))))
+ (il:addmenu bkmenu btw (il:|create| il:position
+ il:xcoord il:_ 0
+ il:ycoord il:_ (- (il:windowprop btw 'il:height)
+ (il:|fetch| (il:menu
+ il:imageheight)
+ il:|of| bkmenu))))
+ ;; IL:ADDMENU sets up buttoneventfn for window that we don't
+ ;; want. We want to catch middle button events before the menu
+ ;; handler, so that we can pop up edit/inspect menu for the frame
+ ;; currently selected. So replace the buttoneventfn, and can
+ ;; nuke the cursorin and cursormoved guys, cause don't need them.
+ (il:windowprop btw 'il:buttoneventfn 'dbg::backtrace-menu-buttoneventfn)
+ (il:windowprop btw 'il:cursorinfn nil)
+ (il:windowprop btw 'il:cursormovedfn nil)))
+
+(defun dbg::collect-backtrace-items (tty-window skip)
+ (xcl:with-collection
+ ;;
+ ;; There are a number of possibilities for the values returned by the
+ ;; filter-fn.
+ ;;
+ ;; (1) INTERESTING-P is false, and the other values are all NIL. This
+ ;; is the simple case where the stack frame NEXT-POS should be ignored
+ ;; completly, and processing should continue with the next frame.
+ ;;
+ ;; (2) INTERESTING-P is true, and the other values are all NIL. This
+ ;; is the simple case where the stack frame NEXT-POS should appear in
+ ;; the backtrace as is, and processing should continue with the next
+ ;; frame.
+ ;;
+ ;; [Note that these two cases take care of old values of the
+ ;; filter-fn.]
+ ;;
+ ;; (3) INTERESTING-P is false, and LAST-FRAME-CONSUMED is a stack
+ ;; frame. In that case, ignore all stack frames from NEXT-POS to
+ ;; LAST-FRAME-CONSUMED, inclusive.
+ ;;
+ ;; (4) INTERESTING-P is true, and LAST-FRAME-CONSUMED is a stack
+ ;; frame. In this case, the backtrace should include a single entry
+ ;; coresponding to the frame USE-FRAME (which defaults to
+ ;; LAST-FRAME-CONSUMED), and processing should continue with the next
+ ;; frame after LAST-FRAME-CONSUMED. If LABEL is non-NIL, it will be
+ ;; the label that appears in the backtrace menu; otherwise the name of
+ ;; USE-FRAME will be used (or the form being EVALed if the frame is an
+ ;; EVAL frame).
+ ;;
+ (let* ((filter (cond ((null skip) #'xcl:true)
+ ((eq skip t) il:*short-backtrace-filter*)
+ (t skip)))
+ (top-frame (il:stknth 0 (il:getwindowprop tty-window
+ 'dbg::stack-position)))
+ (next-frame top-frame)
+ (frame-number 0)
+ interestingp last-frame-consumed frame-to-use label-to-use)
+ (loop (when (null next-frame) (return))
+ ;; Get the values of INTERSTINGP, LAST-FRAME-CONSUMED,
+ ;; FRAME-TO-USE, and LABEL-TO-USE
+ (multiple-value-setq (interestingp last-frame-consumed
+ frame-to-use label-to-use)
+ (funcall filter next-frame))
+ (when (null last-frame-consumed)
+ (setf last-frame-consumed next-frame))
+ (when interestingp
+ (when (null frame-to-use)
+ (setf frame-to-use last-frame-consumed))
+ (when (null label-to-use)
+ (setf label-to-use (il:stkname frame-to-use))
+ (if (member label-to-use '(eval il:eval il:apply apply)
+ :test 'eq)
+ (setf label-to-use (il:stkarg 1 frame-to-use))))
+
+ ;; Walk the stack until we find the frame to use
+ (loop (cond ((not (typep next-frame 'il:stackp))
+ (error "~%Use-frame ~S not found" frame-to-use))
+ ((xcl::stack-eql next-frame frame-to-use)
+ (return))
+ (t (incf frame-number)
+ (setf next-frame
+ (il:stknth -1 next-frame next-frame)))))
+
+ ;; Add the menu item to the list under construction
+ (xcl:collect (il:|create| il:bkmenuitem
+ il:label il:_ (let ((*print-level* 2)
+ (*print-length* 3)
+ (*print-escape* t)
+ (*print-gensym* t)
+ (*print-pretty* nil)
+ (*print-circle* nil)
+ (*print-radix* 10)
+ (*print-array* nil)
+ (il:*print-structure* nil))
+ (prin1-to-string label-to-use))
+ il:bkmenuinfo il:_ frame-number
+ il:frame-name il:_ label-to-use)))
+
+ ;; Update NEXT-POS
+ (loop (cond ((not (typep next-frame 'il:stackp))
+ (error "~%Last-frame-consumed ~S not found"
+ last-frame-consumed))
+ ((prog1
+ (xcl::stack-eql next-frame last-frame-consumed)
+ (incf frame-number)
+ (setf next-frame (il:stknth -1 next-frame
+ next-frame)))
+ (return))))))))
+
+(defun dbg::backtrace-menu-buttoneventfn (window &aux menu)
+ (setq menu (car (il:listp (il:windowprop window 'il:menu))))
+ (unless (or (il:lastmousestate il:up) (null menu))
+ (il:totopw window)
+ (cond ((il:lastmousestate il:middle)
+ ;; look for a selected frame in this menu, and then pop up
+ ;; the editor invoke menu for that frame. don't change the
+ ;; selection, just present the edit menu.
+ (let* ((selection (il:menu.handler menu
+ (il:windowprop window 'il:dsp)))
+ (tty-window (il:windowprop window 'il:mainwindow))
+ (last-pos (il:windowprop tty-window 'dbg::lastpos)))
+
+ ;; don't have to worry about releasing POS because we
+ ;; only look at it here (nobody here hangs on to it)
+ ;; and we will be around for less time than LASTPOS.
+ ;; The debugger is responsible for releasing LASTPOS.
+ (il:inspect/as/function (cond
+ ((and selection
+ (il:|fetch| (il:bkmenuitem il:frame-name)
+ il:|of| (car selection))))
+ ((and (symbolp (il:stkname last-pos))
+ (il:getd (il:stkname last-pos)))
+ (il:stkname last-pos))
+ (t 'il:nill))
+ last-pos tty-window)))
+ (t (let ((selection (il:menu.handler menu
+ (il:windowprop window 'il:dsp))))
+ (when selection
+ (il:doselecteditem menu (car selection) (cdr selection))))))))
+
+;; This function isn't really redefined, but it needs to be recomiled since we
+;; changed the def'n of the BKMENUITEM record.
+
+(defun dbg::backtrace-item-selected (item menu button)
+ ;;When a frame name is selected in the backtrace menu, this is the function
+ ;;that gets called.
+ (declare (special il:brkenv) (ignore button))
+ (let* ((frame-spec (il:|fetch| (il:bkmenuitem il:bkmenuinfo) il:|of| item))
+ (tty-window (il:windowprop (il:wfrommenu menu) 'il:mainwindow))
+ (bkpos (il:windowprop tty-window 'dbg::stack-position))
+ (pos (il:stknth (- frame-spec) bkpos)))
+ (let ((lp (il:windowprop tty-window 'dbg::lastpos)))
+ (and lp (il:stknth 0 pos lp)))
+ ;; change the item selected from OLDITEM to ITEM. Only do this on left
+ ;; buttons now. Middle just pops up the edit menu, doesn't select. -woz
+ (let ((old-item (il:|fetch| (il:menu il:menuuserdata) il:|of| menu)))
+ (when old-item (il:menudeselect old-item menu))
+ (il:menuselect item menu))
+ ;; Change the lexical environment so it is the one in effect as of this
+ ;; frame.
+ (il:process.eval (il:windowprop tty-window (quote dbg::process))
+ `(setq il:brkenv ',(il:find-lexical-environment pos))
+ t)
+ (let ((frame-window (xcl:with-profile
+ (il:process.eval (il:windowprop tty-window
+ 'il:process)
+ `(let ((profile (xcl:copy-profile
+ (xcl:find-profile
+ "READ-PRINT"))))
+ (setf
+ (xcl::profile-entry-value
+ 'xcl:*eval-function* profile)
+ xcl:*eval-function*)
+ (xcl:save-profile profile))
+ t)
+ (il:inspectw.create pos
+ #'(lambda (pos)
+ (dbg::stack-frame-properties pos t))
+ 'dbg::stack-frame-fetchfn
+ 'dbg::stack-frame-storefn
+ nil
+ 'dbg::stack-frame-value-command
+ nil
+ (format nil "~S Frame" (il:stkname pos))
+ nil (dbg::make-frame-inspect-window
+ tty-window)
+ 'dbg::stack-frame-property))))
+ (when (not (il:windowprop frame-window 'il:mainwindow))
+ (il:attachwindow frame-window tty-window
+ (if (> (il:|fetch| (il:region il:bottom) il:|of|
+ (il:windowprop frame-window 'il:region))
+ (il:|fetch| (il:region il:bottom) il:|of|
+ (il:windowprop tty-window 'il:region)))
+ 'il:top 'il:bottom)
+ nil 'il:localclose)
+ (il:windowaddprop frame-window 'il:closefn 'il:detachwindow)))))
+
+) ;end of Xerox-Medley
+
+(defun il:select.fns.editor (&optional function)
+ ;; gives the user a menu choice of editors.
+ (il:menu (il:|create| il:menu
+ il:items il:_ (cond ((il:ccodep function)
+ '((il:|InspectCode| 'il:inspectcode
+ "Shows the compiled code.")
+ (il:|DisplayEdit| 'ed
+ "Edit it with the display editor")
+ (il:|TtyEdit| 'il:ef
+ "Edit it with the standard editor")))
+ ((il:closure-p function)
+ '((il:|Inspect| 'inspect
+ "Inspect this object")))
+ (t '((il:|DisplayEdit| 'ed
+ "Edit it with the display editor")
+ (il:|TtyEdit| 'il:ef
+ "Edit it with the standard editor"))))
+ il:centerflg il:_ t)))
+
+;;
+
+
+;; PCL specific extensions to the debugger
+
+
+;; There are some new things that act as functions, and that we want to be
+;; able to edit from a backtrace window
+
+(pushnew 'methods xcl::*function-types*)
+
+(eval-when (eval compile load)
+ (unless (generic-function-p (symbol-function 'il:inspect/as/function))
+ (make-specializable 'il:inspect/as/function)))
+
+(defmethod il:inspect/as/function (name stack-pointer debugger-window)
+ ;; Calls an editor on function NAME. STKP and WINDOW are the stack pointer
+ ;; and window of the break in which this inspect command was called.
+ (declare (ignore debugger-window))
+ (let ((editor (il:select.fns.editor name)))
+ (case editor
+ ((nil)
+ ;; No editor chosen, so don't do anything
+ nil)
+ (il:inspectcode
+ ;; Inspect the compiled code
+ (let ((frame (xcl::stack-pointer-frame stack-pointer)))
+ (if (and (il:stackp stack-pointer)
+ (xcl::stack-frame-valid-p frame))
+ (il:inspectcode (let ((code-base (xcl::stack-frame-fn-header frame)))
+ (cond ((eq (il:\\get-compiled-code-base name)
+ code-base)
+ name)
+ (t
+ ;; Function executing in this frame is not
+ ;; the one in the definition cell of its
+ ;; name, so fetch the real code. Have to
+ ;; pass a CCODEP
+ (il:make-compiled-closure code-base))))
+ nil nil nil (xcl::stack-frame-pc frame))
+ (il:inspectcode name))))
+ (ed
+ ;; Use the standard editor.
+ ;; This used to take care to apply the editor in the debugger
+ ;; process, so forms evaluated in the editor happen in the
+ ;; context of the break. But that doesn't count for much any
+ ;; more, now that lexical variables are the way to go. Better to
+ ;; use the LEX debugger command (thank you, Herbie) and
+ ;; shift-select pieces of code from the editor into the debugger
+ ;; window.
+ (ed name `(,@xcl::*function-types* :display)))
+ (otherwise (funcall editor name)))))
+
+(defmethod il:inspect/as/function ((name standard-object) stkp window)
+ (when (il:menu (il:|create| il:menu
+ il:items il:_ '(("Inspect" t "Inspect this object"))))
+ (inspect name)))
+
+(defmethod il:inspect/as/function ((x standard-method) stkp window)
+ (let* ((generic-function-name (slot-value (slot-value x 'generic-function)
+ 'name))
+ (method-name (full-method-name x))
+ (editor (il:select.fns.editor method-name)))
+ (il:allow.button.events)
+ (case editor
+ (ed (ed method-name '(:display methods)))
+ (il:inspectcode (il:inspectcode (slot-value x 'function)))
+ ((nil) nil)
+ (otherwise (funcall editor method-name)))))
+
+;; A replacement for the vanilla IL:INTERESTING-FRAME-P so we can see methods
+;; and generic-functions on the stack.
+
+(defun interesting-frame-p (stack-pos &optional interp-flag)
+ ;; Return up to four values: INTERESTING-P LAST-FRAME-CONSUMED USE-FRAME and
+ ;; LABEL. See the function IL:COLLECT-BACKTRACE-ITEMS for a full description
+ ;; of how these values are used.
+ (labels
+ ((function-matches-frame-p (function frame)
+ "Is the function being called in this frame?"
+ (let* ((frame-name (il:stkname frame))
+ (code-being-run (cond
+ ((typep frame-name 'il:closure)
+ frame-name)
+ ((and (consp frame-name)
+ (eq 'il:\\interpreter
+ (xcl::stack-frame-name
+ (il:\\stackargptr frame))))
+ frame-name)
+ (t (xcl::stack-frame-fn-header
+ (il:\\stackargptr frame))))))
+ (or (eq function code-being-run)
+ (and (typep function 'il:compiled-closure)
+ (eq (xcl::compiled-closure-fnheader function)
+ code-being-run)))))
+ (generic-function-from-frame (frame)
+ "If this the frame of a generic function return the gf, otherwise
+ return NIL."
+ ;; Generic functions are implemented as compiled closures. On the
+ ;; stack, we only see the fnheader for the the closure. This could
+ ;; be a discriminator code, or in the default method only case it
+ ;; will be the actual method function. To tell if this is a generic
+ ;; function frame, we have to check very carefully to see if the
+ ;; right stuff is on the stack. Specifically, the closure's ccode,
+ ;; and the first local variable has to be a ptrhunk big enough to be
+ ;; a FIN environment, and fin-env-fin of that ptrhunk has to point
+ ;; to a generic function whose ccode and environment match.
+ (let ((n-args (il:stknargs frame))
+ (env nil)
+ (gf nil))
+ (if (and ;; is there at least one local?
+ (> (il:stknargs frame t) n-args)
+ ;; and does the local contain something that might be
+ ;; the closure environment of a funcallable instance?
+ (setf env (il:stkarg (1+ n-args) frame))
+ ;; and does the local contain something that might be
+ ;; the closure environment of a funcallable instance?
+ (typep env *fin-env-type*)
+ (setf gf (fin-env-fin env))
+ ;; whose fin-env-fin points to a generic function?
+ (generic-function-p gf)
+ ;; whose environment is the same as env?
+ (eq (xcl::compiled-closure-env gf) env)
+ ;; and whose code is the same as the code for this
+ ;; frame?
+ (function-matches-frame-p gf frame))
+ gf
+ nil))))
+ (let ((frame-name (il:stkname stack-pos)))
+ ;; See if there is a generic-function on the stack at this
+ ;; location.
+ (let ((gf (generic-function-from-frame stack-pos)))
+ (when gf
+ (return-from interesting-frame-p (values t stack-pos stack-pos gf))))
+ ;; See if this is an interpreted method. The method body is
+ ;; wrapped in a (BLOCK <function-name> ...). We look for an
+ ;; interpreted call to BLOCK whose block-name is the name of
+ ;; generic-function.
+ (when (and (eq frame-name 'eval)
+ (consp (il:stkarg 1 stack-pos))
+ (eq (first (il:stkarg 1 stack-pos)) 'block)
+ (symbolp (second (il:stkarg 1 stack-pos)))
+ (fboundp (second (il:stkarg 1 stack-pos)))
+ (generic-function-p
+ (symbol-function (second (il:stkarg 1 stack-pos)))))
+ (let* ((form (il:stkarg 1 stack-pos))
+ (block-name (second form))
+ (generic-function (symbol-function block-name))
+ (methods (generic-function-methods (symbol-function block-name))))
+ ;; If this is really a method being called from a
+ ;; generic-function, the g-f should be no more than a
+ ;; few(?) frames up the stack. Check for the method call
+ ;; by looking for a call to APPLY, where the function
+ ;; being applied is the code in one of the methods.
+ (do ((i 100 (1- i))
+ (previous-pos stack-pos current-pos)
+ (current-pos (il:stknth -1 stack-pos) (il:stknth -1 current-pos))
+ (found-method nil)
+ (method-pos))
+ ((or (null current-pos) (<= i 0)) nil)
+ (cond ((equalp generic-function
+ (generic-function-from-frame current-pos))
+ (if found-method
+ (return-from interesting-frame-p
+ (values t previous-pos method-pos found-method))
+ (return)))
+ (found-method nil)
+ ((eq (il:stkname current-pos) 'apply)
+ (dolist (method methods)
+ (when (eq (method-function method)
+ (il:stkarg 1 current-pos))
+ (setq method-pos current-pos)
+ (setq found-method method)
+ (return))))))))
+ ;; Try to handle compiled methods
+ (when (and (symbolp frame-name)
+ (not (fboundp frame-name))
+ (eq (il:chcon1 frame-name)
+ (il:charcode il:\())
+ (or (string-equal "(method " (symbol-name frame-name)
+ :start2 0 :end2 13)
+ (string-equal "(method " (symbol-name frame-name)
+ :start2 0 :end2 12)
+ (string-equal "(method " (symbol-name frame-name)
+ :start2 0 :end2 8)))
+ ;; Looks like a name that PCL consed up. See if there is a
+ ;; GF nearby up the stack. If there is, use it to help
+ ;; determine which method we have.
+ (do ((i 30 (1- i))
+ (current-pos (il:stknth -1 stack-pos)
+ (il:stknth -1 current-pos))
+ (gf))
+ ((or (null current-pos)
+ (<= i 0))
+ nil)
+ (setq gf (generic-function-from-frame current-pos))
+ (when gf
+ (dolist (method (generic-function-methods gf))
+ (when (function-matches-frame-p (method-function method)
+ stack-pos)
+ (return-from interesting-frame-p
+ (values t stack-pos stack-pos method))))
+ (return))))
+ ;; If we haven't already returned, use the default method.
+ (xcl::interesting-frame-p stack-pos interp-flag))))
+
+
+(setq il:*short-backtrace-filter* 'interesting-frame-p)
+
+;;; Support for undo
+
+ (defun undoable-setf-slot-value (object slot-name new-value)
+ (if (slot-boundp object slot-name)
+ (il:undosave (list 'undoable-setf-slot-value
+ object slot-name (slot-value object slot-name)))
+ (il:undosave (list 'slot-makunbound object slot-name)))
+ (setf (slot-value object slot-name) new-value))
+
+ (setf (get 'slot-value :undoable-setf-inverse) 'undoable-setf-slot-value)
+
+
+;;; Support for ?= and friends
+
+;; The arglists for generic-functions are built using gensyms, and don't reflect
+;; any keywords (they are all included in an &REST arg). Rather then use the
+;; arglist in the code, we use the one that PCL kindly keeps in the generic-function.
+
+(xcl:advise-function 'il:smartarglist
+ '(if (and il:explainflg
+ (symbolp il:fn)
+ (fboundp il:fn)
+ (generic-function-p (symbol-function il:fn)))
+ (generic-function-pretty-arglist (symbol-function il:fn))
+ (xcl:inner))
+ :when :around :priority :last)
+
+(setf (get 'defclass 'il:argnames)
+ '(nil (class-name (#\{ superclass-name #\} #\*)
+ (#\{ slot-specifier #\} #\*)
+ #\{ slot-option #\} #\*)))
+
+(setf (get 'defmethod 'il:argnames)
+ '(nil (#\{ name #\| (setf name) #\} #\{ method-qualifier #\} #\*
+ specialized-lambda-list #\{ declaration #\| doc-string #\} #\*
+ #\{ form #\} #\*)))
+
+;;; Prettyprinting support, the result of Harley Davis.
+
+;; Support the standard Prettyprinter. This is really minimal right now. If
+;; anybody wants to fix this, I'd be happy to include their code. In fact,
+;; there is almost no support for Commonlisp in the standard Prettyprinter, so
+;; the field is wide open to hackers with time on their hands.
+
+
+(setf (get 'defmethod :definition-print-template) ;Not quite right, since it
+ '(:name :arglist :body)) ; doesn't handle qualifiers,
+ ; but it will have to do.
+
+(defun defclass-prettyprint (form)
+ (let ((left (il:dspxposition))
+ (char-width (il:charwidth (il:charcode x) *standard-output*)))
+ (xcl:destructuring-bind (defclass name supers slots . options) form
+ (princ "(")
+ (prin1 defclass)
+ (princ " ")
+ (prin1 name)
+ (princ " ")
+ (if (null supers)
+ (princ "()") ;Print "()" instead of "nil"
+ (il:sequential.prettyprint (list supers) (il:dspxposition)))
+ (if (null slots)
+ (progn (il:prinendline (+ left (* 4 char-width)) *standard-output*)
+ (princ "()"))
+ (il:sequential.prettyprint (list slots) (+ left (* 4 char-width))))
+ (when options
+ (il:sequential.prettyprint options (+ left (* 2 char-width))))
+ (princ ")")
+ nil)))
+
+(let ((pprint-macro (assoc 'defclass il:prettyprintmacros)))
+ (if (null pprint-macro)
+ (push (cons 'defclass 'defclass-prettyprint)
+ il:prettyprintmacros)
+ (setf (cdr pprint-macro) 'defclass-prettyprint)))
+
+(defun binder-prettyprint (form)
+ ;; Prettyprints expressions like MULTIPLE-VALUE-BIND and WITH-SLOTS
+ ;; that are of the form (fn (var ...) form &rest body).
+ ;; This code is far from correct, but it's better than nothing.
+ (if (and (consp form)
+ (not (null (cdddr form))))
+ ;; I have no idea what I'm doing here. Seems I can copy and edit somebody
+ ;; elses code without understanding it.
+ (let ((body-indent (+ (il:dspxposition)
+ (* 2 (il:charwidth (il:charcode x)
+ *standard-output*))))
+ (form-indent (+ (il:dspxposition)
+ (* 4 (il:charwidth (il:charcode x)
+ *standard-output*)))))
+ (princ "(")
+ (prin1 (first form))
+ (princ " ")
+ (il:superprint (second form) form nil *standard-output*)
+ (il:sequential.prettyprint (list (third form)) form-indent)
+ (il:sequential.prettyprint (cdddr form) body-indent)
+ (princ ")")
+ nil) ;Return NIL to indicate that we did
+ ; the printing
+ t)) ;Return true to use default printing
+
+
+(dolist (fn '(multiple-value-bind with-accessors with-slots))
+ (let ((pprint-macro (assoc fn 'il:prettyprintmacros)))
+ (if (null pprint-macro)
+ (push (cons fn 'binder-prettyprint)
+ il:prettyprintmacros)
+ (setf (cdr pprint-macro) 'binder-prettyprint))))
+
+
+
+;; SEdit has its own prettyprinter, so we need to support that too. This is due
+;; to Harley Davis. Really.
+
+(push (cons :slot-spec
+ '(((sedit::prev-keyword? (sedit::next-inline? 1 break sedit::from-indent . 1)
+ break sedit::from-indent . 0)
+ (sedit::set-indent . 1)
+ (sedit::next-inline? 1 break sedit::from-indent . 1)
+ (sedit::prev-keyword? (sedit::next-inline? 1 break sedit::from-indent . 1)
+ break sedit::from-indent . 0))
+ ((sedit::prev-keyword? (sedit::next-inline? 1 break sedit::from-indent . 1)
+ break sedit::from-indent . 0)
+ (sedit::set-indent . 1)
+ (sedit::next-inline? 1 break sedit::from-indent . 1)
+ (sedit::prev-keyword? (sedit::next-inline? 1 break sedit::from-indent . 1)
+ break sedit::from-indent . 0))))
+ sedit:*indent-alist*)
+
+(setf (sedit:get-format :slot-spec)
+ '(:indent :slot-spec :inline t))
+
+(setf (sedit:get-format :slot-spec-list)
+ '(:indent :binding-list :args (:slot-spec) :inline nil))
+
+(setf (sedit:get-format 'defclass)
+ '(:indent ((2) 1)
+ :args (:keyword nil nil :slot-spec-list nil)
+ :sublists (4)))
+
+(setf (sedit:get-format 'defmethod)
+ '(:indent ((2))
+ :args (:keyword nil :lambda-list nil)
+ :sublists (3)))
+
+(setf (sedit:get-format 'defgeneric) 'defun)
+
+(setf (sedit:get-format 'generic-flet) 'flet)
+
+(setf (sedit:get-format 'generic-labels) 'flet)
+
+(setf (sedit:get-format 'call-next-method)
+ '(:indent (1) :args (:keyword nil)))
+
+(setf (sedit:get-format 'symbol-macrolet) 'let)
+
+(setf (sedit:get-format 'with-accessors)
+ '(:indent ((1) 1)
+ :args (:keyword :binding-list nil)
+ :sublists (2)
+ :miser :never))
+
+(setf (sedit:get-format 'with-slots) 'with-accessors)
+
+(setf (sedit:get-format 'make-instance)
+ '(:indent ((1))
+ :args (:keyword nil :slot-spec-list)))
+
+(setf (sedit:get-format '*make-instance) 'make-instance)
+
+;;; PrettyFileIndex stuff, the product of Harley Davis.
+
+(defvar *pfi-class-type* '(class defclass pfi-class-namer))
+
+(defvar *pfi-method-type* '(method defmethod pfi-method-namer)
+ "Handles method for prettyfileindex")
+
+(defvar *pfi-index-accessors* nil
+ "t -> each slot accessor gets a listing in the index.")
+
+(defvar *pfi-method-index* :group
+ ":group, :separate, :both, or nil")
+
+(defun pfi-add-class-type ()
+ (pushnew *pfi-class-type* il:*pfi-types*))
+
+(defun pfi-add-method-type ()
+ (pushnew *pfi-method-type* il:*pfi-types*))
+
+(defun pfi-class-namer (expression entry)
+ (let ((class-name (second expression)))
+ ;; Following adds all slot readers/writers/accessors as separate entries in
+ ;; the index. Probably a mistake.
+ (if *pfi-index-accessors*
+ (let ((slot-list (fourth expression))
+ (accessor-names nil))
+ (labels ((add-accessor (method-index name-index)
+ (push (case *pfi-method-index*
+ (:group method-index)
+ (:separate name-index)
+ ((t :both) (list method-index name-index))
+ ((nil) nil)
+ (otherwise (error "Illegal value for *pfi-method-index*: ~S"
+ *pfi-method-index*)))
+ accessor-names))
+ (add-reader (reader-name)
+ (add-accessor `(method (,reader-name (,class-name)))
+ `(,reader-name (,class-name))))
+ (add-writer (writer-name)
+ (add-accessor `(method ((setf ,writer-name) (t ,class-name)))
+ `((setf ,writer-name) (t ,class-name)))))
+ (dolist (slot-def slot-list)
+ (do* ((rest-slot-args (cdr slot-def) (cddr rest-slot-args))
+ (slot-arg (first rest-slot-args) (first rest-slot-args)))
+ ((null rest-slot-args))
+ (case slot-arg
+ (:reader (add-reader (second rest-slot-args)))
+ (:writer (add-writer (second rest-slot-args)))
+ (:accessor (add-reader (second rest-slot-args))
+ (add-writer (second rest-slot-args)))
+ (otherwise nil))))
+ (cons `(class (,class-name)) accessor-names)))
+ class-name)))
+
+(defun pfi-method-namer (expression entry)
+ (let ((method-name (second expression))
+ (specializers nil)
+ (qualifiers nil)
+ lambda-list)
+ (do* ((rest-qualifiers (cddr expression) (cdr rest-qualifiers))
+ (qualifier (first rest-qualifiers) (first rest-qualifiers)))
+ ((listp qualifier) (setq lambda-list qualifier)
+ (setq qualifiers (reverse qualifiers)) qualifiers)
+ (push qualifier qualifiers))
+ (do* ((rest-lambda-list lambda-list (cdr rest-lambda-list))
+ (arg (first rest-lambda-list) (first rest-lambda-list)))
+ ((or (member arg lambda-list-keywords) (null rest-lambda-list))
+ (setq specializers (reverse specializers)))
+ (push (if (listp arg) (second arg) t) specializers))
+ (let ((method-index `(method (,method-name ,@qualifiers ,specializers)))
+ (name-index `(,method-name ,@qualifiers ,specializers)))
+ (case *pfi-method-index*
+ (:group method-index)
+ (:separate name-index)
+ ((t :both) (list method-index name-index))
+ ((nil) nil)
+ (otherwise (error "Illegal value for *pfi-method-index*: ~S" *pfi-method-index*))))))
+
+(defun pfi-install-pcl ()
+ (pfi-add-method-type)
+ (pfi-add-class-type))
+
+(eval-when (eval load)
+ (when (boundp (quote il:*pfi-types*))
+ (pfi-install-pcl))
+ )
+
diff --git a/gcl/pcl/impl/xerox/pcl-env.text b/gcl/pcl/impl/xerox/pcl-env.text
new file mode 100644
index 000000000..25e090f2f
--- /dev/null
+++ b/gcl/pcl/impl/xerox/pcl-env.text
@@ -0,0 +1,105 @@
+A (very) few words about PCL-ENV. If you require more information, consult the
+source code. While it is not particularly well documented, it is the final
+arbiter of truth regarding its own functionality.
+
+The file PCL-ENV.LISP defines some low-level facilities to integrate PCL into
+the XeroxLisp environment. The first order of business is teaching the
+FileManager (nee FilePackage) about CLOS defineing forms. This in turn brings
+us to the issue of names.
+
+
+o Names and the FileManager
+
+For the FileManager to keep track of defining forms, it needs to know how to
+extract a (unique) name and FileManager type from the form. PCL-ENV includes
+FileManager support for the definers DEFCLASS, DEFGENERIC, and DEFMETHOD.
+
+DEFCLASS
+The name of a DEFCLASS form is the name of the class defined by the form. The
+FileManager type is PCL::CLASSES. There is a FileManager "undefiner" provided
+for DEFCLASS.
+
+DEFGENERIC
+The name of a DEFGENERIC form is the name of the generic-function defined by the
+form. The FileManager type is PCL::GENERIC-FUNCTIONS.
+
+DEFMETHOD
+The name of a DEFMETHOD form is a list of the form
+(<gf-name> {<qualifier>}* ({<specializer>*})). The FileManager type is
+PCL::METHODS. There is a FileManager "undefiner" provided for DEFMETHOD.
+However, note that if a generic-function was created as a side-effect of the
+DEFMETHOD, the undefiner will leave the generic-function defined (albet with no
+methods).
+
+When editing, it would be onerous to require the programmer to type in the full name of a
+method. PCL-ENV arranges it so that (ED <gf-name>) will ask the programmer
+which method on that generic-function should be edited. (If there is only one
+method, it is assumed that that is the method to be edited.) As of the
+Victoria-Day release, EQL specialized methods are handled correctly.
+
+
+o Inspecting CLOS objects (and metaobjects)
+
+PCL-ENV defines a protocol that is used to inspect objects, and arranges that
+the standard INSPECT function uses this protocol. Programmers can use this
+protocol by defining additional methods on the following generic-functions.
+
+INSPECT-SLOT-NAMES object
+Returns a list of "slots" to include in the inspector. The default method
+returns a list of all slots on the object.
+
+INSPECT-SLOT-VALUE object slot-name
+Returns the value to associated with the slot-name in the inspector. Slot-name
+is one of the items returned by INSPECT-SLOT-NAMES. The default method returns
+(SLOT-VALUE object slot-name).
+
+INSPECT-SETF-SLOT-VALUE object slot-name new-value
+Sets the value associated with the slot-name in the inspector. Slot-name is one
+of the items returned by INSPECT-SLOT-NAMES. The default method executes
+(SETF (SLOT-VALUE object slot-name) new-value).
+
+INSPECT-TITLE object inspect-window
+Returns the title to use in the inspect-window when inspecting object. The
+default returns the string "Inspecting the class <class-name>" when the object
+is a class, or "Inspecting a <class-name>" otherwise.
+
+
+o Debugging and the Stack
+
+Debugging in PCL is complicated by generic-functions and methods appear on the
+stack not as single objects, but as collections of functions that the programmer
+did not directly call. PCL-ENV redefines a number of internal debugger
+functions to simplify the presentation of the stack, and allow the programmer to
+access to the original defining forms from the stack. These changes only affect
+the "short" display backtrace (brought up by BT in a break window); the full
+backtrace (brought up by BT!) is unaffected.
+
+
+o Misc
+
+Prettyprinting
+
+The support for standard Prettyprinting is pretty minimal. Only DEFMETHOD,
+DEFCLASS, WITH-ACCESSORS, and WITH-SLOTS are supported, and they aren't really
+done right. Thanks to Harley Davis, PCL-ENV defines SEdit pretty-print specs
+for the forms DEFCLASS, DEFMETHOD, DEFGENERIC, GENERIC-FLET, GENERIC-LABELS,
+CALL-NEXT-METHOD, SYMBOL-MACROLET, WITH-ACCESSORS, WITH-SLOTS, and
+MAKE-INSTANCE.
+
+?=
+
+The function SMARTARGLIST is changed to return appropriate values for the
+arglists of generic-functions. The macros DEFCLASS and DEFMETHOD have "pretty"
+arglists defined.
+
+PrettyFileIndex
+
+Again thanks to Harley Davis, PCL-ENV teaches PRETTY-FILE-INDEX about classes,
+methods, and accessors. The variables PCL::*PFI-INDEX-ACCESSORS* and
+PCL::*PFI-METHOD-INDEX* may be changed by the user to tailor the computation of
+the file index. Note that the file PRETTY-FILE-INDEX must be loaded before
+PCL-ENV for this to take effect.
+
+
+--- smL 25-May-89
+
diff --git a/gcl/pcl/impl/xerox/xerox-low.lisp b/gcl/pcl/impl/xerox/xerox-low.lisp
new file mode 100644
index 000000000..861884a5a
--- /dev/null
+++ b/gcl/pcl/impl/xerox/xerox-low.lisp
@@ -0,0 +1,173 @@
+;;; -*- Mode:LISP; Package:(PCL Lisp 1000); Base:10.; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This is the 1100 (Xerox version) of the file portable-low.
+;;;
+
+(in-package 'pcl)
+
+(defmacro load-time-eval (form)
+ `(il:LOADTIMECONSTANT ,form))
+
+;;;
+;;; make the pointer from an instance to its class wrapper be an xpointer.
+;;; this prevents instance creation from spending a lot of time incrementing
+;;; the large refcount of the class-wrapper. This is safe because there will
+;;; always be some other pointer to the wrapper to keep it around.
+;;;
+#+Xerox-Medley
+(defstruct (std-instance (:predicate std-instance-p)
+ (:conc-name %std-instance-)
+ (:constructor %%allocate-instance--class ())
+ (:fast-accessors t)
+ (:print-function %print-std-instance))
+ (wrapper nil :type il:fullxpointer)
+ (slots nil))
+
+#+Xerox-Lyric
+(eval-when (eval load compile)
+ (il:datatype std-instance
+ ((wrapper il:fullxpointer)
+ slots))
+
+ (xcl:definline std-instance-p (x)
+ (typep x 'std-instance))
+
+ (xcl:definline %%allocate-instance--class ()
+ (il:create std-instance))
+
+ (xcl:definline %std-instance-wrapper (x)
+ (il:fetch (std-instance wrapper) il:of x))
+
+ (xcl:definline %std-instance-slots (x)
+ (il:fetch (std-instance slots) il:of x))
+
+ (xcl:definline set-%std-instance-wrapper (x value)
+ (il:replace (std-instance wrapper) il:of x il:with value))
+
+ (xcl:definline set-%std-instance-slots (x value)
+ (il:replace (std-instance slots) il:of x il:with value))
+
+ (defsetf %std-instance-wrapper set-%std-instance-wrapper)
+
+ (defsetf %std-instance-slots set-%std-instance-slots)
+
+ (il:defprint 'std-instance '%print-std-instance)
+
+ )
+
+(defun %print-std-instance (instance &optional stream depth)
+ ;; See the IRM, section 25.3.3. Unfortunatly, that documentation is
+ ;; not correct. In particular, it makes no mention of the third argument.
+ (cond ((streamp stream)
+ ;; Use the standard PCL printing method, then return T to tell
+ ;; the printer that we have done the printing ourselves.
+ (print-std-instance instance stream depth)
+ t)
+ (t
+ ;; Internal printing (again, see the IRM section 25.3.3).
+ ;; Return a list containing the string of characters that
+ ;; would be printed, if the object were being printed for
+ ;; real.
+ (list (with-output-to-string (stream)
+ (print-std-instance instance stream depth))))))
+
+ ;;
+;;;;;; FUNCTION-ARGLIST
+ ;;
+
+(defun function-arglist (x)
+ ;; Xerox lisp has the bad habit of returning a symbol to mean &rest, and
+ ;; strings instead of symbols. How silly.
+ (let ((arglist (il:arglist x)))
+ (when (symbolp arglist)
+ ;; This could be due to trying to extract the arglist of an interpreted
+ ;; function (though why that should be hard is beyond me). On the other
+ ;; hand, if the function is compiled, it helps to ask for the "smart"
+ ;; arglist.
+ (setq arglist
+ (if (consp (symbol-function x))
+ (second (symbol-function x))
+ (il:arglist x t))))
+ (if (symbolp arglist)
+ ;; Probably never get here, but just in case
+ (list '&rest 'rest)
+ ;; Make sure there are no strings where there should be symbols
+ (if (some #'stringp arglist)
+ (mapcar #'(lambda (a) (if (symbolp a) a (intern a))) arglist)
+ arglist))))
+
+(defun printing-random-thing-internal (thing stream)
+ (let ((*print-base* 8))
+ (princ (il:\\hiloc thing) stream)
+ (princ "," stream)
+ (princ (il:\\loloc thing) stream)))
+
+(defun record-definition (name type &optional parent-name parent-type)
+ (declare (ignore type parent-name))
+ ())
+
+
+;;;
+;;; FIN uses this too!
+;;;
+(eval-when (compile load eval)
+ (il:datatype il:compiled-closure (il:fnheader il:environment))
+
+ (il:blockrecord closure-overlay ((funcallable-instance-p il:flag)))
+
+ )
+
+(defun compiled-closure-fnheader (compiled-closure)
+ (il:fetch (il:compiled-closure il:fnheader) il:of compiled-closure))
+
+(defun set-compiled-closure-fnheader (compiled-closure nv)
+ (il:replace (il:compiled-closure il:fnheader) il:of compiled-closure nv))
+
+(defsetf compiled-closure-fnheader set-compiled-closure-fnheader)
+
+;;;
+;;; In Lyric, and until the format of FNHEADER changes, getting the name from
+;;; a compiled closure looks like this:
+;;;
+;;; (fetchfield '(nil 4 pointer)
+;;; (fetch (compiled-closure fnheader) closure))
+;;;
+;;; Of course this is completely non-robust, but it will work for now. This
+;;; is not the place to go into a long tyrade about what is wrong with having
+;;; record package definitions go away when you ship the sysout; there isn't
+;;; enough diskspace.
+;;;
+(defun set-function-name-1 (fn new-name uninterned-name)
+ (cond ((typep fn 'il:compiled-closure)
+ (il:\\rplptr (compiled-closure-fnheader fn) 4 new-name)
+ (when (and (consp uninterned-name)
+ (eq (car uninterned-name) 'method))
+ (let ((debug (si::compiled-function-debugging-info fn)))
+ (when debug (setf (cdr debug) uninterned-name)))))
+ (t nil))
+ fn)
+
diff --git a/gcl/pcl/impl/xerox/xerox-patches.lisp b/gcl/pcl/impl/xerox/xerox-patches.lisp
new file mode 100644
index 000000000..87ed713c0
--- /dev/null
+++ b/gcl/pcl/impl/xerox/xerox-patches.lisp
@@ -0,0 +1,248 @@
+;;; -*- Mode: Lisp; Package: XCL-USER; Base: 10.; Syntax: Common-Lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;;
+
+(in-package "XCL-USER")
+
+
+;;; Patch a bug with Lambda-substitution
+
+#+Xerox-Lyric
+(defun compiler::meta-call-lambda-substitute (node)
+ (let* ((fn (compiler::call-fn node))
+ (var-list (compiler::lambda-required fn))
+ (spec-effects
+ (il:for var il:in var-list
+ il:unless (eq (compiler::variable-scope var) :lexical)
+ il:collect (compiler::effects-representation var)))
+ ;; Bind *SUBST-OCCURED* just so that META-SUBST-VAR-REF ahs a binding
+ ;; to set even when nobody cares.
+ (compiler::*subst-occurred* nil))
+ (il:for var il:in var-list
+ il:as tail il:on (compiler::call-args node)
+ il:when
+ (and (eq (compiler::variable-scope var) :lexical)
+ (compiler::substitutable-p (car tail) var)
+ (dolist (compiler::spec-effect spec-effects t)
+ (when
+ (not (compiler::null-effects-intersection compiler::spec-effect
+ (compiler::node-affected (car tail))))
+ (return nil)))
+ (dolist (compiler::later-arg (cdr tail) t)
+ (when (not (compiler::passable (car tail) compiler::later-arg))
+ (return nil))))
+ il:do
+ (setf (compiler::lambda-body fn)
+ (compiler::meta-substitute (car tail) var
+ (compiler::lambda-body fn))))
+ (when (null (compiler::node-meta-p (compiler::lambda-body fn)))
+ (setf (compiler::node-meta-p fn) nil)
+ (setq compiler::*made-changes* t))))
+
+;;; Some simple optimizations missing from the compiler.
+
+
+;; Shift by a constant.
+
+;; Unfortunately, these cause the compiler to generate spurious warning
+;; messages about "Unknown function IL:LLSH1 called from ..." It's not often
+;; you come across a place where COMPILER-LET is really needed.
+
+#+Xerox-Lyric
+(progn
+
+(defvar *ignore-shift-by-constant-optimization* nil
+ "Marker used for informing the shift-by-constant optimizers that they are in
+ the shift function, and should not optimize.")
+
+(defun il:lrsh1 (x)
+ (compiler-let ((*ignore-shift-by-constant-optimization* t))
+ (il:lrsh x 1)))
+
+(defun il:lrsh8 (x)
+ (compiler-let ((*ignore-shift-by-constant-optimization* t))
+ (il:lrsh x 8)))
+
+(defun il:llsh1 (x)
+ (compiler-let ((*ignore-shift-by-constant-optimization* t))
+ (il:llsh x 1)))
+
+(defun il:llsh8 (x)
+ (compiler-let ((*ignore-shift-by-constant-optimization* t))
+ (il:llsh x 8)))
+
+(defoptimizer il:lrsh il:right-shift-by-constant (x n &environment env)
+ (if (and (constantp n)
+ (not *ignore-shift-by-constant-optimization*))
+ (let ((shift-factor (eval n)))
+ (cond
+ ((not (numberp shift-factor))
+ (error "Non-numeric arg to ~S, ~S" 'il:lrsh shift-factor))
+ ((= shift-factor 0)
+ x)
+ ((< shift-factor 0)
+ `(il:llsh ,x ,(- shift-factor)))
+ ((< shift-factor 8)
+ `(il:lrsh (il:lrsh1 ,x) ,(1- shift-factor)))
+ (t `(il:lrsh (il:lrsh8 ,x) ,(- shift-factor 8)))))
+ 'compiler:pass))
+
+(defoptimizer il:llsh il:left-shift-by-constant (x n &environment env)
+ (if (and (constantp n)
+ (not *ignore-shift-by-constant-optimization*))
+ (let ((shift-factor (eval n)))
+ (cond
+ ((not (numberp shift-factor))
+ (error "Non-numeric arg to ~S, ~S" 'il:llsh shift-factor))
+ ((= shift-factor 0)
+ x)
+ ((< shift-factor 0)
+ `(il:lrsh ,x ,(- shift-factor)))
+ ((< shift-factor 8)
+ `(il:llsh (il:llsh1 ,x) ,(1- shift-factor)))
+ (t `(il:llsh (il:llsh8 ,x) ,(- shift-factor 8)))))
+ 'compiler:pass))
+
+)
+
+
+;; Simple TYPEP optimiziation
+
+#+Xerox-Lyric
+(defoptimizer typep type-t-test (object type)
+ "Everything is of type T"
+ (if (and (constantp type) (eq (eval type) t))
+ `(progn ,object t)
+ 'compiler:pass))
+
+;;; Declare side-effects (actually, lack of side-effects) info for some
+;;; internal arithmetic functions. These are needed because the compiler runs
+;;; the optimizers before checking the side-effects, so side-effect
+;;; declarations on the "real" functions are oft times ignored.
+
+#+Xerox-Lyric
+(progn
+
+(il:putprops cl::%+ compiler::side-effects-data (:none . :none))
+(il:putprops cl::%- compiler::side-effects-data (:none . :none))
+(il:putprops cl::%* compiler::side-effects-data (:none . :none))
+(il:putprops cl::%/ compiler::side-effects-data (:none . :none))
+(il:putprops cl::%logior compiler::side-effects-data (:none . :none))
+(il:putprops cl::%logeqv compiler::side-effects-data (:none . :none))
+(il:putprops cl::%= compiler::side-effects-data (:none . :none))
+(il:putprops cl::%> compiler::side-effects-data (:none . :none))
+(il:putprops cl::%< compiler::side-effects-data (:none . :none))
+(il:putprops cl::%>= compiler::side-effects-data (:none . :none))
+(il:putprops cl::%<= compiler::side-effects-data (:none . :none))
+(il:putprops cl::%/= compiler::side-effects-data (:none . :none))
+(il:putprops il:lrsh1 compiler::side-effects-data (:none . :none))
+(il:putprops il:lrsh8 compiler::side-effects-data (:none . :none))
+(il:putprops il:llsh1 compiler::side-effects-data (:none . :none))
+(il:putprops il:llsh8 compiler::side-effects-data (:none . :none))
+
+)
+
+;;; Fix a nit in the compiler
+#+Xerox-Lyric
+(progn
+
+(il:unadvise 'compile)
+(il:advise 'compile ':around '(let (compiler::*input-stream*) (inner)))
+
+)
+
+;;; While no person would generate code like (logor x), macro can (and do).
+
+(defun optimize-logical-op-1-arg (form env ctxt)
+ (declare (ignore env ctxt))
+ (if (= 2 (length form))
+ (second form)
+ 'compiler::pass))
+
+(xcl:defoptimizer logior optimize-logical-op-1-arg)
+(xcl:defoptimizer logxor optimize-logical-op-1-arg)
+(xcl:defoptimizer logand optimize-logical-op-1-arg)
+(xcl:defoptimizer logeqv optimize-logical-op-1-arg)
+
+
+#+Xerox-Medley
+
+;; A bug compiling LABELS
+
+(defun compiler::meta-call-labels (compiler::node compiler:context)
+ ;; This is similar to META-CALL-LAMBDA, but we have some extra information.
+ ;; There are only required arguments, and we have the correct number of them.
+ (let ((compiler::*made-changes* nil))
+ ;; First, substitute the functions wherever possible.
+ (dolist (compiler::fn-pair (compiler::labels-funs compiler::node)
+ (when (null (compiler::node-meta-p (compiler::labels-body compiler::node)))
+ (setf (compiler::node-meta-p compiler::node) nil)
+ (setq compiler::*made-changes* t)))
+ (when (compiler::substitutable-p (cdr compiler::fn-pair)
+ (car compiler::fn-pair))
+ (let ((compiler::*subst-occurred* nil))
+ ;; First try substituting into the body.
+ (setf (compiler::labels-body compiler::node)
+ (compiler::meta-substitute (cdr compiler::fn-pair)
+ (car compiler::fn-pair)
+ (compiler::labels-body compiler::node)))
+ (when (not compiler::*subst-occurred*)
+ ;; Wasn't in the body - try the other functions.
+ (dolist (compiler::target-pair (compiler::labels-funs compiler::node))
+ (unless (eq compiler::target-pair compiler::fn-pair)
+ (setf (cdr compiler::target-pair)
+ (compiler::meta-substitute (cdr compiler::fn-pair)
+ (car compiler::fn-pair)
+ (cdr compiler::target-pair)))
+ (when compiler::*subst-occurred* ;Found it, we can stop now.
+ (setf (compiler::node-meta-p compiler::node) nil)
+ (setq compiler::*made-changes* t) (return)))))
+ ;; May need to reanalyze the node, since things might have changed.
+ ;; Note that reanalyzing the parts of the node this way means the the
+ ;; state in the enclosing loop is not lost.
+ (dolist (compiler::fns (compiler::labels-funs compiler::node))
+ (compiler::meval (cdr compiler::fns) :argument))
+ (compiler::meval (compiler::labels-body compiler::node) :return))))
+ ;; Now remove any functions that aren't referenced.
+ (dolist (compiler::fn-pair (prog1 (compiler::labels-funs compiler::node)
+ (setf (compiler::labels-funs compiler::node) nil)))
+ (cond ((null (compiler::variable-read-refs (car compiler::fn-pair)))
+ (compiler::release-tree (cdr compiler::fn-pair))
+ (setq compiler::*made-changes* t))
+ (t (push compiler::fn-pair (compiler::labels-funs compiler::node)))))
+ ;; If there aren't any functions left, replace the node with its body.
+ (when (null (compiler::labels-funs compiler::node))
+ (let ((compiler::body (compiler::labels-body compiler::node)))
+ (setf (compiler::labels-body compiler::node) nil)
+ (compiler::release-tree compiler::node)
+ (setq compiler::node compiler::body compiler::*made-changes* t)))
+ ;; Finally, set the meta-p flag if everythings OK.
+ (if (null compiler::*made-changes*)
+ (setf (compiler::node-meta-p compiler::node) compiler:context)
+ (setf (compiler::node-meta-p compiler::node) nil)))
+ compiler::node)
+
diff --git a/gcl/pcl/init.lisp b/gcl/pcl/init.lisp
new file mode 100644
index 000000000..217cca7da
--- /dev/null
+++ b/gcl/pcl/init.lisp
@@ -0,0 +1,261 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;;
+;;; This file defines the initialization and related protocols.
+;;;
+
+(in-package :pcl)
+
+(defmethod make-instance ((class symbol) &rest initargs)
+ (apply #'make-instance (find-class class) initargs))
+
+(defmethod make-instance ((class class) &rest initargs)
+ (unless (class-finalized-p class) (finalize-inheritance class))
+ (setq initargs (default-initargs class initargs))
+ #||
+ (check-initargs-1
+ class initargs
+ (list (list* 'allocate-instance class initargs)
+ (list* 'initialize-instance (class-prototype class) initargs)
+ (list* 'shared-initialize (class-prototype class) t initargs)))
+ ||#
+ (let* ((info (initialize-info class initargs))
+ (valid-p (initialize-info-valid-p info)))
+ (when (and (consp valid-p) (eq (car valid-p) :invalid))
+ (error "Invalid initialization argument ~S for class ~S"
+ (cdr valid-p) (class-name class))))
+ (let ((instance (apply #'allocate-instance class initargs)))
+ (apply #'initialize-instance instance initargs)
+ instance))
+
+(defvar *default-initargs-flag* (list nil))
+
+(defmethod default-initargs ((class slot-class) supplied-initargs)
+ (call-initialize-function
+ (initialize-info-default-initargs-function
+ (initialize-info class supplied-initargs))
+ nil supplied-initargs)
+ #||
+ ;; This implementation of default initargs is critically dependent
+ ;; on all-default-initargs not having any duplicate initargs in it.
+ (let ((all-default (class-default-initargs class))
+ (miss *default-initargs-flag*))
+ (flet ((getf* (plist key)
+ (do ()
+ ((null plist) miss)
+ (if (eq (car plist) key)
+ (return (cadr plist))
+ (setq plist (cddr plist))))))
+ (labels ((default-1 (tail)
+ (if (null tail)
+ nil
+ (if (eq (getf* supplied-initargs (caar tail)) miss)
+ (list* (caar tail)
+ (funcall (cadar tail))
+ (default-1 (cdr tail)))
+ (default-1 (cdr tail))))))
+ (append supplied-initargs (default-1 all-default)))))
+ ||#)
+
+(defmethod initialize-instance ((instance slot-object) &rest initargs)
+ (apply #'shared-initialize instance t initargs))
+
+(defmethod reinitialize-instance ((instance slot-object) &rest initargs)
+ #||
+ (check-initargs-1
+ (class-of instance) initargs
+ (list (list* 'reinitialize-instance instance initargs)
+ (list* 'shared-initialize instance nil initargs)))
+ ||#
+ (let* ((class (class-of instance))
+ (info (initialize-info class initargs))
+ (valid-p (initialize-info-ri-valid-p info)))
+ (when (and (consp valid-p) (eq (car valid-p) :invalid))
+ (error "Invalid initialization argument ~S for class ~S"
+ (cdr valid-p) (class-name class))))
+ (apply #'shared-initialize instance nil initargs)
+ instance)
+
+(defmethod update-instance-for-different-class ((previous standard-object)
+ (current standard-object)
+ &rest initargs)
+ ;; First we must compute the newly added slots. The spec defines
+ ;; newly added slots as "those local slots for which no slot of
+ ;; the same name exists in the previous class."
+ (let ((added-slots '())
+ (current-slotds (class-slots (class-of current)))
+ (previous-slot-names (mapcar #'slot-definition-name
+ (class-slots (class-of previous)))))
+ (dolist (slotd current-slotds)
+ (if (and (not (memq (slot-definition-name slotd) previous-slot-names))
+ (eq (slot-definition-allocation slotd) ':instance))
+ (push (slot-definition-name slotd) added-slots)))
+ (check-initargs-1
+ (class-of current) initargs
+ (list (list* 'update-instance-for-different-class previous current initargs)
+ (list* 'shared-initialize current added-slots initargs)))
+ (apply #'shared-initialize current added-slots initargs)))
+
+(defmethod update-instance-for-redefined-class ((instance standard-object)
+ added-slots
+ discarded-slots
+ property-list
+ &rest initargs)
+ (check-initargs-1
+ (class-of instance) initargs
+ (list (list* 'update-instance-for-redefined-class
+ instance added-slots discarded-slots property-list initargs)
+ (list* 'shared-initialize instance added-slots initargs)))
+ (apply #'shared-initialize instance added-slots initargs))
+
+(defmethod shared-initialize
+ ((instance slot-object) slot-names &rest initargs)
+ (when (eq slot-names 't)
+ (return-from shared-initialize
+ (call-initialize-function
+ (initialize-info-shared-initialize-t-function
+ (initialize-info (class-of instance) initargs))
+ instance initargs)))
+ (when (eq slot-names 'nil)
+ (return-from shared-initialize
+ (call-initialize-function
+ (initialize-info-shared-initialize-nil-function
+ (initialize-info (class-of instance) initargs))
+ instance initargs)))
+ ;;
+ ;; initialize the instance's slots in a two step process
+ ;; (1) A slot for which one of the initargs in initargs can set
+ ;; the slot, should be set by that initarg. If more than
+ ;; one initarg in initargs can set the slot, the leftmost
+ ;; one should set it.
+ ;;
+ ;; (2) Any slot not set by step 1, may be set from its initform
+ ;; by step 2. Only those slots specified by the slot-names
+ ;; argument are set. If slot-names is:
+ ;; T
+ ;; any slot not set in step 1 is set from its
+ ;; initform
+ ;; <list of slot names>
+ ;; any slot in the list, and not set in step 1
+ ;; is set from its initform
+ ;;
+ ;; ()
+ ;; no slots are set from initforms
+ ;;
+ (let* ((class (class-of instance))
+ (slotds (class-slots class))
+ #-new-kcl-wrapper
+ (std-p #+cmu17
+ (pcl-instance-p instance)
+ #-cmu17
+ (or (std-instance-p instance) (fsc-instance-p instance))))
+ (dolist (slotd slotds)
+ (let ((slot-name (slot-definition-name slotd))
+ (slot-initargs (slot-definition-initargs slotd)))
+ (unless (progn
+ ;; Try to initialize the slot from one of the initargs.
+ ;; If we succeed return T, otherwise return nil.
+ (doplist (initarg val) initargs
+ (when (memq initarg slot-initargs)
+ (setf (slot-value-using-class class instance slotd)
+ val)
+ (return 't))))
+ ;; Try to initialize the slot from its initform.
+ (if (and slot-names
+ (or (eq slot-names 't)
+ (memq slot-name slot-names))
+ (or #-new-kcl-wrapper (and (not std-p) (eq slot-names 't))
+ (not (slot-boundp-using-class class instance slotd))))
+ (let ((initfunction (slot-definition-initfunction slotd)))
+ (when initfunction
+ (setf (slot-value-using-class class instance slotd)
+ (funcall (the function initfunction)))))))))
+ instance))
+
+
+;;;
+;;; if initargs are valid return nil, otherwise signal an error
+;;;
+(defun check-initargs-1 (class initargs call-list &optional (plist-p t) (error-p t))
+ (multiple-value-bind (legal allow-other-keys)
+ (check-initargs-values class call-list)
+ (unless allow-other-keys
+ (if plist-p
+ (check-initargs-2-plist initargs class legal error-p)
+ (check-initargs-2-list initargs class legal error-p)))))
+
+(defun check-initargs-values (class call-list)
+ (let ((methods (mapcan #'(lambda (call)
+ (if (consp call)
+ (copy-list (compute-applicable-methods
+ (gdefinition (car call))
+ (cdr call)))
+ (list call)))
+ call-list))
+ (legal (apply #'append (mapcar #'slot-definition-initargs
+ (class-slots class)))))
+ ;; Add to the set of slot-filling initargs the set of
+ ;; initargs that are accepted by the methods. If at
+ ;; any point we come across &allow-other-keys, we can
+ ;; just quit.
+ (dolist (method methods)
+ (multiple-value-bind (nreq nopt keysp restp allow-other-keys keys)
+ (analyze-lambda-list (if (consp method)
+ (early-method-lambda-list method)
+ (method-lambda-list method)))
+ (declare (ignore nreq nopt keysp restp))
+ (when allow-other-keys
+ (return-from check-initargs-values (values nil t)))
+ (setq legal (append keys legal))))
+ (values legal nil)))
+
+(defun check-initargs-2-plist (initargs class legal &optional (error-p t))
+ (unless (getf initargs :allow-other-keys)
+ ;; Now check the supplied-initarg-names and the default initargs
+ ;; against the total set that we know are legal.
+ (doplist (key val) initargs
+ (unless (memq key legal)
+ (if error-p
+ (error "Invalid initialization argument ~S for class ~S"
+ key
+ (class-name class))
+ (return-from check-initargs-2-plist nil)))))
+ t)
+
+(defun check-initargs-2-list (initkeys class legal &optional (error-p t))
+ (unless (memq :allow-other-keys initkeys)
+ ;; Now check the supplied-initarg-names and the default initargs
+ ;; against the total set that we know are legal.
+ (dolist (key initkeys)
+ (unless (memq key legal)
+ (if error-p
+ (error "Invalid initialization argument ~S for class ~S"
+ key
+ (class-name class))
+ (return-from check-initargs-2-list nil)))))
+ t)
+
diff --git a/gcl/pcl/iterate.lisp b/gcl/pcl/iterate.lisp
new file mode 100644
index 000000000..d690a9537
--- /dev/null
+++ b/gcl/pcl/iterate.lisp
@@ -0,0 +1,1267 @@
+;;;-*- Package: ITERATE; Syntax: Common-Lisp; Base: 10 -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; Original source {pooh/n}<pooh>vanmelle>lisp>iterate;4 created 27-Sep-88 12:35:33
+
+(in-package :iterate :use '(:lisp :walker))
+
+
+(export '(iterate iterate* gathering gather with-gathering interval elements
+ list-elements list-tails plist-elements eachtime while until
+ collecting joining maximizing minimizing summing
+ *iterate-warnings*))
+
+(defvar *iterate-warnings* :any "Controls whether warnings are issued for iterate/gather forms that aren't optimized.
+NIL => never; :USER => those resulting from user code; T => always, even if it's the iteration macro that's suboptimal."
+ )
+
+;;; ITERATE macro
+
+
+(defmacro iterate (clauses &body body &environment env)
+ (optimize-iterate-form clauses body env))
+
+(defun
+ simple-expand-iterate-form
+ (clauses body)
+
+ ;; Expand ITERATE. This is the "formal semantics" expansion, which we never
+ ;; use.
+ (let*
+ ((block-name (gensym))
+ (bound-var-lists (mapcar #'(lambda (clause)
+ (let ((names (first clause)))
+ (if (listp names)
+ names
+ (list names))))
+ clauses))
+ (generator-vars (mapcar #'(lambda (clause)
+ (declare (ignore clause))
+ (gensym))
+ clauses)))
+ `(block ,block-name
+ (let*
+ ,(mapcan #'(lambda (gvar clause var-list)
+ ; For each clause, bind a
+ ; generator temp to the clause,
+ ; then bind the specified
+ ; var(s)
+ (cons (list gvar (second clause))
+ (copy-list var-list)))
+ generator-vars clauses bound-var-lists)
+
+ ;; Note bug in formal semantics: there can be declarations in the head
+ ;; of BODY; they go here, rather than inside loop
+ (loop
+ ,@(mapcar
+ #'(lambda (var-list gen-var)
+ ; Set each bound variable (or
+ ; set of vars) to the result of
+ ; calling the corresponding
+ ; generator
+ `(multiple-value-setq
+ ,var-list
+ (funcall ,gen-var #'(lambda nil (return-from
+ ,block-name)))))
+ bound-var-lists generator-vars)
+ ,@body)))))
+
+(defparameter *iterate-temp-vars-list*
+ '(iterate-temp-1 iterate-temp-2 iterate-temp-3 iterate-temp-4
+ iterate-temp-5 iterate-temp-6 iterate-temp-7 iterate-temp-8)
+ "Temp var names used by ITERATE expansions.")
+
+(defun
+ optimize-iterate-form
+ (clauses body iterate-env)
+ (let*
+ ((temp-vars *iterate-temp-vars-list*)
+ (block-name (gensym))
+ (finish-form `(return-from ,block-name))
+ (bound-vars (mapcan #'(lambda (clause)
+ (let ((names (first clause)))
+ (if (listp names)
+ (copy-list names)
+ (list names))))
+ clauses))
+ iterate-decls generator-decls update-forms bindings leftover-body)
+ (do ((tail bound-vars (cdr tail)))
+ ((null tail))
+ ; Check for duplicates
+ (when (member (car tail)
+ (cdr tail))
+ (warn "Variable appears more than once in ITERATE: ~S" (car tail))))
+ (flet
+ ((get-iterate-temp nil
+
+ ;; Make temporary var. Note that it is ok to re-use these symbols
+ ;; in each iterate, because they are not used within BODY.
+ (or (pop temp-vars)
+ (gensym))))
+ (dolist (clause clauses)
+ (cond
+ ((or (not (consp clause))
+ (not (consp (cdr clause))))
+ (warn "Bad syntax in ITERATE: clause not of form (var iterator): ~S"
+ clause))
+ (t
+ (unless (null (cddr clause))
+ (warn
+ "Probable parenthesis error in ITERATE clause--more than 2 elements: ~S"
+ clause))
+ (multiple-value-bind
+ (let-body binding-type let-bindings localdecls otherdecls extra-body)
+ (expand-into-let (second clause)
+ 'iterate iterate-env)
+
+ ;; We have expanded the generator clause and parsed it into its LET
+ ;; pieces.
+ (prog*
+ ((vars (first clause))
+ gen-args renamed-vars)
+ (setq vars (if (listp vars)
+ (copy-list vars)
+ (list vars)))
+ ; VARS is now a (fresh) list of
+ ; all iteration vars bound in
+ ; this clause
+ (cond
+ ((eq let-body :abort)
+ ; Already issued a warning
+ ; about malformedness
+ )
+ ((null (setq let-body (function-lambda-p let-body 1)))
+ ; Not of the expected form
+ (let ((generator (second clause)))
+ (cond ((and (consp generator)
+ (fboundp (car generator)))
+ ; It looks ok--a macro or
+ ; function here--so the guy who
+ ; wrote it just didn't do it in
+ ; an optimizable way
+ (maybe-warn :definition "Could not optimize iterate clause ~S because generator not of form (LET[*] ... (FUNCTION (LAMBDA (finish) ...)))"
+ generator))
+ (t ; Perhaps it's just a
+ ; misspelling? Probably user
+ ; error
+ (maybe-warn :user
+ "Iterate operator in clause ~S is not fboundp."
+ generator)))
+ (setq let-body :abort)))
+ (t
+
+ ;; We have something of the form #'(LAMBDA (finisharg) ...),
+ ;; possibly with some LET bindings around it. LET-BODY =
+ ;; ((finisharg) ...).
+ (setq let-body (cdr let-body))
+ (setq gen-args (pop let-body))
+ (when let-bindings
+
+ ;; The first transformation we want to perform is
+ ;; "LET-eversion": turn (let* ((generator (let (..bindings..)
+ ;; #'(lambda ...)))) ..body..) into (let* (..bindings..
+ ;; (generator #'(lambda ...))) ..body..). This
+ ;; transformation is valid if nothing in body refers to any
+ ;; of the bindings, something we can assure by
+ ;; alpha-converting the inner let (substituting new names for
+ ;; each var). Of course, none of those vars can be special,
+ ;; but we already checked for that above.
+ (multiple-value-setq (let-bindings renamed-vars)
+ (rename-let-bindings let-bindings binding-type
+ iterate-env leftover-body #'get-iterate-temp))
+ (setq leftover-body nil)
+ ; If there was any leftover
+ ; from previous, it is now
+ ; consumed
+ )
+
+ ;; The second transformation is substituting the body of the
+ ;; generator (LAMBDA (finish-arg) . gen-body) for its appearance
+ ;; in the update form (funcall generator #'(lambda ()
+ ;; finish-form)), then simplifying that form. The requirement
+ ;; for this part is that the generator body not refer to any
+ ;; variables that are bound between the generator binding and the
+ ;; appearance in the loop body. The only variables bound in that
+ ;; interval are generator temporaries, which have unique names so
+ ;; are no problem, and the iteration variables remaining for
+ ;; subsequent clauses. We'll discover the story as we walk the
+ ;; body.
+ (multiple-value-bind
+ (finishdecl other rest)
+ (parse-declarations let-body gen-args)
+ (declare (ignore finishdecl))
+ ; Pull out declares, if any,
+ ; separating out the one(s)
+ ; referring to the finish arg,
+ ; which we will throw away
+ (when other
+ ; Combine remaining decls with
+ ; decls extracted from the LET,
+ ; if any
+ (setq otherdecls (nconc otherdecls other)))
+ (setq let-body (cond
+ (otherdecls
+ ; There are interesting
+ ; declarations, so have to keep
+ ; it wrapped.
+ `(let nil (declare ,@otherdecls)
+ ,@rest))
+ ((null (cdr rest))
+ ; Only one form left
+ (first rest))
+ (t `(progn ,@rest)))))
+ (unless (eq (setq let-body (iterate-transform-body let-body
+ iterate-env renamed-vars
+ (first gen-args)
+ finish-form bound-vars clause))
+ :abort)
+
+ ;; Skip the rest if transformation failed. Warning has
+ ;; already been issued.
+
+ ;; Note possible further optimization: if LET-BODY expanded
+ ;; into (prog1 oldvalue prepare-for-next-iteration), as so
+ ;; many do, then we could in most cases split the PROG1 into
+ ;; two pieces: do the (setq var oldvalue) here, and do the
+ ;; prepare-for-next-iteration at the bottom of the loop.
+ ;; This does a slight optimization of the PROG1 and also
+ ;; rearranges the code in a way that a reasonably clever
+ ;; compiler might detect how to get rid of redundant
+ ;; variables altogether (such as happens with INTERVAL and
+ ;; LIST-TAILS); that would make the whole thing closer to
+ ;; what you might have coded by hand. However, to do this
+ ;; optimization, we need to assure that (a) the
+ ;; prepare-for-next-iteration refers freely to no vars other
+ ;; than the internal vars we have extracted from the LET, and
+ ;; (b) that the code has no side effects. These are both
+ ;; true for all the iterators defined by this module, but how
+ ;; shall we represent side-effect info and/or tap into the
+ ;; compiler's knowledge of same?
+ (when localdecls
+ ; There were declarations for
+ ; the generator locals--have to
+ ; keep them for later, and
+ ; rename the vars mentioned
+ (setq
+ generator-decls
+ (nconc
+ generator-decls
+ (mapcar
+ #'(lambda
+ (decl)
+ (let ((head (car decl)))
+ (cons head (if (eq head 'type)
+ (cons (second decl)
+ (sublis renamed-vars
+ (cddr decl)))
+ (sublis renamed-vars
+ (cdr decl))))))
+ localdecls)))))))
+
+ ;; Finished analyzing clause now. LET-BODY is the form which, when
+ ;; evaluated, returns updated values for the iteration variable(s)
+ ;; VARS.
+ (when (eq let-body :abort)
+
+ ;; Some punt case: go with the formal semantics: bind a var to
+ ;; the generator, then call it in the update section
+ (let
+ ((gvar (get-iterate-temp))
+ (generator (second clause)))
+ (setq
+ let-bindings
+ (list (list gvar
+ (cond
+ (leftover-body
+ ; Have to use this up
+ `(progn ,@(prog1 leftover-body (setq
+ leftover-body
+ nil))
+ generator))
+ (t generator)))))
+ (setq let-body `(funcall ,gvar #'(lambda nil ,finish-form)))))
+ (push (mv-setq (copy-list vars)
+ let-body)
+ update-forms)
+ (dolist (v vars)
+ (declare (ignore v))
+ ; Pop off the vars we have now
+ ; bound from the list of vars
+ ; to watch out for--we'll bind
+ ; them right now
+ (pop bound-vars))
+ (setq bindings
+ (nconc bindings let-bindings
+ (cond (extra-body
+ ; There was some computation to
+ ; do after the bindings--here's
+ ; our chance
+ (cons (list (first vars)
+ `(progn ,@extra-body nil))
+ (rest vars)))
+ (t vars))))))))))
+ (do ((tail body (cdr tail)))
+ ((not (and (consp tail)
+ (consp (car tail))
+ (eq (caar tail)
+ 'declare)))
+
+ ;; TAIL now points at first non-declaration. If there were
+ ;; declarations, pop them off so they appear in the right place
+ (unless (eq tail body)
+ (setq iterate-decls (ldiff body tail))
+ (setq body tail))))
+ `(block ,block-name
+ (let* ,bindings ,@(and generator-decls
+ `((declare ,@generator-decls)))
+ ,@iterate-decls
+ ,@leftover-body
+ (loop ,@(nreverse update-forms)
+ ,@body)))))
+
+(defun expand-into-let (clause parent-name env)
+
+ ;; Return values: Body, LET[*], bindings, localdecls, otherdecls, extra
+ ;; body, where BODY is a single form. If multiple forms in a LET, the
+ ;; preceding forms are returned as extra body. Returns :ABORT if it
+ ;; issued a punt warning.
+ (prog ((expansion clause)
+ expandedp binding-type let-bindings let-body)
+ expand
+ (multiple-value-setq (expansion expandedp)
+ (macroexpand-1 expansion env))
+ (cond ((not (consp expansion))
+ ; Shouldn't happen
+ )
+ ((symbolp (setq binding-type (first expansion)))
+ (case binding-type
+ ((let let*)
+ (setq let-bindings (second expansion))
+ ; List of variable bindings
+ (setq let-body (cddr expansion))
+ (go handle-let))))
+ ((and (consp binding-type)
+ (eq (car binding-type)
+ 'lambda)
+ (not (find-if #'(lambda (x)
+ (member x lambda-list-keywords)
+ )
+ (setq let-bindings (second binding-type)))
+ )
+ (eql (length (second expansion))
+ (length let-bindings))
+ (null (cddr expansion)))
+ ; A simple LAMBDA form can be
+ ; treated as LET
+ (setq let-body (cddr binding-type))
+ (setq let-bindings (mapcar #'list let-bindings (second
+ expansion))
+ )
+ (setq binding-type 'let)
+ (go handle-let)))
+
+ ;; Fall thru if not a LET
+ (cond (expandedp ; try expanding again
+ (go expand))
+ (t ; Boring--return form as the
+ ; body
+ (return expansion)))
+ handle-let
+ (return (let ((locals (variables-from-let let-bindings))
+ extra-body specials)
+ (multiple-value-bind
+ (localdecls otherdecls let-body)
+ (parse-declarations let-body locals)
+ (cond ((setq specials (extract-special-bindings
+ locals localdecls))
+ (maybe-warn (cond ((find-if #'variable-globally-special-p
+ specials)
+ ; This could be the fault of a
+ ; user proclamation
+ :user)
+ (t :definition))
+
+ "Couldn't optimize ~S because expansion of ~S binds specials ~(~S ~)"
+ parent-name clause specials)
+ :abort)
+ (t (values (cond ((not (consp let-body))
+
+ ; Null body of LET? unlikely,
+ ; but someone else will likely
+ ; complain
+ nil)
+ ((null (cdr let-body))
+
+ ; A single expression, which we
+ ; hope is (function
+ ; (lambda...))
+ (first let-body))
+ (t
+
+ ;; More than one expression. These are forms to
+ ;; evaluate after the bindings but before the
+ ;; generator form is returned. Save them to
+ ;; evaluate in the next convenient place. Note that
+ ;; this is ok, as there is no construct that can
+ ;; cause a LET to return prematurely (without
+ ;; returning also from some surrounding construct).
+ (setq extra-body
+ (butlast let-body))
+ (car (last let-body))))
+ binding-type let-bindings localdecls
+ otherdecls extra-body))))))))
+
+(defun variables-from-let (bindings)
+
+ ;; Return a list of the variables bound in the first argument to LET[*].
+ (mapcar #'(lambda (binding)
+ (if (consp binding)
+ (first binding)
+ binding))
+ bindings))
+
+(defun iterate-transform-body (let-body iterate-env renamed-vars finish-arg
+ finish-form bound-vars clause)
+
+
+;;; This is the second major transformation for a single iterate clause.
+;;; LET-BODY is the body of the iterator after we have extracted its local
+;;; variables and declarations. We have two main tasks: (1) Substitute
+;;; internal temporaries for occurrences of the LET variables; the alist
+;;; RENAMED-VARS specifies this transformation. (2) Substitute evaluation of
+;;; FINISH-FORM for any occurrence of (funcall FINISH-ARG). Along the way, we
+;;; check for forms that would invalidate these transformations: occurrence of
+;;; FINISH-ARG outside of a funcall, and free reference to any element of
+;;; BOUND-VARS. CLAUSE & TYPE are the original ITERATE clause and its type
+;;; (ITERATE or ITERATE*), for purpose of error messages. On success, we
+;;; return the transformed body; on failure, :ABORT.
+
+ (walk-form let-body iterate-env
+ #'(lambda (form context env)
+ (declare (ignore context))
+
+ ;; Need to substitute RENAMED-VARS, as well as turn
+ ;; (FUNCALL finish-arg) into the finish form
+ (cond ((symbolp form)
+ (let (renaming)
+ (cond ((and (eq form finish-arg)
+ (variable-same-p form env
+ iterate-env))
+ ; An occurrence of the finish
+ ; arg outside of FUNCALL
+ ; context--I can't handle this
+ (maybe-warn :definition "Couldn't optimize iterate form because generator ~S does something with its FINISH arg besides FUNCALL it."
+ (second clause))
+ (return-from iterate-transform-body
+ :abort))
+ ((and (setq renaming (assoc form
+ renamed-vars
+ ))
+ (variable-same-p form env
+ iterate-env))
+ ; Reference to one of the vars
+ ; we're renaming
+ (cdr renaming))
+ ((and (member form bound-vars)
+ (variable-same-p form env
+ iterate-env))
+ ; FORM is a var that is bound
+ ; in this same ITERATE, or
+ ; bound later in this ITERATE*.
+ ; This is a conflict.
+ (maybe-warn :user "Couldn't optimize iterate form because generator ~S is closed over ~S, in conflict with a subsequent iteration variable."
+ (second clause)
+ form)
+ (return-from iterate-transform-body
+ :abort))
+ (t form))))
+ ((and (consp form)
+ (eq (first form)
+ 'funcall)
+ (eq (second form)
+ finish-arg)
+ (variable-same-p (second form)
+ env iterate-env))
+ ; (FUNCALL finish-arg) =>
+ ; finish-form
+ (unless (null (cddr form))
+ (maybe-warn :definition
+ "Generator for ~S applied its finish arg to > 0 arguments ~S--ignored."
+ (second clause)
+ (cddr form)))
+ finish-form)
+ (t form)))))
+
+(defun
+ parse-declarations
+ (tail locals)
+
+ ;; Extract the declarations from the head of TAIL and divide them into 2
+ ;; classes: declares about variables in the list LOCALS, and all other
+ ;; declarations. Returns 3 values: those 2 lists plus the remainder of TAIL.
+ (let
+ (localdecls otherdecls form)
+ (loop
+ (unless (and tail (consp (setq form (car tail)))
+ (eq (car form)
+ 'declare))
+ (return (values localdecls otherdecls tail)))
+ (mapc
+ #'(lambda
+ (decl)
+ (case (first decl)
+ ((inline notinline optimize)
+ ; These don't talk about vars
+ (push decl otherdecls))
+ (t ; Assume all other kinds are
+ ; for vars
+ (let* ((vars (if (eq (first decl)
+ 'type)
+ (cddr decl)
+ (cdr decl)))
+ (l (intersection locals vars))
+ other)
+ (cond
+ ((null l)
+ ; None talk about LOCALS
+ (push decl otherdecls))
+ ((null (setq other (set-difference vars l)))
+ ; All talk about LOCALS
+ (push decl localdecls))
+ (t ; Some of each
+ (let ((head (cons 'type (and (eq (first decl)
+ 'type)
+ (list (second decl))))))
+ (push (append head other)
+ otherdecls)
+ (push (append head l)
+ localdecls))))))))
+ (cdr form))
+ (pop tail))))
+
+(defun extract-special-bindings (vars decls)
+
+ ;; Return the subset of VARS that are special, either globally or
+ ;; because of a declaration in DECLS
+ (let ((specials (remove-if-not #'variable-globally-special-p vars)))
+ (dolist (d decls)
+ (when (eq (car d)
+ 'special)
+ (setq specials (union specials (intersection vars
+ (cdr d))))))
+ specials))
+
+(defun function-lambda-p (form &optional nargs)
+
+ ;; If FORM is #'(LAMBDA bindings . body) and bindings is of length
+ ;; NARGS, return the lambda expression
+ (let (args body)
+ (and (consp form)
+ (eq (car form)
+ 'function)
+ (consp (setq form (cdr form)))
+ (null (cdr form))
+ (consp (setq form (car form)))
+ (eq (car form)
+ 'lambda)
+ (consp (setq body (cdr form)))
+ (listp (setq args (car body)))
+ (or (null nargs)
+ (eql (length args)
+ nargs))
+ form)))
+
+(defun
+ rename-let-bindings
+ (let-bindings binding-type env leftover-body &optional tempvarfn)
+
+ ;; Perform the alpha conversion required for "LET eversion" of (LET[*]
+ ;; LET-BINDINGS . body)--rename each of the variables to an internal name.
+ ;; Returns 2 values: a new set of LET bindings and the alist of old var names
+ ;; to new (so caller can walk the body doing the rest of the renaming).
+ ;; BINDING-TYPE is one of LET or LET*. LEFTOVER-BODY is optional list of
+ ;; forms that must be eval'ed before the first binding happens. ENV is the
+ ;; macro expansion environment, in case we have to walk a LET*. TEMPVARFN is
+ ;; a function of no args to return a temporary var; if omitted, we use
+ ;; GENSYM.
+ (let
+ (renamed-vars)
+ (values (mapcar #'(lambda (binding)
+ (let ((valueform (cond ((not (consp binding))
+
+ ; No initial value
+ nil)
+ ((or (eq binding-type
+ 'let)
+ (null renamed-vars))
+
+ ; All bindings are in parallel,
+ ; so none can refer to others
+ (second binding))
+ (t
+ ; In a LET*, have to substitute
+ ; vars in the 2nd and
+ ; subsequent initialization
+ ; forms
+ (rename-variables
+ (second binding)
+ renamed-vars env))))
+ (newvar (if tempvarfn
+ (funcall tempvarfn)
+ (gensym))))
+ (push (cons (if (consp binding)
+ (first binding)
+ binding)
+ newvar)
+ renamed-vars)
+ ; Add new variable to the list
+ ; AFTER we have walked the
+ ; initial value form
+ (when leftover-body
+
+
+ ;; Previous clause had some computation to do after
+ ;; its bindings. Here is the first opportunity to
+ ;; do it
+ (setq valueform `(progn ,@leftover-body
+ ,valueform))
+ (setq leftover-body nil))
+ (list newvar valueform)))
+ let-bindings)
+ renamed-vars)))
+
+(defun rename-variables (form alist env)
+
+ ;; Walks FORM, renaming occurrences of the key variables in ALIST with
+ ;; their corresponding values. ENV is FORM's environment, so we can
+ ;; make sure we are talking about the same variables.
+ (walk-form form env
+ #'(lambda (form context subenv)
+ (declare (ignore context))
+ (let (pair)
+ (cond ((and (symbolp form)
+ (setq pair (assoc form alist))
+ (variable-same-p form subenv env))
+ (cdr pair))
+ (t form))))))
+
+(defun
+ mv-setq
+ (vars expr)
+
+ ;; Produces (MULTIPLE-VALUE-SETQ vars expr), except that I'll optimize some
+ ;; of the simple cases for benefit of compilers that don't, and I don't care
+ ;; what the value is, and I know that the variables need not be set in
+ ;; parallel, since they can't be used free in EXPR
+ (cond
+ ((null vars)
+ ; EXPR is a side-effect
+ expr)
+ ((not (consp vars))
+ ; This is an error, but I'll
+ ; let MULTIPLE-VALUE-SETQ
+ ; report it
+ `(multiple-value-setq ,vars ,expr))
+ ((and (listp expr)
+ (eq (car expr)
+ 'values))
+
+ ;; (mv-setq (a b c) (values x y z)) can be reduced to a parallel setq
+ ;; (psetq returns nil, but I don't care about returned value). Do this
+ ;; even for the single variable case so that we catch (mv-setq (a) (values
+ ;; x y))
+ (pop expr)
+ ; VALUES
+ `(setq ,@(mapcon #'(lambda (tail)
+ (list (car tail)
+ (cond ((or (cdr tail)
+ (null (cdr expr)))
+ ; One result expression for
+ ; this var
+ (pop expr))
+ (t ; More expressions than vars,
+ ; so arrange to evaluate all
+ ; the rest now.
+ (cons 'prog1 expr)))))
+ vars)))
+ ((null (cdr vars))
+ ; Simple one variable case
+ `(setq ,(car vars)
+ ,expr))
+ (t ; General case--I know nothing
+ `(multiple-value-setq ,vars ,expr))))
+
+(defun variable-same-p (var env1 env2)
+ (eq (variable-lexical-p var env1)
+ (variable-lexical-p var env2)))
+
+(defun maybe-warn (type &rest warn-args)
+
+ ;; Issue a warning about not being able to optimize this thing. TYPE
+ ;; is one of :DEFINITION, meaning the definition is at fault, and
+ ;; :USER, meaning the user's code is at fault.
+ (when (case *iterate-warnings*
+ ((nil) nil)
+ ((:user) (eq type :user))
+ (t t))
+ (apply #'warn warn-args)))
+
+
+;; Sample iterators
+
+
+(defmacro
+ interval
+ (&whole whole &key from downfrom to downto above below by type)
+ (cond
+ ((and from downfrom)
+ (error "Can't use both FROM and DOWNFROM in ~S" whole))
+ ((cdr (remove nil (list to downto above below)))
+ (error "Can't use more than one limit keyword in ~S" whole))
+ (t
+ (let*
+ ((down (or downfrom downto above))
+ (limit (or to downto above below))
+ (inc (cond ((null by)
+ 1)
+ ((constantp by)
+ ; Can inline this increment
+ by))))
+ `(let
+ ((from ,(or from downfrom 0))
+ ,@(and limit `((to ,limit)))
+ ,@(and (null inc)
+ `((by ,by))))
+ ,@(and type `((declare (type ,type from ,@(and limit '(to))
+ ,@(and (null inc)
+ `(by))))))
+ #'(lambda
+ (finish)
+ ,@(cond ((null limit)
+ ; We won't use the FINISH arg
+ '((declare (ignore finish)))))
+ (prog1 ,(cond (limit ; Test the limit. If ok,
+ ; return current value and
+ ; increment, else quit
+ `(if (,(cond (above '>)
+ (below '<)
+ (down '>=)
+ (t '<=))
+ from to)
+ from
+ (funcall finish)))
+ (t ; No test
+ 'from))
+ (setq from (,(if down
+ '-
+ '+)
+ from
+ ,(or inc 'by))))))))))
+
+(defmacro list-elements (list &key (by '#'cdr))
+ `(let ((tail ,list))
+ #'(lambda (finish)
+ (prog1 (if (endp tail)
+ (funcall finish)
+ (first tail))
+ (setq tail (funcall ,by tail))))))
+
+(defmacro list-tails (list &key (by '#'cdr))
+ `(let ((tail ,list))
+ #'(lambda (finish)
+ (prog1 (if (endp tail)
+ (funcall finish)
+ tail)
+ (setq tail (funcall ,by tail))))))
+
+(defmacro
+ elements
+ (sequence)
+ "Generates successive elements of SEQUENCE, with second value being the index. Use (ELEMENTS (THE type arg)) if you care about the type."
+ (let*
+ ((type (and (consp sequence)
+ (eq (first sequence)
+ 'the)
+ (second sequence)))
+ (accessor (if type
+ (sequence-accessor type)
+ 'elt))
+ (listp (eq type 'list)))
+
+ ;; If type is given via THE, we may be able to generate a good accessor here
+ ;; for the benefit of implementations that aren't smart about (ELT (THE
+ ;; STRING FOO)). I'm not bothering to keep the THE inside the body,
+ ;; however, since I assume any compiler that would understand (AREF (THE
+ ;; SIMPLE-ARRAY S)) would also understand that (AREF S) is the same when I
+ ;; bound S to (THE SIMPLE-ARRAY foo) and never modified it.
+
+ ;; If sequence is declared to be a list, it's better to cdr down it, so we
+ ;; have some extra cases here. Normally folks would write LIST-ELEMENTS,
+ ;; but maybe they wanted to get the index for free...
+ `(let* ((index 0)
+ (s ,sequence)
+ ,@(and (not listp)
+ '((size (length s)))))
+ #'(lambda (finish)
+ (values (cond ,(if listp
+ '((not (endp s))
+ (pop s))
+ `((< index size)
+ (,accessor s index)))
+ (t (funcall finish)))
+ (prog1 index
+ (setq index (1+ index))))))))
+
+(defmacro
+ plist-elements
+ (plist)
+ "Generates each time 2 items, the indicator and the value."
+ `(let ((tail ,plist))
+ #'(lambda (finish)
+ (values (if (endp tail)
+ (funcall finish)
+ (first tail))
+ (prog1 (if (endp (setq tail (cdr tail)))
+ (funcall finish)
+ (first tail))
+ (setq tail (cdr tail)))))))
+
+(defun sequence-accessor (type)
+
+ ;; returns the function with which most efficiently to make accesses to
+ ;; a sequence of type TYPE.
+ (case (if (consp type)
+ ; e.g., (VECTOR FLOAT *)
+ (car type)
+ type)
+ ((array simple-array vector) 'aref)
+ (simple-vector 'svref)
+ (string 'char)
+ (simple-string 'schar)
+ (bit-vector 'bit)
+ (simple-bit-vector 'sbit)
+ (t 'elt)))
+
+
+;; These "iterators" may be withdrawn
+
+
+(defmacro eachtime (expr)
+ `#'(lambda (finish)
+ (declare (ignore finish))
+ ,expr))
+
+(defmacro while (expr)
+ `#'(lambda (finish)
+ (unless ,expr (funcall finish))))
+
+(defmacro until (expr)
+ `#'(lambda (finish)
+ (when ,expr (funcall finish))))
+
+ ; GATHERING macro
+
+
+(defmacro gathering (clauses &body body &environment env)
+ (or (optimize-gathering-form clauses body env)
+ (simple-expand-gathering-form clauses body env)))
+
+(defmacro with-gathering (clauses gather-body &body use-body)
+ "Binds the variables specified in CLAUSES to the result of (GATHERING clauses gather-body) and evaluates the forms in USE-BODY inside that contour."
+
+ ;; We may optimize this a little better later for those compilers that
+ ;; don't do a good job on (m-v-bind vars (... (values ...)) ...).
+ `(multiple-value-bind ,(mapcar #'car clauses)
+ (gathering ,clauses ,gather-body)
+ ,@use-body))
+
+(defun
+ simple-expand-gathering-form
+ (clauses body env)
+ (declare (ignore env))
+
+ ;; The "formal semantics" of GATHERING. We use this only in cases that can't
+ ;; be optimized.
+ (let
+ ((acc-names (mapcar #'first (if (symbolp clauses)
+ ; Shorthand using anonymous
+ ; gathering site
+ (setq clauses `((*anonymous-gathering-site*
+ (,clauses))))
+ clauses)))
+ (realizer-names (mapcar #'(lambda (binding)
+ (declare (ignore binding))
+ (gensym))
+ clauses)))
+ `(multiple-value-call
+ #'(lambda
+ ,(mapcan #'list acc-names realizer-names)
+ (flet ((gather (value &optional (accumulator *anonymous-gathering-site*)
+ )
+ (funcall accumulator value)))
+ ,@body
+ (values ,@(mapcar #'(lambda (rname)
+ `(funcall ,rname))
+ realizer-names))))
+ ,@(mapcar #'second clauses))))
+
+(defvar *active-gatherers* nil
+ "List of GATHERING bindings currently active during macro expansion)")
+
+(defvar *anonymous-gathering-site* nil "Variable used in formal expansion of an abbreviated GATHERING form (one with anonymous gathering site)."
+ )
+
+(defun
+ optimize-gathering-form
+ (clauses body gathering-env)
+ (let*
+ (acc-info leftover-body top-bindings finish-forms top-decls)
+ (dolist (clause (if (symbolp clauses)
+ ; A shorthand
+ `((*anonymous-gathering-site* (,clauses)))
+ clauses))
+ (multiple-value-bind
+ (let-body binding-type let-bindings localdecls otherdecls extra-body)
+ (expand-into-let (second clause)
+ 'gathering gathering-env)
+ (prog*
+ ((acc-var (first clause))
+ renamed-vars accumulator realizer)
+ (when (and (consp let-body)
+ (eq (car let-body)
+ 'values)
+ (consp (setq let-body (cdr let-body)))
+ (setq accumulator (function-lambda-p (car let-body)))
+ (consp (setq let-body (cdr let-body)))
+ (setq realizer (function-lambda-p (car let-body)
+ 0))
+ (null (cdr let-body)))
+
+ ;; Macro returned something of the form (VALUES #'(lambda (value)
+ ;; ...) #'(lambda () ...)), a function to accumulate values and a
+ ;; function to realize the result.
+ (when binding-type
+
+ ;; Gatherer expanded into a LET
+ (cond (otherdecls (maybe-warn :definition "Couldn't optimize GATHERING clause ~S because its expansion carries declarations about more than the bound variables: ~S"
+ (second clause)
+ `(declare ,@otherdecls))
+ (go punt)))
+ (when let-bindings
+
+ ;; The first transformation we want to perform is a
+ ;; variant of "LET-eversion": turn (mv-bind (acc real)
+ ;; (let (..bindings..) (values #'(lambda ...) #'(lambda
+ ;; ...))) ..body..) into (let* (..bindings.. (acc
+ ;; #'(lambda ...)) (real #'(lambda ...))) ..body..). This
+ ;; transformation is valid if nothing in body refers to
+ ;; any of the bindings, something we can assure by
+ ;; alpha-converting the inner let (substituting new names
+ ;; for each var). Of course, none of those vars can be
+ ;; special, but we already checked for that above.
+ (multiple-value-setq (let-bindings renamed-vars)
+ (rename-let-bindings let-bindings binding-type
+ gathering-env leftover-body))
+ (setq top-bindings (nconc top-bindings let-bindings))
+ (setq leftover-body nil)
+ ; If there was any leftover
+ ; from previous, it is now
+ ; consumed
+ ))
+ (setq leftover-body (nconc leftover-body extra-body))
+ ; Computation to do after these
+ ; bindings
+ (push (cons acc-var (rename-and-capture-variables accumulator
+ renamed-vars gathering-env))
+ acc-info)
+ (setq realizer (rename-variables realizer renamed-vars
+ gathering-env))
+ (push (cond ((null (cdddr realizer))
+ ; Simple (LAMBDA () expr) =>
+ ; expr
+ (third realizer))
+ (t ; There could be declarations
+ ; or something, so leave as a
+ ; LET
+ (cons 'let (cdr realizer))))
+ finish-forms)
+ (unless (null localdecls)
+ ; Declarations about the LET
+ ; variables also has to
+ ; percolate up
+ (setq top-decls (nconc top-decls (sublis renamed-vars
+ localdecls))))
+ (return))
+ (maybe-warn :definition "Couldn't optimize GATHERING clause ~S because its expansion is not of the form (VALUES #'(LAMBDA ...) #'(LAMBDA () ...))"
+ (second clause))
+ punt
+ (let
+ ((gs (gensym))
+ (expansion `(multiple-value-list ,(second clause))))
+ ; Slow way--bind gensym to the
+ ; macro expansion, and we will
+ ; funcall it in the body
+ (push (list acc-var gs)
+ acc-info)
+ (push `(funcall (cadr ,gs))
+ finish-forms)
+ (setq
+ top-bindings
+ (nconc
+ top-bindings
+ (list (list gs (cond (leftover-body
+ `(progn ,@(prog1 leftover-body
+ (setq leftover-body nil))
+ ,expansion))
+ (t expansion))))))))))
+ (setq body (walk-gathering-body body gathering-env acc-info))
+ (cond ((eq body :abort)
+ ; Couldn't finish expansion
+ nil)
+ (t `(let* ,top-bindings
+ ,@(and top-decls `((declare ,@top-decls)))
+ ,body
+ ,(cond ((null (cdr finish-forms))
+ ; just a single value
+ (car finish-forms))
+ (t `(values ,@(reverse finish-forms)))))))))
+
+(defun rename-and-capture-variables (form alist env)
+
+ ;; Walks FORM, renaming occurrences of the key variables in ALIST with
+ ;; their corresponding values, and capturing any other free variables.
+ ;; Returns a list of the new form and the list of other closed-over
+ ;; vars. ENV is FORM's environment, so we can make sure we are talking
+ ;; about the same variables.
+ (let (closed)
+ (list (walk-form
+ form env
+ #'(lambda (form context subenv)
+ (declare (ignore context))
+ (let (pair)
+ (cond ((or (not (symbolp form))
+ (not (variable-same-p form subenv
+ env)))
+ ; non-variable or one that has
+ ; been rebound
+ form)
+ ((setq pair (assoc form alist))
+ ; One to rename
+ (cdr pair))
+ (t ; var is free
+ (pushnew form closed)
+ form)))))
+ closed)))
+
+(defun
+ walk-gathering-body
+ (body gathering-env acc-info)
+
+ ;; Walk the body of (GATHERING (...) . BODY) in environment GATHERING-ENV.
+ ;; ACC-INFO is a list of information about each of the gathering "bindings"
+ ;; in the form, in the form (var gatheringfn freevars env)
+ (let
+ ((*active-gatherers* (nconc (mapcar #'car acc-info)
+ *active-gatherers*)))
+
+ ;; *ACTIVE-GATHERERS* tells us what vars are currently legal as GATHER
+ ;; targets. This is so that when we encounter a GATHER not belonging to us
+ ;; we can know whether to warn about it.
+ (walk-form
+ (cons 'progn body)
+ gathering-env
+ #'(lambda
+ (form context env)
+ (declare (ignore context))
+ (let (info site)
+ (cond ((consp form)
+ (cond
+ ((not (eq (car form)
+ 'gather))
+ ; We only care about GATHER
+ (when (and (eq (car form)
+ 'function)
+ (eq (cadr form)
+ 'gather))
+ ; Passed as functional--can't
+ ; macroexpand
+ (maybe-warn :user
+ "Can't optimize GATHERING because of reference to #'GATHER."
+ )
+ (return-from walk-gathering-body :abort))
+ form)
+ ((setq info (assoc (setq site (if (null (cddr form))
+
+ '
+ *anonymous-gathering-site*
+ (third form)))
+ acc-info))
+ ; One of ours--expand (GATHER
+ ; value var). INFO = (var
+ ; gatheringfn freevars env)
+ (unless (null (cdddr form))
+ (warn "Extra arguments (> 2) in ~S discarded." form)
+ )
+ (let ((fn (second info)))
+ (cond ((symbolp fn)
+ ; Unoptimized case--just call
+ ; the gatherer. FN is the
+ ; gensym that we bound to the
+ ; list of two values returned
+ ; from the gatherer.
+ `(funcall (car ,fn)
+ ,(second form)))
+ (t ; FN = (lambda (value) ...)
+ (dolist (s (third info))
+ (unless (or (variable-same-p s env
+ gathering-env)
+ (and (variable-special-p
+ s env)
+ (variable-special-p
+ s gathering-env)))
+
+
+ ;; Some var used free in the LAMBDA form has been
+ ;; rebound between here and the parent GATHERING
+ ;; form, so can't substitute the lambda. Ok if it's
+ ;; a special reference both here and in the LAMBDA,
+ ;; because then it's not closed over.
+ (maybe-warn :user "Can't optimize GATHERING because the expansion closes over the variable ~S, which is rebound around a GATHER for it."
+ s)
+ (return-from walk-gathering-body
+ :abort)))
+
+
+ ;; Return ((lambda (value) ...) actual-value). In
+ ;; many cases we could simplify this further by
+ ;; substitution, but we'd have to be careful (for
+ ;; example, we would need to alpha-convert any LET
+ ;; we found inside). Any decent compiler will do it
+ ;; for us.
+ (list fn (second form))))))
+ ((and (setq info (member site *active-gatherers*))
+ (or (eq site '*anonymous-gathering-site*)
+ (variable-same-p site env (fourth info))))
+ ; Some other GATHERING will
+ ; take care of this form, so
+ ; pass it up for now.
+ ; Environment check is to make
+ ; sure nobody shadowed it
+ ; between here and there
+ form)
+ (t ; Nobody's going to handle it
+ (if (eq site '*anonymous-gathering-site*)
+ ; More likely that she forgot
+ ; to mention the site than
+ ; forget to write an anonymous
+ ; gathering.
+ (warn "There is no gathering site specified in ~S."
+ form)
+ (warn
+ "The site ~S in ~S is not defined in an enclosing GATHERING form."
+ site form))
+ ; Turn it into something else
+ ; so we don't warn twice in the
+ ; nested case
+ `(%orphaned-gather ,@(cdr form)))))
+ ((and (symbolp form)
+ (setq info (assoc form acc-info))
+ (variable-same-p form env gathering-env))
+ ; A variable reference to a
+ ; gather binding from
+ ; environment TEM
+ (maybe-warn :user "Can't optimize GATHERING because site variable ~S is used outside of a GATHER form."
+ form)
+ (return-from walk-gathering-body :abort))
+ (t form)))))))
+
+
+;; Sample gatherers
+
+
+(defmacro
+ collecting
+ (&key initial-value)
+ `(let* ((head ,initial-value)
+ (tail ,(and initial-value `(last head))))
+ (values #'(lambda (value)
+ (if (null head)
+ (setq head (setq tail (list value)))
+ (setq tail (cdr (rplacd tail (list value))))))
+ #'(lambda nil head))))
+
+(defmacro joining (&key initial-value)
+ `(let ((result ,initial-value))
+ (values #'(lambda (value)
+ (setq result (nconc result value)))
+ #'(lambda nil result))))
+
+(defmacro
+ maximizing
+ (&key initial-value)
+ `(let ((result ,initial-value))
+ (values
+ #'(lambda (value)
+ (when ,(cond ((and (constantp initial-value)
+ (not (null (eval initial-value))))
+ ; Initial value is given and we
+ ; know it's not NIL, so leave
+ ; out the null check
+ '(> value result))
+ (t '(or (null result)
+ (> value result))))
+ (setq result value)))
+ #'(lambda nil result))))
+
+(defmacro
+ minimizing
+ (&key initial-value)
+ `(let ((result ,initial-value))
+ (values
+ #'(lambda (value)
+ (when ,(cond ((and (constantp initial-value)
+ (not (null (eval initial-value))))
+ ; Initial value is given and we
+ ; know it's not NIL, so leave
+ ; out the null check
+ '(< value result))
+ (t '(or (null result)
+ (< value result))))
+ (setq result value)))
+ #'(lambda nil result))))
+
+(defmacro summing (&key (initial-value 0))
+ `(let ((sum ,initial-value))
+ (values #'(lambda (value)
+ (setq sum (+ sum value)))
+ #'(lambda nil sum))))
+
+ ; Easier to read expanded code
+ ; if PROG1 gets left alone
+
+
+(define-walker-template prog1 (nil return walker::repeat (eval)))
+
diff --git a/gcl/pcl/low.lisp b/gcl/pcl/low.lisp
new file mode 100644
index 000000000..913fb3b66
--- /dev/null
+++ b/gcl/pcl/low.lisp
@@ -0,0 +1,459 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; This file contains portable versions of low-level functions and macros
+;;; which are ripe for implementation specific customization. None of the
+;;; code in this file *has* to be customized for a particular Common Lisp
+;;; implementation. Moreover, in some implementations it may not make any
+;;; sense to customize some of this code.
+;;;
+;;; But, experience suggests that MOST Common Lisp implementors will want
+;;; to customize some of the code in this file to make PCL run better in
+;;; their implementation. The code in this file has been separated and
+;;; heavily commented to make that easier.
+;;;
+;;; Implementation-specific version of this file already exist for:
+;;;
+;;; Symbolics Genera family genera-low.lisp
+;;; Lucid Lisp lucid-low.lisp
+;;; Xerox 1100 family xerox-low.lisp
+;;; ExCL (Franz) excl-low.lisp
+;;; Kyoto Common Lisp kcl-low.lisp
+;;; Vaxlisp vaxl-low.lisp
+;;; CMU Lisp cmu-low.lisp
+;;; H.P. Common Lisp hp-low.lisp
+;;; Golden Common Lisp gold-low.lisp
+;;; Ti Explorer ti-low.lisp
+;;;
+;;;
+;;; These implementation-specific files are loaded after this file. Because
+;;; none of the macros defined by this file are used in functions defined by
+;;; this file the implementation-specific files can just contain the parts of
+;;; this file they want to change. They don't have to copy this whole file
+;;; and then change the parts they want.
+;;;
+;;; If you make changes or improvements to these files, or if you need some
+;;; low-level part of PCL re-modularized to make it more portable to your
+;;; system please send mail to CommonLoops.pa@Xerox.com.
+;;;
+;;; Thanks.
+;;;
+
+(in-package :pcl)
+
+(eval-when (compile load eval)
+(defvar *optimize-speed* '(optimize (speed 3) (safety 0)))
+)
+
+(defmacro %svref (vector index)
+ `(locally (declare #.*optimize-speed*
+ (inline svref))
+ (svref (the simple-vector ,vector) (the fixnum ,index))))
+
+(defsetf %svref %set-svref)
+
+(defmacro %set-svref (vector index new-value)
+ `(locally (declare #.*optimize-speed*
+ (inline svref))
+ (setf (svref (the simple-vector ,vector) (the fixnum ,index))
+ ,new-value)))
+
+
+;;;
+;;; without-interrupts
+;;;
+;;; OK, Common Lisp doesn't have this and for good reason. But For all of
+;;; the Common Lisp's that PCL runs on today, there is a meaningful way to
+;;; implement this. WHAT I MEAN IS:
+;;;
+;;; I want the body to be evaluated in such a way that no other code that is
+;;; running PCL can be run during that evaluation. I agree that the body
+;;; won't take *long* to evaluate. That is to say that I will only use
+;;; without interrupts around relatively small computations.
+;;;
+;;; INTERRUPTS-ON should turn interrupts back on if they were on.
+;;; INTERRUPTS-OFF should turn interrupts back off.
+;;; These are only valid inside the body of WITHOUT-INTERRUPTS.
+;;;
+;;; OK?
+;;;
+(defmacro without-interrupts (&body body)
+ `(macrolet ((interrupts-on () ())
+ (interrupts-off () ()))
+ (progn ,.body)))
+
+
+;;;
+;;; Very Low-Level representation of instances with meta-class standard-class.
+;;;
+#-new-kcl-wrapper
+(progn
+#-cmu17
+(defstruct (std-instance (:predicate std-instance-p)
+ (:conc-name %std-instance-)
+ (:constructor %%allocate-instance--class ())
+ (:print-function print-std-instance))
+ (wrapper nil)
+ (slots nil))
+
+(defmacro %instance-ref (slots index)
+ `(%svref ,slots ,index))
+
+(defmacro instance-ref (slots index)
+ `(svref ,slots ,index))
+)
+
+#+new-kcl-wrapper
+(progn
+(defvar *init-vector* (make-array 40 :fill-pointer 1 :adjustable t
+ :initial-element nil))
+
+(defun get-init-list (i)
+ (declare (fixnum i)(special *slot-unbound*))
+ (loop (when (< i (fill-pointer *init-vector*))
+ (return (aref *init-vector* i)))
+ (vector-push-extend
+ (cons *slot-unbound*
+ (aref *init-vector* (1- (fill-pointer *init-vector*))))
+ *init-vector*)))
+
+(defmacro %std-instance-wrapper (instance)
+ `(structure-def ,instance))
+
+(defmacro %std-instance-slots (instance)
+ instance)
+
+(defmacro std-instance-p (x)
+ `(structurep ,x))
+)
+
+(defmacro std-instance-wrapper (x) `(%std-instance-wrapper ,x))
+(defmacro std-instance-slots (x) `(%std-instance-slots ,x))
+
+(defmacro get-wrapper (inst)
+ `(cond ((std-instance-p ,inst) (std-instance-wrapper ,inst))
+ ((fsc-instance-p ,inst) (fsc-instance-wrapper ,inst))
+ (t (error "What kind of instance is this?"))))
+
+(defmacro get-instance-wrapper-or-nil (inst)
+ `(cond ((std-instance-p ,inst) (std-instance-wrapper ,inst))
+ ((fsc-instance-p ,inst) (fsc-instance-wrapper ,inst))))
+
+(defmacro get-slots (inst)
+ `(cond ((std-instance-p ,inst) (std-instance-slots ,inst))
+ ((fsc-instance-p ,inst) (fsc-instance-slots ,inst))
+ (t (error "What kind of instance is this?"))))
+
+(defmacro get-slots-or-nil (inst)
+ `(cond ((std-instance-p ,inst) (std-instance-slots ,inst))
+ ((fsc-instance-p ,inst) (fsc-instance-slots ,inst))))
+
+(defun print-std-instance (instance stream depth) ;A temporary definition used
+ (declare (ignore depth)) ;for debugging the bootstrap
+ (printing-random-thing (instance stream) ;code of PCL (See high.lisp).
+ (let ((class (class-of instance)))
+ (if (or (eq class (find-class 'standard-class nil))
+ (eq class (find-class 'funcallable-standard-class nil))
+ (eq class (find-class 'built-in-class nil)))
+ (format stream "~a ~a" (early-class-name class)
+ (early-class-name instance))
+ (format stream "~a" (early-class-name class))))))
+
+;;;
+;;; This is the value that we stick into a slot to tell us that it is unbound.
+;;; It may seem gross, but for performance reasons, we make this an interned
+;;; symbol. That means that the fast check to see if a slot is unbound is to
+;;; say (EQ <val> '..SLOT-UNBOUND..). That is considerably faster than looking
+;;; at the value of a special variable. Be careful, there are places in the
+;;; code which actually use ..slot-unbound.. rather than this variable. So
+;;; much for modularity
+;;;
+(defvar *slot-unbound* '..slot-unbound..)
+
+(defmacro %allocate-static-slot-storage--class (no-of-slots)
+ #+new-kcl-wrapper (declare (ignore no-of-slots))
+ #-new-kcl-wrapper
+ `(make-array ,no-of-slots :initial-element *slot-unbound*)
+ #+new-kcl-wrapper
+ (error "don't call this"))
+
+(defmacro std-instance-class (instance)
+ `(wrapper-class* (std-instance-wrapper ,instance)))
+
+
+ ;;
+;;;;;; FUNCTION-ARGLIST
+ ;;
+;;; Given something which is functionp, function-arglist should return the
+;;; argument list for it. PCL does not count on having this available, but
+;;; MAKE-SPECIALIZABLE works much better if it is available. Versions of
+;;; function-arglist for each specific port of pcl should be put in the
+;;; appropriate xxx-low file. This is what it should look like:
+;(defun function-arglist (function)
+; (<system-dependent-arglist-function> function))
+
+(defun function-pretty-arglist (function)
+ (declare (ignore function))
+ ())
+
+(defsetf function-pretty-arglist set-function-pretty-arglist)
+
+(defun set-function-pretty-arglist (function new-value)
+ (declare (ignore function))
+ new-value)
+
+;;;
+;;; set-function-name
+;;; When given a function should give this function the name <new-name>.
+;;; Note that <new-name> is sometimes a list. Some lisps get the upset
+;;; in the tummy when they start thinking about functions which have
+;;; lists as names. To deal with that there is set-function-name-intern
+;;; which takes a list spec for a function name and turns it into a symbol
+;;; if need be.
+;;;
+;;; When given a funcallable instance, set-function-name MUST side-effect
+;;; that FIN to give it the name. When given any other kind of function
+;;; set-function-name is allowed to return new function which is the 'same'
+;;; except that it has the name.
+;;;
+;;; In all cases, set-function-name must return the new (or same) function.
+;;;
+(defun set-function-name (function new-name)
+ (declare (notinline set-function-name-1 intern-function-name))
+ (set-function-name-1 function
+ (intern-function-name new-name)
+ new-name))
+
+(defun set-function-name-1 (function new-name uninterned-name)
+ (declare (ignore new-name uninterned-name))
+ function)
+
+(defun intern-function-name (name)
+ (cond ((symbolp name) name)
+ ((listp name)
+ (intern (let ((*package* *the-pcl-package*)
+ (*print-case* :upcase)
+ (*print-pretty* nil)
+ (*print-gensym* 't))
+ (format nil "~S" name))
+ *the-pcl-package*))))
+
+
+;;;
+;;; COMPILE-LAMBDA
+;;;
+;;; This is like the Common Lisp function COMPILE. In fact, that is what
+;;; it ends up calling. The difference is that it deals with things like
+;;; watching out for recursive calls to the compiler or not calling the
+;;; compiler in certain cases or allowing the compiler not to be present.
+;;;
+;;; This starts out with several variables and support functions which
+;;; should be conditionalized for any new port of PCL. Note that these
+;;; default to reasonable values, many new ports won't need to look at
+;;; these values at all.
+;;;
+;;; *COMPILER-PRESENT-P* NIL means the compiler is not loaded
+;;;
+;;; *COMPILER-SPEED* one of :FAST :MEDIUM or :SLOW
+;;;
+;;; *COMPILER-REENTRANT-P* T ==> OK to call compiler recursively
+;;; NIL ==> not OK
+;;;
+;;; function IN-THE-COMPILER-P returns T if in the compiler, NIL otherwise
+;;; This is not called if *compiler-reentrant-p*
+;;; is T, so it only needs to be implemented for
+;;; ports which have non-reentrant compilers.
+;;;
+;;;
+(defvar *compiler-present-p* t)
+
+(defvar *compiler-speed*
+ #+(or KCL IBCL GCLisp CMU) :slow
+ #-(or KCL IBCL GCLisp CMU) :fast)
+
+(defvar *compiler-reentrant-p*
+ #+(and (not XKCL) (or KCL IBCL)) nil
+ #-(and (not XKCL) (or KCL IBCL)) t)
+
+(defun in-the-compiler-p ()
+ #+(and (not xkcl) (or KCL IBCL))compiler::*compiler-in-use*
+ #+gclisp (typep (eval '(function (lambda ()))) 'lexical-closure)
+ )
+
+(defvar *compile-lambda-break-p* nil)
+
+(defun compile-lambda (lambda &optional (desirability :fast))
+ (when *compile-lambda-break-p* (break))
+ (cond ((null *compiler-present-p*)
+ (compile-lambda-uncompiled lambda))
+ ((and (null *compiler-reentrant-p*)
+ (in-the-compiler-p))
+ (compile-lambda-deferred lambda))
+ ((eq desirability :fast)
+ (compile nil lambda))
+ ((and (eq desirability :medium)
+ (member *compiler-speed* '(:fast :medium)))
+ (compile nil lambda))
+ ((and (eq desirability :slow)
+ (eq *compiler-speed* ':fast))
+ (compile nil lambda))
+ (t
+ (compile-lambda-uncompiled lambda))))
+
+(defun compile-lambda-uncompiled (uncompiled)
+ #'(lambda (&rest args) (apply (coerce uncompiled 'function) args)))
+
+(defun compile-lambda-deferred (uncompiled)
+ (let ((function (coerce uncompiled 'function))
+ (compiled nil))
+ (declare (type (or function null) compiled))
+ #'(lambda (&rest args)
+ (if compiled
+ (apply compiled args)
+ (if (in-the-compiler-p)
+ (apply function args)
+ (progn (setq compiled (compile nil uncompiled))
+ (apply compiled args)))))))
+
+(defmacro precompile-random-code-segments (&optional system)
+ `(progn
+ (eval-when (compile)
+ (update-dispatch-dfuns)
+ (compile-iis-functions nil))
+ (precompile-function-generators ,system)
+ (precompile-dfun-constructors ,system)
+ (precompile-iis-functions ,system)
+ (eval-when (load)
+ (compile-iis-functions t))))
+
+
+
+(defun record-definition (type spec &rest args)
+ (declare (ignore type spec args))
+ ())
+
+(defun doctor-dfun-for-the-debugger (gf dfun) (declare (ignore gf)) dfun)
+
+;; From braid.lisp
+#-new-kcl-wrapper
+(defmacro built-in-or-structure-wrapper (x)
+ (once-only (x)
+ (if (structure-functions-exist-p) ; otherwise structurep is too slow for this
+ `(if (structurep ,x)
+ (wrapper-for-structure ,x)
+ (if (symbolp ,x)
+ (if ,x *the-wrapper-of-symbol* *the-wrapper-of-null*)
+ (built-in-wrapper-of ,x)))
+ `(or (and (symbolp ,x)
+ (if ,x *the-wrapper-of-symbol* *the-wrapper-of-null*))
+ (built-in-or-structure-wrapper1 ,x)))))
+
+#-cmu17
+(defmacro wrapper-of-macro (x)
+ `(cond ((std-instance-p ,x)
+ (std-instance-wrapper ,x))
+ ((fsc-instance-p ,x)
+ (fsc-instance-wrapper ,x))
+ (t
+ (#+new-kcl-wrapper built-in-wrapper-of
+ #-new-kcl-wrapper built-in-or-structure-wrapper
+ ,x))))
+
+#+cmu17
+(defmacro wrapper-of-macro (x)
+ `(kernel:layout-of ,x))
+
+;Low level functions for structures
+
+;Functions on arbitrary objects
+
+(defvar *structure-table* (make-hash-table :test 'eq))
+
+(defun declare-structure (name included-name slot-description-list)
+ (setf (gethash name *structure-table*)
+ (cons included-name slot-description-list)))
+
+(unless (fboundp 'structure-functions-exist-p)
+ (setf (symbol-function 'structure-functions-exist-p)
+ #'(lambda () nil)))
+
+(defun default-structurep (x)
+ (structure-type-p (type-of x)))
+
+(defun default-structure-instance-p (x)
+ (let ((type (type-of x)))
+ (and (not (eq type 'std-instance))
+ (structure-type-p type))))
+
+(defun default-structure-type (x)
+ (type-of x))
+
+(unless (fboundp 'structurep)
+ (setf (symbol-function 'structurep) #'default-structurep))
+
+; excludes std-instance
+(unless (fboundp 'structure-instance-p)
+ (setf (symbol-function 'structure-instance-p) #'default-structure-instance-p))
+
+; returns a symbol
+(unless (fboundp 'structure-type)
+ (setf (symbol-function 'structure-type) #'default-structure-type))
+
+
+;Functions on symbols naming structures
+
+; Excludes structures types created with the :type option
+(defun structure-type-p (symbol)
+ (not (null (gethash symbol *structure-table*))))
+
+(defun structure-type-included-type-name (symbol)
+ (car (gethash symbol *structure-table*)))
+
+; direct slots only
+; The results of this function are used only by the functions below.
+(defun structure-type-slot-description-list (symbol)
+ (cdr (gethash symbol *structure-table*)))
+
+
+;Functions on slot-descriptions (returned by the function above)
+
+;returns a symbol
+(defun structure-slotd-name (structure-slot-description)
+ (first structure-slot-description))
+
+;returns a symbol
+(defun structure-slotd-accessor-symbol (structure-slot-description)
+ (second structure-slot-description))
+
+;returns a symbol or a list or nil
+(defun structure-slotd-writer-function (structure-slot-description)
+ (third structure-slot-description))
+
+(defun structure-slotd-type (structure-slot-description)
+ (fourth structure-slot-description))
+
+(defun structure-slotd-init-form (structure-slot-description)
+ (fifth structure-slot-description))
diff --git a/gcl/pcl/macros.lisp b/gcl/pcl/macros.lisp
new file mode 100644
index 000000000..e45ed9107
--- /dev/null
+++ b/gcl/pcl/macros.lisp
@@ -0,0 +1,787 @@
+;;;-*-Mode:LISP; Package:(PCL (LISP WALKER)); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; Macros global variable definitions, and other random support stuff used
+;;; by the rest of the system.
+;;;
+;;; For simplicity (not having to use eval-when a lot), this file must be
+;;; loaded before it can be compiled.
+;;;
+
+(in-package :pcl)
+
+(proclaim '(declaration
+ #-Genera values ;I use this so that Zwei can remind
+ ;me what values a function returns.
+
+ #-Genera arglist ;Tells me what the pretty arglist
+ ;of something (which probably takes
+ ;&rest args) is.
+
+ #-Genera indentation ;Tells ZWEI how to indent things
+ ;like defclass.
+ class
+ variable-rebinding
+ pcl-fast-call
+ method-name
+ method-lambda-list
+ ))
+
+;;; Age old functions which CommonLisp cleaned-up away. They probably exist
+;;; in other packages in all CommonLisp implementations, but I will leave it
+;;; to the compiler to optimize into calls to them.
+;;;
+;;; Common Lisp BUG:
+;;; Some Common Lisps define these in the Lisp package which causes
+;;; all sorts of lossage. Common Lisp should explictly specify which
+;;; symbols appear in the Lisp package.
+;;;
+(eval-when (compile load eval)
+
+(defmacro memq (item list) `(member ,item ,list :test #'eq))
+(defmacro assq (item list) `(assoc ,item ,list :test #'eq))
+(defmacro rassq (item list) `(rassoc ,item ,list :test #'eq))
+(defmacro delq (item list) `(delete ,item ,list :test #'eq))
+(defmacro posq (item list) `(position ,item ,list :test #'eq))
+(defmacro neq (x y) `(not (eq ,x ,y)))
+
+
+(defun make-caxr (n form)
+ (if (< n 4)
+ `(,(nth n '(car cadr caddr cadddr)) ,form)
+ (make-caxr (- n 4) `(cddddr ,form))))
+
+(defun make-cdxr (n form)
+ (cond ((zerop n) form)
+ ((< n 5) `(,(nth n '(identity cdr cddr cdddr cddddr)) ,form))
+ (t (make-cdxr (- n 4) `(cddddr ,form)))))
+)
+
+(deftype non-negative-fixnum ()
+ '(and fixnum (integer 0 *)))
+
+(defun true (&rest ignore) (declare (ignore ignore)) t)
+(defun false (&rest ignore) (declare (ignore ignore)) nil)
+(defun zero (&rest ignore) (declare (ignore ignore)) 0)
+
+(defun make-plist (keys vals)
+ (if (null vals)
+ ()
+ (list* (car keys)
+ (car vals)
+ (make-plist (cdr keys) (cdr vals)))))
+
+(defun remtail (list tail)
+ (if (eq list tail) () (cons (car list) (remtail (cdr list) tail))))
+
+;;; ONCE-ONLY does the same thing as it does in zetalisp. I should have just
+;;; lifted it from there but I am honest. Not only that but this one is
+;;; written in Common Lisp. I feel a lot like bootstrapping, or maybe more
+;;; like rebuilding Rome.
+(defmacro once-only (vars &body body)
+ (let ((gensym-var (gensym))
+ (run-time-vars (gensym))
+ (run-time-vals (gensym))
+ (expand-time-val-forms ()))
+ (dolist (var vars)
+ (push `(if (or (symbolp ,var)
+ (numberp ,var)
+ (and (listp ,var)
+ (member (car ,var) '(quote function))))
+ ,var
+ (let ((,gensym-var (gensym)))
+ (push ,gensym-var ,run-time-vars)
+ (push ,var ,run-time-vals)
+ ,gensym-var))
+ expand-time-val-forms))
+ `(let* (,run-time-vars
+ ,run-time-vals
+ (wrapped-body
+ (let ,(mapcar #'list vars (reverse expand-time-val-forms))
+ ,@body)))
+ `(let ,(mapcar #'list (reverse ,run-time-vars)
+ (reverse ,run-time-vals))
+ ,wrapped-body))))
+
+(eval-when (compile load eval)
+(defun extract-declarations (body &optional environment)
+ ;;(declare (values documentation declarations body))
+ (let (documentation declarations form)
+ (when (and (stringp (car body))
+ (cdr body))
+ (setq documentation (pop body)))
+ (block outer
+ (loop
+ (when (null body) (return-from outer nil))
+ (setq form (car body))
+ (when (block inner
+ (loop (cond ((not (listp form))
+ (return-from outer nil))
+ ((eq (car form) 'declare)
+ (return-from inner 't))
+ (t
+ (multiple-value-bind (newform macrop)
+ (macroexpand-1 form environment)
+ (if (or (not (eq newform form)) macrop)
+ (setq form newform)
+ (return-from outer nil)))))))
+ (pop body)
+ (dolist (declaration (cdr form))
+ (push declaration declarations)))))
+ (values documentation
+ (and declarations `((declare ,.(nreverse declarations))))
+ body)))
+)
+
+(defun get-declaration (name declarations &optional default)
+ (dolist (d declarations default)
+ (dolist (form (cdr d))
+ (when (and (consp form) (eq (car form) name))
+ (return-from get-declaration (cdr form))))))
+
+
+#+Lucid
+(eval-when (compile load eval)
+ (eval `(defstruct ,(intern "FASLESCAPE" (find-package 'lucid)))))
+
+(defvar *keyword-package* (find-package 'keyword))
+
+(defun make-keyword (symbol)
+ (intern (symbol-name symbol) *keyword-package*))
+
+(eval-when (compile load eval)
+
+(defun string-append (&rest strings)
+ (setq strings (copy-list strings)) ;The explorer can't even
+ ;rplaca an &rest arg?
+ (do ((string-loc strings (cdr string-loc)))
+ ((null string-loc)
+ (apply #'concatenate 'string strings))
+ (rplaca string-loc (string (car string-loc)))))
+)
+
+(defun symbol-append (sym1 sym2 &optional (package *package*))
+ (intern (string-append sym1 sym2) package))
+
+(defmacro check-member (place list &key (test #'eql) (pretty-name place))
+ (once-only (place list)
+ `(or (member ,place ,list :test ,test)
+ (error "The value of ~A, ~S is not one of ~S."
+ ',pretty-name ,place ,list))))
+
+(defmacro alist-entry (alist key make-entry-fn)
+ (once-only (alist key)
+ `(or (assq ,key ,alist)
+ (progn (setf ,alist (cons (,make-entry-fn ,key) ,alist))
+ (car ,alist)))))
+
+;;; A simple version of destructuring-bind.
+
+;;; This does no more error checking than CAR and CDR themselves do. Some
+;;; attempt is made to be smart about preserving intermediate values. It
+;;; could be better, although the only remaining case should be easy for
+;;; the compiler to spot since it compiles to PUSH POP.
+;;;
+;;; Common Lisp BUG:
+;;; Common Lisp should have destructuring-bind.
+;;;
+(defmacro destructuring-bind (pattern form &body body)
+ (multiple-value-bind (ignore declares body)
+ (extract-declarations body)
+ (declare (ignore ignore))
+ (multiple-value-bind (setqs binds)
+ (destructure pattern form)
+ `(let ,binds
+ ,@declares
+ ,@setqs
+ (progn .destructure-form.)
+ . ,body))))
+
+(eval-when (compile load eval)
+(defun destructure (pattern form)
+ ;;(declare (values setqs binds))
+ (let ((*destructure-vars* ())
+ (setqs ()))
+ (declare (special *destructure-vars*))
+ (setq *destructure-vars* '(.destructure-form.)
+ setqs (list `(setq .destructure-form. ,form))
+ form '.destructure-form.)
+ (values (nconc setqs (nreverse (destructure-internal pattern form)))
+ (delete nil *destructure-vars*))))
+
+(defun destructure-internal (pattern form)
+ ;; When we are called, pattern must be a list. Form should be a symbol
+ ;; which we are free to setq containing the value to be destructured.
+ ;; Optimizations are performed for the last element of pattern cases.
+ ;; we assume that the compiler is smart about gensyms which are bound
+ ;; but only for a short period of time.
+ (declare (special *destructure-vars*))
+ (let ((gensym (gensym))
+ (pending-pops 0)
+ (var nil)
+ (setqs ()))
+ (labels
+ ((make-pop (var form pop-into)
+ (prog1
+ (cond ((zerop pending-pops)
+ `(progn ,(and var `(setq ,var (car ,form)))
+ ,(and pop-into `(setq ,pop-into (cdr ,form)))))
+ ((null pop-into)
+ (and var `(setq ,var ,(make-caxr pending-pops form))))
+ (t
+ `(progn (setq ,pop-into ,(make-cdxr pending-pops form))
+ ,(and var `(setq ,var (pop ,pop-into))))))
+ (setq pending-pops 0))))
+ (do ((pat pattern (cdr pat)))
+ ((null pat) ())
+ (if (symbolp (setq var (car pat)))
+ (progn
+ #-:coral (unless (memq var '(nil ignore))
+ (push var *destructure-vars*))
+ #+:coral (push var *destructure-vars*)
+ (cond ((null (cdr pat))
+ (push (make-pop var form ()) setqs))
+ ((symbolp (cdr pat))
+ (push (make-pop var form (cdr pat)) setqs)
+ (push (cdr pat) *destructure-vars*)
+ (return ()))
+ #-:coral
+ ((memq var '(nil ignore)) (incf pending-pops))
+ #-:coral
+ ((memq (cadr pat) '(nil ignore))
+ (push (make-pop var form ()) setqs)
+ (incf pending-pops 1))
+ (t
+ (push (make-pop var form form) setqs))))
+ (progn
+ (push `(let ((,gensym ()))
+ ,(make-pop gensym
+ form
+ (if (symbolp (cdr pat)) (cdr pat) form))
+ ,@(nreverse
+ (destructure-internal
+ (if (consp pat) (car pat) pat)
+ gensym)))
+ setqs)
+ (when (symbolp (cdr pat))
+ (push (cdr pat) *destructure-vars*)
+ (return)))))
+ setqs)))
+)
+
+
+(defmacro collecting-once (&key initial-value)
+ `(let* ((head ,initial-value)
+ (tail ,(and initial-value `(last head))))
+ (values #'(lambda (value)
+ (if (null head)
+ (setq head (setq tail (list value)))
+ (unless (memq value head)
+ (setq tail
+ (cdr (rplacd tail (list value)))))))
+ #'(lambda nil head))))
+
+(defmacro doplist ((key val) plist &body body &environment env)
+ (multiple-value-bind (doc decls bod)
+ (extract-declarations body env)
+ (declare (ignore doc))
+ `(let ((.plist-tail. ,plist) ,key ,val)
+ ,@decls
+ (loop (when (null .plist-tail.) (return nil))
+ (setq ,key (pop .plist-tail.))
+ (when (null .plist-tail.)
+ (error "Malformed plist in doplist, odd number of elements."))
+ (setq ,val (pop .plist-tail.))
+ (progn ,@bod)))))
+
+(defmacro if* (condition true &rest false)
+ `(if ,condition ,true (progn ,@false)))
+
+(defmacro dolist-carefully ((var list improper-list-handler) &body body)
+ `(let ((,var nil)
+ (.dolist-carefully. ,list))
+ (loop (when (null .dolist-carefully.) (return nil))
+ (if (consp .dolist-carefully.)
+ (progn
+ (setq ,var (pop .dolist-carefully.))
+ ,@body)
+ (,improper-list-handler)))))
+
+ ;;
+;;;;;; printing-random-thing
+ ;;
+;;; Similar to printing-random-object in the lisp machine but much simpler
+;;; and machine independent.
+(defmacro printing-random-thing ((thing stream) &body body)
+ #+cmu17
+ `(print-unreadable-object (,thing ,stream :identity t) ,@body)
+ #-cmu17
+ (once-only (thing stream)
+ `(progn
+ #+cmu
+ (when *print-readably*
+ (error "~S cannot be printed readably." ,thing))
+ (format ,stream "#<")
+ ,@body
+ (format ,stream " ")
+ (printing-random-thing-internal ,thing ,stream)
+ (format ,stream ">"))))
+
+(defun printing-random-thing-internal (thing stream)
+ (declare (ignore thing stream))
+ nil)
+
+ ;;
+;;;;;;
+ ;;
+
+(defun capitalize-words (string &optional (dashes-p t))
+ (let ((string (copy-seq (string string))))
+ (declare (string string))
+ (do* ((flag t flag)
+ (length (length string) length)
+ (char nil char)
+ (i 0 (+ i 1)))
+ ((= i length) string)
+ (setq char (elt string i))
+ (cond ((both-case-p char)
+ (if flag
+ (and (setq flag (lower-case-p char))
+ (setf (elt string i) (char-upcase char)))
+ (and (not flag) (setf (elt string i) (char-downcase char))))
+ (setq flag nil))
+ ((char-equal char #\-)
+ (setq flag t)
+ (unless dashes-p (setf (elt string i) #\space)))
+ (t (setq flag nil))))))
+
+#-(or lucid kcl)
+(eval-when (compile load eval)
+;(warn "****** Things will go faster if you fix define-compiler-macro")
+)
+
+#-cmu
+(defmacro define-compiler-macro (name arglist &body body)
+ #+(or lucid kcl)
+ `(#+lucid lcl:def-compiler-macro #+kcl si::define-compiler-macro
+ ,name ,arglist
+ ,@body)
+ #-(or kcl lucid)
+ (declare (ignore name arglist body))
+ #-(or kcl lucid)
+ nil)
+
+
+;;;
+;;; FIND-CLASS
+;;;
+;;; This is documented in the CLOS specification.
+;;;
+(defvar *find-class* (make-hash-table :test #'eq))
+
+(defun make-constant-function (value)
+ #'(lambda (object)
+ (declare (ignore object))
+ value))
+
+(defun function-returning-nil (x)
+ (declare (ignore x))
+ nil)
+
+(defun function-returning-t (x)
+ (declare (ignore x))
+ t)
+
+(defmacro find-class-cell-class (cell)
+ `(car ,cell))
+
+(defmacro find-class-cell-predicate (cell)
+ `(cadr ,cell))
+
+(defmacro find-class-cell-make-instance-function-keys (cell)
+ `(cddr ,cell))
+
+(defmacro make-find-class-cell (class-name)
+ (declare (ignore class-name))
+ '(list* nil #'function-returning-nil nil))
+
+(defun find-class-cell (symbol &optional dont-create-p)
+ (or (gethash symbol *find-class*)
+ (unless dont-create-p
+ (unless (legal-class-name-p symbol)
+ (error "~S is not a legal class name." symbol))
+ (setf (gethash symbol *find-class*) (make-find-class-cell symbol)))))
+
+(defvar *create-classes-from-internal-structure-definitions-p* t)
+
+(defun find-class-from-cell (symbol cell &optional (errorp t))
+ (or (find-class-cell-class cell)
+ (and *create-classes-from-internal-structure-definitions-p*
+ (structure-type-p symbol)
+ (find-structure-class symbol))
+ (cond ((null errorp) nil)
+ ((legal-class-name-p symbol)
+ (error "No class named: ~S." symbol))
+ (t
+ (error "~S is not a legal class name." symbol)))))
+
+(defun find-class-predicate-from-cell (symbol cell &optional (errorp t))
+ (unless (find-class-cell-class cell)
+ (find-class-from-cell symbol cell errorp))
+ (find-class-cell-predicate cell))
+
+(defun legal-class-name-p (x)
+ (and (symbolp x)
+ (not (keywordp x))))
+
+(defun find-class (symbol &optional (errorp t) environment)
+ (declare (ignore environment))
+ (find-class-from-cell
+ symbol (find-class-cell symbol errorp) errorp))
+
+(defun find-class-predicate (symbol &optional (errorp t) environment)
+ (declare (ignore environment))
+ (find-class-predicate-from-cell
+ symbol (find-class-cell symbol errorp) errorp))
+
+(defvar *boot-state* nil) ; duplicate defvar to defs.lisp
+
+; Use this definition in any CL implementation supporting
+; both define-compiler-macro and load-time-value.
+#+cmu ; Note that in CMU, lisp:find-class /= pcl:find-class
+(define-compiler-macro find-class (&whole form
+ symbol &optional (errorp t) environment)
+ (declare (ignore environment))
+ (if (and (constantp symbol)
+ (legal-class-name-p (eval symbol))
+ (constantp errorp)
+ (member *boot-state* '(braid complete)))
+ (let ((symbol (eval symbol))
+ (errorp (not (null (eval errorp))))
+ (class-cell (make-symbol "CLASS-CELL")))
+ `(let ((,class-cell (load-time-value (find-class-cell ',symbol))))
+ (or (find-class-cell-class ,class-cell)
+ #-cmu17
+ (find-class-from-cell ',symbol ,class-cell ,errorp)
+ #+cmu17
+ ,(if errorp
+ `(find-class-from-cell ',symbol ,class-cell t)
+ `(and (kernel:class-cell-class
+ ',(kernel:find-class-cell symbol))
+ (find-class-from-cell ',symbol ,class-cell nil))))))
+ form))
+
+#-setf
+(defsetf find-class (symbol &optional (errorp t) environment) (new-value)
+ (declare (ignore errorp environment))
+ `(SETF\ PCL\ FIND-CLASS ,new-value ,symbol))
+
+(defun #-setf SETF\ PCL\ FIND-CLASS #+setf (setf find-class) (new-value symbol)
+ (if (legal-class-name-p symbol)
+ (let ((cell (find-class-cell symbol)))
+ (setf (find-class-cell-class cell) new-value)
+ (when (or (eq *boot-state* 'complete)
+ (eq *boot-state* 'braid))
+ #+cmu17
+ (let ((lclass (kernel:layout-class (class-wrapper new-value))))
+ (setf (lisp:class-name lclass) (class-name new-value))
+ (unless (eq (lisp:find-class symbol nil) lclass)
+ (setf (lisp:find-class symbol) lclass)))
+
+ (setf (find-class-cell-predicate cell)
+ (symbol-function (class-predicate-name new-value)))
+ (when (and new-value (not (forward-referenced-class-p new-value)))
+
+ (dolist (keys+aok (find-class-cell-make-instance-function-keys cell))
+ (update-initialize-info-internal
+ (initialize-info new-value (car keys+aok) nil (cdr keys+aok))
+ 'make-instance-function)))))
+ (error "~S is not a legal class name." symbol)))
+
+#-setf
+(defsetf find-class-predicate (symbol &optional (errorp t) environment) (new-value)
+ (declare (ignore errorp environment))
+ `(SETF\ PCL\ FIND-CLASS-PREDICATE ,new-value ,symbol))
+
+(defun #-setf SETF\ PCL\ FIND-CLASS-PREDICATE #+setf (setf find-class-predicate)
+ (new-value symbol)
+ (if (legal-class-name-p symbol)
+ (setf (find-class-cell-predicate (find-class-cell symbol)) new-value)
+ (error "~S is not a legal class name." symbol)))
+
+(defun find-wrapper (symbol)
+ (class-wrapper (find-class symbol)))
+
+#|| ; Anything that used this should use eval instead.
+(defun reduce-constant (old)
+ (let ((new (eval old)))
+ (if (eq new old)
+ new
+ (if (constantp new)
+ (reduce-constant new)
+ new))))
+||#
+
+(defmacro gathering1 (gatherer &body body)
+ `(gathering ((.gathering1. ,gatherer))
+ (macrolet ((gather1 (x) `(gather ,x .gathering1.)))
+ ,@body)))
+
+;;;
+;;;
+;;;
+(defmacro vectorizing (&key (size 0))
+ `(let* ((limit ,size)
+ (result (make-array limit))
+ (index 0))
+ (values #'(lambda (value)
+ (if (= index limit)
+ (error "vectorizing more elements than promised.")
+ (progn
+ (setf (svref result index) value)
+ (incf index)
+ value)))
+ #'(lambda () result))))
+
+;;;
+;;; These are augmented definitions of list-elements and list-tails from
+;;; iterate.lisp. These versions provide the extra :by keyword which can
+;;; be used to specify the step function through the list.
+;;;
+(defmacro *list-elements (list &key (by #'cdr))
+ `(let ((tail ,list))
+ #'(lambda (finish)
+ (if (endp tail)
+ (funcall finish)
+ (prog1 (car tail)
+ (setq tail (funcall ,by tail)))))))
+
+(defmacro *list-tails (list &key (by #'cdr))
+ `(let ((tail ,list))
+ #'(lambda (finish)
+ (prog1 (if (endp tail)
+ (funcall finish)
+ tail)
+ (setq tail (funcall ,by tail))))))
+
+(defmacro function-funcall (form &rest args)
+ #-cmu `(funcall ,form ,@args)
+ #+cmu `(funcall (the function ,form) ,@args))
+
+(defmacro function-apply (form &rest args)
+ #-cmu `(apply ,form ,@args)
+ #+cmu `(apply (the function ,form) ,@args))
+
+
+;;;
+;;; Convert a function name to its standard setf function name. We have to
+;;; do this hack because not all Common Lisps have yet converted to having
+;;; setf function specs.
+;;;
+;;; In a port that does have setf function specs you can use those just by
+;;; making the obvious simple changes to these functions. The rest of PCL
+;;; believes that there are function names like (SETF <foo>), this is the
+;;; only place that knows about this hack.
+;;;
+(eval-when (compile load eval)
+; In 15e (and also 16c), using the built in setf mechanism costs
+; a hash table lookup every time a setf function is called.
+; Uncomment the next line to use the built in setf mechanism.
+;#+cmu (pushnew :setf *features*)
+)
+
+(eval-when (compile load eval)
+
+#-setf
+(defvar *setf-function-names* (make-hash-table :size 200 :test #'eq))
+
+(defun get-setf-function-name (name)
+ #+setf `(setf ,name)
+ #-setf
+ (or (gethash name *setf-function-names*)
+ (setf (gethash name *setf-function-names*)
+ (let ((pkg (symbol-package name)))
+ (if pkg
+ (intern (format nil
+ "SETF ~A ~A"
+ (package-name pkg)
+ (symbol-name name))
+ *the-pcl-package*)
+ (make-symbol (format nil "SETF ~A" (symbol-name name))))))))
+
+;;;
+;;; Call this to define a setf macro for a function with the same behavior as
+;;; specified by the SETF function cleanup proposal. Specifically, this will
+;;; cause: (SETF (FOO a b) x) to expand to (|SETF FOO| x a b).
+;;;
+;;; do-standard-defsetf A macro interface for use at top level
+;;; in files. Unfortunately, users may
+;;; have to use this for a while.
+;;;
+;;; do-standard-defsetfs-for-defclass A special version called by defclass.
+;;;
+;;; do-standard-defsetf-1 A functional interface called by the
+;;; above, defmethod and defgeneric.
+;;; Since this is all a crock anyways,
+;;; users are free to call this as well.
+;;;
+(defmacro do-standard-defsetf (&rest function-names)
+ `(eval-when (compile load eval)
+ (dolist (fn-name ',function-names) (do-standard-defsetf-1 fn-name))))
+
+(defun do-standard-defsetfs-for-defclass (accessors)
+ (dolist (name accessors) (do-standard-defsetf-1 name)))
+
+(defun do-standard-defsetf-1 (function-name)
+ #+setf
+ (declare (ignore function-name))
+ #+setf nil
+ #-setf
+ (unless (and (setfboundp function-name)
+ (get function-name 'standard-setf))
+ (setf (get function-name 'standard-setf) t)
+ (let* ((setf-function-name (get-setf-function-name function-name)))
+
+ #+Genera
+ (let ((fn #'(lambda (form)
+ (lt::help-defsetf
+ '(&rest accessor-args) '(new-value) function-name 'nil
+ `(`(,',setf-function-name ,new-value .,accessor-args))
+ form))))
+ (setf (get function-name 'lt::setf-method) fn
+ (get function-name 'lt::setf-method-internal) fn))
+
+ #+Lucid
+ (lucid::set-simple-setf-method
+ function-name
+ #'(lambda (form new-value)
+ (let* ((bindings (mapcar #'(lambda (x) `(,(gensym) ,x))
+ (cdr form)))
+ (vars (mapcar #'car bindings)))
+ ;; This may wrap spurious LET bindings around some form,
+ ;; but the PQC compiler will unwrap then.
+ `(LET (,.bindings)
+ (,setf-function-name ,new-value . ,vars)))))
+
+ #+kcl
+ (let ((helper (gensym)))
+ (setf (macro-function helper)
+ #'(lambda (form env)
+ (declare (ignore env))
+ (let* ((loc-args (butlast (cdr form)))
+ (bindings (mapcar #'(lambda (x) `(,(gensym) ,x)) loc-args))
+ (vars (mapcar #'car bindings)))
+ `(let ,bindings
+ (,setf-function-name ,(car (last form)) ,@vars)))))
+ (eval `(defsetf ,function-name ,helper)))
+ #+Xerox
+ (flet ((setf-expander (body env)
+ (declare (ignore env))
+ (let ((temps
+ (mapcar #'(lambda (x) (declare (ignore x)) (gensym))
+ (cdr body)))
+ (forms (cdr body))
+ (vars (list (gensym))))
+ (values temps
+ forms
+ vars
+ `(,setf-function-name ,@vars ,@temps)
+ `(,function-name ,@temps)))))
+ (let ((setf-method-expander (intern (concatenate 'string
+ (symbol-name function-name)
+ "-setf-expander")
+ (symbol-package function-name))))
+ (setf (get function-name :setf-method-expander) setf-method-expander
+ (symbol-function setf-method-expander) #'setf-expander)))
+
+ #-(or Genera Lucid kcl Xerox)
+ (eval `(defsetf ,function-name (&rest accessor-args) (new-value)
+ (let* ((bindings (mapcar #'(lambda (x) `(,(gensym) ,x)) accessor-args))
+ (vars (mapcar #'car bindings)))
+ `(let ,bindings
+ (,',setf-function-name ,new-value ,@vars)))))
+
+ )))
+
+(defun setfboundp (symbol)
+ #+Genera (not (null (get-properties (symbol-plist symbol)
+ 'lt::(derived-setf-function trivial-setf-method
+ setf-equivalence setf-method))))
+ #+Lucid (locally
+ (declare (special lucid::*setf-inverse-table*
+ lucid::*simple-setf-method-table*
+ lucid::*setf-method-expander-table*))
+ (or (gethash symbol lucid::*setf-inverse-table*)
+ (gethash symbol lucid::*simple-setf-method-table*)
+ (gethash symbol lucid::*setf-method-expander-table*)))
+ #+kcl (or (get symbol 'si::setf-method)
+ (get symbol 'si::setf-update-fn)
+ (get symbol 'si::setf-lambda))
+ #+Xerox (or (get symbol :setf-inverse)
+ (get symbol 'il:setf-inverse)
+ (get symbol 'il:setfn)
+ (get symbol :shared-setf-inverse)
+ (get symbol :setf-method-expander)
+ (get symbol 'il:setf-method-expander))
+ #+:coral (or (get symbol 'ccl::setf-inverse)
+ (get symbol 'ccl::setf-method-expander))
+ #+cmu (fboundp `(setf ,symbol))
+ #-(or Genera Lucid KCL Xerox :coral cmu) nil)
+
+);eval-when
+
+
+;;;
+;;; PCL, like user code, must endure the fact that we don't have a properly
+;;; working setf. Many things work because they get mentioned by a defclass
+;;; or defmethod before they are used, but others have to be done by hand.
+;;;
+(do-standard-defsetf
+ class-wrapper ;***
+ generic-function-name
+ method-function-plist
+ method-function-get
+ plist-value
+ object-plist
+ gdefinition
+ slot-value-using-class
+ )
+
+(defsetf slot-value set-slot-value)
+
+(defvar *redefined-functions* nil)
+
+(defmacro original-definition (name)
+ `(get ,name ':definition-before-pcl))
+
+(defun redefine-function (name new)
+ (pushnew name *redefined-functions*)
+ (unless (original-definition name)
+ (setf (original-definition name)
+ (symbol-function name)))
+ (setf (symbol-function name)
+ (symbol-function new)))
+
diff --git a/gcl/pcl/makefile b/gcl/pcl/makefile
new file mode 100644
index 000000000..5fbdb7815
--- /dev/null
+++ b/gcl/pcl/makefile
@@ -0,0 +1,40 @@
+# makefile for making pcl -- W. Schelter.
+
+# Directions:
+# make -f makefile.gcl compile
+# make -f makefile.gcl saved_pcl
+
+#LISP=../unixport/saved_gcl
+
+
+SETUP='(load "sys-package.lisp")' \
+ '(setq *features* (delete (quote kcl) *features*))'\
+ '(load "defsys.lisp")(push (quote kcl) *features*)' \
+ '(setq pcl::*default-pathname-extensions* (cons "lisp" "o"))' \
+ '(setq pcl::*pathname-extensions* (cons "lisp" "o"))' \
+ '(load "sys-proclaim.lisp")(compiler::emit-fn t)'
+
+compile:
+ echo ${SETUP} '(pcl::compile-pcl)' | $(LISP)
+
+saved_gcl_pcl:
+ echo ${SETUP} '(pcl::load-pcl)(si::save-system "saved_gcl_pcl")' | $(LISP)
+
+clean:
+ rm -f *.o *.fn
+
+
+# remake the sys-package.lisp and sys-proclaim.lisp files
+# Those files may be empty on a first build.
+remake-sys-files:
+ echo ${SETUP} '(pcl::load-pcl)(in-package "PCL")(renew-sys-files)' | $(LISP)
+ cp sys-proclaim.lisp xxx
+ cat xxx | sed -e "s/COMPILER::CMP-ANON//g" > sys-proclaim.lisp
+ rm xxx
+
+
+tar:
+ make -f makefile.gcl tar1 DIR=`pwd`
+
+tar1:
+ (cd .. ; tar cvf - `basename ${DIR}` | gzip -c > `basename ${DIR}`.tgz)
diff --git a/gcl/pcl/methods.lisp b/gcl/pcl/methods.lisp
new file mode 100644
index 000000000..a8ec01a4c
--- /dev/null
+++ b/gcl/pcl/methods.lisp
@@ -0,0 +1,1646 @@
+;;;-*-Mode:LISP; Package: PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+(defmethod print-object (instance stream)
+ (printing-random-thing (instance stream)
+ (let ((name (class-name (class-of instance))))
+ (if name
+ (format stream "~S" name)
+ (format stream "Instance")))))
+
+(defmethod print-object ((class class) stream)
+ (named-object-print-function class stream))
+
+(defmethod print-object ((slotd slot-definition) stream)
+ (named-object-print-function slotd stream))
+
+(defun named-object-print-function (instance stream
+ &optional (extra nil extra-p))
+ (printing-random-thing (instance stream)
+ (if extra-p
+ (format stream "~A ~S ~:S"
+ (capitalize-words (class-name (class-of instance)))
+ (slot-value-or-default instance 'name)
+ extra)
+ (format stream "~A ~S"
+ (capitalize-words (class-name (class-of instance)))
+ (slot-value-or-default instance 'name)))))
+
+(defmethod print-object ((mc standard-method-combination) stream)
+ (printing-random-thing (mc stream)
+ (format stream
+ "Method-Combination ~S ~S"
+ (slot-value-or-default mc 'type)
+ (slot-value-or-default mc 'options))))
+
+
+;;;
+;;;
+;;;
+(defmethod shared-initialize :after ((slotd standard-slot-definition) slot-names &key)
+ (declare (ignore slot-names))
+ (with-slots (allocation class)
+ slotd
+ (setq allocation (if (eq allocation :class) class allocation))))
+
+(defmethod shared-initialize :after ((slotd structure-slot-definition) slot-names
+ &key (allocation :instance))
+ (declare (ignore slot-names))
+ (unless (eq allocation :instance)
+ (error "structure slots must have :instance allocation")))
+
+(defmethod inform-type-system-about-class ((class structure-class) (name t))
+ nil)
+
+;;;
+;;; METHODS
+;;;
+;;; Methods themselves are simple inanimate objects. Most properties of
+;;; methods are immutable, methods cannot be reinitialized. The following
+;;; properties of methods can be changed:
+;;; METHOD-GENERIC-FUNCTION
+;;; METHOD-FUNCTION ??
+;;;
+;;;
+
+(defmethod method-function ((method standard-method))
+ (or (slot-value method 'function)
+ (let ((fmf (slot-value method 'fast-function)))
+ (unless fmf ; the :before shared-initialize method prevents this
+ (error "~S doesn't seem to have a method-function" method))
+ (setf (slot-value method 'function)
+ (method-function-from-fast-function fmf)))))
+
+(defmethod accessor-method-class ((method standard-accessor-method))
+ (car (slot-value method 'specializers)))
+
+(defmethod accessor-method-class ((method standard-writer-method))
+ (cadr (slot-value method 'specializers)))
+
+(defmethod print-object ((method standard-method) stream)
+ (printing-random-thing (method stream)
+ (if (slot-boundp method 'generic-function)
+ (let ((generic-function (method-generic-function method))
+ (class-name (capitalize-words (class-name (class-of method)))))
+ (format stream "~A ~S ~{~S ~}~:S"
+ class-name
+ (and generic-function (generic-function-name generic-function))
+ (method-qualifiers method)
+ (unparse-specializers method)))
+ (call-next-method))))
+
+(defmethod print-object ((method standard-accessor-method) stream)
+ (printing-random-thing (method stream)
+ (if (slot-boundp method 'generic-function)
+ (let ((generic-function (method-generic-function method))
+ (class-name (capitalize-words (class-name (class-of method)))))
+ (format stream "~A ~S, slot:~S, ~:S"
+ class-name
+ (and generic-function (generic-function-name generic-function))
+ (accessor-method-slot-name method)
+ (unparse-specializers method)))
+ (call-next-method))))
+
+;;;
+;;; INITIALIZATION
+;;;
+;;; Error checking is done in before methods. Because of the simplicity of
+;;; standard method objects the standard primary method can fill the slots.
+;;;
+;;; Methods are not reinitializable.
+;;;
+
+(defmethod reinitialize-instance ((method standard-method) &rest initargs)
+ (declare (ignore initargs))
+ (error "Attempt to reinitialize the method ~S.~%~
+ Method objects cannot be reinitialized."
+ method))
+
+(defmethod legal-documentation-p ((object standard-method) x)
+ (if (or (null x) (stringp x))
+ t
+ "a string or NULL"))
+
+(defmethod legal-lambda-list-p ((object standard-method) x)
+ (declare (ignore x))
+ t)
+
+(defmethod legal-method-function-p ((object standard-method) x)
+ (if (functionp x)
+ t
+ "a function"))
+
+(defmethod legal-qualifiers-p ((object standard-method) x)
+ (flet ((improper-list ()
+ (return-from legal-qualifiers-p "Is not a proper list.")))
+ (dolist-carefully (q x improper-list)
+ (let ((ok (legal-qualifier-p object q)))
+ (unless (eq ok t)
+ (return-from legal-qualifiers-p
+ (format nil "Contains ~S which ~A" q ok)))))
+ t))
+
+(defmethod legal-qualifier-p ((object standard-method) x)
+ (if (and x (atom x))
+ t
+ "is not a non-null atom"))
+
+(defmethod legal-slot-name-p ((object standard-method) x)
+ (cond ((not (symbolp x)) "is not a symbol and so cannot be bound")
+ ((keywordp x) "is a keyword and so cannot be bound")
+ ((memq x '(t nil)) "cannot be bound")
+ ((constantp x) "is a constant and so cannot be bound")
+ (t t)))
+
+(defmethod legal-specializers-p ((object standard-method) x)
+ (flet ((improper-list ()
+ (return-from legal-specializers-p "Is not a proper list.")))
+ (dolist-carefully (s x improper-list)
+ (let ((ok (legal-specializer-p object s)))
+ (unless (eq ok t)
+ (return-from legal-specializers-p
+ (format nil "Contains ~S which ~A" s ok)))))
+ t))
+
+(defvar *allow-experimental-specializers-p* nil)
+
+(defmethod legal-specializer-p ((object standard-method) x)
+ (if (if *allow-experimental-specializers-p*
+ (specializerp x)
+ (or (classp x)
+ (eql-specializer-p x)))
+ t
+ "is neither a class object nor an eql specializer"))
+
+(defmethod shared-initialize :before ((method standard-method)
+ slot-names
+ &key qualifiers
+ lambda-list
+ specializers
+ function
+ fast-function
+ documentation)
+ (declare (ignore slot-names))
+ (flet ((lose (initarg value string)
+ (error "When initializing the method ~S:~%~
+ The ~S initialization argument was: ~S.~%~
+ which ~A."
+ method initarg value string)))
+ (let ((check-qualifiers (legal-qualifiers-p method qualifiers))
+ (check-lambda-list (legal-lambda-list-p method lambda-list))
+ (check-specializers (legal-specializers-p method specializers))
+ (check-function (legal-method-function-p method (or function
+ fast-function)))
+ (check-documentation (legal-documentation-p method documentation)))
+ (unless (eq check-qualifiers t)
+ (lose :qualifiers qualifiers check-qualifiers))
+ (unless (eq check-lambda-list t)
+ (lose :lambda-list lambda-list check-lambda-list))
+ (unless (eq check-specializers t)
+ (lose :specializers specializers check-specializers))
+ (unless (eq check-function t)
+ (lose :function function check-function))
+ (unless (eq check-documentation t)
+ (lose :documentation documentation check-documentation)))))
+
+(defmethod shared-initialize :before ((method standard-accessor-method)
+ slot-names
+ &key slot-name slot-definition)
+ (declare (ignore slot-names))
+ (unless slot-definition
+ (let ((legalp (legal-slot-name-p method slot-name)))
+ (unless (eq legalp t)
+ (error "The value of the :SLOT-NAME initarg ~A." legalp)))))
+
+(defmethod shared-initialize :after ((method standard-method) slot-names
+ &rest initargs
+ &key qualifiers method-spec plist)
+ (declare (ignore slot-names method-spec plist))
+ (initialize-method-function initargs nil method)
+ (setf (plist-value method 'qualifiers) qualifiers)
+ #+ignore
+ (setf (slot-value method 'closure-generator)
+ (method-function-closure-generator (slot-value method 'function))))
+
+(defmethod shared-initialize :after ((method standard-accessor-method)
+ slot-names
+ &key)
+ (declare (ignore slot-names))
+ (with-slots (slot-name slot-definition)
+ method
+ (unless slot-definition
+ (let ((class (accessor-method-class method)))
+ (when (slot-class-p class)
+ (setq slot-definition (find slot-name (class-direct-slots class)
+ :key #'slot-definition-name)))))
+ (when (and slot-definition (null slot-name))
+ (setq slot-name (slot-definition-name slot-definition)))))
+
+(defmethod method-qualifiers ((method standard-method))
+ (plist-value method 'qualifiers))
+
+
+
+(defvar *the-class-generic-function* (find-class 'generic-function))
+(defvar *the-class-standard-generic-function* (find-class 'standard-generic-function))
+
+
+
+(defmethod print-object ((generic-function generic-function) stream)
+ (named-object-print-function
+ generic-function
+ stream
+ (if (slot-boundp generic-function 'methods)
+ (list (length (generic-function-methods generic-function)))
+ "?")))
+
+(defmethod shared-initialize :before
+ ((generic-function standard-generic-function)
+ slot-names
+ &key (name nil namep)
+ (lambda-list () lambda-list-p)
+ argument-precedence-order
+ declarations
+ documentation
+ (method-class nil method-class-supplied-p)
+ (method-combination nil method-combination-supplied-p))
+ (declare (ignore slot-names
+ declarations argument-precedence-order documentation
+ lambda-list lambda-list-p))
+
+ (when namep
+ (set-function-name generic-function name))
+
+ (flet ((initarg-error (initarg value string)
+ (error "When initializing the generic-function ~S:~%~
+ The ~S initialization argument was: ~A.~%~
+ It must be ~A."
+ generic-function initarg value string)))
+ (cond (method-class-supplied-p
+ (when (symbolp method-class)
+ (setq method-class (find-class method-class)))
+ (unless (and (classp method-class)
+ (*subtypep (class-eq-specializer method-class)
+ *the-class-method*))
+ (initarg-error :method-class
+ method-class
+ "a subclass of the class METHOD"))
+ (setf (slot-value generic-function 'method-class) method-class))
+ ((slot-boundp generic-function 'method-class))
+ (t
+ (initarg-error :method-class
+ "not supplied"
+ "a subclass of the class METHOD")))
+ (cond (method-combination-supplied-p
+ (unless (method-combination-p method-combination)
+ (initarg-error :method-combination
+ method-combination
+ "a method combination object")))
+ ((slot-boundp generic-function 'method-combination))
+ (t
+ (initarg-error :method-combination
+ "not supplied"
+ "a method combination object")))))
+
+
+#||
+(defmethod reinitialize-instance ((generic-function standard-generic-function)
+ &rest initargs
+ &key name
+ lambda-list
+ argument-precedence-order
+ declarations
+ documentation
+ method-class
+ method-combination)
+ (declare (ignore documentation declarations argument-precedence-order
+ lambda-list name method-class method-combination))
+ (macrolet ((add-initarg (check name slot-name)
+ `(unless ,check
+ (push (slot-value generic-function ,slot-name) initargs)
+ (push ,name initargs))))
+; (add-initarg name :name 'name)
+; (add-initarg lambda-list :lambda-list 'lambda-list)
+; (add-initarg argument-precedence-order
+; :argument-precedence-order
+; 'argument-precedence-order)
+; (add-initarg declarations :declarations 'declarations)
+; (add-initarg documentation :documentation 'documentation)
+; (add-initarg method-class :method-class 'method-class)
+; (add-initarg method-combination :method-combination 'method-combination)
+ (apply #'call-next-method generic-function initargs)))
+||#
+
+
+;;;
+;;; These three are scheduled for demolition.
+;;;
+(defmethod remove-named-method (generic-function-name argument-specifiers
+ &optional extra)
+ (let ((generic-function ())
+ (method ()))
+ (cond ((or (null (fboundp generic-function-name))
+ (not (generic-function-p
+ (setq generic-function
+ (symbol-function generic-function-name)))))
+ (error "~S does not name a generic-function."
+ generic-function-name))
+ ((null (setq method (get-method generic-function
+ extra
+ (parse-specializers
+ argument-specifiers)
+ nil)))
+ (error "There is no method for the generic-function ~S~%~
+ which matches the argument-specifiers ~S."
+ generic-function
+ argument-specifiers))
+ (t
+ (remove-method generic-function method)))))
+
+(defun real-add-named-method (generic-function-name
+ qualifiers
+ specializers
+ lambda-list
+ &rest other-initargs)
+ #+copy-&rest-arg (setq other-initargs (copy-list other-initargs))
+ ;; What about changing the class of the generic-function if there is
+ ;; one. Whose job is that anyways. Do we need something kind of
+ ;; like class-for-redefinition?
+ (let* ((generic-function
+ (ensure-generic-function generic-function-name))
+ (specs (parse-specializers specializers))
+; (existing (get-method generic-function qualifiers specs nil))
+ (proto (method-prototype-for-gf generic-function-name))
+ (new (apply #'make-instance (class-of proto)
+ :qualifiers qualifiers
+ :specializers specs
+ :lambda-list lambda-list
+ other-initargs)))
+; (when existing (remove-method generic-function existing))
+ (add-method generic-function new)))
+
+
+(defun make-specializable (function-name &key (arglist nil arglistp))
+ (cond ((not (null arglistp)))
+ ((not (fboundp function-name)))
+ ((fboundp 'function-arglist)
+ ;; function-arglist exists, get the arglist from it.
+ (setq arglist (function-arglist function-name)))
+ (t
+ (error
+ "The :arglist argument to make-specializable was not supplied~%~
+ and there is no version of FUNCTION-ARGLIST defined for this~%~
+ port of Portable CommonLoops.~%~
+ You must either define a version of FUNCTION-ARGLIST (which~%~
+ should be easy), and send it off to the Portable CommonLoops~%~
+ people or you should call make-specializable again with the~%~
+ :arglist keyword to specify the arglist.")))
+ (let ((original (and (fboundp function-name)
+ (symbol-function function-name)))
+ (generic-function (make-instance 'standard-generic-function
+ :name function-name))
+ (nrequireds 0))
+ (if (generic-function-p original)
+ original
+ (progn
+ (dolist (arg arglist)
+ (if (memq arg lambda-list-keywords)
+ (return)
+ (incf nrequireds)))
+ (setf (gdefinition function-name) generic-function)
+ (set-function-name generic-function function-name)
+ (when arglistp
+ (setf (gf-pretty-arglist generic-function) arglist))
+ (when original
+ (add-named-method function-name
+ ()
+ (make-list nrequireds :initial-element 't)
+ arglist
+ (list :function
+ #'(lambda (args next-methods)
+ (declare (ignore next-methods))
+ (apply original args)))))
+ generic-function))))
+
+
+
+(defun real-get-method (generic-function qualifiers specializers
+ &optional (errorp t))
+ (let ((hit
+ (dolist (method (generic-function-methods generic-function))
+ (when (and (equal qualifiers (method-qualifiers method))
+ (every #'same-specializer-p specializers
+ (method-specializers method)))
+ (return method)))))
+ (cond (hit hit)
+ ((null errorp) nil)
+ (t
+ (error "No method on ~S with qualifiers ~:S and specializers ~:S."
+ generic-function qualifiers specializers)))))
+
+
+;;;
+;;; Compute various information about a generic-function's arglist by looking
+;;; at the argument lists of the methods. The hair for trying not to use
+;;; &rest arguments lives here.
+;;; The values returned are:
+;;; number-of-required-arguments
+;;; the number of required arguments to this generic-function's
+;;; discriminating function
+;;; &rest-argument-p
+;;; whether or not this generic-function's discriminating
+;;; function takes an &rest argument.
+;;; specialized-argument-positions
+;;; a list of the positions of the arguments this generic-function
+;;; specializes (e.g. for a classical generic-function this is the
+;;; list: (1)).
+;;;
+(defmethod compute-discriminating-function-arglist-info
+ ((generic-function standard-generic-function))
+ ;;(declare (values number-of-required-arguments &rest-argument-p
+ ;; specialized-argument-postions))
+ (let ((number-required nil)
+ (restp nil)
+ (specialized-positions ())
+ (methods (generic-function-methods generic-function)))
+ (dolist (method methods)
+ (multiple-value-setq (number-required restp specialized-positions)
+ (compute-discriminating-function-arglist-info-internal
+ generic-function method number-required restp specialized-positions)))
+ (values number-required restp (sort specialized-positions #'<))))
+
+(defun compute-discriminating-function-arglist-info-internal
+ (generic-function method number-of-requireds restp
+ specialized-argument-positions)
+ (declare (ignore generic-function) (type (or null fixnum) number-of-requireds))
+ (let ((requireds 0))
+ (declare (fixnum requireds))
+ ;; Go through this methods arguments seeing how many are required,
+ ;; and whether there is an &rest argument.
+ (dolist (arg (method-lambda-list method))
+ (cond ((eq arg '&aux) (return))
+ ((memq arg '(&optional &rest &key))
+ (return (setq restp t)))
+ ((memq arg lambda-list-keywords))
+ (t (incf requireds))))
+ ;; Now go through this method's type specifiers to see which
+ ;; argument positions are type specified. Treat T specially
+ ;; in the usual sort of way. For efficiency don't bother to
+ ;; keep specialized-argument-positions sorted, rather depend
+ ;; on our caller to do that.
+ (iterate ((type-spec (list-elements (method-specializers method)))
+ (pos (interval :from 0)))
+ (unless (eq type-spec *the-class-t*)
+ (pushnew pos specialized-argument-positions)))
+ ;; Finally merge the values for this method into the values
+ ;; for the exisiting methods and return them. Note that if
+ ;; num-of-requireds is NIL it means this is the first method
+ ;; and we depend on that.
+ (values (min (or number-of-requireds requireds) requireds)
+ (or restp
+ (and number-of-requireds (/= number-of-requireds requireds)))
+ specialized-argument-positions)))
+
+(defun make-discriminating-function-arglist (number-required-arguments restp)
+ (nconc (gathering ((args (collecting)))
+ (iterate ((i (interval :from 0 :below number-required-arguments)))
+ (gather (intern (format nil "Discriminating Function Arg ~D" i))
+ args)))
+ (when restp
+ `(&rest ,(intern "Discriminating Function &rest Arg")))))
+
+
+;;;
+;;;
+;;;
+
+(defmethod generic-function-lambda-list ((gf generic-function))
+ (gf-lambda-list gf))
+
+(defmethod gf-fast-method-function-p ((gf standard-generic-function))
+ (gf-info-fast-mf-p (slot-value gf 'arg-info)))
+
+(defmethod initialize-instance :after ((gf standard-generic-function)
+ &key (lambda-list nil lambda-list-p)
+ argument-precedence-order)
+ (with-slots (arg-info)
+ gf
+ (if lambda-list-p
+ (set-arg-info gf
+ :lambda-list lambda-list
+ :argument-precedence-order argument-precedence-order)
+ (set-arg-info gf))
+ (when (arg-info-valid-p arg-info)
+ (update-dfun gf))))
+
+(defmethod reinitialize-instance :after ((gf standard-generic-function)
+ &rest args
+ &key (lambda-list nil lambda-list-p)
+ (argument-precedence-order
+ nil argument-precedence-order-p))
+ (with-slots (arg-info)
+ gf
+ (if lambda-list-p
+ (if argument-precedence-order-p
+ (set-arg-info gf
+ :lambda-list lambda-list
+ :argument-precedence-order argument-precedence-order)
+ (set-arg-info gf
+ :lambda-list lambda-list))
+ (set-arg-info gf))
+ (when (and (arg-info-valid-p arg-info)
+ args
+ (or lambda-list-p (cddr args)))
+ (update-dfun gf))))
+
+;;;
+;;;
+;;;
+
+(proclaim '(special *lazy-dfun-compute-p*))
+
+(defun set-methods (gf methods)
+ (setf (generic-function-methods gf) nil)
+ (loop (when (null methods) (return gf))
+ (real-add-method gf (pop methods) methods)))
+
+(defun real-add-method (generic-function method &optional skip-dfun-update-p)
+ (if (method-generic-function method)
+ (error "The method ~S is already part of the generic~@
+ function ~S. It can't be added to another generic~@
+ function until it is removed from the first one."
+ method (method-generic-function method))
+
+ (let* ((name (generic-function-name generic-function))
+ (qualifiers (method-qualifiers method))
+ (specializers (method-specializers method))
+ (existing (get-method generic-function qualifiers specializers nil)))
+ ;;
+ ;; If there is already a method like this one then we must
+ ;; get rid of it before proceeding. Note that we call the
+ ;; generic function remove-method to remove it rather than
+ ;; doing it in some internal way.
+ ;;
+ (when existing (remove-method generic-function existing))
+ ;;
+ (setf (method-generic-function method) generic-function)
+ (pushnew method (generic-function-methods generic-function))
+ (dolist (specializer specializers)
+ (add-direct-method specializer method))
+ (set-arg-info generic-function :new-method method)
+ (unless skip-dfun-update-p
+ (when (member name
+ '(make-instance default-initargs
+ allocate-instance shared-initialize initialize-instance))
+ (update-make-instance-function-table (type-class (car specializers))))
+ (update-dfun generic-function))
+ method)))
+
+(defun real-remove-method (generic-function method)
+ (if (neq generic-function (method-generic-function method))
+ (error "The method ~S is attached to the generic function~@
+ ~S. It can't be removed from the generic function~@
+ to which it is not attached."
+ method (method-generic-function method))
+ (let* ((name (generic-function-name generic-function))
+ (specializers (method-specializers method))
+ (methods (generic-function-methods generic-function))
+ (new-methods (remove method methods)))
+ (setf (method-generic-function method) nil)
+ (setf (generic-function-methods generic-function) new-methods)
+ (dolist (specializer (method-specializers method))
+ (remove-direct-method specializer method))
+ (set-arg-info generic-function)
+ (when (member name '(make-instance default-initargs
+ allocate-instance shared-initialize initialize-instance))
+ (update-make-instance-function-table (type-class (car specializers))))
+ (update-dfun generic-function)
+ generic-function)))
+
+
+(defun compute-applicable-methods-function (generic-function arguments)
+ (values (compute-applicable-methods-using-types
+ generic-function
+ (types-from-arguments generic-function arguments 'eql))))
+
+(defmethod compute-applicable-methods
+ ((generic-function generic-function) arguments)
+ (values (compute-applicable-methods-using-types
+ generic-function
+ (types-from-arguments generic-function arguments 'eql))))
+
+(defmethod compute-applicable-methods-using-classes
+ ((generic-function generic-function) classes)
+ (compute-applicable-methods-using-types
+ generic-function
+ (types-from-arguments generic-function classes 'class-eq)))
+
+(defun proclaim-incompatible-superclasses (classes)
+ (setq classes (mapcar #'(lambda (class)
+ (if (symbolp class)
+ (find-class class)
+ class))
+ classes))
+ (dolist (class classes)
+ (dolist (other-class classes)
+ (unless (eq class other-class)
+ (pushnew other-class (class-incompatible-superclass-list class))))))
+
+(defun superclasses-compatible-p (class1 class2)
+ (let ((cpl1 (class-precedence-list class1))
+ (cpl2 (class-precedence-list class2)))
+ (dolist (sc1 cpl1 t)
+ (dolist (ic (class-incompatible-superclass-list sc1))
+ (when (memq ic cpl2)
+ (return-from superclasses-compatible-p nil))))))
+
+(mapc
+ #'proclaim-incompatible-superclasses
+ '(;; superclass class
+ (built-in-class std-class structure-class) ; direct subclasses of pcl-class
+ (standard-class funcallable-standard-class)
+ ;; superclass metaobject
+ (class eql-specializer class-eq-specializer method method-combination
+ generic-function slot-definition)
+ ;; metaclass built-in-class
+ (number sequence character ; direct subclasses of t, but not array
+ standard-object structure-object) ; or symbol
+ (number array character symbol ; direct subclasses of t, but not sequence
+ standard-object structure-object)
+ (complex float rational) ; direct subclasses of number
+ (integer ratio) ; direct subclasses of rational
+ (list vector) ; direct subclasses of sequence
+ (cons null) ; direct subclasses of list
+ (string bit-vector) ; direct subclasses of vector
+ ))
+
+
+
+
+(defmethod same-specializer-p ((specl1 specializer) (specl2 specializer))
+ nil)
+
+(defmethod same-specializer-p ((specl1 class) (specl2 class))
+ (eq specl1 specl2))
+
+(defmethod specializer-class ((specializer class))
+ specializer)
+
+(defmethod same-specializer-p ((specl1 class-eq-specializer)
+ (specl2 class-eq-specializer))
+ (eq (specializer-class specl1) (specializer-class specl2)))
+
+(defmethod same-specializer-p ((specl1 eql-specializer)
+ (specl2 eql-specializer))
+ (eq (specializer-object specl1) (specializer-object specl2)))
+
+(defmethod specializer-class ((specializer eql-specializer))
+ (class-of (slot-value specializer 'object)))
+
+(defvar *in-gf-arg-info-p* nil)
+(setf (gdefinition 'arg-info-reader)
+ (let ((mf (initialize-method-function
+ (make-internal-reader-method-function
+ 'standard-generic-function 'arg-info)
+ t)))
+ #'(lambda (&rest args) (funcall mf args nil))))
+
+(defun types-from-arguments (generic-function arguments &optional type-modifier)
+ (multiple-value-bind (nreq applyp metatypes nkeys arg-info)
+ (get-generic-function-info generic-function)
+ (declare (ignore applyp metatypes nkeys))
+ (let ((types-rev nil))
+ (dotimes (i nreq)
+ i
+ (unless arguments
+ (error "The function ~S requires at least ~D arguments"
+ (generic-function-name generic-function)
+ nreq))
+ (let ((arg (pop arguments)))
+ (push (if type-modifier `(,type-modifier ,arg) arg) types-rev)))
+ (values (nreverse types-rev) arg-info))))
+
+(defun get-wrappers-from-classes (nkeys wrappers classes metatypes)
+ (let* ((w wrappers) (w-tail w) (mt-tail metatypes))
+ (dolist (class (if (listp classes) classes (list classes)))
+ (unless (eq 't (car mt-tail))
+ (let ((c-w (class-wrapper class)))
+ (unless c-w (return-from get-wrappers-from-classes nil))
+ (if (eql nkeys 1)
+ (setq w c-w)
+ (setf (car w-tail) c-w
+ w-tail (cdr w-tail)))))
+ (setq mt-tail (cdr mt-tail)))
+ w))
+
+(defun sdfun-for-caching (gf classes)
+ (let ((types (mapcar #'class-eq-type classes)))
+ (multiple-value-bind (methods all-applicable-and-sorted-p)
+ (compute-applicable-methods-using-types gf types)
+ (function-funcall (get-secondary-dispatch-function1
+ gf methods types nil t all-applicable-and-sorted-p)
+ nil (mapcar #'class-wrapper classes)))))
+
+(defun value-for-caching (gf classes)
+ (let ((methods (compute-applicable-methods-using-types
+ gf (mapcar #'class-eq-type classes))))
+ (method-function-get (or (method-fast-function (car methods))
+ (method-function (car methods)))
+ :constant-value)))
+
+(defun default-secondary-dispatch-function (generic-function)
+ #'(lambda (&rest args)
+ #+copy-&rest-arg (setq args (copy-list args))
+ (let ((methods (compute-applicable-methods generic-function args)))
+ (if methods
+ (let ((emf (get-effective-method-function generic-function methods)))
+ (invoke-emf emf args))
+ (apply #'no-applicable-method generic-function args)))))
+
+(defun list-eq (x y)
+ (loop (when (atom x) (return (eq x y)))
+ (when (atom y) (return nil))
+ (unless (eq (car x) (car y)) (return nil))
+ (setq x (cdr x) y (cdr y))))
+
+(defvar *std-cam-methods* nil)
+
+(defun compute-applicable-methods-emf (generic-function)
+ (if (eq *boot-state* 'complete)
+ (let* ((cam (gdefinition 'compute-applicable-methods))
+ (cam-methods (compute-applicable-methods-using-types
+ cam (list `(eql ,generic-function) t))))
+ (values (get-effective-method-function cam cam-methods)
+ (list-eq cam-methods
+ (or *std-cam-methods*
+ (setq *std-cam-methods*
+ (compute-applicable-methods-using-types
+ cam (list `(eql ,cam) t)))))))
+ (values #'compute-applicable-methods-function t)))
+
+(defun compute-applicable-methods-emf-std-p (gf)
+ (gf-info-c-a-m-emf-std-p (gf-arg-info gf)))
+
+(defvar *old-c-a-m-gf-methods* nil)
+
+(defun update-all-c-a-m-gf-info (c-a-m-gf)
+ (let ((methods (generic-function-methods c-a-m-gf)))
+ (if (and *old-c-a-m-gf-methods*
+ (every #'(lambda (old-method)
+ (member old-method methods))
+ *old-c-a-m-gf-methods*))
+ (let ((gfs-to-do nil)
+ (gf-classes-to-do nil))
+ (dolist (method methods)
+ (unless (member method *old-c-a-m-gf-methods*)
+ (let ((specl (car (method-specializers method))))
+ (if (eql-specializer-p specl)
+ (pushnew (specializer-object specl) gfs-to-do)
+ (pushnew (specializer-class specl) gf-classes-to-do)))))
+ (map-all-generic-functions
+ #'(lambda (gf)
+ (when (or (member gf gfs-to-do)
+ (dolist (class gf-classes-to-do nil)
+ (member class (class-precedence-list (class-of gf)))))
+ (update-c-a-m-gf-info gf)))))
+ (map-all-generic-functions #'update-c-a-m-gf-info))
+ (setq *old-c-a-m-gf-methods* methods)))
+
+(defun update-gf-info (gf)
+ (update-c-a-m-gf-info gf)
+ (update-gf-simple-accessor-type gf))
+
+(defun update-c-a-m-gf-info (gf)
+ (unless (early-gf-p gf)
+ (multiple-value-bind (c-a-m-emf std-p)
+ (compute-applicable-methods-emf gf)
+ (let ((arg-info (gf-arg-info gf)))
+ (setf (gf-info-static-c-a-m-emf arg-info) c-a-m-emf)
+ (setf (gf-info-c-a-m-emf-std-p arg-info) std-p)))))
+
+(defun update-gf-simple-accessor-type (gf)
+ (let ((arg-info (gf-arg-info gf)))
+ (setf (gf-info-simple-accessor-type arg-info)
+ (let* ((methods (generic-function-methods gf))
+ (class (and methods (class-of (car methods))))
+ (type (and class (cond ((eq class *the-class-standard-reader-method*)
+ 'reader)
+ ((eq class *the-class-standard-writer-method*)
+ 'writer)
+ ((eq class *the-class-standard-boundp-method*)
+ 'boundp)))))
+ (when (and (gf-info-c-a-m-emf-std-p arg-info)
+ type
+ (dolist (method (cdr methods) t)
+ (unless (eq class (class-of method)) (return nil)))
+ (eq (generic-function-method-combination gf)
+ *standard-method-combination*))
+ type)))))
+
+(defun get-accessor-method-function (gf type class slotd)
+ (let* ((std-method (standard-svuc-method type))
+ (str-method (structure-svuc-method type))
+ (types1 `((eql ,class) (class-eq ,class) (eql ,slotd)))
+ (types (if (eq type 'writer) `(t ,@types1) types1))
+ (methods (compute-applicable-methods-using-types gf types))
+ (std-p (null (cdr methods))))
+ (values
+ (if std-p
+ (get-optimized-std-accessor-method-function class slotd type)
+ (get-accessor-from-svuc-method-function
+ class slotd
+ (get-secondary-dispatch-function
+ gf methods types
+ `((,(car (or (member std-method methods)
+ (member str-method methods)
+ (error "error in get-accessor-method-function")))
+ ,(get-optimized-std-slot-value-using-class-method-function
+ class slotd type)))
+ (unless (and (eq type 'writer)
+ (dolist (method methods t)
+ (unless (eq (car (method-specializers method))
+ *the-class-t*)
+ (return nil))))
+ (let ((wrappers (list (wrapper-of class)
+ (class-wrapper class)
+ (wrapper-of slotd))))
+ (if (eq type 'writer)
+ (cons (class-wrapper *the-class-t*) wrappers)
+ wrappers))))
+ type))
+ std-p)))
+
+;used by optimize-slot-value-by-class-p (vector.lisp)
+(defun update-slot-value-gf-info (gf type)
+ (unless *new-class*
+ (update-std-or-str-methods gf type))
+ (when (and (standard-svuc-method type) (structure-svuc-method type))
+ (flet ((update-class (class)
+ (when (class-finalized-p class)
+ (dolist (slotd (class-slots class))
+ (compute-slot-accessor-info slotd type gf)))))
+ (if *new-class*
+ (update-class *new-class*)
+ (map-all-classes #'update-class 'slot-object)))))
+
+(defvar *standard-slot-value-using-class-method* nil)
+(defvar *standard-setf-slot-value-using-class-method* nil)
+(defvar *standard-slot-boundp-using-class-method* nil)
+(defvar *structure-slot-value-using-class-method* nil)
+(defvar *structure-setf-slot-value-using-class-method* nil)
+(defvar *structure-slot-boundp-using-class-method* nil)
+
+(defun standard-svuc-method (type)
+ (case type
+ (reader *standard-slot-value-using-class-method*)
+ (writer *standard-setf-slot-value-using-class-method*)
+ (boundp *standard-slot-boundp-using-class-method*)))
+
+(defun set-standard-svuc-method (type method)
+ (case type
+ (reader (setq *standard-slot-value-using-class-method* method))
+ (writer (setq *standard-setf-slot-value-using-class-method* method))
+ (boundp (setq *standard-slot-boundp-using-class-method* method))))
+
+(defun structure-svuc-method (type)
+ (case type
+ (reader *structure-slot-value-using-class-method*)
+ (writer *structure-setf-slot-value-using-class-method*)
+ (boundp *structure-slot-boundp-using-class-method*)))
+
+(defun set-structure-svuc-method (type method)
+ (case type
+ (reader (setq *structure-slot-value-using-class-method* method))
+ (writer (setq *structure-setf-slot-value-using-class-method* method))
+ (boundp (setq *structure-slot-boundp-using-class-method* method))))
+
+(defun update-std-or-str-methods (gf type)
+ (dolist (method (generic-function-methods gf))
+ (let ((specls (method-specializers method)))
+ (when (and (or (not (eq type 'writer))
+ (eq (pop specls) *the-class-t*))
+ (every #'classp specls))
+ (cond ((and (eq (class-name (car specls))
+ 'std-class)
+ (eq (class-name (cadr specls))
+ 'standard-object)
+ (eq (class-name (caddr specls))
+ 'standard-effective-slot-definition))
+ (set-standard-svuc-method type method))
+ ((and (eq (class-name (car specls))
+ 'structure-class)
+ (eq (class-name (cadr specls))
+ 'structure-object)
+ (eq (class-name (caddr specls))
+ 'structure-effective-slot-definition))
+ (set-structure-svuc-method type method)))))))
+
+(defun mec-all-classes-internal (spec precompute-p)
+ (cons (specializer-class spec)
+ (and (classp spec)
+ precompute-p
+ (not (or (eq spec *the-class-t*)
+ (eq spec *the-class-slot-object*)
+ (eq spec *the-class-standard-object*)
+ (eq spec *the-class-structure-object*)))
+ (let ((sc (class-direct-subclasses spec)))
+ (when sc
+ (mapcan #'(lambda (class)
+ (mec-all-classes-internal class precompute-p))
+ sc))))))
+
+(defun mec-all-classes (spec precompute-p)
+ (let ((classes (mec-all-classes-internal spec precompute-p)))
+ (if (null (cdr classes))
+ classes
+ (let* ((a-classes (cons nil classes))
+ (tail classes))
+ (loop (when (null (cdr tail))
+ (return (cdr a-classes)))
+ (let ((class (cadr tail))
+ (ttail (cddr tail)))
+ (if (dolist (c ttail nil)
+ (when (eq class c) (return t)))
+ (setf (cdr tail) (cddr tail))
+ (setf tail (cdr tail)))))))))
+
+(defun mec-all-class-lists (spec-list precompute-p)
+ (if (null spec-list)
+ (list nil)
+ (let* ((car-all-classes (mec-all-classes (car spec-list) precompute-p))
+ (all-class-lists (mec-all-class-lists (cdr spec-list) precompute-p)))
+ (mapcan #'(lambda (list)
+ (mapcar #'(lambda (c) (cons c list)) car-all-classes))
+ all-class-lists))))
+
+(defun make-emf-cache (generic-function valuep cache classes-list new-class)
+ (let* ((arg-info (gf-arg-info generic-function))
+ (nkeys (arg-info-nkeys arg-info))
+ (metatypes (arg-info-metatypes arg-info))
+ (wrappers (unless (eq nkeys 1) (make-list nkeys)))
+ (precompute-p (gf-precompute-dfun-and-emf-p arg-info))
+ (default '(default)))
+ (flet ((add-class-list (classes)
+ (when (or (null new-class) (memq new-class classes))
+ (let ((wrappers (get-wrappers-from-classes
+ nkeys wrappers classes metatypes)))
+ (when (and wrappers
+ (eq default (probe-cache cache wrappers default)))
+ (let ((value (cond ((eq valuep t)
+ (sdfun-for-caching generic-function classes))
+ ((eq valuep :constant-value)
+ (value-for-caching generic-function classes)))))
+ (setq cache (fill-cache cache wrappers value t))))))))
+ (if classes-list
+ (mapc #'add-class-list classes-list)
+ (dolist (method (generic-function-methods generic-function))
+ (mapc #'add-class-list
+ (mec-all-class-lists (method-specializers method) precompute-p))))
+ cache)))
+
+(defmacro class-test (arg class)
+ (cond ((eq class *the-class-t*)
+ 't)
+ ((eq class *the-class-slot-object*)
+ #-(or new-kcl-wrapper cmu17)
+ `(not (eq *the-class-built-in-class*
+ (wrapper-class (std-instance-wrapper (class-of ,arg)))))
+ #+new-kcl-wrapper
+ `(or (std-instance-p ,arg)
+ (fsc-instance-p ,arg))
+ #+cmu17
+ `(not (lisp:typep (lisp:class-of ,arg) 'lisp:built-in-class)))
+ #-new-kcl-wrapper
+ ((eq class *the-class-standard-object*)
+ `(or (std-instance-p ,arg) (fsc-instance-p ,arg)))
+ #-cmu17
+ ((eq class *the-class-structure-object*)
+ `(memq ',class (class-precedence-list (class-of ,arg))))
+ ;; TYPEP is now sometimes faster than doing memq of the cpl
+ (t
+ `(typep ,arg ',(class-name class)))))
+
+(defmacro class-eq-test (arg class)
+ `(eq (class-of ,arg) ',class))
+
+(defmacro eql-test (arg object)
+ `(eql ,arg ',object))
+
+(defun dnet-methods-p (form)
+ (and (consp form)
+ (or (eq (car form) 'methods)
+ (eq (car form) 'unordered-methods))))
+
+(defmacro scase (arg &rest clauses) ; This is case, but without gensyms
+ `(let ((.case-arg. ,arg))
+ (cond ,@(mapcar #'(lambda (clause)
+ (list* (cond ((null (car clause))
+ nil)
+ ((consp (car clause))
+ (if (null (cdar clause))
+ `(eql .case-arg. ',(caar clause))
+ `(member .case-arg. ',(car clause))))
+ ((member (car clause) '(t otherwise))
+ `t)
+ (t
+ `(eql .case-arg. ',(car clause))))
+ nil
+ (cdr clause)))
+ clauses))))
+
+(defmacro mcase (arg &rest clauses) `(scase ,arg ,@clauses))
+
+(defun generate-discrimination-net (generic-function methods types sorted-p)
+ (let* ((arg-info (gf-arg-info generic-function))
+ (precedence (arg-info-precedence arg-info)))
+ (generate-discrimination-net-internal
+ generic-function methods types
+ #'(lambda (methods known-types)
+ (if (or sorted-p
+ (block one-order-p
+ (let ((sorted-methods nil))
+ (map-all-orders
+ (copy-list methods) precedence
+ #'(lambda (methods)
+ (when sorted-methods (return-from one-order-p nil))
+ (setq sorted-methods methods)))
+ (setq methods sorted-methods))
+ t))
+ `(methods ,methods ,known-types)
+ `(unordered-methods ,methods ,known-types)))
+ #'(lambda (position type true-value false-value)
+ (let ((arg (dfun-arg-symbol position)))
+ (if (eq (car type) 'eql)
+ (let* ((false-case-p (and (consp false-value)
+ (or (eq (car false-value) 'scase)
+ (eq (car false-value) 'mcase))
+ (eq arg (cadr false-value))))
+ (false-clauses (if false-case-p
+ (cddr false-value)
+ `((t ,false-value))))
+ (case-sym (if (and (dnet-methods-p true-value)
+ (if false-case-p
+ (eq (car false-value) 'mcase)
+ (dnet-methods-p false-value)))
+ 'mcase
+ 'scase))
+ (type-sym `(,(cadr type))))
+ `(,case-sym ,arg
+ (,type-sym ,true-value)
+ ,@false-clauses))
+ `(if ,(let ((arg (dfun-arg-symbol position)))
+ (case (car type)
+ (class `(class-test ,arg ,(cadr type)))
+ (class-eq `(class-eq-test ,arg ,(cadr type)))))
+ ,true-value
+ ,false-value))))
+ #'identity)))
+
+(defun class-from-type (type)
+ (if (or (atom type) (eq (car type) 't))
+ *the-class-t*
+ (case (car type)
+ (and (dolist (type (cdr type) *the-class-t*)
+ (when (and (consp type) (not (eq (car type) 'not)))
+ (return (class-from-type type)))))
+ (not *the-class-t*)
+ (eql (class-of (cadr type)))
+ (class-eq (cadr type))
+ (class (cadr type)))))
+
+(defun precompute-effective-methods (gf caching-p &optional classes-list-p)
+ (let* ((arg-info (gf-arg-info gf))
+ (methods (generic-function-methods gf))
+ (precedence (arg-info-precedence arg-info))
+ (*in-precompute-effective-methods-p* t)
+ (classes-list nil))
+ (generate-discrimination-net-internal
+ gf methods nil
+ #'(lambda (methods known-types)
+ (when methods
+ (when classes-list-p
+ (push (mapcar #'class-from-type known-types) classes-list))
+ (let ((no-eql-specls-p (not (methods-contain-eql-specializer-p methods))))
+ (map-all-orders
+ methods precedence
+ #'(lambda (methods)
+ (get-secondary-dispatch-function1
+ gf methods known-types
+ nil caching-p no-eql-specls-p))))))
+ #'(lambda (position type true-value false-value)
+ (declare (ignore position type true-value false-value))
+ nil)
+ #'(lambda (type)
+ (if (and (consp type) (eq (car type) 'eql))
+ `(class-eq ,(class-of (cadr type)))
+ type)))
+ classes-list))
+
+; we know that known-type implies neither new-type nor `(not ,new-type)
+(defun augment-type (new-type known-type)
+ (if (or (eq known-type 't)
+ (eq (car new-type) 'eql))
+ new-type
+ (let ((so-far (if (and (consp known-type) (eq (car known-type) 'and))
+ (cdr known-type)
+ (list known-type))))
+ (unless (eq (car new-type) 'not)
+ (setq so-far
+ (mapcan #'(lambda (type)
+ (unless (*subtypep new-type type)
+ (list type)))
+ so-far)))
+ (if (null so-far)
+ new-type
+ `(and ,new-type ,@so-far)))))
+
+#+lcl3.0 (dont-use-production-compiler)
+
+(defun generate-discrimination-net-internal
+ (gf methods types methods-function test-function type-function)
+ #+cmu
+ (declare (type function methods-function test-function type-function))
+ (let* ((arg-info (gf-arg-info gf))
+ (precedence (arg-info-precedence arg-info))
+ (nreq (arg-info-number-required arg-info))
+ (metatypes (arg-info-metatypes arg-info)))
+ (labels ((do-column (p-tail contenders known-types)
+ (if p-tail
+ (let* ((position (car p-tail))
+ (known-type (or (nth position types) t)))
+ (if (eq (nth position metatypes) 't)
+ (do-column (cdr p-tail) contenders
+ (cons (cons position known-type) known-types))
+ (do-methods p-tail contenders
+ known-type () known-types)))
+ (funcall methods-function contenders
+ (let ((k-t (make-list nreq)))
+ (dolist (index+type known-types)
+ (setf (nth (car index+type) k-t) (cdr index+type)))
+ k-t))))
+ (do-methods (p-tail contenders known-type winners known-types)
+ ;;
+ ;; <contenders>
+ ;; is a (sorted) list of methods that must be discriminated
+ ;; <known-type>
+ ;; is the type of this argument, constructed from tests already made.
+ ;; <winners>
+ ;; is a (sorted) list of methods that are potentially applicable
+ ;; after the discrimination has been made.
+ ;;
+ (if (null contenders)
+ (do-column (cdr p-tail) winners
+ (cons (cons (car p-tail) known-type) known-types))
+ (let* ((position (car p-tail))
+ (method (car contenders))
+ (specl (nth position (method-specializers method)))
+ (type (funcall type-function (type-from-specializer specl))))
+ (multiple-value-bind (app-p maybe-app-p)
+ (specializer-applicable-using-type-p type known-type)
+ (flet ((determined-to-be (truth-value)
+ (if truth-value app-p (not maybe-app-p)))
+ (do-if (truth &optional implied)
+ (let ((ntype (if truth type `(not ,type))))
+ (do-methods p-tail
+ (cdr contenders)
+ (if implied
+ known-type
+ (augment-type ntype known-type))
+ (if truth
+ (append winners `(,method))
+ winners)
+ known-types))))
+ (cond ((determined-to-be nil) (do-if nil t))
+ ((determined-to-be t) (do-if t t))
+ (t (funcall test-function position type
+ (do-if t) (do-if nil))))))))))
+ (do-column precedence methods ()))))
+
+#+lcl3.0 (use-previous-compiler)
+
+(defun compute-secondary-dispatch-function (generic-function net &optional
+ method-alist wrappers)
+ (function-funcall (compute-secondary-dispatch-function1 generic-function net)
+ method-alist wrappers))
+
+(defvar *eq-case-table-limit* 15)
+(defvar *case-table-limit* 10)
+
+(defun compute-mcase-parameters (case-list)
+ (unless (eq 't (caar (last case-list)))
+ (error "The key for the last case arg to mcase was not T"))
+ (let* ((eq-p (dolist (case case-list t)
+ (unless (or (eq (car case) 't)
+ (symbolp (caar case)))
+ (return nil))))
+ (len (1- (length case-list)))
+ (type (cond ((= len 1)
+ :simple)
+ ((<= len
+ (if eq-p
+ *eq-case-table-limit*
+ *case-table-limit*))
+ :assoc)
+ (t
+ :hash-table))))
+ (list eq-p type)))
+
+(defmacro mlookup (key info default &optional eq-p type)
+ (unless (or (eq eq-p 't) (null eq-p))
+ (error "Invalid eq-p argument"))
+ (ecase type
+ (:simple
+ `(if (,(if eq-p 'eq 'eql) ,key (car ,info))
+ (cdr ,info)
+ ,default))
+ (:assoc
+ `(dolist (e ,info ,default)
+ (when (,(if eq-p 'eq 'eql) (car e) ,key)
+ (return (cdr e)))))
+ (:hash-table
+ `(gethash ,key ,info ,default))))
+
+(defun net-test-converter (form)
+ (if (atom form)
+ (default-test-converter form)
+ (case (car form)
+ ((invoke-effective-method-function invoke-fast-method-call)
+ '.call.)
+ (methods
+ '.methods.)
+ (unordered-methods
+ '.umethods.)
+ (mcase
+ `(mlookup ,(cadr form) nil nil ,@(compute-mcase-parameters (cddr form))))
+ (t (default-test-converter form)))))
+
+(defun net-code-converter (form)
+ (if (atom form)
+ (default-code-converter form)
+ (case (car form)
+ ((methods unordered-methods)
+ (let ((gensym (gensym)))
+ (values gensym
+ (list gensym))))
+ (mcase
+ (let ((mp (compute-mcase-parameters (cddr form)))
+ (gensym (gensym)) (default (gensym)))
+ (values `(mlookup ,(cadr form) ,gensym ,default ,@mp)
+ (list gensym default))))
+ (t
+ (default-code-converter form)))))
+
+(defun net-constant-converter (form generic-function)
+ (or (let ((c (methods-converter form generic-function)))
+ (when c (list c)))
+ (if (atom form)
+ (default-constant-converter form)
+ (case (car form)
+ (mcase
+ (let* ((mp (compute-mcase-parameters (cddr form)))
+ (list (mapcar #'(lambda (clause)
+ (let ((key (car clause))
+ (meth (cadr clause)))
+ (cons (if (consp key) (car key) key)
+ (methods-converter
+ meth generic-function))))
+ (cddr form)))
+ (default (car (last list))))
+ (list (list* ':mcase mp (nbutlast list))
+ (cdr default))))
+ (t
+ (default-constant-converter form))))))
+
+(defun methods-converter (form generic-function)
+ (cond ((and (consp form) (eq (car form) 'methods))
+ (cons '.methods.
+ (get-effective-method-function1 generic-function (cadr form))))
+ ((and (consp form) (eq (car form) 'unordered-methods))
+ (default-secondary-dispatch-function generic-function))))
+
+(defun convert-methods (constant method-alist wrappers)
+ (if (and (consp constant)
+ (eq (car constant) '.methods.))
+ (funcall (the function (cdr constant)) method-alist wrappers)
+ constant))
+
+(defun convert-table (constant method-alist wrappers)
+ (cond ((and (consp constant)
+ (eq (car constant) ':mcase))
+ (let ((alist (mapcar #'(lambda (k+m)
+ (cons (car k+m)
+ (convert-methods (cdr k+m)
+ method-alist wrappers)))
+ (cddr constant)))
+ (mp (cadr constant)))
+ (ecase (cadr mp)
+ (:simple
+ (car alist))
+ (:assoc
+ alist)
+ (:hash-table
+ (let ((table (make-hash-table :test (if (car mp) 'eq 'eql))))
+ (dolist (k+m alist)
+ (setf (gethash (car k+m) table) (cdr k+m)))
+ table)))))))
+
+(defun compute-secondary-dispatch-function1 (generic-function net
+ &optional function-p)
+ (cond
+ ((and (eq (car net) 'methods) (not function-p))
+ (get-effective-method-function1 generic-function (cadr net)))
+ (t
+ (let* ((name (generic-function-name generic-function))
+ (arg-info (gf-arg-info generic-function))
+ (metatypes (arg-info-metatypes arg-info))
+ (applyp (arg-info-applyp arg-info))
+ (fmc-arg-info (cons (length metatypes) applyp)))
+ (multiple-value-bind
+ (cfunction constants)
+ (get-function1 (make-dispatch-lambda
+ function-p metatypes applyp
+ `((locally (declare #.*optimize-speed*)
+ (let ((emf ,net))
+ ,(make-emf-call metatypes applyp 'emf)))))
+ #'net-test-converter
+ #'net-code-converter
+ #'(lambda (form)
+ (net-constant-converter form generic-function)))
+ #'(lambda (method-alist wrappers)
+ (let* ((alist (list nil))
+ (alist-tail alist))
+ (dolist (constant constants)
+ (let* ((a (or (dolist (a alist nil)
+ (when (eq (car a) constant)
+ (return a)))
+ (cons constant
+ (or (convert-table
+ constant method-alist wrappers)
+ (convert-methods
+ constant method-alist wrappers)))))
+ (new (list a)))
+ (setf (cdr alist-tail) new)
+ (setf alist-tail new)))
+ (let ((function (apply cfunction (mapcar #'cdr (cdr alist)))))
+ (if function-p
+ function
+ (make-fast-method-call
+ :function (set-function-name function `(sdfun-method ,name))
+ :arg-info fmc-arg-info))))))))))
+
+(defvar *show-make-unordered-methods-emf-calls* nil)
+
+(defun make-unordered-methods-emf (generic-function methods)
+ (when *show-make-unordered-methods-emf-calls*
+ (format t "~&make-unordered-methods-emf ~s~%"
+ (generic-function-name generic-function)))
+ #'(lambda (&rest args)
+ #+copy-&rest-arg (setq args (copy-list args))
+ (let* ((types (types-from-arguments generic-function args 'eql))
+ (smethods (sort-applicable-methods generic-function methods types))
+ (emf (get-effective-method-function generic-function smethods)))
+ (invoke-emf emf args))))
+
+
+;;;
+;;; The value returned by compute-discriminating-function is a function
+;;; object. It is called a discriminating function because it is called
+;;; when the generic function is called and its role is to discriminate
+;;; on the arguments to the generic function and then call appropriate
+;;; method functions.
+;;;
+;;; A discriminating function can only be called when it is installed as
+;;; the funcallable instance function of the generic function for which
+;;; it was computed.
+;;;
+;;; More precisely, if compute-discriminating-function is called with an
+;;; argument <gf1>, and returns a result <df1>, that result must not be
+;;; passed to apply or funcall directly. Rather, <df1> must be stored as
+;;; the funcallable instance function of the same generic function <gf1>
+;;; (using set-funcallable-instance-function). Then the generic function
+;;; can be passed to funcall or apply.
+;;;
+;;; An important exception is that methods on this generic function are
+;;; permitted to return a function which itself ends up calling the value
+;;; returned by a more specific method. This kind of `encapsulation' of
+;;; discriminating function is critical to many uses of the MOP.
+;;;
+;;; As an example, the following canonical case is legal:
+;;;
+;;; (defmethod compute-discriminating-function ((gf my-generic-function))
+;;; (let ((std (call-next-method)))
+;;; #'(lambda (arg)
+;;; (print (list 'call-to-gf gf arg))
+;;; (funcall std arg))))
+;;;
+;;; Because many discriminating functions would like to use a dynamic
+;;; strategy in which the precise discriminating function changes with
+;;; time it is important to specify how a discriminating function is
+;;; permitted itself to change the funcallable instance function of the
+;;; generic function.
+;;;
+;;; Discriminating functions may set the funcallable instance function
+;;; of the generic function, but the new value must be generated by making
+;;; a call to COMPUTE-DISCRIMINATING-FUNCTION. This is to ensure that any
+;;; more specific methods which may have encapsulated the discriminating
+;;; function will get a chance to encapsulate the new, inner discriminating
+;;; function.
+;;;
+;;; This implies that if a discriminating function wants to modify itself
+;;; it should first store some information in the generic function proper,
+;;; and then call compute-discriminating-function. The appropriate method
+;;; on compute-discriminating-function will see the information stored in
+;;; the generic function and generate a discriminating function accordingly.
+;;;
+;;; The following is an example of a discriminating function which modifies
+;;; itself in accordance with this protocol:
+;;;
+;;; (defmethod compute-discriminating-function ((gf my-generic-function))
+;;; #'(lambda (arg)
+;;; (cond (<some condition>
+;;; <store some info in the generic function>
+;;; (set-funcallable-instance-function
+;;; gf
+;;; (compute-discriminating-function gf))
+;;; (funcall gf arg))
+;;; (t
+;;; <call-a-method-of-gf>))))
+;;;
+;;; Whereas this code would not be legal:
+;;;
+;;; (defmethod compute-discriminating-function ((gf my-generic-function))
+;;; #'(lambda (arg)
+;;; (cond (<some condition>
+;;; (set-funcallable-instance-function
+;;; gf
+;;; #'(lambda (a) ..))
+;;; (funcall gf arg))
+;;; (t
+;;; <call-a-method-of-gf>))))
+;;;
+;;; NOTE: All the examples above assume that all instances of the class
+;;; my-generic-function accept only one argument.
+;;;
+;;;
+;;;
+;;;
+(defun slot-value-using-class-dfun (class object slotd)
+ (declare (ignore class))
+ (function-funcall (slot-definition-reader-function slotd) object))
+
+(defun setf-slot-value-using-class-dfun (new-value class object slotd)
+ (declare (ignore class))
+ (function-funcall (slot-definition-writer-function slotd) new-value object))
+
+(defun slot-boundp-using-class-dfun (class object slotd)
+ (declare (ignore class))
+ (function-funcall (slot-definition-boundp-function slotd) object))
+
+(defmethod compute-discriminating-function ((gf standard-generic-function))
+ (with-slots (dfun-state arg-info) gf
+ (typecase dfun-state
+ (null (let ((name (generic-function-name gf)))
+ (when (eq name 'compute-applicable-methods)
+ (update-all-c-a-m-gf-info gf))
+ (cond ((eq name 'slot-value-using-class)
+ (update-slot-value-gf-info gf 'reader)
+ #'slot-value-using-class-dfun)
+ ((equal name '(setf slot-value-using-class))
+ (update-slot-value-gf-info gf 'writer)
+ #'setf-slot-value-using-class-dfun)
+ ((eq name 'slot-boundp-using-class)
+ (update-slot-value-gf-info gf 'boundp)
+ #'slot-boundp-using-class-dfun)
+ ((gf-precompute-dfun-and-emf-p arg-info)
+ (make-final-dfun gf))
+ (t
+ (make-initial-dfun gf)))))
+ (function dfun-state)
+ (cons (car dfun-state)))))
+
+(defmethod update-gf-dfun ((class std-class) gf)
+ (let ((*new-class* class)
+ #|| (name (generic-function-name gf)) ||#
+ (arg-info (gf-arg-info gf)))
+ (cond #||
+ ((eq name 'slot-value-using-class)
+ (update-slot-value-gf-info gf 'reader))
+ ((equal name '(setf slot-value-using-class))
+ (update-slot-value-gf-info gf 'writer))
+ ((eq name 'slot-boundp-using-class)
+ (update-slot-value-gf-info gf 'boundp))
+ ||#
+ ((gf-precompute-dfun-and-emf-p arg-info)
+ (multiple-value-bind (dfun cache info)
+ (make-final-dfun-internal gf)
+ (set-dfun gf dfun cache info) ; otherwise cache might get freed twice
+ (update-dfun gf dfun cache info))))))
+
+;;;
+;;;
+;;;
+(defmethod function-keywords ((method standard-method))
+ (multiple-value-bind (nreq nopt keysp restp allow-other-keys-p keywords)
+ (analyze-lambda-list (if (consp method)
+ (early-method-lambda-list method)
+ (method-lambda-list method)))
+ (declare (ignore nreq nopt keysp restp))
+ (values keywords allow-other-keys-p)))
+
+(defun method-ll->generic-function-ll (ll)
+ (multiple-value-bind (nreq nopt keysp restp allow-other-keys-p keywords keyword-parameters)
+ (analyze-lambda-list ll)
+ (declare (ignore nreq nopt keysp restp allow-other-keys-p keywords))
+ (remove-if #'(lambda (s)
+ (or (memq s keyword-parameters)
+ (eq s '&allow-other-keys)))
+ ll)))
+
+
+;;;
+;;; This is based on the rules of method lambda list congruency defined in
+;;; the spec. The lambda list it constructs is the pretty union of the
+;;; lambda lists of all the methods. It doesn't take method applicability
+;;; into account at all yet.
+;;;
+(defmethod generic-function-pretty-arglist
+ ((generic-function standard-generic-function))
+ (let ((methods (generic-function-methods generic-function))
+ (arglist ()))
+ (when methods
+ (multiple-value-bind (required optional rest key allow-other-keys)
+ (method-pretty-arglist (car methods))
+ (dolist (m (cdr methods))
+ (multiple-value-bind (method-key-keywords
+ method-allow-other-keys
+ method-key)
+ (function-keywords m)
+ ;; we've modified function-keywords to return what we want as
+ ;; the third value, no other change here.
+ (declare (ignore method-key-keywords))
+ (setq key (union key method-key))
+ (setq allow-other-keys (or allow-other-keys
+ method-allow-other-keys))))
+ (when allow-other-keys
+ (setq arglist '(&allow-other-keys)))
+ (when key
+ (setq arglist (nconc (list '&key) key arglist)))
+ (when rest
+ (setq arglist (nconc (list '&rest rest) arglist)))
+ (when optional
+ (setq arglist (nconc (list '&optional) optional arglist)))
+ (nconc required arglist)))))
+
+
+(defmethod method-pretty-arglist ((method standard-method))
+ (let ((required ())
+ (optional ())
+ (rest nil)
+ (key ())
+ (allow-other-keys nil)
+ (state 'required)
+ (arglist (method-lambda-list method)))
+ (dolist (arg arglist)
+ (cond ((eq arg '&optional) (setq state 'optional))
+ ((eq arg '&rest) (setq state 'rest))
+ ((eq arg '&key) (setq state 'key))
+ ((eq arg '&allow-other-keys) (setq allow-other-keys 't))
+ ((memq arg lambda-list-keywords))
+ (t
+ (ecase state
+ (required (push arg required))
+ (optional (push arg optional))
+ (key (push arg key))
+ (rest (setq rest arg))))))
+ (values (nreverse required)
+ (nreverse optional)
+ rest
+ (nreverse key)
+ allow-other-keys)))
+
diff --git a/gcl/pcl/notes/12-7-88-notes.text b/gcl/pcl/notes/12-7-88-notes.text
new file mode 100644
index 000000000..a9405156f
--- /dev/null
+++ b/gcl/pcl/notes/12-7-88-notes.text
@@ -0,0 +1,45 @@
+Copyright (c) Xerox Corporation 1988. All rights reserved.
+
+
+These notes correspond to the "12/7/88 Can't think of a cute name PCL"
+version of PCL.
+
+Please read this entire file carefully. You may also be interested in
+looking at previous versions of the notes.text file. These are called
+xxx-notes.text where xxx is the version of the PCL system the file
+corresponds to. At least the last two versions of this file contain
+useful information for any PCL user.
+
+This version of PCL has been tested at PARC in the following Common
+Lisps:
+
+ Symbolics 7.2
+ Coral 1.2
+ Lucid 3.0
+ KCL (October 15, 1987)
+ Allegro 3.0.1
+
+These three should work, but haven't been tested just yet.
+
+ EnvOS Medley
+ TI
+
+The notes file hasn't yet been fleshed out yet.
+
+The two major changes in this release are:
+
+ - The generic function cache algorithm has been revised. In addition
+ generic function caches now expand automatically. Programs that used
+ to run into problems with lots of cache misses shouldn't run into
+ those problems anymore.
+
+ - the DEFCONSTRUCTOR hack now works. Please see the construct.lisp
+ file for details. If you are consing lots of instances, you may be
+ able to get a tremendous performance boost by using this hack.
+
+
+Another important change is that this version includes some KCL patches
+which dramatically improve PCL performance in KCL. See the kcl-mods.text
+file for more details.
+
+
diff --git a/gcl/pcl/notes/3-17-88-notes.text b/gcl/pcl/notes/3-17-88-notes.text
new file mode 100644
index 000000000..7602fb07e
--- /dev/null
+++ b/gcl/pcl/notes/3-17-88-notes.text
@@ -0,0 +1,167 @@
+Copyright (c) Xerox Corporation 1988. All rights reserved.
+
+These notes correspond to the beta test release of March 17th 1988.
+Later versions of this release will run in the usual lisps, but for the
+time being this has only been tested in Symbolics, Lucid, Coral,
+Xerox, Ibuki (01/01), TI and VAXLisp Common Lisps.
+
+Note may not run in all Franz Lisps, I believe it runs on the SUN3
+though. I will get back to this in a few days when I get the needed
+code from Franz.
+
+***
+This release will run in Lucid 3.0 beta 2, with the boolean.lbin patch.
+
+***
+This release contains a prototype implementation of the make-instance
+behavior documented in the CLOS specification (X3J13 document # 88-002).
+This prototype implementation does not provide high performance, but it
+should conform to the specification with one exception, it does not
+check the validity of the initargs.
+
+All the generic functions in the instance creation protocol are as
+specified in the CLOS specification except that make-instance is called
+mki instead. This name is a temporary name, it is so that people can
+try out the new make-instance protocol without having to convert all
+their code at once. In a future release, the name make-instance will be
+switched to the new behavior.
+
+***
+Standard method combination is supported. General declarative
+method combination is not yet supported, so define-method-combination does
+not yet work, but standard method combination is what generic functions
+do by default now. :after :before :around and unqualified methods are
+supported. Error checking is minimal.
+
+***
+call-next-method works with standard-method-combination.
+call-next-method is much faster than it was before, and call-next-method
+behaves as a lexically defined function. This means it is possible to
+pass around funargs which include call-next-method.
+
+***
+All uses of slot-value within a method body should be optimized. It
+should no longer be necessary to use with-slots just to get the
+optimization.
+
+***
+There are new macros with-slots* and with-accessors*. These correspond
+to the macros which will appear in the final specification, with-slots
+and with-accessors. They work as follows:
+
+(with-slots* ((x x-slot)
+ (y y-slot)) ===\ (let ((#:g1 (foo)))
+ (foo) ===/ (swapf (slot-value #:g1 'x-slot)
+ (swapf x y)) (slot-value #:g1 'y-slot)))
+
+(with-accessors* ((x position-x)
+ (y position-y)) ===\ (let ((#:g1 (foo)))
+ (foo) ===/ (incf (position-x #:g1))
+ (incf x) (incf (position-y #:g1)))
+ (incf y))
+
+As an abbreviation, the (<variable-name> <slot-name>) pairs in with-slots*
+can be abbreviated to just <variable-and-slot-name> when the variable
+and slot name are the same. This means that:
+
+(with-slots* (x y z) <instance-form> &body <body>)
+
+is equivalent to:
+
+(with-slots* ((x x) (y y) (z z)) <instance-form> &body <body>)
+
+You should begin to convert your code to use these macros as soon as
+possible since the old macro with-slots will swap names with with-slots*
+sometime soon.
+
+A trick you may want to use for remembering the order of the first two
+arguments to with-slots* and with-accessors* is that it is "like
+multiple-value-bind".
+
+***
+In addition this release includes the beginnings of support for doing
+some of the compiling which PCL does a load time at compile time
+instead. To use this support, put the form:
+
+ (pcl::precompile-random-code-segments)
+
+in a file which is compiled after all your other pcl using files are
+loaded. Then arrange for that file to be loaded before all your
+other pcl using files are loaded.
+
+For example, if your system has two files called "classes" and "methods",
+create a new file called "precom" that contains:
+
+ (in-package 'pcl)
+
+ (pcl::precompile-random-code-segments)
+
+
+Then you can use the defsystem stuff defined in the file defsys to
+maintain your system as follows:
+
+(defsystem my-very-own-system
+ "/usr/myname/lisp/"
+ ((classes (precom) () ())
+ (methods (precom classes) (classes) ())
+ (precom () (classes methods) (classes methods))))
+
+This defsystem should be read as follows:
+
+* Define a system named MY-VERY-OWN-SYSTEM, the sources and binaries
+ should be in the directory "/usr/me/lisp/". There are three files
+ in the system, there are named classes, methods and precom. (The
+ extension the filenames have depends on the lisp you are running in.)
+
+* For the first file, classes, the (precom) in the line means that
+ the file precom should be loaded before this file is loaded. The
+ first () means that no other files need to be loaded before this
+ file is compiled. The second () means that changes in other files
+ don't force this file to be recompiled.
+
+* For the second file, methods, the (precom classes) means that both
+ of the files precom and classes must be loaded before this file
+ can be loaded. The (classes) means that the file classes must be
+ loaded before this file can be compiled. The () means that changes
+ in other files don't force this file to be recompiled.
+
+* For the third file, precom, the first () means that no other files
+ need to be loaded before this file is loaded. The first use of
+ (classes methods) means that both classes and methods must be
+ loaded before this file can be compiled. The second use of (classes
+ methods) mean that whenever either classes or methods changes precom
+ must be recompiled.
+
+Then you can compile your system with:
+
+ (operate-on-system 'my-very-own-system :compile)
+
+and load your system with:
+
+ (operate-on-system 'my-very-own-system :load)
+
+***
+The code walker has gone through some signigificant revision. The
+principle change is that the function walk-form now takes three required
+arguments, and the walk-function itself now must accept an environment
+argument. There are other changes having to do with the implementation
+specific representation of macroexpansion environments. For details see
+the file walk.lisp.
+
+***
+The following functions and macros which used to be supported for
+backward compatibility only are now not supported at all:
+
+WITH* and WITH
+
+DEFMETH
+
+GET-SLOT
+
+MAKE
+
+
+***
+There are other small changes in this release. If you notice one that
+causes you problems please send me a message about it.
+
diff --git a/gcl/pcl/notes/3-19-87-notes.text b/gcl/pcl/notes/3-19-87-notes.text
new file mode 100644
index 000000000..ce332f63a
--- /dev/null
+++ b/gcl/pcl/notes/3-19-87-notes.text
@@ -0,0 +1,138 @@
+
+
+These notes correspond to *pcl-system-date* 3/19/87 prime.
+
+This release runs in:
+ ExCL
+ Lucid
+ Symbolics Common Lisp (Genera)
+ Vaxlisp (2.0)
+ Xerox Common Lisp (Lyric Release)
+
+CMU Lisp (nee Spice) and KCL should be working soon, I will announce
+another release at that time. I figured it was better to get some
+people beating on it as soon as possibl.
+
+Xerox Lisp users should FTP all the source files from /pub/pcl/ as well
+as all the dfasl files from /pub/pcl/xerox/. Included in the xerox
+specific directory is a file called PCL-ENV, which provides some simple
+environment support for using PCL in Xerox Lisp.
+
+
+
+Following is a description of some of the things that are different in
+this release of PCL. This list isn't in any particular order. There
+are a number of incompatible changes in this release, please read the
+whole thing carefully.
+
+As usual, please enjoy, and send bug-reports, questions etc. to
+CommonLoops@Xerox.com.
+
+***
+The single most significant change is that discriminator-objects with
+corresponding discriminating functions have been replaced by generic
+function objects. What does this mean?? Well, in previous releases of
+PCL, if you did:
+
+(defmethod foo ((x class)) 'class)
+(defmethod foo ((x method)) 'method)
+
+Then (discriminator-named 'foo) returned a discriminator object which
+had both of these methods defined on it. (symbol-function 'foo)
+returned a discriminating function, which (discriminator-named 'foo) had
+put in foo's function cell.
+
+In this release of PCL, the above defmethod's put a generic-function
+object in foo's function cell. This generic-function object is a
+combination of the discriminator object and discriminating function of
+the previous releases of PCL. This generic-function object is
+funcallable, funcalling it causes the appropriate method to be looked up
+and called. This generic function object has accessors which return the
+methods defined on the generic function. This generic function object
+is mutable. It is possible to add and remove methods from it.
+
+(defmethod foo ((x class)) 'class)
+(defmethod foo ((x method)) 'method)
+
+(generic-function-methods #'foo)
+(#<Method FOO (METHOD) 3434> #<Method FOO (CLASS) 3245>)
+
+(foo (make 'class)) ==> 'class
+(foo (make 'method)) ==> 'method
+
+(remove-method #'foo (car (generic-function-methods #'foo)))
+
+(foo (make 'class)) ==> 'class
+(foo (make 'method)) ==> no matching method error
+
+
+Note that as part of this change, the name of any function, generic
+function or class which included the string "DISCRIMINATOR" has changed.
+The name changes that happened were:
+ The class essential-discriminator was renamed to generic-function,
+ The class basic-discriminator and the class discrimiantor were
+ combined and renamed to standard-generic-function.
+
+If you went through your code and made the following name changes, you
+would probably win, (this is what I did to PCL and it worked).
+
+ essential-discriminator ==> generic-function
+ basic-discriminator ==> standard-generic-function
+ discriminator
+ (when it appears as a specializer)
+ ==> standard-generic-function
+ discriminator
+ (when it appears as part of a variable name or something)
+ ==> generic-function
+
+***
+In most Lisp implementations, method lookup is at least twice as fast as
+it was in the previous release.
+
+***
+The compiler isn't called when PCL is loaded anymore. In a future
+release, the compiler will also not be called when any other method
+definitions are loaded. This is part of an effort to get PCL to a state
+where the compiler will never be needed when compiled files are loaded.
+
+***
+PCL now has a mechanism for naming the generic-function's and method
+functions defined by defmethod. This means that in ports of PCL which
+take advantage of this mechanism, you will see useful function names in
+the debugger rather than the useless gensym names that have been in the
+past few releases.
+
+***
+Compiled files containing defmethod forms should be smaller and load
+faster.
+
+***
+Many of the files in the system have been renamed. More files will be
+renamed in upcoming releases.
+
+***
+An important part of the bootstrapping code has been re-written. The
+remainder of this code (the BRAID1 and BRAID2 files) will be re-written
+sometime soon.
+
+The changes made to bootstrapping in this release were done to make
+early methods more understandable, and as part of implementing generic
+function objects. Also, most users should find that PCL loads in less
+time than it did before.
+
+The changes which will be made to bootstrapping in a future release will
+make understanding the "Braid" stuff easier, and will make it possible
+to implement slot-description objects as described in the CURRENT DRAFT
+of the Common Lisp Object System Chapter 3.
+
+***
+The defsys file has been re-written AGAIN. This shouldn't affect users
+since there are still the old familiar variables *pcl-pathname-defaults*
+and *pathname-extensions*.
+
+***
+The specialized foo-notes files are all gone. Most of them were
+hopelessly out of date, and installing pcl is now the same operation for
+any Lisp. In particular, note that in Vaxlisp, it is no longer
+necessary to push lisp:vaxlisp on the *features* list.
+
diff --git a/gcl/pcl/notes/4-21-87-notes.text b/gcl/pcl/notes/4-21-87-notes.text
new file mode 100644
index 000000000..b1acd73f5
--- /dev/null
+++ b/gcl/pcl/notes/4-21-87-notes.text
@@ -0,0 +1,53 @@
+
+
+These notes correspond to *pcl-system-date* "4/21/87 April 21rst 1987".
+
+The notes from the last release are stored as 3-19-notes.text
+
+This release runs in:
+ ExCL
+ Lucid
+ Symbolics Common Lisp (Genera)
+ Vaxlisp (2.0)
+ Xerox Common Lisp (Lyric Release)
+ Kyoto Common Lisp (5.2)
+
+CMU Lisp (nee Spice) should be working soon, I will announce another
+release at that time.
+
+Xerox Lisp users should FTP all the source files from /pub/pcl/ as well
+as all the dfasl files from /pub/pcl/xerox/. Included in the xerox
+specific directory is a file called PCL-ENV, which provides some simple
+environment support for using PCL in Xerox Lisp.
+
+
+The major difference in this release is that defclass conforms to the
+CLOS specification (pretty much I hope). Previous warnings about what
+would happen when defclass became CLOS defclass now apply. Once major
+difference is that PCL currently does require that all a classes
+superclasses be defined when a defclass form is evaluated. This will
+change sometime soon.
+
+Other small changes include:
+
+Some more of the files have been renamed and restructured (as promised).
+
+the defclass parsing protocol has changed
+
+slotd datastructures are now instances of the class
+standard-slot-description.
+
+a performance bug in the ExCL port which causes method lookup and slot
+access to cons needlessly.
+
+a bug in the 3600 port which broke the printer for stack consed closures
+
+make-specializable
+
+a bug in Lucid lisp which made it impossible to say (compile-pcl) has
+been patched around, this is the bug that manifested itself as NAME
+being ubound.
+
+
+As usual, please enjoy and send comments.
+
diff --git a/gcl/pcl/notes/4-29-87-notes.text b/gcl/pcl/notes/4-29-87-notes.text
new file mode 100644
index 000000000..307b86e86
--- /dev/null
+++ b/gcl/pcl/notes/4-29-87-notes.text
@@ -0,0 +1,80 @@
+
+
+These notes correspond to *pcl-system-date* "4/29/87 prime April 29, 1987".
+
+The notes from the last release are stored as 4-21-notes.text
+
+This release runs in:
+ ExCL
+ Lucid
+ Symbolics Common Lisp (Genera)
+ Vaxlisp (2.0)
+ Xerox Common Lisp (Lyric Release)
+ Kyoto Common Lisp (5.2)
+ TI Common Lisp (Release 3)
+
+CMU Lisp (nee Spice) should be working soon, I will announce another
+release at that time.
+
+TI release 2 should also be working soon, I will announce that when it
+happens.
+
+
+Note once again, that Xerox Lisp users should FTP all the source files
+from /pub/pcl/ as well as all the dfasl files from /pub/pcl/xerox/.
+Included in the xerox specific directory is a file called PCL-ENV, which
+provides some simple environment support for using PCL in Xerox Lisp.
+You must load PCL BEFORE loading pcl-env.
+
+
+MAJOR CHANGES IN THIS RELEASE:
+
+ make has been renamed to make-instance
+
+ make-instance has been renamed to allocate-instance
+
+for compatibility, make can continue to be used as a synonym for
+make-instance. unfortunately, code which used to call make-instance
+must be converted.
+
+I would actually suggest that you do both of these name changes right
+away. Two passes through the code using Query Replace seems to work
+quite well (changing make-instance to allocate-instance and then make to
+make-instance.) I was able to change all of PCL in about 10 minutes
+that way.
+
+---
+
+all functions and generic functions whose name included the string
+"get-slot" have been renamed. Basically, get-slot was replaced
+everywhere it appeared with slot-value.
+
+get-slot itself still exists for compatibility, but you should start
+converting your code to use slot-value.
+
+
+
+OTHER CHANGES in this release:
+
+There is a new file called PKG which does the exports for PCL. PCL now
+exports fewer symbols than before. Specifically, PCL now exports only
+those symbols documented in the CLOS spec chapters 1 and 2. This means
+that some symbols which may be needed by some programs are not exported.
+
+A good example is print-instance. print-instance is not exported and
+since print-instance has not yet been renamed to print-object programs
+which define methods on print-instance may want to import that symbol.
+
+---
+
+pcl should load faster in this release. In particular, the file fixup
+should load in less than half the time it did before. This release
+should load in something like 80% of the time it took in the last
+release. Remember, these numbers are only for comparison, your mileage
+may vary.
+
+---
+
+This release of PCL, as well as the last one, has *pcl-system-date*
+which presents the date in both mm/dd/yy and Month day year format.
+
diff --git a/gcl/pcl/notes/5-22-87-notes.text b/gcl/pcl/notes/5-22-87-notes.text
new file mode 100644
index 000000000..01aed9fd0
--- /dev/null
+++ b/gcl/pcl/notes/5-22-87-notes.text
@@ -0,0 +1,126 @@
+
+
+These notes correspond to *pcl-system-date* "5/22/87 May 22nd, 1987".
+
+The notes from the last release are stored as 4-29-notes.text
+
+This release runs in:
+ CMU Lisp
+ ExCL
+ Lucid
+ Symbolics Common Lisp (Genera)
+ Vaxlisp (2.0)
+ Xerox Common Lisp (Lyric Release)
+ Kyoto Common Lisp (5.2)
+ TI Common Lisp (Release 3)
+
+TI release 2 should also be working soon, I will announce that when it
+happens.
+
+
+Note once again, that Xerox Lisp users should FTP all the source files
+from /pub/pcl/ as well as all the dfasl files from /pub/pcl/xerox/.
+Included in the xerox specific directory is a file called PCL-ENV, which
+provides some simple environment support for using PCL in Xerox Lisp.
+You must load PCL BEFORE loading pcl-env.
+
+
+MAJOR CHANGES IN THIS RELEASE:
+
+---
+ it is possible to forward reference classes in a defclass (or
+ add-named-class) form. This means it is possible to say:
+
+ (defclass foo (bar) (i j k))
+
+ (defclass bar () (x y z))
+
+ Rather than having to put the in the "right" order.
+
+ NOTE: the full-on error checking for this is not finished yet.
+ don't try to break it by doing things like:
+
+ (defclass foo (bar) (i j k))
+ (make-instance 'foo)
+ (defclass bar () (x y z))
+
+---
+ print-instance has been renamed to print-object
+
+---
+ the defclass and class-definition protocol has changed. some of the
+effects of this change are:
+
+* ADD-NAMED-CLASS is a true functional interface for defclass, so for
+ example,
+
+ (defclass foo () (x y z) (:accessor-prefix foo-))
+
+ is equivalent to:
+
+ (add-named-class (class-prototype (class-named 'class))
+ 'foo
+ ()
+ '(x y z)
+ '((:accessor-prefix foo-)))
+
+* defclass (and add-named-class) now undefined accessor methods, reader
+ methods and constructors which 'went away'. For example:
+
+ (defclass foo () (x y z) (:reader-prefix foo-))
+
+ defines methods on the generic functions foo-x foo-y and foo-z.
+
+ but if you then evaluated the defclass form:
+
+ (defclass foo () (x y z))
+
+ those reader methods will be removed from the generic functions
+ foo-x foo-y and foo-z.
+
+ Similarly constructors which 'went away' will be undefined.
+
+---
+ writer methods generated by the :accessor and :accessor-prefix options
+ now pay attention to the :type slot-option. So,
+
+ (defclass foo () ((x :accessor foo-x :type symbol)))
+
+ (defvar *foo-1* (make-instance 'foo))
+
+ (setf (foo-x *foo-1*) 'bar) ; is OK
+
+ (setf (foo-x *foo-1*) 10) ; signals an error
+
+---
+ There are fewer built-in classes. Specifically, only the following
+ Common Lisp types have classes:
+
+ ARRAY BIT-VECTOR CHARACTER COMPLEX CONS FLOAT INTEGER LIST
+ NULL NUMBER RATIO RATIONAL SEQUENCE STRING SYMBOL T VECTOR
+
+* In a future release the subtypes of FLOAT may have classes, that issue
+ is still under discussion.
+
+* Some ports of PCL also define classes for:
+
+ HASH-TABLE PACKAGE PATHNAME RANDOM-STATE READTABLE STREAM
+
+ it depends on how the type is represented in that Lisp's type system.
+
+
+---
+ The with-slots option :use-slot-value is now obsolete. You should use
+ the :use-accessors option as specified in the CLOS spec instead.
+
+ with-slot forms which did not use the :use-slot-value option are OK,
+ you don't have to touch them.
+
+ with-slot forms which used :USE-SLOT-VALUE T should be changed to say
+ :USE-ACCESSORS NIL.
+
+ with-slot forms which used :USE-SLOT-VALUE NIL should be changed to
+ use neither option, or if you insist :USE-ACCESSORS T
+
+
+
diff --git a/gcl/pcl/notes/5-22-89-notes.text b/gcl/pcl/notes/5-22-89-notes.text
new file mode 100644
index 000000000..3f198d8a1
--- /dev/null
+++ b/gcl/pcl/notes/5-22-89-notes.text
@@ -0,0 +1,152 @@
+Copyright (c) Xerox Corporation 1989. All rights reserved.
+
+These notes correspond to the "5/22/89 Victoria PCL" version of PCL.
+
+Please read this entire file carefully. Failure to do so guarantees
+that you will have problems porting your code from the previous release
+of PCL.
+
+You may also be interested in looking at previous versions of the
+notes.text file. These are called xxx-notes.text where xxx is the
+version of the PCL system the file corresponds to. At least the last
+two versions of this file contain useful information for any PCL user.
+
+This version of PCL has been tested at PARC in the following Common
+Lisps:
+
+ Symbolics 7.2, 7.4
+ Coral 1.2
+ Lucid 3.0
+ IBCL (October 15, 1987)
+ Allegro 3.0.1
+ Golden Common Lisp 3.1
+ EnvOS Medley
+
+These should work, but haven't been tested yet:
+
+ TI
+
+This release is similar to Cinco de Mayo and Passover PCL. The major
+difference is that this release actually works.
+
+***
+
+*other-exports* flushed. More exports now on *exports*
+
+The symbol STANDARD is now exported from the PCL package. standard-class
+standard-method standard-generic-function standard-object built-in-class
+structure-class
+
+scoping problem with *next-methods*
+
+
+method and generic function initialization protocol
+
+methods are immutable
+
+type-specifiers --> specializers
+
+load-truename etc.
+
+defgeneric ensure-generic-function define-method-combination
+
+metabraid changes
+
+file namings
+
+***
+
+There are a number of minor and one major difference between this
+release and No Cute Name PCL.
+
+
+- In the last release there was an implementation of the specified CLOS
+initialization protocol. This implementation had the correct behavior,
+but some of the generic functions had temporary names (*make-instance,
+*initialize-instance and *default-initargs). This was done to give
+people time to convert their code to the behavior of the new
+initialization protocol.
+
+In this release, all generic functions in the specified initialization
+protocol have their proper names. The implementation of the old,
+obsolete initialization protocol has disappeared entirely.
+
+The following renamings have happened:
+
+ 12/7/88 release this release
+
+ *make-instance make-instance
+ *initialize-instance initialize-instance
+ *default-initargs default-initargs
+
+The functions shared-initialize and reinitialize-instance already had
+the proper names.
+
+The new initialization protocol is documented fully in the 88-002R
+specification.
+
+As part of this change, PCL now uses the new initialization protocol to
+create metaobjects internally. That is it calls make-instance to create
+these metaobjects. The actual initargs passed are not yet as specified,
+that will be in a later release.
+
+This is the largest change in this release. If you have not already
+started using the new initialization protocol (with the temporary *xxx
+names) you are going to have to do so now. In most cases, old methods
+on the generic functions INITIALIZE, INITIALIZE-FROM-DEFAULTS and
+INITIALIZE-FROM-INIT-PLIST must be substantially rewritten to convert
+them to methods on INITIALIZE and SHARED-INITIALIZE.
+
+- slots with :ALLOCATION, :CLASS now inherit properly. As part of this
+change, some slot description objects now return a class object as the
+result of SLOTD-ALLOCATION.
+
+- There is now a minimal implementation of the DEFGENERIC macro. This
+implementation supports no options, but it does allow you to define a
+generic function in one place and put some comments there with it.
+
+- The following functions and macros have disappeared. This table also
+ show briefly what you use instead.
+
+ DEFMETHOD-SETF (use DEFMETHOD)
+ RUN-SUPER (use CALL-NEXT-METHOD)
+ OBSOLETE-WITH-SLOTS (use WITH-SLOTS or WITH-ACCESSORS)
+ SYMBOL-CLASS (use FIND-CLASS)
+ CBOUNDP (use FIND-CLASS)
+ CLASS-NAMED (use FIND-CLASS)
+ GET-SETF-GENERIC-FUNCTION (use GDEFINITION)
+
+- In certain ports, method lookup will be faster because of a new scheme
+to deal with interrupts and the cache code. In other ports it will be
+slightly slower. In all ports, the cache code now interacts properly
+with interrupts.
+
+- DEFMETHOD should interact properly with TRACE, ADVISE etc. in most
+ports. two new port-specific functions (in defs.lisp) implement this.
+These are unencapsulated-fdefinition and fdefine-carefully. If this
+doesn't work properly in your port, fix the definition of these
+functions and send it back so it can be in the next release.
+
+- This release runs in Golden Common Lisp version 3.0.
+
+- Previously, the use of slot-value (or with-slots) in the body of a
+method which had an illegal specializer gave strange errors. Now it
+gives a more reasonable error message.
+
+- An annoying problem which caused KCL and friends to complain about
+*exports* being unbound has been fixed.
+
+- The walker has been modified to understand the ccl:%stack-block
+special form in Coral Common Lisp.
+
+- The use of defadvice in pre 3.0 releases has been fixed in Lucid Low.
+
+- multiple-value-setq inside of with-slots now returns the correct
+value.
+
+- A minor bug having to do with macroexpansion environments and the KCL
+walker has been fixed.
+
+- A bug in the parsing of defmethod which caused only symbols (rather
+than non-nil atoms) to be used as qualifiers.
+
diff --git a/gcl/pcl/notes/8-28-88-notes.text b/gcl/pcl/notes/8-28-88-notes.text
new file mode 100644
index 000000000..854a90bcf
--- /dev/null
+++ b/gcl/pcl/notes/8-28-88-notes.text
@@ -0,0 +1,537 @@
+Copyright (c) Xerox Corporation 1988. All rights reserved.
+
+
+These notes correspond to the "8/24/88 (beta) AAAI PCL" version of PCL.
+
+Please read this entire document carefully.
+
+There have been a number of changes since the 8/2/88 version of PCL. As
+usual, these changes are part of our efforts to make PCL conform with
+the CLOS specicification (88-002R). This release contains the big
+changes which the 7/7 through 8/2 releases were really getting ready
+for.
+
+This version of PCL has been tested at PARC in the following Common
+Lisps:
+
+ Symbolics 7.2
+ Coral 1.2
+ Lucid 3.0
+ Franz ??
+ Xerox Lyric
+ Xerox Medley (aka EnvOS Medley)
+ KCL (October 15, 1987)
+
+
+Most of the changes in this version of PCL fall into one of two
+categories.
+
+The first major set of changes makes the order of arguments to setf
+generic functions and methods conform with the spec. In addition, these
+changes allow the first argument to defmethod to be of the form (SETF
+<symbol>).
+
+The second major set of changes have to do with slot access and instance
+structure. Importantly, PCL now checks to see if a slot is bound, and
+calls slot-unbound if the slot is unbound. This is a major change from
+previous releases in which slot access just returned NIL for slots which
+had not yet been set. These changes affect all the functions which
+access the slots of an instance. In addition, the generic functions
+which are called by the slot access functions in exceptional
+circumstances are affected. This set of changes also include the
+implemenentation of the real initialization protocol as specified by
+88-002R.
+
+In addition, there are a number of other changes. The most significant
+of these has to do with the symbols which the PCL package exports by
+default.
+
+The rest of this document goes on to first describe the slot access
+changes, then describe the setf generic function changes, and finally
+describe some of the other minor changes.
+
+At the very end of this file is a new section which lists PCL features
+which are scheduled to disappear in future releases. Please read this
+section and take it to heart. This features will be disappearing.
+
+
+*** Changes to slot access and instance structure ***
+
+This release includes a number of changes to the way slot access works
+in PCL. Some of these changes are incompatible with old behavior. Code
+which was written with the actual CLOS spec in mind should not be
+affected by these incompatible changes, but some older code may be
+affected.
+
+The basic thrust of the changes to slot access is to bring the following
+functions and generic functions in line with the specification:
+
+ slot-boundp
+ slot-exists-p
+ slot-makunbound
+ slot-missing
+ slot-unbound
+ slot-value
+
+ slot-boundp-using-class
+ slot-exists-p-using-class
+ slot-makunbound-using-class
+ slot-value-using-class
+
+ (setf slot-value)
+ (setf slot-value-using-class)
+
+ change-class
+ make-instances-obsolete
+
+ make-instance (temporarily called *make-instance)
+ initialize-instance (temporarily called *initialize-instance)
+ reinitialize-instance
+ update-instance-for-different-class
+ update-instance-for-redefined-class
+ shared-initialize
+
+In this release, these functions accept the specified number of
+arguments, return the specified values, have the specified effects, and
+are called by the rest of PCL in the specified way at the specified
+times (with the exception that PCL does not yet call *make-instance to
+create its own metaobjects). Because PCL now checks for unbound slots,
+you may notice a slight performance degradation in certain applications.
+
+For complete information, you should of course see the CLOS specification.
+The rest of this note is a short summary of how this new behavior is
+different from the last release.
+
+- Dynamic slots are no longer supported. Various functions like
+ slot-value-always and remove-slot no longer exist. Also,
+ slot-value-using-class now only accepts the three arguments as
+ described in the spec. The two extra arguments having to do with
+ dynamic slots are no longer accepted.
+
+ Shortly, we will release a metaclass which provides the now missing
+ dynamic slot behavior.
+
+- slot-missing now receives and accepts different arguments.
+
+- slot-unbound is now implemented, and is called at the appropriate
+ times.
+
+- the initialization protocol specified in 88-002R is now almost
+ completely implemented. The only difference is that the current
+ implementation does not currently check the validity of initargs.
+ So, no errors are signalled in improper initargs are supplied.
+
+ Because of name conflicts with the two other initialization protocols
+ PCL currently supports, some of the specified initialization functions
+ do not have their proper name. The mapping between names in the
+ specification and names in this version of PCL is as follows:
+
+ SPECIFIED IN PCL
+
+ make-instance *make-instance
+ initialize-instance *initialize-instance
+ reinitialize-instance <has proper name>
+ update-instance-for-different-class <has proper name>
+ update-instance-for-redefined-class <has proper name>
+ shared-initialize <has proper name>
+
+
+ In a future release of PCL, these functions will have their proper
+ names, and all the old, obsolete initialization protocols will
+ disappear.
+
+ Convert to using this new wonderful initialization protocol soon.
+
+ Sometime soon we will release a version of PCL which does significant
+ optimization of calls to make-instance. This should speed up instance
+ creation dramatically, which should significantly improve the
+ performance of some programs.
+
+- The function all-slots no longer exists. There is a new generic
+ function called slots-to-inspect, which controls the default behavior
+ of describe. It also controls the default behavior of the inspector
+ in ports which have connected their inspectors to PCL. It specifies
+ which slots of a given class should be inspected. See the definition
+ in the file high.lisp for more.
+
+- the metaclass obsolete-class no longer exists. The mechanism by which
+ instances are marked as being obsolete is now internal, as described
+ in the spec. The generic-function make-instances-obsolete can be used
+ to force the instances of a class to go through the obsolete instance
+ update protocol (see update-instance-for-redefined-class).
+
+- all-std-class-readers-miss-1, a generic function which was part of
+ the database interface code I sent out a few weeks ago, has a slightly
+ different argument list. People using the code I sent out a few weeks
+ ago should replace the definition there with:
+
+ (defmethod all-std-class-readers-miss-1
+ ((class db-class) wrapper slot-name)
+ (declare (ignore wrapper slot-name))
+ ())
+
+- The implementation of the slot access generic functions have been
+ considerably streamlined. The impenetrable macrology which used to be
+ used is now gone.
+
+- Because the behavior of the underlying slot access generic functions
+ has changed, it is possible that some user code which hacks the
+ underlying instance structure may break. Most of this code shouldn't
+ break though. There have been some questions on the mailing list
+ about what is the right way to modify the structure of an instance.
+ I am working on that section of chapter 3 right now, and will answer
+ those questions sometime soon.
+
+
+*** Changes to SETF generic functions ***
+
+This release of PCL includes a significant change related to the order
+of arguments of setf generic functions. To most user programs, this
+change should be invisible. Your program should run just fine in the
+new version of PCL. Even so, there is some conversion you should do to
+your program, since DEFMETHOD-SETF is now obsolete and will be going
+away soon.
+
+Some programs may take some work to adapt to this change. This will
+be particularly true of programs which manipulated methods for setf
+generic-functions using make-instance, add-method and friends.
+
+Included here is a brief overview of this change to PCL. Most people
+will find that this is all they need to know about this change.
+
+The CLOS specification assumes a default behavior for SETF in the
+absence of any defsetf or define-modify-macro. The default behavior is
+to expand forms like:
+
+ (SETF (FOO x y) a)
+
+into:
+
+ (FUNCALL #'(SETF FOO) a x y)
+
+The key point is that by default, setf expands into a call to a function
+with a well-defined name, and that in that call, the new value argument
+comes before all the other arguments.
+
+This requires a change in PCL, because previously, PCL arranged for the
+new-value argument to be the last required argument. This change
+affects the way automatically generated writer methods work, and the way
+that defmethod with a first argument of the form (SETF <symbol>) works.
+
+An important point is that I cannot implement function names of the form
+(SETF <symbol>) portably in PCL. As a result, in PCL, I am using names
+of the form |SETF FOO|. Note that the symbol |SETF FOO| is interned in
+the home package of the symbol FOO. (See the description of the
+GET-SETF-FUNCTION and GET-SETF-FUNCTION-NAME).
+
+
+The user-visible changes are:
+
+- DEFMETHOD will accept lists of the form (SETF FOO) as a first
+ argument. This will define methods on the generic function named
+ by the symbol |SETF FOO|. As specified in the spec, these methods
+ should expect to receive the new-value as their first argument.
+ Calls to defmethod of this form will also arrange for SETF of FOO to
+ expand into an appropriate call to |SETF FOO|.
+
+- Automatically generated writer methods will expect to receive the new
+ value as their first argument.
+
+- DEFMETHOD-SETF will also place the new-value as the first argument.
+ This is for backward compatibility, since defmethod-setf itself will
+ be obsolete, and you should convert your code to stop using it.
+
+- GET-SETF-FUNCTION is a function which takes a function name and
+ returns the setf function for that function if there is one. Note
+ that it doesn't take an environment argument. Note that this function
+ is not specified in Common Lisp or CLOS. PCL will continue to support
+ it as an extra export indefinetely.
+
+- GET-SETF-FUNCTION-NAME is a function which takes a function name
+ and returns the symbol which names the setf function for that
+ function. Note that this function is not specified in Common Lisp
+ or CLOS. PCL will continue to support it as an extra export
+ indefinetely.
+
+- For convenience, PCL defines a macro called DO-STANDARD-DEFSETF which
+ can be used to do the appropriate defsetf. This may be helpful for
+ programs which have calls to setf of a generic-function before any
+ of the generic function's method definitions. A use of this macro
+ looks like:
+
+ (do-standard-defsetf position-x)
+
+ Afterwards, a form like (SETF (POSITION-X P) V) will expand into a
+ form like (|SETF POSITION-X| V P).
+
+ The reason you may have to use do-standard-defsetf is that I cannot
+ portably change every implementations SETF to have the new default
+ behavior. The proper way to use this is to take an early file in
+ your system, and put a bunch of calls to do-standard-defsetf in it.
+ Note that as soon as PCL sees a defmethod with a name argument of
+ the form (SETF FOO), or it sees a :accessor in a defclass, it will
+ do an appropriate do-standard-defsetf for you.
+
+
+In summary, the only things that will need to be changed in most
+programs is that uses of defmethod-setf should be converted to
+appropriate uses of defmethod.
+
+Here is an example of a typical user program which is affected by this
+change.
+
+(defclass position ()
+ ((x :initform 0 :accessor pos-x)
+ (y :initform 0 :accessor pos-y)))
+
+(defclass monitored-position (position)
+ ())
+
+(defmethod-setf pos-x :before ((p monitored-position)) (new)
+ (format *trace-output* "~&Changing x coord of ~S to ~D." p new))
+
+(defmethod-setf pos-y :before ((p monitored-position)) (new)
+ (format *trace-output* "~&Changing y coord of ~S to ~D." p new))
+
+
+To bring this program up to date, you should convert the two
+defmethod-setf forms as follows:
+
+(defmethod (setf pos-x) :before (new (p monitored-position))
+ (format *trace-output* "~&Changing x coord of ~S to ~D." p new))
+
+(defmethod (setf pos-y) :before (new (p monitored-position))
+ (format *trace-output* "~&Changing y coord of ~S to ~D." p new))
+
+
+*** Other changes in this release ***
+
+* The symbols exported by the PCL package have now changed. The PCL
+package now exports the symbols listed in the table of contents of
+chapter 2 of the spec. This list of symbols is the value of the
+variable pcl::*exports*.
+
+Following is the list of symbols which were exported in the 8/2/88
+version but which are not exported in the 8/18/88 version.
+
+DEFMETHOD-SETF DEFGENERIC-OPTIONS DEFGENERIC-OPTIONS-SETF
+CLASS-CHANGED CLASS-NAMED SYMBOL-CLASS
+CBOUNDP GET-METHOD GET-SETF-GENERIC-FUNCTION
+MAKE-METHOD-CALL
+
+Following is the list of symbols which are exported in the 8/18/88
+version, but which were not exported in previous versions:
+
+CALL-METHOD CLASS-NAME COMPUTE-APPLICABLE-METHODS
+DEFGENERIC ENSURE-GENERIC-FUNCTION FIND-METHOD
+FUNCTION-KEYWORDS GENERIC-FLET GENERIC-LABELS
+INITIALIZE-INSTANCE MAKE-INSTANCES-OBSOLETE NO-APPLICABLE-METHOD
+NO-NEXT-METHOD REINITIALIZE-INSTANCE SHARED-INITIALIZE
+SLOT-BOUNDP SLOT-EXISTS-P SLOT-MAKUNBOUND
+SLOT-MISSING SLOT-UNBOUND SYMBOL-MACROLET
+UPDATE-INSTANCE-FOR-DIFFERENT-CLASS
+UPDATE-INSTANCE-FOR-REDEFINED-CLASS
+WITH-ADDED-METHODS
+
+It should be noted that not all of these newly exported symbols have
+been "implemented" yet.
+
+
+* Any program written using PCL will need to be completely recompiled
+to run with this release of PCL.
+
+* The generic-function generic-function-pretty-arglist now returns a
+nice arglist for any generic function. It combines all the keyword
+arguments accepted by the methods to get the combined set of keywords.
+In some ports, the environment specific ARGLIST function has been
+connected to this, and so the environments will print out nice arglists
+for generic functions.
+
+* Some bugs in trace-method have been fixed. Trace-method should now
+work in all ports of PCL.
+
+* NO-MATCHING-METHOD has been renamed to NO-APPLICABLE-METHOD. In
+addition, it now receives arguments as specified.
+
+* defmethod has been modified to allow macros which expand into
+declarations.
+
+* The :documentation slot option is now accepted in defclass forms. The
+documentation string put here cannot yet be retrieved using the
+documentation function. That will happen in a later release.
+
+* The :writer slot option is now implemented.
+
+* Some brain damage in high.lisp which caused method lookup to work
+incorrectly for built in classes. In addition, it caused the
+class-local-supers and class-direct-subclasses of the built in classes
+to be strange. People using CLOS browsers should notice this change
+dramatically, as it will make the browse of the built in part of the
+class lattice look right.
+
+
+*** Older Changes ***
+
+Following are changes which appeared in release of PCL from 7/7/88 to
+8/2/88. Each change is marked with the release it appeared in.
+
+
+
+8/2/88
+Loading defclass forms should be much faster now. The bug which caused
+all the generic functions in the world to be invalidated whenever a
+class was defined has now been fixed.
+
+Loading defmethod forms should also be much faster. A bug which caused
+a tremendous amount of needles computation whenever a method was also
+fixed.
+
+
+
+8/2/88
+A bug which caused several slots of the classes T, OBJECT, CLASS and
+STANDARD-CLASS to be unbound has been fixed.
+
+
+
+8/1/88
+load-pcl now adds the symbols :PCL and :PORTABLE-COMMONLOOPS to
+*features*.
+
+PCL still doesn't do any sort of call to PROVIDE because of the total
+lack of uniformity in the behavior of require and provide in the various
+common lisp implementations.
+
+
+8/1/88
+This version of PCL finally fixes the horrible bug that prevented
+the initform for :class allocation slots from being evaluated when the
+class was defined.
+
+
+7/20/88
+PCL now converts the function describe into a generic function of one
+argument. This is to bring it into conformance with the spec as
+described in 88-002.
+
+In Symbolics Genera, it is actually a function of one required and one
+optional argument. This is because the 3600 sometimes calls describe
+with more than one argument.
+
+In Lucid Lisp, describe only takes an optional argument. This argument
+defaults to the value of *. PCL converts describe to a generic function
+of one required argument so it is not possible to call describe with
+only one argument.
+
+
+7/7/88
+class-named and symbol-class have been replaced by find-class.
+find-class is documented in 88-002R.
+
+
+7/7/88
+with-slots and with-accessors now conform to 88-002R.
+
+The old definition of with-slots is now called obsolete-with-slots. The
+same is true for with-accessors.
+
+ with-slots ---> obsolete-with-slots
+ with-accessors --> obsolete-with-accessors
+
+The temporary correct definition of with-slots, with-slots* is now
+called with-slots. The same is true for with-accessors*.
+
+ with-slots* --> with-slots
+ with-accessors* -> with-accessors
+
+
+7/7/88
+The class-precedence list of the class null now conforms to 88-002R.
+
+In previous releases of PCL, the class precedence-list of the class
+null was: (null list symbol sequence t). In this release the class
+precedence list of the class null is: (null symbol list sequence t).
+
+This change was made to bring PCL into conformance with the spec.
+
+
+
+7/7/88
+
+print-object now takes only two arguments.
+
+This changes was made to begin bringing print-object in conformance with
+88-002R. print-object conforms to the spec to the extent that is is
+called at the approrpiate times for PCL instances. In most
+implementations, it is not called at the appropriate times for other
+instances. This is not under my control, encourage your vendor to
+provide the proper support for print-object.
+
+
+7/7/88
+This version of PCL now includes a beta test version of a new iteration
+package. This iteration package was designed by Pavel Curtis and
+implemented by Bill vanMelle. This iteration package is defined in the
+file iterate.lisp. Please feel free to experiment with it. We are all
+very interested in comments on its use.
+
+
+
+*** PCL Features that will be disappearing ***
+
+This section describes features in PCL that will be disappearing in
+future releases. For each change, I try to give a release date after
+which I will feel free to remove this feature. This list should not be
+considered complete. Certain other PCL features will disappear as well.
+The items on this list are the user-interface level items that it is
+possible to give a lot of warning about. Other changes will have more
+subtle effects, for example when the lambda-list congruence rules are
+implemented.
+
+- :accessor-prefix in defclass
+
+Can disappear anytime after 8/29.
+
+Warning that this is obsolete has been out for some time. You should
+use :accessor in each of the slot specifications of the defclass form.
+It is true that this is slightly more cumbersome, but the semantic
+difficulties associated with :accesor-prefix are even worse.
+
+- :constructor in defclass
+
+Can disappear anytime after 8/29.
+
+Warning that this is obsolete has been out for some time. It will be
+disappearing shortly because the intialization protocol which it goes
+with will be disappearing. A future release of PCL will support a
+special mechanism for defining functions of the form:
+
+(defun make-foo (x y &optional z)
+ (make-instance 'foo 'x x :y y :z z))
+
+In the case where there are only :after methods on initialize-instance
+and shared-initialize, these functions will run like the wind. We hope
+to release this facility by 9/15.
+
+- old definition of make-instance, intialize, initialize-from-defaults,
+ initialize-from-init-plist
+
+Can disappear anytime after 8/29.
+
+Convert to using the new initialization protocol as described in the
+spec and above.
+
+- mki, old definition of initialize-instance
+
+Can disappear anytime after 8/29.
+
+Convert to using the new initialization protocol as described in the
+spec and above.
+
+- defmethod-setf
+
+Can disappear anytime after 9/15.
+
+Convert to using (defmethod (setf foo) ...
+
+
diff --git a/gcl/pcl/notes/get-pcl.text b/gcl/pcl/notes/get-pcl.text
new file mode 100644
index 000000000..e743744db
--- /dev/null
+++ b/gcl/pcl/notes/get-pcl.text
@@ -0,0 +1,180 @@
+Here is the standard information about PCL. I have also added you to
+the CommonLoops@Xerox.com mailing list.
+
+Portable CommonLoops (PCL) started out as an implementation of
+CommonLoops written entirely in CommonLisp. It is in the process of
+being converted to an implementation of CLOS. Currently it implements a
+only a subset of the CLOS specification. Unfortunately, there is no
+detailed description of the differences between PCL and the CLOS
+specification, the source code is often the best documentation.
+
+ Currently, PCL runs in the following implementations of
+ Common Lisp:
+
+ EnvOS Medley
+ Symbolics (Release 7.2)
+ Lucid (3.0)
+ ExCL (Franz Allegro 3.0.1)
+ KCL (June 3, 1987)
+ AKCL (1.86, June 30, 1987)
+ Ibuki Common Lisp (01/01, October 15, 1987)
+ TI (Release 4.1)
+ Coral Common Lisp (Allegro 1.2)
+ Golden Common Lisp (3.1)
+ CMU
+ VAXLisp (2.0)
+ HP Common Lisp
+ Pyramid Lisp
+
+There are several ways of obtaining a copy of PCL.
+
+*** Arpanet Access to PCL ***
+
+The primary way of getting PCL is by Arpanet FTP.
+
+The files are stored on arisia.xerox.com. You can copy them using
+anonymous FTP (username "anonymous", password "anonymous"). There are
+several directories which are of interest:
+
+/pcl
+
+This directory contains the PCL sources as well as some rudimentary
+documentation (including this file). All of these files are combined
+into a single Unix TAR file. The name of this file is "tarfile".
+
+Extract the individual files from this tarfile by saying:
+
+tar -xf tarfile *
+
+where `tarfile' is the name you have given the tarfile in your
+directory. Once you have done this, the following files are of special
+interest:
+
+readme.text READ IT
+
+notes.text contains notes about the current state of PCL, and some
+ instructions for installing PCL at your site. You should
+ read this file whenever you get a new version of PCL.
+
+get-pcl.text contains the latest draft of this message
+
+
+/pcl/doc
+
+This directory contains TeX source files for the most recent draft of
+the CLOS specification. There are TeX source files for two documents
+called concep.tex and functi.tex. These correspond to chapter 1 and 2
+of the CLOS specification.
+
+
+/pcl/archive
+
+This directory contains the joint archives of two important mailings
+lists:
+
+ CommonLoops@Xerox.com
+
+ is the mailing list for all PCL users. It carries announcements
+ of new releases of PCL, bug reports and fixes, and general advice
+ about how to use PCL and CLOS.
+
+ Common-Lisp-Object-System@Sail.Stanford.edu
+
+ is a small mailing list used by the designers of CLOS.
+
+The file cloops.text is always the newest of the archive files.
+
+The file cloops1.text is the oldest of the archive files. Higher
+numbered versions are more recent versions of the files.
+
+*** Getting PCL on Macintosh floppies ***
+
+PCL is listed in APDAlog. It is distributed on Macintosh floppies.
+This makes it possible for people who don't have FTP access to arisia
+(but who do have a Macintosh) to get PCL.
+
+For 40ドル you receive a version of PCL and a copy of the CLOS spec (X3J13
+document number 88-002R). The APDAlog catalog number is T0259LL/A and
+you can order by calling:
+
+ From the U.S. (800)282-2732
+ From Canada (800)637-0029
+ International (408)562-3910
+ FAX (408)562-3971
+
+
+NOTE: Whenever there is a new release of PCL you want, you should
+probably wait a couple of months before ordering it from APDAlog. We
+want to let new PCL's stabilize a bit before sending it to them, and it
+will take them some time to integrate the new disks into their
+distribution.
+
+*** Using the BITFTP server at Princeton ***
+
+For people who can't FTP from Internet (Arpanet) hosts, but who have
+mail access to the BITNET, there exists a way to get the PCL files using
+the BITFTP service provided by Princeton Univerity. If you know exactly
+where to find the files that interest you, this is quite easy. In
+particular, you have to know:
+
+ * the Internet host name of the host that maintains the files (such
+ as `arisia.Xerox.COM')
+ * the directory where to find the files, relative to the root of the
+ FTP tree (i.E. `pub')
+ * whether the files are binary or ASCII text.
+ * the names of the files (say `pcl90.tar.Z' and `pcl90.README')
+
+To do this, send a message to BITFTP@PUCC (or BITFTP@PUCC.BITNET if you
+aren't on BITNET itself). The subject line of the message will be
+ignored. The text (body) of the message should be:
+
+ FTP arisia.xerox.com UUENCODE
+ CD pcl
+ BINARY
+ GET tarfile
+ QUIT
+
+Then you wait (probably for about a day when you are in Europe) and
+eventually you will receive E-Mail messages from BITFTP@PUCC (or
+BITFTP2%PUCC...) with subject lines like `uudecoded file tarfile part
+13'. Then you have to carefully concatenate the contents of ALL of
+these files in the correct order.
+
+ Note: The following works on our Suns and should work on any
+ Berkeley UNIX machine. If you don't have the `compress' or `zcat'
+ program, you can get a free version (with MIT's X Window System
+ distribution, for example).
+
+The resulting file can be `uudecode'd like this:
+
+ dagobert% uudecode name-of-the-assembled-file
+
+This will give you a file tarfile.Z (it may actually have a different
+name; then you may want to rename it in the first place). The `.Z' at
+the end means that the file you now have is compressed. You can
+uncompress it with `uncompress tarfile. You can untar the uncompressed
+file with `tar -xvf tarfile'.
+
+This will write all files in the tarfile to the current directory.
+
+If you want to know more about the BITFTP service, send a letter to
+`BITFTP@PUCC' that contains the single line `HELP'.
+
+*** Xerox Internet Access to PCL ***
+
+Xerox XNS users can get PCL from {NB:PARC:XEROX}<PCL>
+
+
+
+Send any comments, bug-reports or suggestions for improvements to:
+
+ CommonLoops.pa@Xerox.com
+
+Send mailing list requests or other administrative stuff to:
+
+ CommonLoops-Request@Xerox.com
+
+
+Thanks for your interest in PCL.
+----------
+
diff --git a/gcl/pcl/notes/may-day-notes.text b/gcl/pcl/notes/may-day-notes.text
new file mode 100644
index 000000000..3e2175e24
--- /dev/null
+++ b/gcl/pcl/notes/may-day-notes.text
@@ -0,0 +1,98 @@
+Copyright (c) Xerox Corporation 1989, 1990. All rights reserved.
+
+These notes correspond to the "5/1/90 May Day PCL (REV 2)" version of PCL.
+
+This version is just Rainy Day PCL with the various patches people have
+mailed out included. Barring unforseen circumstances, this will be the
+last version of PCL. We are now working on the Metaobject Protocol.
+
+
+Please read this entire file carefully. Failure to do so guarantees
+that you will have problems porting your code from the previous release
+of PCL.
+
+You may also be interested in looking at previous versions of the
+notes.text file. These are called xxx-notes.text where xxx is the
+version of the PCL system the file corresponds to. At least the last
+two versions of this file contain useful information for any PCL user.
+
+This version of PCL has been tested at PARC in the following Common
+Lisps:
+
+ Symbolics 7.2, 7.4
+ Coral 1.3
+ Lucid 3.0
+ Allegro 3.0.1
+
+These should work, but haven't been tested yet:
+
+ TI
+ Golden Common Lisp 3.1
+ EnvOS Medley
+ IBCL (October 15, 1987)
+
+This release of PCL is substantially different from previous releases.
+The architecture of the runtime system (method lookup and slot access)
+is different, and the metaobject protocol is different. Much of the
+code in this release is new or modified from the last release.
+
+When it stabilizes, this release should be much faster for all
+applications especially large ones.
+
+This beta version of the new release includes a number of known
+problems. These include:
+
+* Even less documentation than ever before. I haven't written much of a
+notes file for what is different yet. Please send me comments for what
+to include in this file.
+
+* Some known performance problems in development versions of compilers.
+At the very least, you want to compile PCL itself using the highest
+performance compiler settings you have.
+
+
+=== Notes for this release (such as they are) ===
+
+* There is one major incompatible change in this release. In this
+release compiling files with defmethod and defclass forms doesn't, by
+default, affect the running lisp image. The winning part of this is you
+can compile a file without `installing' the class and method definitions
+in the file. The losing part is that because PCL is a portable program,
+it can't both do this and let a class definition and a method which
+specializes to that class appear in the same file.
+
+So, you can't (by default) have:
+
+ (defclass foo () ())
+ (defmethod bar ((f foo)) 'foo)
+
+in the same file.
+
+But you say you want to do this, almost everyone does. If you want to
+do this just evaluate the following form before after loading PCL but
+before working with it:
+
+ (pushnew 'compile pcl::*defclass-times*)
+
+You may also want to do:
+
+ (pushnew 'compile pcl::*defmethod-times*)
+
+
+* You probably also want to begin using a precom file for your system.
+Do this by having a file whose only contents is
+
+ (pcl::precompile-random-code-segments <your-system-name>)
+
+don't quote <your-system-name>
+
+for example, for the clim system, the precom file has the one line:
+
+ (pcl::precompile-random-code-segments clim)
+
+compile this file after loading and running your system for a while.
+load it before loading your compiled system. A future version of this
+feature won't require you to have run your system for a while, it will
+only require that you have loaded it.
+
+
diff --git a/gcl/pcl/notes/notes.text b/gcl/pcl/notes/notes.text
new file mode 100644
index 000000000..6cb00a95d
--- /dev/null
+++ b/gcl/pcl/notes/notes.text
@@ -0,0 +1,366 @@
+Summary of changes from the PCL in cmucl 17f:
+ Add a few read-time conditionalizations on cmu17, so that PCL can again
+ work in Lisps other than CMU. (*sgf-wrapper*)
+ Add a read-time conditionalization on cmu for the defstruct
+ pcl-funcallable-instance.
+ Make MAKE-INSTANCE faster.
+ The initial slot values objects are now vectors rather than lists.
+ The new macro copy-slots is the fast way to use the initial slot values vectors.
+ Improve the functions generated by make-instance-function-simple.
+ Hide all uses of kernel:instance-lambda (CMU) inside the new macro fin-lambda-fn,
+ and the new function make-dispatch-lambda. (see line 1082 of cache.lisp)
+ Improve dispatch-dfun-cost. (Otherwise, DEFMETHOD can take much too long).
+ Add a #-lucid before the use of *print-readably* in printing-random-thing.
+ Move wrapper-of-macro to low.lisp.
+Summary of changes from cmucl 17e to cmucl 17f:
+ Fix a problem with :after methods on accessors in PCL. Also, fixed some problems
+ with the result of get-secondary-dispatch-function1 when there are no
+ methods.
+ Fix make-defmethod-form (boot.lisp), to avoid calling standard-char-p on
+ non-characters.
+ Add compiler-macro for pcl:find-class which does lookup at load-time
+ when the name is a constant. (Needs load-time-value and define-compiler-macro)
+ Fix to update-instance-for-different-class.
+ Improved handling of invalid structure instances.
+ New parameterized version of use-dispatch-dfun-p which avoids pessimizing
+ GFs with many methods.
+ Fix change-class-internal.
+ When signalling an incompatible superclass error, added a hint to the
+ message to check out VALIDATE-SUPERCLASSES.
+ CMU: Structure-object is now no longer shadowed in PCL. Code that was using
+ PCL::STRUCTURE-OBJECT will now work better.
+ CMU: BUILT-IN-CLASS, CLASS-NAME, CLASS-OF and FIND-CLASS are once again exported
+ from PCL. This will cause a name conflict if anyone use-package's PCL, but
+ this will at least warn about the distinction. Probably you shouldn't
+ USE-PACKAGE PCL for this reason, but you can now say PCL:FIND-CLASS instead
+ of PCL::FIND-CLASS. It is also possible to use SHADOW or SHADOWING-IMPORT
+ to resolve the conflict.
+ When updating arg-info slots, check to see if the value is already there.
+ This can reduce non-shared pages.
+ CMU: Fix a problem with PCL clobbering byte functions when setting their names.
+ Definitive tweak for handling function-p in
+ compute-secondary-dispatch-function1 which avoids an infinite recursion.
+
+
+
+
+
+
+
+These notes correspond to the "August 5 92 PCL" version of PCL.
+
+ This version of PCL is much closer than previous versions of PCL
+to the metaobject protocol specified in "The Art of the Metaobject Protocol",
+chapters 5 and 6, by Gregor Kiczales, Jim des Riveres, and Daniel G. Bobrow.
+
+
+[Please read the file may-day-notes.text also. Most of that file still applies.]
+
+Support for structures
+ You can use structure-class as a metaclass to create new classes.
+ Classes created this way create and evaluate defstruct forms which
+ have generated symbols for the structure accessors and constructor.
+ The generated symbols are used by the primary slot-value-using-class
+ methods and by the primary allocate-instance method for structures.
+ Defmethod optimizes usages of slot-value (when no user-defined
+ slot-value-using-class methods exist) into direct calls of the
+ generated symbol accessor, which the compiler can then optimize further.
+ Even when there are user-defined methods on slot-value-using-class,
+ PCL does a variety of optimizations.
+
+ If your implementation's version of the *-low.lisp file
+ contains definitions of certain structure functions (see the end of
+ low.lisp, cmu-low.lisp, lucid-low.lisp, and kcl-low.lisp), then
+ structure classes are supported for all defstructs. In this case,
+ structure classes are created automatically, when necessary.
+
+New Classes:
+structure-class
+structure-object
+slot-class
+slot-object
+structure-direct-slot-definition
+structure-effective-slot-definition
+
+Improvements to slot-access
+ Optimization for slot-value outsize of defmethod
+ Optimization for slot-value inside of defmethod, but not of a specialized parameter.
+ Optimizations that work even when there are :around methods
+ on slot-value-using-class.
+
+New types:
+ `(class ,class-object)
+ `(class-eq ,class-object)
+
+New specializer class: class-eq-specializer
+ Every class has a class-eq specializer which represents all
+ the direct instances of that class.
+ This is useful in *subtypep. For example, here is the way
+ generic-function initialization checks that the method-class is valid:
+ (and (classp method-class)
+ (*subtypep (class-eq-specializer method-class)
+ (find-class 'standard-method)))
+ If you want to define methods having class-eq specializers,
+ see "Initialization of method metaobjects". The default behavior of PCL
+ is to disallow this.
+
+compute-applicable-methods-using-types
+
+caching improvements
+
+no magic-generic-functions list
+ This simplifies some things, but complicates some other things.
+ I wanted to support user-defined classes which are their own metaclass.
+ You can now do:
+(defclass y (standard-class) ())
+(defmethod validate-superclass ((c y) (sc standard-class)) t)
+(defclass y (standard-class) () (:metaclass y))
+
+method-function changes (see the comments for make-method-lambda, below)
+
+final dfuns
+
+-------------------------
+
+gfs which obey AMOP ch 6
+ accessor-method-slot-definition
+ add-dependent
+ add-direct-method
+ add-direct-subclass
+ add-method
+ allocate-instance
+ compute-class-precedence-list
+ compute-default-initargs
+ compute-discriminating-function
+ compute-effective-slot-definition
+[Note: compute-effective-slot-definition relys on
+ compute-effective-slot-definition-initargs and effective-slot-definition-class.
+ compute-effective-slot-definition-initargs is quite useful, but is not in
+ AMOP ch 6.]
+ compute-slots
+ direct-slot-definition-class
+ effective-slot-definition-class
+ ensure-class
+ ensure-class-using-class
+ ensure-generic-function
+ ensure-generic-function-using-class
+ eql-specializer-object
+ extract-lambda-list
+ extract-specializer-names
+ finalize-inheritance
+ find-method-combination
+ funcallable-standard-instance-access
+ {generic-function-method-class, generic-function-method-combination,
+ generic-function-lambda-list, generic-function-methods, generic-function-name}
+ intern-eql-specializer
+ make-instance
+ make-method-lambda
+ map-dependents
+ {method-function, method-generic-function, method-lambda-list,
+ method-specializers, method-qualifiers}
+ {class-default-initargs, class-direct-default-initargs, class-direct-slots,
+ class-direct-subclasses, class-direct-superclasses, class-finalized-p,
+ class-name, class-precedence-list, class-prototype, class-slots}
+ {slot-definition-allocation, slot-definition-initargs, slot-definition-initform,
+ slot-definition-initfunction, slot-definition-name, slot-definition-type}
+ {slot-definition-readers, slot-definition-writers}
+ {slot-definition-location}
+ remove-dependent
+ remove-direct-method
+ remove-direct-subclass
+ remove-method
+ set-funcallable-instance-function
+ (setf slot-value-using-class)
+ slot-boundp-using-class
+ slot-makunbound-using-class
+ specializer-direct-generic-functions
+ specializer-direct-methods
+ standard-instance-access
+ update-dependent
+
+gfs which DO NOT obey AMOP ch 6
+
+compute-applicable-methods
+compute-applicable-methods-using-classes
+ Handles class-eq specializers without signalling an error.
+ But see "Initialization of method metaobjects", below.
+
+compute-effective-method
+ Returns only one value.
+
+generic-function-argument-precedence-order
+ Not yet defined. Can get this information from the arg-info structure.
+
+generic-function-declarations
+ Not yet defined.
+
+reader-method-class
+ Not yet defined. Some bootstrapping considerations are involved,
+ but adding this will not be very hard.
+
+(setf class-name)
+ Currently just a writer method. Does not call reinitialize-instance or
+ (setf find-class).
+
+(setf generic-function-name)
+ Currently just a writer method. Does not call reinitialize-instance.
+
+writer-method-class
+ Not yet defined. Some bootstrapping considerations are involved,
+ but adding this will not be very hard.
+
+---------------------------
+
+Initialization of method metaobjects
+ The following methods are defined:
+ legal-qualifiers-p (method standard-method) qualifiers
+ legal-lambda-list-p (method standard-method) lambda-list
+ legal-specializers-p (method standard-method) specializers
+ legal-method-function-p (method standard-method) function
+ legal-documentation-p (method standard-method) documentation
+
+ legal-specializer-p (method standard-method) specializer
+
+ You can override them if you want.
+ The method for legal-specializers-p calls legal-specializer-p
+ on each specializer.
+ The method for legal-specializer-p allows any kind of specializer
+ when the variable *allow-experimental-specializers-p* is t
+ (this variable is initially nil).
+
+---------------------------
+Optimizations on slot-value
+ Outside of a defmethod when define-compiler-macro is not implemented
+ or the slot-name is not constant, or
+ Inside a defmethod when the slot-name is not a constant:
+(1) no optimization of slot-value, slot-value-using-class is called.
+ slot-value-using-class has a special dfun, though, which calls
+ the slot's slot-definition-reader-function. This function is
+ a result of get-accessor-method-function.
+ Outside of a defmethod when define-compiler-macro is implemented and
+ the slot-name is a constant, or
+ Inside a defmethod when the slot-name is a constant but the object is
+ not either (the value of a parameter specialized to a subclass of structure-object
+ for which no user-defined slot-value-using-class methods apply at defmethod time),
+ or (the value of a parameter specialized to a subclass of standard-object).
+(2) PCL arranges to call an automatically created generic function
+ which has one method: a reader method defined on class slot-object.
+ Inside a defmethod when the slot-name is a constant and the object
+ is (the value of a parameter specialized to a subclass of structure-object
+ for which no user-defined slot-value-using-class methods apply).
+(3) The slot-value form is converted to a call of the structure slot's
+ accessor function, which the compiler can then optimize further.
+ Inside a defmethod when the slot-name is a constant and the object
+ is (the value of a parameter specialized to a subclass of standard-object).
+(4) The access requires two arefs, a call to (typep x 'fixnum), and a call to eq,
+ in the best case. If user defined slot-value-using-class methods apply
+ at slot-value execution time, or the slot is unbound, the unoptimized
+ slot-value function (1) is called. This was in May Day PCL; what is new here
+ is that the PV (permutation vector) is looked up at defmethod load time
+ rather than at run time, if the effective method is cached.
+
+Generic functions containing only accessor methods for which no user-defined
+methods on slot-value-using-class apply and which involve only standard-classes:
+ A special dfun is called: one-class, two-class, one-index, or n-n.
+ These were all in May Day PCL.
+Generic functions excluded by the above, which contain accessor methods:
+ In place of each accessor method's method-function, a function returned by
+ get-accessor-method-function is used.
+
+get-accessor-method-function (gf type class slotd) ; type is reader, writer, or boundp.
+ If there is only one applicable method,
+ (This method will be the system supplied one)
+ the function that is returned is optimized for the current state of the
+ class. When the class changes, it must be recomputed.
+ otherwise,
+ a secondary dispatch function for slot-value-using-class is computed
+ (using what is known about the types of the arguments) and converted
+ into an accessor function.
+
+get-secondary-dispatch-function (gf methods types &optional method-alist wrappers)
+ The types argument describes what is known about the types of the arguments.
+ Method-alist is used (when supplied) to do things like replace the
+ standard slot-value-using-class method function with a function optimized
+ for what is known about the arguments.
+ Wrappers (when supplied) means that the resulting function is guaranteed to
+ be called only whith those wrappers. Make-effective-method-function calls
+ the generic-function method-function-for-caching with method-alist and
+ wrappers to get a optimized method function. (PV lookup is done at the time
+ method-function-for-caching is called).
+
+compute-applicable-methods: Here I tried to stick with the MOP.
+ The function cache-miss-values looks at the second value of the result of
+ compute-applicable-methods-using-classes. If this value is null, we aren't
+ supposed to cache the result of camuc. So we don't. Instead we cache a
+ result of (default-secondary-dispatch-function gf), which in turn calls
+ compute-applicable-methods each time it is called.
+---------------------------
+
+To do:
+
+Problem: sometimes there is no need to call a gf's dfun: the emf that is invoked
+ can be cached in the caller's method closure.
+1. In expand-defmethod-internal, optimize calls to generic-functions.
+ Add the support for this optimization.
+
+2. [When CMUCL improves its setf handling, remove the comment in
+ the file macros.lisp beginning the line ";#+cmu (pushnew :setf *features*)"]
+
+
+
+--------------
+1) Generalize expand-defmethod-internal so that it can be used for non-defmethod
+code. Maybe by (a) having a parameter that says whether it is being called by
+defmethod, and (b) using the techniques used by the series package (shadowing
+defun and some others, making the shadowed definitions call e-d-i, making it
+easy for people to do the relevant package modifications)
+
+2) Extending generic-functions by allowing the user at defgeneric time to supply
+the name of a function which will be supplied (by the system) with a definition
+which will return equivalent results to those returned by the generic function,
+but which will (in some cases) have less checking than the generic function.
+One-class, two-class, and one-index gf dfuns will map to a result of
+get-optimized-std-accessor-method-function, checking gf dfuns will map to their
+function, and any other dfun will remain the same.
+
+3) Extending expand-defmethod-internal to optimize calls to generic-functions.
+There are a variety of possibilities that need to be considered; one of them
+will be to arrange to call the optimized functions produced by (2) when it
+is known to be safe.
+
+----------------------------------------------------------------------
+----------------------------------------------------------------------
+
+Here is how PCL uses the compiler at run time:
+
+ The only function that uses COMPILE is COMPILE-LAMBDA, defined in
+low.lisp. See the code for some comments on how it works.
+
+There are basically three uses of COMPILE-LAMBDA:
+ for creating discriminator functions (March 92 PCL creates discriminator
+ functions via lap code, September 16 PCL creates lisp code directly -
+ it is easier to read the Sept PCL code. Both versions invoke
+ COMPILE-LAMBDA in a similar manner.) Precompiling of discriminator
+ functions is done via the macro precompile-dfun-constructors.
+ for creating constructor functions (This is in Sept PCL only;
+ see fast-init.lisp for more information). Precompiling of
+ constructor functions is done via the macro precompile-iis-functions.
+ for creating the internal functions used by GET-FUNCTION (defined in
+ fngen.lisp. Refer to the September 16 92 PCL version because it has
+ better documentation on GET-FUNCTION.) Precompiling of these functions
+ is done by precompile-function-generators.
+
+Precompiling of all three kinds of functions is done by
+PRECOMPILILE-RANDOM-CODE-SEGMENTS (defined in low.lisp).
+
+There are two uses of GET-FUNCTION (actually GET-FUNCTION1):
+ to create effective-method-functions, which are the functions which
+ actually call methods. Every method referred to by an
+ effective-method-function is an applicable method as determined by
+ COMPUTE-APPLICABLE-METHODS (or maybe -USING-CLASSES or
+ -USING-TYPES). See the file combin.lisp.
+ to create secondary dispatch functions. These functions are called by
+ discriminator functions when the dfun couldn't determine the set of
+ applicable methods (when EQL specializers are present), and are
+ actually discriminator functions in themselves sometimes (these
+ are called dispatch dfuns). See the file methods.lisp.
diff --git a/gcl/pcl/notes/readme.text b/gcl/pcl/notes/readme.text
new file mode 100644
index 000000000..ce9dc700f
--- /dev/null
+++ b/gcl/pcl/notes/readme.text
@@ -0,0 +1,11 @@
+Please read the file get-pcl.text carefully, it contains the most up to
+date version of the message you received when you first asked about PCL.
+You should read it when you get each new release because it will contain
+any new information about PCL distribution or documentation.
+
+Also whenever there is a new release, you should read the notes.text
+file carefully.
+
+To install PCL at your site, follow the instructions in the defsys.lisp
+file.
+
diff --git a/gcl/pcl/old/construct.lisp b/gcl/pcl/old/construct.lisp
new file mode 100644
index 000000000..17784e2fe
--- /dev/null
+++ b/gcl/pcl/old/construct.lisp
@@ -0,0 +1,1064 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;;
+;;; This file defines the defconstructor and other make-instance optimization
+;;; mechanisms.
+;;;
+
+(in-package :pcl)
+
+;;;
+;;; defconstructor is used to define special purpose functions which just
+;;; call make-instance with a symbol as the first argument. The semantics
+;;; of defconstructor is that it is equivalent to defining a function which
+;;; just calls make-instance. The purpose of defconstructor is to provide
+;;; PCL with a way of noticing these calls to make-instance so that it can
+;;; optimize them. Specific ports of PCL could just have their compiler
+;;; spot these calls to make-instance and then call this code. Having the
+;;; special defconstructor facility is the best we can do portably.
+;;;
+;;;
+;;; A call to defconstructor like:
+;;;
+;;; (defconstructor make-foo foo (a b &rest r) a a :mumble b baz r)
+;;;
+;;; Is equivalent to a defun like:
+;;;
+;;; (defun make-foo (a b &rest r)
+;;; (make-instance 'foo 'a a ':mumble b 'baz r))
+;;;
+;;; Calls like the following are also legal:
+;;;
+;;; (defconstructor make-foo foo ())
+;;; (defconstructor make-bar bar () :x *x* :y *y*)
+;;; (defconstructor make-baz baz (a b c) a-b (list a b) b-c (list b c))
+;;;
+;;;
+;;; The general idea of this implementation is that the expansion of the
+;;; defconstructor form includes the creation of closure generators which
+;;; can be called to create constructor code for the class. The ways that
+;;; a constructor can be optimized depends not only on the defconstructor
+;;; form, but also on the state of the class and the generic functions in
+;;; the initialization protocol. Because of this, the determination of the
+;;; form of constructor code to be used is a two part process.
+;;;
+;;; At compile time, make-constructor-code-generators looks at the actual
+;;; defconstructor form and makes a list of appropriate constructor code
+;;; generators. All that is really taken into account here is whether
+;;; any initargs are supplied in the call to make-instance, and whether
+;;; any of those are constant.
+;;;
+;;; At constructor code generation time (see note about lazy evaluation)
+;;; compute-constructor-code calls each of the constructor code generators
+;;; to try to get code for this constructor. Each generator looks at the
+;;; state of the class and initialization protocol generic functions and
+;;; decides whether its type of code is appropriate. This depends on things
+;;; like whether there are any applicable methods on initialize-instance,
+;;; whether class slots are affected by initialization etc.
+;;;
+;;;
+;;; Constructor objects are funcallable instances, the protocol followed to
+;;; to compute the constructor code for them is quite similar to the protocol
+;;; followed to compute the discriminator code for a generic function. When
+;;; the constructor is first loaded, we install as its code a function which
+;;; will compute the actual constructor code the first time it is called.
+;;;
+;;; If there is an update to the class structure which might invalidate the
+;;; optimized constructor, the special lazy constructor installer is put back
+;;; so that it can compute the appropriate constructor when it is called.
+;;; This is the same kind of lazy evaluation update strategy used elswhere
+;;; in PCL.
+;;;
+;;; To allow for flexibility in the PCL implementation and to allow PCL users
+;;; to specialize this constructor facility for their own metaclasses, there
+;;; is an internal protocol followed by the code which loads and installs
+;;; the constructors. This is documented in the comments in the code.
+;;;
+;;; This code is also designed so that one of its levels, can be used to
+;;; implement optimization of calls to make-instance which can't go through
+;;; the defconstructor facility. This has not been implemented yet, but the
+;;; hooks are there.
+;;;
+;;;
+
+(defmacro defconstructor
+ (name class lambda-list &rest initialization-arguments)
+ (expand-defconstructor class
+ name
+ lambda-list
+ (copy-list initialization-arguments)))
+
+(defun expand-defconstructor (class-name name lambda-list supplied-initargs)
+ (let ((class (find-class class-name nil))
+ (supplied-initarg-names
+ (gathering1 (collecting)
+ (iterate ((name (*list-elements supplied-initargs :by #'cddr)))
+ (gather1 name)))))
+ (when (null class)
+ (error "defconstructor form being compiled (or evaluated) before~@
+ class ~S is defined."
+ class-name))
+ `(progn
+ ;; In order to avoid undefined function warnings, we want to tell
+ ;; the compile time environment that a function with this name and
+ ;; this argument list has been defined. The portable way to do this
+ ;; is with defun.
+ (proclaim '(notinline ,name))
+ (defun ,name ,lambda-list
+ (declare (ignore ,@(extract-parameters lambda-list)))
+ (error "Constructor ~S not loaded." ',name))
+
+ ,(make-top-level-form `(defconstructor ,name)
+ '(load eval)
+ `(load-constructor
+ ',class-name
+ ',(class-name (class-of class))
+ ',name
+ ',supplied-initarg-names
+ ;; make-constructor-code-generators is called to return a list
+ ;; of constructor code generators. The actual interpretation
+ ;; of this list is left to compute-constructor-code, but the
+ ;; general idea is that it should be an plist where the keys
+ ;; name a kind of constructor code and the values are generator
+ ;; functions which return the actual constructor code. The
+ ;; constructor code is usually a closures over the arguments
+ ;; to the generator.
+ ,(make-constructor-code-generators class
+ name
+ lambda-list
+ supplied-initarg-names
+ supplied-initargs))))))
+
+(defun load-constructor (class-name metaclass-name constructor-name
+ supplied-initarg-names code-generators)
+ (let ((class (find-class class-name nil)))
+ (cond ((null class)
+ (error "defconstructor form being loaded (or evaluated) before~@
+ class ~S is defined."
+ class-name))
+ ((neq (class-name (class-of class)) metaclass-name)
+ (error "When defconstructor ~S was compiled, the metaclass of the~@
+ class ~S was ~S. The metaclass is now ~S.~@
+ The constructor must be recompiled."
+ constructor-name
+ class-name
+ metaclass-name
+ (class-name (class-of class))))
+ (t
+ (load-constructor-internal class
+ constructor-name
+ supplied-initarg-names
+ code-generators)
+ constructor-name))))
+
+;;;
+;;; The actual constructor objects.
+;;;
+(defclass constructor ()
+ ((class ;The class with which this
+ :initarg :class ;constructor is associated.
+ :reader constructor-class) ;The actual class object,
+ ;not the class name.
+ ;
+ (name ;The name of this constructor.
+ :initform nil ;This is the symbol in whose
+ :initarg :name ;function cell the constructor
+ :reader constructor-name) ;usually sits. Of course, this
+ ;is optional. defconstructor
+ ;makes named constructors, but
+ ;it is possible to manipulate
+ ;anonymous constructors also.
+ ;
+ (code-type ;The type of code currently in
+ :initform nil ;use by this constructor. This
+ :accessor constructor-code-type) ;is mostly for debugging and
+ ;analysis purposes.
+ ;The lazy installer sets this
+ ;to LAZY. The most basic and
+ ;least optimized type of code
+ ;is called FALLBACK.
+ ;
+ (supplied-initarg-names ;The names of the initargs this
+ :initarg :supplied-initarg-names ;constructor supplies when it
+ :reader ;"calls" make-instance.
+ constructor-supplied-initarg-names) ;
+ ;
+ (code-generators ;Generators for the different
+ :initarg :code-generators ;types of code this constructor
+ :reader constructor-code-generators)) ;could use.
+ (:metaclass funcallable-standard-class))
+
+
+;;;
+;;; Because the value in the code-type slot should always correspond to the
+;;; funcallable-instance-function of the constructor, this function should
+;;; always be used to set the both at the same time.
+;;;
+(defun set-constructor-code (constructor code type)
+ (set-funcallable-instance-function constructor code)
+ (set-function-name constructor (constructor-name constructor))
+ (setf (constructor-code-type constructor) type))
+
+
+(defmethod print-object ((constructor constructor) stream)
+ (printing-random-thing (constructor stream)
+ (format stream
+ "~S ~S (~S)"
+ (or (class-name (class-of constructor)) "Constructor")
+ (or (slot-value-or-default constructor 'name) "Anonymous")
+ (slot-value-or-default constructor 'code-type))))
+
+(defmethod describe-object ((constructor constructor) stream)
+ (format stream
+ "~S is a constructor for the class ~S.~%~
+ The current code type is ~S.~%~
+ Other possible code types are ~S."
+ constructor (constructor-class constructor)
+ (constructor-code-type constructor)
+ (gathering1 (collecting)
+ (doplist (key val) (constructor-code-generators constructor)
+ (gather1 key)))))
+
+;;;
+;;; I am not in a hairy enough mood to make this implementation be metacircular
+;;; enough that it can support a defconstructor for constructor objects.
+;;;
+(defun make-constructor (class name supplied-initarg-names code-generators)
+ (make-instance 'constructor
+ :class class
+ :name name
+ :supplied-initarg-names supplied-initarg-names
+ :code-generators code-generators))
+
+; This definition actually appears in std-class.lisp.
+;(defmethod class-constructors ((class std-class))
+; (with-slots (plist) class (getf plist 'constructors)))
+
+(defmethod add-constructor ((class slot-class)
+ (constructor constructor))
+ (with-slots (plist) class
+ (pushnew constructor (getf plist 'constructors))))
+
+(defmethod remove-constructor ((class slot-class)
+ (constructor constructor))
+ (with-slots (plist) class
+ (setf (getf plist 'constructors)
+ (delete constructor (getf plist 'constructors)))))
+
+(defmethod get-constructor ((class slot-class) name &optional (error-p t))
+ (or (dolist (c (class-constructors class))
+ (when (eq (constructor-name c) name) (return c)))
+ (if error-p
+ (error "Couldn't find a constructor with name ~S for class ~S."
+ name class)
+ ())))
+
+;;;
+;;; This is called to actually load a defconstructor constructor. It must
+;;; install the lazy installer in the function cell of the constructor name,
+;;; and also add this constructor to the list of constructors the class has.
+;;;
+(defmethod load-constructor-internal
+ ((class slot-class) name initargs generators)
+ (let ((constructor (make-constructor class name initargs generators))
+ (old (get-constructor class name nil)))
+ (when old (remove-constructor class old))
+ (install-lazy-constructor-installer constructor)
+ (add-constructor class constructor)
+ (setf (gdefinition name) constructor)))
+
+(defmethod install-lazy-constructor-installer ((constructor constructor))
+ (let ((class (constructor-class constructor)))
+ (set-constructor-code constructor
+ #'(lambda (&rest args)
+ (multiple-value-bind (code type)
+ (compute-constructor-code class constructor)
+ (prog1 (apply code args)
+ (set-constructor-code constructor
+ code
+ type))))
+ 'lazy)))
+
+;;;
+;;; The interface to keeping the constructors updated.
+;;;
+;;; add-method and remove-method (for standard-generic-function and -method),
+;;; promise to call maybe-update-constructors on the generic function and
+;;; the method.
+;;;
+;;; The class update code promises to call update-constructors whenever the
+;;; class is changed. That is, whenever the supers, slots or options change.
+;;; If user defined classes of constructor needs to be updated in more than
+;;; these circumstances, they should use the dependent updating mechanism to
+;;; make sure update-constructors is called.
+;;;
+;;; Bootstrapping concerns force the definitions of maybe-update-constructors
+;;; and update-constructors to be in the file std-class. For clarity, they
+;;; also appear below. Be sure to keep the definition here and there in sync.
+;;;
+;(defvar *initialization-generic-functions*
+; (list #'make-instance
+; #'default-initargs
+; #'allocate-instance
+; #'initialize-instance
+; #'shared-initialize))
+;
+;(defmethod maybe-update-constructors
+; ((generic-function generic-function)
+; (method method))
+; (when (memq generic-function *initialization-generic-functions*)
+; (labels ((recurse (class)
+; (update-constructors class)
+; (dolist (subclass (class-direct-subclasses class))
+; (recurse subclass))))
+; (when (classp (car (method-specializers method)))
+; (recurse (car (method-specializers method)))))))
+;
+;(defmethod update-constructors ((class slot-class))
+; (dolist (cons (class-constructors class))
+; (install-lazy-constructor-installer cons)))
+;
+;(defmethod update-constructors ((class class))
+; ())
+
+
+
+;;;
+;;; Here is the actual smarts for making the code generators and then trying
+;;; each generator to get constructor code. This extensible mechanism allows
+;;; new kinds of constructor code types to be added. A programmer defining a
+;;; specialization of the constructor class can either use this mechanism to
+;;; define new code types, or can override this mechanism by overriding the
+;;; methods on make-constructor-code-generators and compute-constructor-code.
+;;;
+;;; The function defined by define-constructor-code-type will receive the
+;;; class object, and the 4 original arguments to defconstructor. It can
+;;; return a constructor code generator, or return nil if this type of code
+;;; is determined to not be appropriate after looking at the defconstructor
+;;; arguments.
+;;;
+;;; When compute-constructor-code is called, it first performs basic checks
+;;; to make sure that the basic assumptions common to all the code types are
+;;; valid. (For details see method definition). If any of the tests fail,
+;;; the fallback constructor code type is used. If none of the tests fail,
+;;; the constructor code generators are called in order. They receive 5
+;;; arguments:
+;;;
+;;; CLASS the class the constructor is making instances of
+;;; WRAPPER that class's wrapper
+;;; DEFAULTS the result of calling class-default-initargs on class
+;;; INITIALIZE the applicable methods on initialize-instance
+;;; SHARED the applicable methosd on shared-initialize
+;;;
+;;; The first code generator to return code is used. The code generators are
+;;; called in reverse order of definition, so define-constructor-code-type
+;;; forms which define better code should appear after ones that define less
+;;; good code. The fallback code type appears first. Note that redefining a
+;;; code type does not change its position in the list. To do that, define
+;;; a new type at the end with the behavior.
+;;;
+
+(defvar *constructor-code-types* ())
+
+(defmacro define-constructor-code-type (type arglist &body body)
+ (let ((fn-name (intern (format nil
+ "CONSTRUCTOR-CODE-GENERATOR ~A ~A"
+ (package-name (symbol-package type))
+ (symbol-name type))
+ *the-pcl-package*)))
+ `(progn
+ (defun ,fn-name ,arglist .,body)
+ (load-define-constructor-code-type ',type ',fn-name))))
+
+(defun load-define-constructor-code-type (type generator)
+ (let ((old-entry (assq type *constructor-code-types*)))
+ (if old-entry
+ (setf (cadr old-entry) generator)
+ (push (list type generator) *constructor-code-types*))
+ type))
+
+(defmethod make-constructor-code-generators
+ ((class slot-class)
+ name lambda-list supplied-initarg-names supplied-initargs)
+ (cons 'list
+ (gathering1 (collecting)
+ (dolist (entry *constructor-code-types*)
+ (let ((generator
+ (funcall (cadr entry) class name lambda-list
+ supplied-initarg-names
+ supplied-initargs)))
+ (when generator
+ (gather1 `',(car entry))
+ (gather1 generator)))))))
+
+(defmethod compute-constructor-code ((class slot-class)
+ (constructor constructor))
+ (let* ((proto (class-prototype class))
+ (wrapper (class-wrapper class))
+ (defaults (class-default-initargs class))
+ (make
+ (compute-applicable-methods (gdefinition 'make-instance) (list class)))
+ (supplied-initarg-names
+ (constructor-supplied-initarg-names constructor))
+ (default
+ (compute-applicable-methods (gdefinition 'default-initargs)
+ (list class supplied-initarg-names))) ;?
+ (allocate
+ (compute-applicable-methods (gdefinition 'allocate-instance)
+ (list class)))
+ (initialize
+ (compute-applicable-methods (gdefinition 'initialize-instance)
+ (list proto)))
+ (shared
+ (compute-applicable-methods (gdefinition 'shared-initialize)
+ (list proto t)))
+ (code-generators
+ (constructor-code-generators constructor)))
+ (flet ((call-code-generator (generator)
+ (when (null generator)
+ (unless (setq generator (getf code-generators 'fallback))
+ (error "No FALLBACK generator?")))
+ (funcall generator class wrapper defaults initialize shared)))
+ (if (or (cdr make)
+ (cdr default)
+ (cdr allocate)
+ (not (check-initargs-1 class
+ supplied-initarg-names
+ (append initialize shared)
+ nil nil)))
+ ;; These are basic shared assumptions, if one of the
+ ;; has been violated, we have to resort to the fallback
+ ;; case. Any of these assumptions could be moved out
+ ;; of here and into the individual code types if there
+ ;; was a need to do so.
+ (values (call-code-generator nil) 'fallback)
+ ;; Otherwise try all the generators until one produces
+ ;; code for us.
+ (doplist (type generator) code-generators
+ (let ((code (call-code-generator generator)))
+ (when code (return (values code type)))))))))
+
+;;;
+;;; The facilities are useful for debugging, and to measure the performance
+;;; boost from constructors.
+;;;
+
+(defun map-constructors (fn)
+ (let ((nclasses 0)
+ (nconstructors 0))
+ (labels ((recurse (class)
+ (incf nclasses)
+ (dolist (constructor (class-constructors class))
+ (incf nconstructors)
+ (funcall fn constructor))
+ (dolist (subclass (class-direct-subclasses class))
+ (recurse subclass))))
+ (recurse (find-class 't))
+ (values nclasses nconstructors))))
+
+(defun reset-constructors ()
+ (multiple-value-bind (nclass ncons)
+ (map-constructors #'install-lazy-constructor-installer )
+ (format t "~&~D classes, ~D constructors." nclass ncons)))
+
+(defun disable-constructors ()
+ (multiple-value-bind (nclass ncons)
+ (map-constructors
+ #'(lambda (c)
+ (let ((gen (getf (constructor-code-generators c) 'fallback)))
+ (if (null gen)
+ (error "No fallback constructor for ~S." c)
+ (set-constructor-code c
+ (funcall gen
+ (constructor-class c)
+ () () () ())
+ 'fallback)))))
+ (format t "~&~D classes, ~D constructors." nclass ncons)))
+
+(defun enable-constructors ()
+ (reset-constructors))
+
+
+;;;
+;;; Helper functions and utilities that are shared by all of the code types
+;;; and by the main compute-constructor-code method as well.
+;;;
+
+(defvar *standard-initialize-instance-method*
+ (get-method #'initialize-instance
+ ()
+ (list *the-class-slot-object*)))
+
+(defvar *standard-shared-initialize-method*
+ (get-method #'shared-initialize
+ ()
+ (list *the-class-slot-object* *the-class-t*)))
+
+(defun non-pcl-initialize-instance-methods-p (methods)
+ (notevery #'(lambda (m) (eq m *standard-initialize-instance-method*))
+ methods))
+
+(defun non-pcl-shared-initialize-methods-p (methods)
+ (notevery #'(lambda (m) (eq m *standard-shared-initialize-method*))
+ methods))
+
+(defun non-pcl-or-after-initialize-instance-methods-p (methods)
+ (notevery #'(lambda (m) (or (eq m *standard-initialize-instance-method*)
+ (equal '(:after) (method-qualifiers m))))
+ methods))
+
+(defun non-pcl-or-after-shared-initialize-methods-p (methods)
+ (notevery #'(lambda (m) (or (eq m *standard-shared-initialize-method*)
+ (equal '(:after) (method-qualifiers m))))
+ methods))
+
+;;;
+;;; This returns two values. The first is a vector which can be used as the
+;;; initial value of the slots vector for the instance. The second is a symbol
+;;; describing the initforms this class has.
+;;;
+;;; If the first value is:
+;;;
+;;; :unsupplied no slot has an initform
+;;; :constants all slots have either a constant initform
+;;; or no initform at all
+;;; t there is at least one non-constant initform
+;;;
+(defun compute-constant-vector (class)
+ ;;(declare (values constants flag))
+ (let* ((wrapper (class-wrapper class))
+ (layout (wrapper-instance-slots-layout wrapper))
+ (flag :unsupplied)
+ (constants ()))
+ (dolist (slotd (class-slots class))
+ (let ((name (slot-definition-name slotd))
+ (initform (slot-definition-initform slotd))
+ (initfn (slot-definition-initfunction slotd)))
+ (cond ((null (memq name layout)))
+ ((null initfn)
+ (push (cons name *slot-unbound*) constants))
+ ((constantp initform)
+ (push (cons name (eval initform)) constants)
+ (when (eq flag ':unsupplied) (setq flag ':constants)))
+ (t
+ (push (cons name *slot-unbound*) constants)
+ (setq flag 't)))))
+ (let* ((constants-alist (sort constants #'(lambda (x y)
+ (memq (car y)
+ (memq (car x) layout)))))
+ (constants-list (mapcar #'cdr constants-alist)))
+ (values constants-list flag))))
+
+
+;;;
+;;; This takes a class and a list of initarg-names, and returns an alist
+;;; indicating the positions of the slots those initargs may fill. The
+;;; order of the initarg-names argument is important of course, since we
+;;; have to respect the rules about the leftmost initarg that fills a slot
+;;; having precedence. This function allows initarg names to appear twice
+;;; in the list, it only considers the first appearance.
+;;;
+(defun compute-initarg-positions (class initarg-names)
+ (let* ((layout (wrapper-instance-slots-layout (class-wrapper class)))
+ (positions
+ (gathering1 (collecting)
+ (iterate ((slot-name (list-elements layout))
+ (position (interval :from 0)))
+ (gather1 (cons slot-name position)))))
+ (slot-initargs
+ (mapcar #'(lambda (slotd)
+ (list (slot-definition-initargs slotd)
+ (or (cdr (assq (slot-definition-name slotd) positions))
+ ':class)))
+ (class-slots class))))
+ ;; Go through each of the initargs, and figure out what position
+ ;; it fills by replacing the entries in slot-initargs it fills.
+ (dolist (initarg initarg-names)
+ (dolist (slot-entry slot-initargs)
+ (let ((slot-initargs (car slot-entry)))
+ (when (and (listp slot-initargs)
+ (not (null slot-initargs))
+ (memq initarg slot-initargs))
+ (setf (car slot-entry) initarg)))))
+ (gathering1 (collecting)
+ (dolist (initarg initarg-names)
+ (let ((positions (gathering1 (collecting)
+ (dolist (slot-entry slot-initargs)
+ (when (eq (car slot-entry) initarg)
+ (gather1 (cadr slot-entry)))))))
+ (when positions
+ (gather1 (cons initarg positions))))))))
+
+
+;;;
+;;; The FALLBACK case allows anything. This always works, and always appears
+;;; as the last of the generators for a constructor. It does a full call to
+;;; make-instance.
+;;;
+
+(define-constructor-code-type fallback
+ (class name arglist supplied-initarg-names supplied-initargs)
+ (declare (ignore name supplied-initarg-names))
+ `(function
+ (lambda (&rest ignore)
+ (declare (ignore ignore))
+ (function
+ (lambda ,arglist
+ (make-instance
+ ',(class-name class)
+ ,@(gathering1 (collecting)
+ (iterate ((tail (*list-tails supplied-initargs :by #'cddr)))
+ (gather1 `',(car tail))
+ (gather1 (cadr tail))))))))))
+
+;;;
+;;; The GENERAL case allows:
+;;; constant, unsupplied or non-constant initforms
+;;; constant or non-constant default initargs
+;;; supplied initargs
+;;; slot-filling initargs
+;;; :after methods on shared-initialize and initialize-instance
+;;;
+(define-constructor-code-type general
+ (class name arglist supplied-initarg-names supplied-initargs)
+ (declare (ignore name))
+ (let ((raw-allocator (raw-instance-allocator class))
+ (slots-fetcher (slots-fetcher class)))
+ `(function
+ (lambda (class .wrapper. defaults init shared)
+ (multiple-value-bind (.constants.
+ .constant-initargs.
+ .initfns-initargs-and-positions.
+ .supplied-initarg-positions.
+ .shared-initfns.
+ .initfns.)
+ (general-generator-internal class
+ defaults
+ init
+ shared
+ ',supplied-initarg-names
+ ',supplied-initargs)
+ .supplied-initarg-positions.
+ (when (and .constants.
+ (null (non-pcl-or-after-initialize-instance-methods-p
+ init))
+ (null (non-pcl-or-after-shared-initialize-methods-p
+ shared)))
+ (function
+ (lambda ,arglist
+ (declare #.*optimize-speed*)
+ (let* ((.instance. (,raw-allocator .wrapper. .constants.))
+ (.slots. (,slots-fetcher .instance.))
+ (.positions. .supplied-initarg-positions.)
+ (.initargs. .constant-initargs.))
+ .positions.
+
+ (dolist (entry .initfns-initargs-and-positions.)
+ (let ((val (funcall (car entry)))
+ (initarg (cadr entry)))
+ (when initarg
+ (push val .initargs.)
+ (push initarg .initargs.))
+ (dolist (pos (cddr entry))
+ (setf (%instance-ref .slots. pos) val))))
+
+ ,@(gathering1 (collecting)
+ (doplist (initarg value) supplied-initargs
+ (unless (constantp value)
+ (gather1 `(let ((.value. ,value))
+ (push .value. .initargs.)
+ (push ',initarg .initargs.)
+ (dolist (.p. (pop .positions.))
+ (setf (%instance-ref .slots. .p.)
+ .value.)))))))
+
+ (dolist (fn .shared-initfns.)
+ (apply fn .instance. t .initargs.))
+ (dolist (fn .initfns.)
+ (apply fn .instance. .initargs.))
+
+ .instance.)))))))))
+
+(defun general-generator-internal
+ (class defaults init shared supplied-initarg-names supplied-initargs)
+ (flet ((bail-out () (return-from general-generator-internal nil)))
+ (let* ((constants (compute-constant-vector class))
+ (layout (wrapper-instance-slots-layout (class-wrapper class)))
+ (initarg-positions
+ (compute-initarg-positions class
+ (append supplied-initarg-names
+ (mapcar #'car defaults))))
+ (initfns-initargs-and-positions ())
+ (supplied-initarg-positions ())
+ (constant-initargs ())
+ (used-positions ()))
+
+ ;;
+ ;; Go through each of the supplied initargs for three reasons.
+ ;;
+ ;; - If it fills a class slot, bail out.
+ ;; - If its a constant form, fill the constant vector.
+ ;; - Otherwise remember the positions no two initargs
+ ;; will try to fill the same position, since compute
+ ;; initarg positions already took care of that, but
+ ;; we do need to know what initforms will and won't
+ ;; be needed.
+ ;;
+ (doplist (initarg val) supplied-initargs
+ (let ((positions (cdr (assq initarg initarg-positions))))
+ (cond ((memq :class positions) (bail-out))
+ ((constantp val)
+ (setq val (eval val))
+ (push val constant-initargs)
+ (push initarg constant-initargs)
+ (dolist (pos positions) (setf (svref constants pos) val)))
+ (t
+ (push positions supplied-initarg-positions)))
+ (setq used-positions (append positions used-positions))))
+ ;;
+ ;; Go through each of the default initargs, for three reasons.
+ ;;
+ ;; - If it fills a class slot, bail out.
+ ;; - If it is a constant, and it does fill a slot, put that
+ ;; into the constant vector.
+ ;; - If it isn't a constant, record its initfn and position.
+ ;;
+ (dolist (default defaults)
+ (let* ((name (car default))
+ (initfn (cadr default))
+ (form (caddr default))
+ (value ())
+ (positions (cdr (assq name initarg-positions))))
+ (unless (memq name supplied-initarg-names)
+ (cond ((memq :class positions) (bail-out))
+ ((constantp form)
+ (setq value (eval form))
+ (push value constant-initargs)
+ (push name constant-initargs)
+ (dolist (pos positions)
+ (setf (svref constants pos) value)))
+ (t
+ (push (list* initfn name positions)
+ initfns-initargs-and-positions)))
+ (setq used-positions (append positions used-positions)))))
+ ;;
+ ;; Go through each of the slot initforms:
+ ;;
+ ;; - If its position has already been filled, do nothing.
+ ;; The initfn won't need to be called, and the slot won't
+ ;; need to be touched.
+ ;; - If it is a class slot, and has an initform, bail out.
+ ;; - If its a constant or unsupplied, ignore it, it is
+ ;; already in the constant vector.
+ ;; - Otherwise, record its initfn and position
+ ;;
+ (dolist (slotd (class-slots class))
+ (let* ((alloc (slot-definition-allocation slotd))
+ (name (slot-definition-name slotd))
+ (form (slot-definition-initform slotd))
+ (initfn (slot-definition-initfunction slotd))
+ (position (position name layout)))
+ (cond ((neq alloc :instance)
+ (unless (null initfn)
+ (bail-out)))
+ ((member position used-positions))
+ ((or (constantp form)
+ (null initfn)))
+ (t
+ (push (list initfn nil position)
+ initfns-initargs-and-positions)))))
+
+ (values constants
+ constant-initargs
+ (nreverse initfns-initargs-and-positions)
+ (nreverse supplied-initarg-positions)
+ (mapcar #'method-function
+ (remove *standard-shared-initialize-method* shared))
+ (mapcar #'method-function
+ (remove *standard-initialize-instance-method* init))))))
+
+
+;;;
+;;; The NO-METHODS case allows:
+;;; constant, unsupplied or non-constant initforms
+;;; constant or non-constant default initargs
+;;; supplied initargs that are arguments to constructor, or constants
+;;; slot-filling initargs
+;;;
+
+(define-constructor-code-type no-methods
+ (class name arglist supplied-initarg-names supplied-initargs)
+ (declare (ignore name))
+ (let ((raw-allocator (raw-instance-allocator class))
+ (slots-fetcher (slots-fetcher class)))
+ `(function
+ (lambda (class .wrapper. defaults init shared)
+ (multiple-value-bind (.constants.
+ .initfns-and-positions.
+ .supplied-initarg-positions.)
+ (no-methods-generator-internal class
+ defaults
+ ',supplied-initarg-names
+ ',supplied-initargs)
+ .initfns-and-positions.
+ .supplied-initarg-positions.
+ (when (and .constants.
+ (null (non-pcl-initialize-instance-methods-p init))
+ (null (non-pcl-shared-initialize-methods-p shared)))
+ #'(lambda ,arglist
+ (declare #.*optimize-speed*)
+ (let* ((.instance. (,raw-allocator .wrapper. .constants.))
+ (.slots. (,slots-fetcher .instance.))
+ (.positions. .supplied-initarg-positions.))
+ .positions.
+
+ (dolist (entry .initfns-and-positions.)
+ (let ((val (funcall (car entry))))
+ (dolist (pos (cdr entry))
+ (setf (%instance-ref .slots. pos) val))))
+
+ ,@(gathering1 (collecting)
+ (doplist (initarg value) supplied-initargs
+ (unless (constantp value)
+ (gather1
+ `(let ((.value. ,value))
+ (dolist (.p. (pop .positions.))
+ (setf (%instance-ref .slots. .p.) .value.)))))))
+
+ .instance.))))))))
+
+(defun no-methods-generator-internal
+ (class defaults supplied-initarg-names supplied-initargs)
+ (flet ((bail-out () (return-from no-methods-generator-internal nil)))
+ (let* ((constants (compute-constant-vector class))
+ (layout (wrapper-instance-slots-layout (class-wrapper class)))
+ (initarg-positions
+ (compute-initarg-positions class
+ (append supplied-initarg-names
+ (mapcar #'car defaults))))
+ (initfns-and-positions ())
+ (supplied-initarg-positions ())
+ (used-positions ()))
+ ;;
+ ;; Go through each of the supplied initargs for three reasons.
+ ;;
+ ;; - If it fills a class slot, bail out.
+ ;; - If its a constant form, fill the constant vector.
+ ;; - Otherwise remember the positions, no two initargs
+ ;; will try to fill the same position, since compute
+ ;; initarg positions already took care of that, but
+ ;; we do need to know what initforms will and won't
+ ;; be needed.
+ ;;
+ (doplist (initarg val) supplied-initargs
+ (let ((positions (cdr (assq initarg initarg-positions))))
+ (cond ((memq :class positions) (bail-out))
+ ((constantp val)
+ (setq val (eval val))
+ (dolist (pos positions)
+ (setf (svref constants pos) val)))
+ (t
+ (push positions supplied-initarg-positions)))
+ (setq used-positions (append positions used-positions))))
+ ;;
+ ;; Go through each of the default initargs, for three reasons.
+ ;;
+ ;; - If it fills a class slot, bail out.
+ ;; - If it is a constant, and it does fill a slot, put that
+ ;; into the constant vector.
+ ;; - If it isn't a constant, record its initfn and position.
+ ;;
+ (dolist (default defaults)
+ (let* ((name (car default))
+ (initfn (cadr default))
+ (form (caddr default))
+ (value ())
+ (positions (cdr (assq name initarg-positions))))
+ (unless (memq name supplied-initarg-names)
+ (cond ((memq :class positions) (bail-out))
+ ((constantp form)
+ (setq value (eval form))
+ (dolist (pos positions)
+ (setf (svref constants pos) value)))
+ (t
+ (push (cons initfn positions)
+ initfns-and-positions)))
+ (setq used-positions (append positions used-positions)))))
+ ;;
+ ;; Go through each of the slot initforms:
+ ;;
+ ;; - If its position has already been filled, do nothing.
+ ;; The initfn won't need to be called, and the slot won't
+ ;; need to be touched.
+ ;; - If it is a class slot, and has an initform, bail out.
+ ;; - If its a constant or unsupplied, do nothing, we know
+ ;; that it is already in the constant vector.
+ ;; - Otherwise, record its initfn and position
+ ;;
+ (dolist (slotd (class-slots class))
+ (let* ((alloc (slot-definition-allocation slotd))
+ (name (slot-definition-name slotd))
+ (form (slot-definition-initform slotd))
+ (initfn (slot-definition-initfunction slotd))
+ (position (position name layout)))
+ (cond ((neq alloc :instance)
+ (unless (null initfn)
+ (bail-out)))
+ ((member position used-positions))
+ ((or (constantp form)
+ (null initfn)))
+ (t
+ (push (list initfn position) initfns-and-positions)))))
+
+ (values constants
+ (nreverse initfns-and-positions)
+ (nreverse supplied-initarg-positions)))))
+
+
+;;;
+;;; The SIMPLE-SLOTS case allows:
+;;; constant or unsupplied initforms
+;;; constant default initargs
+;;; supplied initargs
+;;; slot filling initargs
+;;;
+
+(define-constructor-code-type simple-slots
+ (class name arglist supplied-initarg-names supplied-initargs)
+ (declare (ignore name))
+ (let ((raw-allocator (raw-instance-allocator class))
+ (slots-fetcher (slots-fetcher class)))
+ `(function
+ (lambda (class .wrapper. defaults init shared)
+ (when (and (null (non-pcl-initialize-instance-methods-p init))
+ (null (non-pcl-shared-initialize-methods-p shared)))
+ (multiple-value-bind (.constants. .supplied-initarg-positions.)
+ (simple-slots-generator-internal class
+ defaults
+ ',supplied-initarg-names
+ ',supplied-initargs)
+ (when .constants.
+ (function
+ (lambda ,arglist
+ (declare #.*optimize-speed*)
+ (let* ((.instance. (,raw-allocator .wrapper. .constants.))
+ (.slots. (,slots-fetcher .instance.))
+ (.positions. .supplied-initarg-positions.))
+ .positions.
+
+ ,@(gathering1 (collecting)
+ (doplist (initarg value) supplied-initargs
+ (unless (constantp value)
+ (gather1
+ `(let ((.value. ,value))
+ (dolist (.p. (pop .positions.))
+ (setf (%instance-ref .slots. .p.) .value.)))))))
+
+ .instance.))))))))))
+
+(defun simple-slots-generator-internal
+ (class defaults supplied-initarg-names supplied-initargs)
+ (flet ((bail-out () (return-from simple-slots-generator-internal nil)))
+ (let* ((constants (compute-constant-vector class))
+ (layout (wrapper-instance-slots-layout (class-wrapper class)))
+ (initarg-positions
+ (compute-initarg-positions class
+ (append supplied-initarg-names
+ (mapcar #'car defaults))))
+ (supplied-initarg-positions ())
+ (used-positions ()))
+ ;;
+ ;; Go through each of the supplied initargs for three reasons.
+ ;;
+ ;; - If it fills a class slot, bail out.
+ ;; - If its a constant form, fill the constant vector.
+ ;; - Otherwise remember the positions, no two initargs
+ ;; will try to fill the same position, since compute
+ ;; initarg positions already took care of that, but
+ ;; we do need to know what initforms will and won't
+ ;; be needed.
+ ;;
+ (doplist (initarg val) supplied-initargs
+ (let ((positions (cdr (assq initarg initarg-positions))))
+ (cond ((memq :class positions) (bail-out))
+ ((constantp val)
+ (setq val (eval val))
+ (dolist (pos positions)
+ (setf (svref constants pos) val)))
+ (t
+ (push positions supplied-initarg-positions)))
+ (setq used-positions (append used-positions positions))))
+ ;;
+ ;; Go through each of the default initargs for three reasons.
+ ;;
+ ;; - If it isn't a constant form, bail out.
+ ;; - If it fills a class slot, bail out.
+ ;; - If it is a constant, and it does fill a slot, put that
+ ;; into the constant vector.
+ ;;
+ (dolist (default defaults)
+ (let* ((name (car default))
+ (form (caddr default))
+ (value ())
+ (positions (cdr (assq name initarg-positions))))
+ (unless (memq name supplied-initarg-names)
+ (cond ((memq :class positions) (bail-out))
+ ((not (constantp form))
+ (bail-out))
+ (t
+ (setq value (eval form))
+ (dolist (pos positions)
+ (setf (svref constants pos) value)))))))
+ ;;
+ ;; Go through each of the slot initforms:
+ ;;
+ ;; - If its position has already been filled, do nothing.
+ ;; The initfn won't need to be called, and the slot won't
+ ;; need to be touched, we are OK.
+ ;; - If it has a non-constant initform, bail-out. This
+ ;; case doesn't handle those.
+ ;; - If it has a constant or unsupplied initform we don't
+ ;; really need to do anything, the value is in the
+ ;; constants vector.
+ ;;
+ (dolist (slotd (class-slots class))
+ (let* ((alloc (slot-definition-allocation slotd))
+ (name (slot-definition-name slotd))
+ (form (slot-definition-initform slotd))
+ (initfn (slot-definition-initfunction slotd))
+ (position (position name layout)))
+ (cond ((neq alloc :instance)
+ (unless (null initfn)
+ (bail-out)))
+ ((member position used-positions))
+ ((or (constantp form)
+ (null initfn)))
+ (t
+ (bail-out)))))
+
+ (values constants (nreverse supplied-initarg-positions)))))
+
diff --git a/gcl/pcl/old/dlap.lisp b/gcl/pcl/old/dlap.lisp
new file mode 100644
index 000000000..88710c107
--- /dev/null
+++ b/gcl/pcl/old/dlap.lisp
@@ -0,0 +1,639 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+
+
+(defun emit-one-class-reader (class-slot-p)
+ (emit-reader/writer :reader 1 class-slot-p))
+
+(defun emit-one-class-writer (class-slot-p)
+ (emit-reader/writer :writer 1 class-slot-p))
+
+(defun emit-two-class-reader (class-slot-p)
+ (emit-reader/writer :reader 2 class-slot-p))
+
+(defun emit-two-class-writer (class-slot-p)
+ (emit-reader/writer :writer 2 class-slot-p))
+
+
+
+(defun emit-reader/writer (reader/writer 1-or-2-class class-slot-p)
+ (let ((instance nil)
+ (arglist ())
+ (closure-variables ())
+ (field (first-wrapper-cache-number-index)))
+ ;;we need some field to do the fast obsolete check
+ (ecase reader/writer
+ (:reader (setq instance (dfun-arg-symbol 0)
+ arglist (list instance)))
+ (:writer (setq instance (dfun-arg-symbol 1)
+ arglist (list (dfun-arg-symbol 0) instance))))
+ (ecase 1-or-2-class
+ (1 (setq closure-variables '(wrapper-0 index miss-fn)))
+ (2 (setq closure-variables '(wrapper-0 wrapper-1 index miss-fn))))
+ (generating-lap closure-variables
+ arglist
+ (with-lap-registers ((inst t) ;reg for the instance
+ (wrapper #-structure-wrapper vector ;reg for the wrapper
+ #+structure-wrapper t)
+ #+structure-wrapper (cnv fixnum-vector)
+ (cache-no index)) ;reg for the cache no
+ (let ((index cache-no) ;This register is used
+ ;for different values at
+ ;different times.
+ (slots (and (null class-slot-p)
+ (allocate-register #-new-kcl-wrapper 'vector
+ #+new-kcl-wrapper t)))
+ (csv (and class-slot-p
+ (allocate-register t))))
+ (prog1 (flatten-lap
+ (opcode :move (operand :arg instance) inst) ;get the instance
+ (opcode :std-instance-p inst 'std-instance) ;if not either std-inst
+ (opcode :fsc-instance-p inst 'fsc-instance) ;or fsc-instance then
+ (opcode :go 'trap) ;we lose
+
+ (opcode :label 'fsc-instance)
+ (opcode :move (operand :fsc-wrapper inst) wrapper)
+ (and slots
+ (opcode :move (operand :fsc-slots inst) slots))
+ (opcode :go 'have-wrapper)
+
+ (opcode :label 'std-instance)
+ (opcode :move (operand :std-wrapper inst) wrapper)
+ (and slots
+ (opcode :move (operand :std-slots inst) slots))
+
+ (opcode :label 'have-wrapper)
+ #-structure-wrapper
+ (opcode :move (operand :cref wrapper field) cache-no)
+ #+structure-wrapper
+ (opcode :move (emit-wrapper-cache-number-vector wrapper) cnv)
+ #+structure-wrapper
+ (opcode :move (operand :cref cnv field) cache-no)
+ (opcode :izerop cache-no 'trap) ;obsolete wrapper?
+
+ (ecase 1-or-2-class
+ (1 (emit-check-1-class-wrapper wrapper 'wrapper-0 'trap))
+ (2 (emit-check-2-class-wrapper wrapper 'wrapper-0 'wrapper-1 'trap)))
+
+ (if class-slot-p
+ (flatten-lap
+ (opcode :move (operand :cvar 'index) csv)
+ (ecase reader/writer
+ (:reader (emit-get-class-slot csv 'trap inst))
+ (:writer (emit-set-class-slot csv (car arglist) inst))))
+ (flatten-lap
+ (opcode :move (operand :cvar 'index) index)
+ (ecase reader/writer
+ (:reader (emit-get-slot slots index 'trap inst))
+ (:writer (emit-set-slot slots index (car arglist) inst)))))
+
+ (opcode :label 'trap)
+ (emit-miss 'miss-fn))
+ (when slots (deallocate-register slots))
+ (when csv (deallocate-register csv))))))))
+
+
+
+(defun emit-one-index-readers (class-slot-p)
+ (let ((arglist (list (dfun-arg-symbol 0))))
+ (generating-lap '(field cache-vector mask size index miss-fn)
+ arglist
+ (with-lap-registers ((slots #-new-kcl-wrapper vector #+new-kcl-wrapper t))
+ (emit-dlap arglist
+ '(standard-instance)
+ 'trap
+ (with-lap-registers ((index index))
+ (flatten-lap
+ (opcode :move (operand :cvar 'index) index)
+ (if class-slot-p
+ (emit-get-class-slot index 'trap slots)
+ (emit-get-slot slots index 'trap))))
+ (flatten-lap
+ (opcode :label 'trap)
+ (emit-miss 'miss-fn))
+ nil
+ (and (null class-slot-p) (list slots)))))))
+
+(defun emit-one-index-writers (class-slot-p)
+ (let ((arglist (list (dfun-arg-symbol 0) (dfun-arg-symbol 1))))
+ (generating-lap '(field cache-vector mask size index miss-fn)
+ arglist
+ (with-lap-registers ((slots #-new-kcl-wrapper vector #+new-kcl-wrapper t))
+ (emit-dlap arglist
+ '(t standard-instance)
+ 'trap
+ (with-lap-registers ((index index))
+ (flatten-lap
+ (opcode :move (operand :cvar 'index) index)
+ (if class-slot-p
+ (emit-set-class-slot index (dfun-arg-symbol 0) slots)
+ (emit-set-slot slots index (dfun-arg-symbol 0)))))
+ (flatten-lap
+ (opcode :label 'trap)
+ (emit-miss 'miss-fn))
+ nil
+ (and (null class-slot-p) (list nil slots)))))))
+
+
+
+(defun emit-n-n-readers ()
+ (let ((arglist (list (dfun-arg-symbol 0))))
+ (generating-lap '(field cache-vector mask size miss-fn)
+ arglist
+ (with-lap-registers ((slots #-new-kcl-wrapper vector #+new-kcl-wrapper t)
+ (index index))
+ (emit-dlap arglist
+ '(standard-instance)
+ 'trap
+ (emit-get-slot slots index 'trap)
+ (flatten-lap
+ (opcode :label 'trap)
+ (emit-miss 'miss-fn))
+ index
+ (list slots))))))
+
+(defun emit-n-n-writers ()
+ (let ((arglist (list (dfun-arg-symbol 0) (dfun-arg-symbol 1))))
+ (generating-lap '(field cache-vector mask size miss-fn)
+ arglist
+ (with-lap-registers ((slots #-new-kcl-wrapper vector #+new-kcl-wrapper t)
+ (index index))
+ (flatten-lap
+ (emit-dlap arglist
+ '(t standard-instance)
+ 'trap
+ (emit-set-slot slots index (dfun-arg-symbol 0))
+ (flatten-lap
+ (opcode :label 'trap)
+ (emit-miss 'miss-fn))
+ index
+ (list nil slots)))))))
+
+
+
+(defun emit-checking (metatypes applyp)
+ (let ((dlap-lambda-list (make-dlap-lambda-list metatypes applyp)))
+ (generating-lap '(field cache-vector mask size
+ #-excl-sun4 emf #+excl-sun4 function
+ miss-fn)
+ dlap-lambda-list
+ (emit-dlap (remove '&rest dlap-lambda-list)
+ metatypes
+ 'trap
+ (with-lap-registers ((#-excl-sun4 emf #+excl-sun4 function t))
+ (flatten-lap
+ (opcode :move (operand :cvar
+ #-excl-sun4 'emf #+excl-sun4 'function)
+ #-excl-sun4 emf
+ #+excl-sun4 function)
+ #-excl-sun4 (opcode :emf-call emf)
+ #+excl-sun4 (opcode :jmp function)))
+ (with-lap-registers ((miss-function t))
+ (flatten-lap
+ (opcode :label 'trap)
+ (opcode :move (operand :cvar 'miss-fn) miss-function)
+ (opcode :jmp miss-function)))
+ nil))))
+
+(defun emit-caching (metatypes applyp)
+ (let ((dlap-lambda-list (make-dlap-lambda-list metatypes applyp)))
+ (generating-lap '(field cache-vector mask size miss-fn)
+ dlap-lambda-list
+ (with-lap-registers ((#-excl-sun4 emf #+excl-sun4 function t))
+ (emit-dlap (remove '&rest dlap-lambda-list)
+ metatypes
+ 'trap
+ (flatten-lap
+ #-excl-sun4 (opcode :emf-call emf)
+ #+excl-sun4 (opcode :jmp function))
+ (with-lap-registers ((miss-function t))
+ (flatten-lap
+ (opcode :label 'trap)
+ (opcode :move (operand :cvar 'miss-fn) miss-function)
+ (opcode :jmp miss-function)))
+ #-excl-sun4 emf #+excl-sun4 function)))))
+
+(defun emit-constant-value (metatypes)
+ (let ((dlap-lambda-list (make-dlap-lambda-list metatypes nil)))
+ (generating-lap '(field cache-vector mask size miss-fn)
+ dlap-lambda-list
+ (with-lap-registers ((value t))
+ (emit-dlap dlap-lambda-list
+ metatypes
+ 'trap
+ (flatten-lap
+ (opcode :return value))
+ (with-lap-registers ((miss-function t))
+ (flatten-lap
+ (opcode :label 'trap)
+ (opcode :move (operand :cvar 'miss-fn) miss-function)
+ (opcode :jmp miss-function)))
+ value)))))
+
+
+
+(defun emit-check-1-class-wrapper (wrapper cwrapper-0 miss-label)
+ (with-lap-registers ((cwrapper #-structure-wrapper vector
+ #+structure-wrapper t))
+ (flatten-lap
+ (opcode :move (operand :cvar cwrapper-0) cwrapper)
+ (opcode :neq wrapper cwrapper miss-label)))) ;wrappers not eq, trap
+
+(defun emit-check-2-class-wrapper (wrapper cwrapper-0 cwrapper-1 miss-label)
+ (with-lap-registers ((cwrapper #-structure-wrapper vector
+ #+structure-wrapper t))
+ (flatten-lap
+ (opcode :move (operand :cvar cwrapper-0) cwrapper) ;This is an OR. Isn't
+ (opcode :eq wrapper cwrapper 'hit-internal) ;assembly code fun
+ (opcode :move (operand :cvar cwrapper-1) cwrapper) ;
+ (opcode :neq wrapper cwrapper miss-label) ;
+ (opcode :label 'hit-internal))))
+
+(defun emit-get-slot (slots index trap-label &optional temp)
+ (let ((slot-unbound (operand :constant *slot-unbound*)))
+ (with-lap-registers ((val t :reuse temp))
+ (flatten-lap
+ (opcode :move (operand :instance-ref slots index) val) ;get slot value
+ (opcode :eq val slot-unbound trap-label) ;is the slot unbound?
+ (opcode :return val))))) ;return the slot value
+
+(defun emit-set-slot (slots index new-value-arg &optional temp)
+ (with-lap-registers ((new-val t :reuse temp))
+ (flatten-lap
+ (opcode :move (operand :arg new-value-arg) new-val) ;get new value into a reg
+ (opcode :move new-val (operand :instance-ref slots index));set slot value
+ (opcode :return new-val))))
+
+(defun emit-get-class-slot (index trap-label &optional temp)
+ (let ((slot-unbound (operand :constant *slot-unbound*)))
+ (with-lap-registers ((val t :reuse temp))
+ (flatten-lap
+ (opcode :move (operand :cdr index) val)
+ (opcode :eq val slot-unbound trap-label)
+ (opcode :return val)))))
+
+(defun emit-set-class-slot (index new-value-arg &optional temp)
+ (with-lap-registers ((new-val t :reuse temp))
+ (flatten-lap
+ (opcode :move (operand :arg new-value-arg) new-val)
+ (opcode :move new-val (operand :cdr index))
+ (opcode :return new-val))))
+
+(defun emit-miss (miss-fn)
+ (with-lap-registers ((miss-fn-reg t))
+ (flatten-lap
+ (opcode :move (operand :cvar miss-fn) miss-fn-reg) ;get the miss function
+ (opcode :jmp miss-fn-reg)))) ;and call it
+
+
+
+(defun dlap-wrappers (metatypes)
+ (mapcar #'(lambda (x) (and (neq x 't)
+ (allocate-register #-structure-wrapper 'vector
+ #+structure-wrapper t)))
+ metatypes))
+
+(defun dlap-wrapper-moves (wrappers args metatypes miss-label slot-regs)
+ (gathering1 (collecting)
+ (iterate ((mt (list-elements metatypes))
+ (arg (list-elements args))
+ (wrapper (list-elements wrappers))
+ (i (interval :from 0)))
+ (when wrapper
+ (gather1
+ (emit-fetch-wrapper mt arg wrapper miss-label (nth i slot-regs)))))))
+
+(defun emit-dlap (args metatypes miss-label hit miss value-reg &optional slot-regs)
+ (let* ((wrappers (dlap-wrappers metatypes))
+ (nwrappers (remove nil wrappers))
+ (wrapper-moves (dlap-wrapper-moves wrappers args metatypes miss-label slot-regs)))
+ (prog1 (emit-dlap-internal nwrappers
+ wrapper-moves
+ hit
+ miss
+ miss-label
+ value-reg)
+ (mapc #'deallocate-register nwrappers))))
+
+(defun emit-dlap-internal (wrapper-regs wrapper-moves hit miss miss-label value-reg)
+ (cond ((cdr wrapper-regs)
+ (emit-greater-than-1-dlap
+ wrapper-regs wrapper-moves hit miss miss-label value-reg))
+ ((null value-reg)
+ (emit-1-nil-dlap
+ (car wrapper-regs) (car wrapper-moves) hit miss miss-label))
+ (t
+ (emit-1-t-dlap
+ (car wrapper-regs) (car wrapper-moves) hit miss miss-label value-reg))))
+
+
+
+(defun emit-1-nil-dlap (wrapper wrapper-move hit miss miss-label)
+ (with-lap-registers ((location index)
+ (primary index)
+ (cache-vector vector))
+ (flatten-lap
+ wrapper-move
+ (opcode :move (operand :cvar 'cache-vector) cache-vector)
+ (with-lap-registers ((wrapper-cache-no index))
+ (flatten-lap
+ (emit-1-wrapper-compute-primary-cache-location wrapper primary wrapper-cache-no)
+ (opcode :move primary location)
+ (emit-check-1-wrapper-in-cache cache-vector location wrapper hit) ;inline hit code
+ (opcode :izerop wrapper-cache-no miss-label)))
+ (with-lap-registers ((size index))
+ (flatten-lap
+ (opcode :move (operand :cvar 'size) size)
+ (opcode :label 'loop)
+ (opcode :move (operand :i1+ location) location)
+ (opcode :fix= location primary miss-label)
+ (opcode :fix= location size 'set-location-to-min)
+ (opcode :label 'continue)
+ (emit-check-1-wrapper-in-cache cache-vector location wrapper hit)
+ (opcode :go 'loop)
+ (opcode :label 'set-location-to-min)
+ (opcode :izerop primary miss-label)
+ (opcode :move (operand :constant (index-value->index 0)) location)
+ (opcode :go 'continue)))
+ miss)))
+
+;;;
+;;; The function below implements CACHE-VECTOR-LOCK-COUNT as the first entry
+;;; in a cache (svref cache-vector 0). This should probably be abstracted.
+;;;
+(defun emit-1-t-dlap (wrapper wrapper-move hit miss miss-label value)
+ (with-lap-registers ((location index)
+ (primary index)
+ (cache-vector vector)
+ (initial-lock-count t))
+ (flatten-lap
+ wrapper-move
+ (opcode :move (operand :cvar 'cache-vector) cache-vector)
+ (with-lap-registers ((wrapper-cache-no index))
+ (flatten-lap
+ (emit-1-wrapper-compute-primary-cache-location wrapper primary wrapper-cache-no)
+ (opcode :move primary location)
+ (opcode :move (operand :cref cache-vector 0) initial-lock-count) ;get lock-count
+ (emit-check-cache-entry cache-vector location wrapper 'hit-internal)
+ (opcode :izerop wrapper-cache-no miss-label))) ;check for obsolescence
+ (with-lap-registers ((size index))
+ (flatten-lap
+ (opcode :move (operand :cvar 'size) size)
+
+ (opcode :label 'loop)
+ (opcode :move (operand :i1+ location) location)
+ (opcode :move (operand :i1+ location) location)
+ (opcode :label 'continue)
+ (opcode :fix= location primary miss-label)
+ (opcode :fix= location size 'set-location-to-min)
+ (emit-check-cache-entry cache-vector location wrapper 'hit-internal)
+ (opcode :go 'loop)
+
+ (opcode :label 'set-location-to-min)
+ (opcode :izerop primary miss-label)
+ (opcode :move (operand :constant (index-value->index 2)) location)
+ (opcode :go 'continue)))
+ (opcode :label 'hit-internal)
+ (opcode :move (operand :i1+ location) location) ;position for getting value
+ (opcode :move (emit-cache-vector-ref cache-vector location) value)
+ (emit-lock-count-test initial-lock-count cache-vector 'hit)
+ miss
+ (opcode :label 'hit)
+ hit)))
+
+(defun emit-greater-than-1-dlap (wrappers wrapper-moves hit miss miss-label value)
+ (let ((cache-line-size (compute-line-size (+ (length wrappers) (if value 1 0)))))
+ (with-lap-registers ((location index)
+ (primary index)
+ (cache-vector vector)
+ (initial-lock-count t)
+ (next-location index)
+ (line-size index)) ;Line size holds a constant
+ ;that can be folded in if there was
+ ;a way to add a constant to
+ ;an index register
+ (flatten-lap
+ (apply #'flatten-lap wrapper-moves)
+ (opcode :move (operand :constant cache-line-size) line-size)
+ (opcode :move (operand :cvar 'cache-vector) cache-vector)
+ (emit-n-wrapper-compute-primary-cache-location wrappers primary miss-label)
+ (opcode :move primary location)
+ (opcode :move location next-location)
+ (opcode :move (operand :cref cache-vector 0) initial-lock-count) ;get the lock-count
+ (with-lap-registers ((size index))
+ (flatten-lap
+ (opcode :move (operand :cvar 'size) size)
+ (opcode :label 'continue)
+ (opcode :move (operand :i+ location line-size) next-location)
+ (emit-check-cache-line cache-vector location wrappers 'hit)
+ (emit-adjust-location location next-location primary size 'continue miss-label)
+ (opcode :label 'hit)
+ (and value (opcode :move (emit-cache-vector-ref cache-vector location) value))
+ (emit-lock-count-test initial-lock-count cache-vector 'hit-internal)
+ miss
+ (opcode :label 'hit-internal)
+ hit))))))
+
+
+
+;;;
+;;; Cache related lap code
+;;;
+
+(defun emit-check-1-wrapper-in-cache (cache-vector location wrapper hit-code)
+ (let ((exit-emit-check-1-wrapper-in-cache
+ (make-symbol "exit-emit-check-1-wrapper-in-cache")))
+ (with-lap-registers ((cwrapper #-structure-wrapper vector
+ #+structure-wrapper t))
+ (flatten-lap
+ (opcode :move (emit-cache-vector-ref cache-vector location) cwrapper)
+ (opcode :neq cwrapper wrapper exit-emit-check-1-wrapper-in-cache)
+ hit-code
+ (opcode :label exit-emit-check-1-wrapper-in-cache)))))
+
+(defun emit-check-cache-entry (cache-vector location wrapper hit-label)
+ (with-lap-registers ((cwrapper #-structure-wrapper vector
+ #+structure-wrapper t))
+ (flatten-lap
+ (opcode :move (emit-cache-vector-ref cache-vector location) cwrapper)
+ (opcode :eq cwrapper wrapper hit-label))))
+
+(defun emit-check-cache-line (cache-vector location wrappers hit-label)
+ (let ((checks
+ (flatten-lap
+ (gathering1 (flattening-lap)
+ (iterate ((wrapper (list-elements wrappers)))
+ (with-lap-registers ((cwrapper #-structure-wrapper vector
+ #+structure-wrapper t))
+ (gather1
+ (flatten-lap
+ (opcode :move (emit-cache-vector-ref cache-vector location) cwrapper)
+ (opcode :neq cwrapper wrapper 'exit-emit-check-cache-line)
+ (opcode :move (operand :i1+ location) location)))))))))
+ (flatten-lap
+ checks
+ (opcode :go hit-label)
+ (opcode :label 'exit-emit-check-cache-line))))
+
+(defun emit-lock-count-test (initial-lock-count cache-vector hit-label)
+ ;;
+ ;; jumps to hit-label if cache-vector-lock-count consistent, otherwise, continues
+ ;;
+ (with-lap-registers ((new-lock-count t))
+ (flatten-lap
+ (opcode :move (operand :cref cache-vector 0) new-lock-count) ;get new cache-vector-lock-count
+ (opcode :fix= new-lock-count initial-lock-count hit-label))))
+
+
+
+(defun emit-adjust-location (location next-location primary size cont-label miss-label)
+ (flatten-lap
+ (opcode :move next-location location)
+ (opcode :fix= location size 'at-end-of-cache)
+ (opcode :fix= location primary miss-label)
+ (opcode :go cont-label)
+ (opcode :label 'at-end-of-cache)
+ (opcode :fix= primary (operand :constant (index-value->index 1)) miss-label)
+ (opcode :move (operand :constant (index-value->index 1)) location)
+ (opcode :go cont-label)))
+
+
+;; From cache.lisp
+(defun emit-cache-vector-ref (cache-vector-operand location-operand)
+ (operand :iref cache-vector-operand location-operand))
+
+(defun emit-wrapper-ref (wrapper-operand field-operand)
+ (operand :iref wrapper-operand field-operand))
+
+(defun emit-wrapper-cache-number-vector (wrapper-operand)
+ (operand :wrapper-cache-number-vector wrapper-operand))
+
+(defun emit-cache-number-vector-ref (cnv-operand field-operand)
+ (operand :iref cnv-operand field-operand))
+
+(defun emit-1-wrapper-compute-primary-cache-location (wrapper primary wrapper-cache-no)
+ (with-lap-registers ((mask index)
+ #+structure-wrapper (cnv fixnum-vector))
+ (let ((field wrapper-cache-no))
+ (flatten-lap
+ (opcode :move (operand :cvar 'mask) mask)
+ (opcode :move (operand :cvar 'field) field)
+ #-structure-wrapper
+ (opcode :move (emit-wrapper-ref wrapper field) wrapper-cache-no)
+ #+structure-wrapper
+ (opcode :move (emit-wrapper-cache-number-vector wrapper) cnv)
+ #+structure-wrapper
+ (opcode :move (emit-cache-number-vector-ref cnv field) wrapper-cache-no)
+ (opcode :move (operand :ilogand wrapper-cache-no mask) primary)))))
+
+(defun emit-n-wrapper-compute-primary-cache-location (wrappers primary miss-label)
+ (with-lap-registers ((field index)
+ (mask index))
+ (let ((add-wrapper-cache-numbers
+ (flatten-lap
+ (gathering1 (flattening-lap)
+ (iterate ((wrapper (list-elements wrappers))
+ (i (interval :from 1)))
+ (gather1
+ (with-lap-registers ((wrapper-cache-no index)
+ #+structure-wrapper (cnv fixnum-vector))
+ (flatten-lap
+ #-structure-wrapper
+ (opcode :move (emit-wrapper-ref wrapper field) wrapper-cache-no)
+ #+structure-wrapper
+ (opcode :move (emit-wrapper-cache-number-vector wrapper) cnv)
+ #+structure-wrapper
+ (opcode :move (emit-cache-number-vector-ref cnv field)
+ wrapper-cache-no)
+ (opcode :izerop wrapper-cache-no miss-label)
+ (opcode :move (operand :i+ primary wrapper-cache-no) primary)
+ (when (zerop (mod i wrapper-cache-number-adds-ok))
+ (opcode :move (operand :ilogand primary mask) primary))))))))))
+ (flatten-lap
+ (opcode :move (operand :constant 0) primary)
+ (opcode :move (operand :cvar 'field) field)
+ (opcode :move (operand :cvar 'mask) mask)
+ add-wrapper-cache-numbers
+ (opcode :move (operand :ilogand primary mask) primary)
+ (opcode :move (operand :i1+ primary) primary)))))
+
+(defun emit-fetch-wrapper (metatype argument dest miss-label &optional slot)
+ (let ((exit-emit-fetch-wrapper (make-symbol "exit-emit-fetch-wrapper")))
+ (with-lap-registers ((arg t))
+ (ecase metatype
+ ((standard-instance #+new-kcl-wrapper structure-instance)
+ (let ((get-std-inst-wrapper (make-symbol "get-std-inst-wrapper"))
+ (get-fsc-inst-wrapper (make-symbol "get-fsc-inst-wrapper")))
+ (flatten-lap
+ (opcode :move (operand :arg argument) arg)
+ (opcode :std-instance-p arg get-std-inst-wrapper) ;is it a std wrapper?
+ (opcode :fsc-instance-p arg get-fsc-inst-wrapper) ;is it a fsc wrapper?
+ (opcode :go miss-label)
+ (opcode :label get-fsc-inst-wrapper)
+ (opcode :move (operand :fsc-wrapper arg) dest) ;get fsc wrapper
+ (and slot
+ (opcode :move (operand :fsc-slots arg) slot))
+ (opcode :go exit-emit-fetch-wrapper)
+ (opcode :label get-std-inst-wrapper)
+ (opcode :move (operand :std-wrapper arg) dest) ;get std wrapper
+ (and slot
+ (opcode :move (operand :std-slots arg) slot))
+ (opcode :label exit-emit-fetch-wrapper))))
+ (class
+ (when slot (error "Can't do a slot reg for this metatype."))
+ (let ((get-std-inst-wrapper (make-symbol "get-std-inst-wrapper"))
+ (get-fsc-inst-wrapper (make-symbol "get-fsc-inst-wrapper")))
+ (flatten-lap
+ (opcode :move (operand :arg argument) arg)
+ (opcode :std-instance-p arg get-std-inst-wrapper)
+ (opcode :fsc-instance-p arg get-fsc-inst-wrapper)
+ #-new-kcl-wrapper
+ (opcode :move (operand :built-in-or-structure-wrapper arg) dest)
+ #+new-kcl-wrapper
+ (opcode :move (operand :built-in-wrapper arg) dest)
+ (opcode :go exit-emit-fetch-wrapper)
+ (opcode :label get-fsc-inst-wrapper)
+ (opcode :move (operand :fsc-wrapper arg) dest)
+ (opcode :go exit-emit-fetch-wrapper)
+ (opcode :label get-std-inst-wrapper)
+ (opcode :move (operand :std-wrapper arg) dest)
+ (opcode :label exit-emit-fetch-wrapper))))
+ ((built-in-instance #-new-kcl-wrapper structure-instance)
+ (when slot (error "Can't do a slot reg for this metatype."))
+ (let ()
+ (flatten-lap
+ (opcode :move (operand :arg argument) arg)
+ (opcode :std-instance-p arg miss-label)
+ (opcode :fsc-instance-p arg miss-label)
+ #-new-kcl-wrapper
+ (opcode :move (operand :built-in-or-structure-wrapper arg) dest)
+ #+new-kcl-wrapper
+ (opcode :move (operand :built-in-wrapper arg) dest))))))))
+
diff --git a/gcl/pcl/old/lap.lisp b/gcl/pcl/old/lap.lisp
new file mode 100644
index 000000000..3e250fa5a
--- /dev/null
+++ b/gcl/pcl/old/lap.lisp
@@ -0,0 +1,500 @@
+;;;-*-Mode: LISP; Package: PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package 'pcl)
+
+;;;
+;;; This file defines PCL's interface to the LAP mechanism.
+;;;
+;;; The file is divided into two parts. The first part defines the interface
+;;; used by PCL to create abstract LAP code vectors. PCL never creates lists
+;;; that represent LAP code directly, it always calls this mechanism to do so.
+;;; This provides a layer of error checking on the LAP code before it gets to
+;;; the implementation-specific assembler. Note that this error checking is
+;;; syntactic only, but even so is useful to have. Because of it, no specific
+;;; LAP assembler should worry itself with checking the syntax of the LAP code.
+;;;
+;;; The second part of the file defines the LAP assemblers for each PCL port.
+;;; These are included together in the same file to make it easier to change
+;;; them all should some random change be made in the LAP mechanism.
+;;;
+
+(defvar *make-lap-closure-generator*)
+(defvar *precompile-lap-closure-generator*)
+(defvar *lap-in-lisp*)
+
+(defun make-lap-closure-generator
+ (closure-variables arguments iregs vregs fvregs tregs lap-code)
+ (funcall *make-lap-closure-generator*
+ closure-variables arguments iregs
+ vregs fvregs tregs lap-code))
+
+(defmacro precompile-lap-closure-generator
+ (cvars args i-regs v-regs fv-regs t-regs lap)
+ (funcall *precompile-lap-closure-generator* cvars args i-regs
+ v-regs fv-regs t-regs lap))
+
+(defmacro lap-in-lisp (cvars args iregs vregs fvregs tregs lap)
+ (declare (ignore cvars args))
+ `(locally (declare #.*optimize-speed*)
+ ,(make-lap-prog iregs vregs fvregs tregs
+ (flatten-lap lap (opcode :label 'exit-lap-in-lisp)))))
+
+
+;;;
+;;; The following functions and macros are used by PCL when generating LAP
+;;; code:
+;;;
+;;; GENERATING-LAP
+;;; WITH-LAP-REGISTERS
+;;; ALLOCATE-REGISTER
+;;; DEALLOCATE-REGISTER
+;;; LAP-FLATTEN
+;;; OPCODE
+;;; OPERAND
+;;;
+(proclaim '(special *generating-lap*)) ;CAR - alist of free registers
+ ;CADR - alist of allocated registers
+ ;CADDR - max reg number allocated
+ ;
+ ;in each alist, the entries have
+ ;the form: (type . (:REG <n>))
+ ;
+
+;;;
+;;; This goes around the generation of any lap code. <body> should return a lap
+;;; code sequence, this macro will take care of converting that to a lap closure
+;;; generator.
+;;;
+(defmacro generating-lap (closure-variables arguments &body body)
+ `(let* ((*generating-lap* (list () () -1)))
+ (finalize-lap-generation nil ,closure-variables ,arguments (progn ,@body))))
+
+(defmacro generating-lap-in-lisp (closure-variables arguments &body body)
+ `(let* ((*generating-lap* (list () () -1)))
+ (finalize-lap-generation t ,closure-variables ,arguments (progn ,@body))))
+
+;;;
+;;; Each register specification looks like:
+;;;
+;;; (<var> <type> &key :reuse <other-reg>)
+;;;
+(defmacro with-lap-registers (register-specifications &body body)
+ ;;
+ ;; Given that, for now, there is only one keyword argument and
+ ;; that, for now, we do no error checking, we can be pretty
+ ;; sleazy about how this works.
+ ;;
+ (flet ((make-allocations ()
+ (gathering1 (collecting)
+ (dolist (spec register-specifications)
+ (gather1
+ `(,(car spec) (or ,(cadddr spec) (allocate-register ',(cadr spec))))))))
+ (make-deallocations ()
+ (gathering1 (collecting)
+ (dolist (spec register-specifications)
+ (gather1
+ `(unless ,(cadddr spec) (deallocate-register ,(car spec))))))))
+ `(let ,(make-allocations)
+ (multiple-value-prog1 (progn ,@body)
+ ,@(make-deallocations)))))
+
+(defun allocate-register (type)
+ (destructuring-bind (free allocated) *generating-lap*
+ (let ((entry (assoc type free)))
+ (cond (entry
+ (setf (car *generating-lap*) (delete entry free)
+ (cadr *generating-lap*) (cons entry allocated))
+ (cdr entry))
+ (t
+ (let ((new `(,type . (:reg ,(incf (caddr *generating-lap*))))))
+ (setf (cadr *generating-lap*) (cons new allocated))
+ (cdr new)))))))
+
+(defun deallocate-register (reg)
+ (let ((entry (rassoc reg (cadr *generating-lap*))))
+ (unless entry (error "Attempt to free an unallocated register."))
+ (push entry (car *generating-lap*))
+ (setf (cadr *generating-lap*) (delete entry (cadr *generating-lap*)))))
+
+(defvar *precompiling-lap* nil)
+
+(defun finalize-lap-generation (in-lisp-p closure-variables arguments lap-code)
+ (when (cadr *generating-lap*) (error "Registers still allocated when lap being finalized."))
+ (let ((iregs ())
+ (vregs ())
+ (fvregs ())
+ (tregs ()))
+ (dolist (entry (car *generating-lap*))
+ (ecase (car entry)
+ (index (push (caddr entry) iregs))
+ (vector (push (caddr entry) vregs))
+ (fixnum-vector (push (caddr entry) fvregs))
+ ((t) (push (caddr entry) tregs))))
+ (cond (in-lisp-p
+ `(lap-in-lisp ,closure-variables ,arguments ,iregs
+ ,vregs ,fvregs ,tregs ,lap-code))
+ (*precompiling-lap*
+ `(precompile-lap-closure-generator
+ ,closure-variables ,arguments ,iregs
+ ,vregs ,fvregs ,tregs ,lap))
+ (t
+ (make-lap-closure-generator
+ closure-variables arguments iregs
+ vregs fvregs tregs lap-code)))))
+
+(defun flatten-lap (&rest opcodes-or-sequences)
+ (let ((result ()))
+ (dolist (opcode-or-sequence opcodes-or-sequences result)
+ (cond ((null opcode-or-sequence))
+ ((not (consp (car opcode-or-sequence))) ;its an opcode
+ (setf result (append result (list opcode-or-sequence))))
+ (t
+ (setf result (append result opcode-or-sequence)))))))
+
+(defmacro flattening-lap ()
+ '(let ((result ()))
+ (values #'(lambda (value) (push value result))
+ #'(lambda () (apply #'flatten-lap (reverse result))))))
+
+
+
+;;;
+;;; This code deals with the syntax of the individual opcodes and operands.
+;;;
+
+;;;
+;;; The first two of these variables are documented to all ports. They are
+;;; lists of the symbols which name the lap opcodes and operands. They can
+;;; be useful to determine whether a port has implemented all the required
+;;; opcodes and operands.
+;;;
+;;; The third of these variables is for use of the emitter only.
+;;;
+(defvar *lap-operands* ())
+(defvar *lap-opcodes* ())
+(defvar *lap-emitters* (make-hash-table :test #'eq :size 30))
+
+(defun opcode (name &rest args)
+ (let ((emitter (gethash name *lap-emitters*)))
+ (if emitter
+ (apply emitter args)
+ (error "No opcode named ~S." name))))
+
+(defun operand (name &rest args)
+ (let ((emitter (gethash name *lap-emitters*)))
+ (if emitter
+ (apply emitter args)
+ (error "No operand named ~S." name))))
+
+(defmacro defopcode (name types)
+ (let ((fn-name (symbol-append "LAP Opcode " name *the-pcl-package*))
+ (lambda-list
+ (mapcar #'(lambda (x) (declare (ignore x)) (gensym)) types)))
+ `(progn
+ (eval-when (load eval) (load-defopcode ',name ',fn-name))
+ (defun ,fn-name ,lambda-list
+ #+Genera (declare (sys:function-parent ,name defopcode))
+ (defopcode-1 ',name ',types ,@lambda-list)))))
+
+(defmacro defoperand (name types)
+ (let ((fn-name (symbol-append "LAP Operand " name *the-pcl-package*))
+ (lambda-list
+ (mapcar #'(lambda (x) (declare (ignore x)) (gensym)) types)))
+ `(progn
+ (eval-when (load eval) (load-defoperand ',name ',fn-name))
+ (defun ,fn-name ,lambda-list
+ #+Genera (declare (sys:function-parent ,name defoperand))
+ (defoperand-1 ',name ',types ,@lambda-list)))))
+
+(defun load-defopcode (name fn-name)
+ (if* (memq name *lap-operands*)
+ (error "LAP opcodes and operands must have disjoint names.")
+ (setf (gethash name *lap-emitters*) fn-name)
+ (pushnew name *lap-opcodes*)))
+
+(defun load-defoperand (name fn-name)
+ (if* (memq name *lap-opcodes*)
+ (error "LAP opcodes and operands must have disjoint names.")
+ (setf (gethash name *lap-emitters*) fn-name)
+ (pushnew name *lap-operands*)))
+
+(defun defopcode-1 (name operand-types &rest args)
+ (iterate ((arg (list-elements args))
+ (type (list-elements operand-types)))
+ (check-opcode-arg name arg type))
+ (cons name (copy-list args)))
+
+(defun defoperand-1 (name operand-types &rest args)
+ (iterate ((arg (list-elements args))
+ (type (list-elements operand-types)))
+ (check-operand-arg name arg type))
+ (cons name (copy-list args)))
+
+(defun check-opcode-arg (name arg type)
+ (labels ((usual (x)
+ (and (consp arg) (eq (car arg) x)))
+ (check (x)
+ (ecase x
+ ((:reg :cdr :constant :iref :instance-ref :cvar :arg :lisp :lisp-variable)
+ (usual x))
+ (:label (symbolp arg))
+ (:operand (and (consp arg) (memq (car arg) *lap-operands*))))))
+ (unless (if (consp type)
+ (if (eq (car type) 'or)
+ (some #'check (cdr type))
+ (error "What type is this?"))
+ (check type))
+ (error "The argument ~S to the opcode ~A is not of type ~S." arg name type))))
+
+(defun check-operand-arg (name arg type)
+ (flet ((check (x)
+ (ecase x
+ (:symbol (symbolp arg))
+ (:register-number (and (integerp arg) (>= arg 0)))
+ (:t t)
+ (:reg (and (consp arg) (eq (car arg) :reg)))
+ (:fixnum (typep arg 'fixnum)))))
+ (unless (if (consp type)
+ (if (eq (car type) 'or)
+ (some #'check (cdr type))
+ (error "What type is this?"))
+ (check type))
+ (error "The argument ~S to the operand ~A is not of type ~S." arg name type))))
+
+
+
+;;;
+;;; The actual opcodes.
+;;;
+(defopcode :break ()) ;For debugging only. Not
+(defopcode :beep ()) ;all ports are required to
+(defopcode :print (:reg)) ;implement this.
+
+
+(defopcode :move (:operand (or :reg :iref :instance-ref :cdr :lisp-variable)))
+
+(defopcode :eq ((or :reg :constant) (or :reg :constant) :label))
+(defopcode :neq ((or :reg :constant) (or :reg :constant) :label))
+(defopcode :fix= ((or :reg :constant) (or :reg :constant) :label))
+(defopcode :izerop (:reg :label))
+
+(defopcode :std-instance-p (:reg :label))
+(defopcode :fsc-instance-p (:reg :label))
+(defopcode :built-in-instance-p (:reg :label))
+(defopcode :structure-instance-p (:reg :label))
+
+(defopcode :jmp ((or :reg :constant)))
+(defopcode :emf-call ((or :reg :constant)))
+
+(defopcode :label (:label))
+(defopcode :go (:label))
+
+(defopcode :return ((or :reg :constant)))
+
+(defopcode :exit-lap-in-lisp ())
+
+;;;
+;;; The actual operands.
+;;;
+(defoperand :reg (:register-number))
+(defoperand :cvar (:symbol))
+(defoperand :arg (:symbol))
+
+(defoperand :cdr (:reg))
+
+(defoperand :constant (:t))
+
+(defoperand :std-wrapper (:reg))
+(defoperand :fsc-wrapper (:reg))
+(defoperand :built-in-wrapper (:reg))
+(defoperand :structure-wrapper (:reg))
+(defoperand :other-wrapper (:reg))
+(defoperand :built-in-or-structure-wrapper (:reg))
+
+(defoperand :std-slots (:reg))
+(defoperand :fsc-slots (:reg))
+
+(defoperand :wrapper-cache-number-vector (:reg))
+
+(defoperand :cref (:reg :fixnum))
+
+(defoperand :iref (:reg :reg))
+(defoperand :iset (:reg :reg :reg))
+
+(defoperand :instance-ref (:reg :reg))
+(defoperand :instance-set (:reg :reg :reg))
+
+(defoperand :i1+ (:reg))
+(defoperand :i+ (:reg :reg))
+(defoperand :i- (:reg :reg))
+(defoperand :ilogand (:reg :reg))
+(defoperand :ilogxor (:reg :reg))
+(defoperand :ishift (:reg :fixnum))
+
+(defoperand :lisp (:t))
+(defoperand :lisp-variable (:symbol))
+
+
+
+;;;
+;;; LAP tests (there need to be a lot more of these)
+;;;
+#|
+(defun make-lap-test-closure-1 (result)
+ #'(lambda (arg1)
+ (declare (pcl-fast-call))
+ (declare (ignore arg1))
+ result))
+
+(defun make-lap-test-closure-2 (result)
+ #'(lambda (arg1 arg2)
+ (declare (pcl-fast-call))
+ (declare (ignore arg1 arg2))
+ result))
+
+(eval-when (eval)
+ (compile 'make-lap-test-closure-1)
+ (compile 'make-lap-test-closure-2))
+
+(proclaim '(special lap-win lap-lose))
+(eval-when (load eval)
+ (setq lap-win (make-lap-test-closure-1 'win)
+ lap-lose (make-lap-test-closure-1 'lose)))
+
+(defun lap-test-1 ()
+ (let* ((cg (generating-lap '(cache)
+ '(arg)
+ (with-lap-registers ((i0 index)
+ (v0 vector)
+ (t0 t))
+ (flatten-lap
+ (opcode :move (operand :cvar 'cache) v0)
+ (opcode :move (operand :arg 'arg) i0)
+ (opcode :move (operand :iref v0 i0) t0)
+ (opcode :jmp t0)))))
+
+ (cache (make-array 32))
+ (closure (funcall cg cache))
+ (fn0 (make-lap-test-closure-1 'fn0))
+ (fn1 (make-lap-test-closure-1 'fn1))
+ (fn2 (make-lap-test-closure-1 'fn2))
+ (in0 (index-value->index 2))
+ (in1 (index-value->index 10))
+ (in2 (index-value->index 27)))
+
+ (setf (svref cache (index->index-value in0)) fn0
+ (svref cache (index->index-value in1)) fn1
+ (svref cache (index->index-value in2)) fn2)
+
+ (unless (and (eq (funcall closure in0) 'fn0)
+ (eq (funcall closure in1) 'fn1)
+ (eq (funcall closure in2) 'fn2))
+ (error "LAP TEST 1 failed."))))
+
+(defun lap-test-2 ()
+ (let* ((cg (generating-lap '(cache mask)
+ '(arg)
+ (with-lap-registers ((i0 index)
+ (i1 index)
+ (i2 index)
+ (v0 vector)
+ (t0 t))
+
+ (flatten-lap
+ (opcode :move (operand :cvar 'cache) v0)
+ (opcode :move (operand :arg 'arg) i0)
+ (opcode :move (operand :cvar 'mask) i1)
+ (opcode :move (operand :ilogand i0 i1) i2)
+ (opcode :move (operand :iref v0 i2) t0)
+ (opcode :jmp t0)))))
+ (cache (make-array 32))
+ (mask #b00110)
+ (closure (funcall cg cache mask))
+ (in0 (index-value->index #b00010))
+ (in1 (index-value->index #b01010))
+ (in2 (index-value->index #b10011)))
+ (fill cache lap-lose)
+ (setf (svref cache (index->index-value in0)) lap-win)
+
+ (unless (and (eq (funcall closure in0) 'win)
+ (eq (funcall closure in1) 'win)
+ (eq (funcall closure in2) 'win))
+ (error "LAP TEST 2 failed."))))
+
+(defun lap-test-3 ()
+ (let* ((cg (generating-lap '(addend) '(arg)
+ (with-lap-registers
+ ((i0 index)
+ (i1 index)
+ (i2 index))
+
+ (flatten-lap
+ (opcode :move (operand :cvar 'addend) i0)
+ (opcode :move (operand :arg 'arg) i1)
+ (opcode :move (operand :i+ i0 i1) i2)
+ (opcode :return i2)))))
+ (closure (funcall cg (index-value->index 5))))
+
+ (unless (= (index->index-value (funcall closure (index-value->index 2))) 7)
+ (error "LAP TEST 3 failed."))))
+
+(defun lap-test-4 ()
+ (let* ((cg (generating-lap '(winner loser) '(arg)
+ (with-lap-registers ((t0 t))
+ (flatten-lap
+ (opcode :move (operand :arg 'arg) t0)
+ (opcode :eq t0 (operand :constant 'foo) 'win)
+ (opcode :move (operand :cvar 'loser) t0)
+ (opcode :jmp t0)
+ (opcode :label 'win)
+ (opcode :move (operand :cvar 'winner) t0)
+ (opcode :jmp t0)))))
+ (closure (funcall cg #'true #'false)))
+ (unless (and (eq (funcall closure 'foo) 't)
+ (eq (funcall closure 'bar) 'nil))
+ (error "LAP TEST 4 failed."))))
+
+(defun lap-test-5 ()
+ (let* ((cg (generating-lap '(array) '(arg)
+ (with-lap-registers ((r0 vector)
+ (r1 t)
+ (r2 index))
+ (flatten-lap
+ (opcode :move (operand :cvar 'array) r0)
+ (opcode :move (operand :arg 'arg) r1)
+ (opcode :move (operand :constant (index-value->index 0)) r2)
+ (opcode :move r1 (operand :iref r0 r2))
+ (opcode :return r1)))))
+ (array (make-array 1))
+ (closure (funcall cg array)))
+ (unless (and (= (funcall closure 1) (svref array 0))
+ (eq (funcall closure 'foo) (svref array 0)))
+ (error "LAP TEST 5 failed."))))
+
+|#
+
diff --git a/gcl/pcl/old/plap.lisp b/gcl/pcl/old/plap.lisp
new file mode 100644
index 000000000..622dd5c3c
--- /dev/null
+++ b/gcl/pcl/old/plap.lisp
@@ -0,0 +1,369 @@
+;;;-*-Mode: LISP; Package: PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package 'pcl)
+
+;;;
+;;; The portable implementation of the LAP assembler.
+;;;
+;;; The portable implementation of the LAP assembler works by translating
+;;; LAP code back into Lisp code and then compiling that Lisp code. Note
+;;; that this implementation is actually going to get a lot of use. Some
+;;; implementations (KCL) won't implement a native LAP assembler at all.
+;;; Other implementations may not implement native LAP assemblers for all
+;;; of their ports. All of this implies that this portable LAP assembler
+;;; needs to generate the best code it possibly can.
+;;;
+
+
+;;;
+;;;
+;;;
+
+(defmacro lap-case (operand &body cases)
+ (once-only (operand)
+ `(ecase (car ,operand)
+ ,@(mapcar #'(lambda (case)
+ `(,(car case)
+ (apply #'(lambda ,(cadr case) ,@(cddr case))
+ (cdr ,operand))))
+ cases))))
+
+(defvar *lap-args*)
+(defvar *lap-rest-p*)
+(defvar *lap-i-regs*)
+(defvar *lap-v-regs*)
+(defvar *lap-fv-regs*)
+(defvar *lap-t-regs*)
+
+(defvar *lap-optimize-declaration* '#.*optimize-speed*)
+
+
+(eval-when (load eval)
+ (setq *make-lap-closure-generator*
+ #'(lambda (closure-var-names arg-names index-regs
+ vector-regs fixnum-vector-regs t-regs lap-code)
+ (compile-lambda
+ (make-lap-closure-generator-lambda
+ closure-var-names arg-names index-regs
+ vector-regs fixnum-vector-regs t-regs lap-code)))
+
+ *precompile-lap-closure-generator*
+ #'(lambda (cvars args i-regs v-regs fv-regs t-regs lap)
+ `(function
+ ,(make-lap-closure-generator-lambda cvars args i-regs
+ v-regs fv-regs t-regs lap)))
+ *lap-in-lisp*
+ #'(lambda (cvars args iregs vregs fvregs tregs lap)
+ (declare (ignore cvars args))
+ (make-lap-prog
+ iregs vregs fvregs tregs
+ (flatten-lap lap ;(opcode :label 'exit-lap-in-lisp)
+ )))))
+
+(defun make-lap-closure-generator-lambda (cvars args i-regs v-regs fv-regs t-regs lap)
+ (let* ((rest (memq '&rest args))
+ (ldiff (and rest (ldiff args rest))))
+ (when rest (setq args (append ldiff '(&rest .lap-rest-arg.))))
+ (let* ((*lap-args* (if rest ldiff args))
+ (*lap-rest-p* (not (null rest))))
+ `(lambda ,cvars
+ #'(lambda ,args
+ #-CMU (declare ,*lap-optimize-declaration*)
+ #-CMU ,(make-lap-prog-internal i-regs v-regs fv-regs t-regs lap)
+ #+CMU
+ ;;
+ ;; Use LOCALLY instead of a declare on the lambda so that we don't
+ ;; suppress arg count checking...
+ (locally (declare ,*lap-optimize-declaration*)
+ ,(make-lap-prog-internal i-regs v-regs fv-regs t-regs lap)))))))
+
+(defun make-lap-prog (i-regs v-regs fv-regs t-regs lap)
+ (let* ((*lap-args* 'lap-in-lisp)
+ (*lap-rest-p* 'lap-in-lisp))
+ (make-lap-prog-internal i-regs v-regs fv-regs t-regs lap)))
+
+(defun make-lap-prog-internal (i-regs v-regs fv-regs t-regs lap)
+ (let* ((*lap-i-regs* i-regs)
+ (*lap-v-regs* v-regs)
+ (*lap-fv-regs* fv-regs)
+ (*lap-t-regs* t-regs)
+ (code (mapcar #'lap-opcode lap)))
+ `(prog ,(mapcar #'(lambda (reg)
+ `(,(lap-reg reg)
+ ,(lap-reg-initial-value-form reg)))
+ (append i-regs v-regs fv-regs t-regs))
+ (declare (type fixnum ,@(mapcar #'lap-reg *lap-i-regs*))
+ (type simple-vector ,@(mapcar #'lap-reg *lap-v-regs*))
+ (type #+structure-wrapper cache-number-vector
+ #-structure-wrapper (simple-array fixnum)
+ ,@(mapcar #'lap-reg *lap-fv-regs*))
+ #-cmu ,*lap-optimize-declaration*)
+ ,.code)))
+
+(defvar *empty-vector* '#())
+(defvar *empty-fixnum-vector*
+ (make-array 8
+ :element-type 'fixnum
+ :initial-element 0))
+
+(defun lap-reg-initial-value-form (reg)
+ (cond ((member reg *lap-i-regs*) 0)
+ ((member reg *lap-v-regs*) '*empty-vector*)
+ ((member reg *lap-fv-regs*) '*empty-fixnum-vector*)
+ ((member reg *lap-t-regs*) nil)
+ (t
+ (error "What kind of register is ~S?" reg))))
+
+(defun lap-opcode (opcode)
+ (lap-case opcode
+ (:move (from to)
+ `(setf ,(lap-operand to) ,(lap-operand from)))
+
+ ((:eq :neq :fix=) (arg1 arg2 label)
+ `(when ,(lap-operands (ecase (car opcode)
+ (:eq 'eq) (:neq 'neq) (:fix= 'RUNTIME\ FIX=))
+ arg1
+ arg2)
+ (go ,label)))
+
+ ((:izerop) (arg label)
+ `(when ,(lap-operands 'RUNTIME\ IZEROP arg)
+ (go ,label)))
+
+ (:std-instance-p (from label)
+ `(when ,(lap-operands 'RUNTIME\ STD-INSTANCE-P from) (go ,label)))
+ (:fsc-instance-p (from label)
+ `(when ,(lap-operands 'RUNTIME\ FSC-INSTANCE-P from) (go ,label)))
+ (:built-in-instance-p (from label)
+ (declare (ignore from))
+ `(when ,t (go ,label))) ;***
+ (:structure-instance-p (from label)
+ `(when ,(lap-operands 'RUNTIME\ STRUCTURE-INSTANCE-P from) (go ,label))) ;***
+
+ ((:jmp :emf-call) (fn)
+ (if (eq *lap-args* 'lap-in-lisp)
+ (error "Can't do a :JMP in LAP-IN-LISP.")
+ `(return
+ ,(if (eq (car opcode) :jmp)
+ (if *lap-rest-p*
+ `(RUNTIME\ APPLY ,(lap-operand fn) ,@*lap-args* .lap-rest-arg.)
+ `(RUNTIME\ FUNCALL ,(lap-operand fn) ,@*lap-args*))
+ `(RUNTIME\ EMF-CALL ,(lap-operand fn) ,*lap-rest-p* ,@*lap-args*
+ ,@(when *lap-rest-p* `(.lap-rest-arg.)))))))
+
+ (:return (value)
+ `(return ,(lap-operand value)))
+
+ (:label (label) label)
+ (:go (label) `(go ,label))
+
+ (:exit-lap-in-lisp () `(go exit-lap-in-lisp))
+
+ (:break () `(break))
+ (:beep () #+Genera`(zl:beep))
+ (:print (val) (lap-operands 'print val))
+ ))
+
+(defun lap-operand (operand)
+ (lap-case operand
+ (:reg (n) (lap-reg n))
+ (:cdr (reg) (lap-operands 'cdr reg))
+ ((:cvar :arg) (name) name)
+ (:constant (c) `',c)
+ ((:std-wrapper :fsc-wrapper :built-in-wrapper :structure-wrapper
+ :built-in-or-structure-wrapper :std-slots :fsc-slots
+ :wrapper-cache-number-vector)
+ (x)
+ (lap-operands (ecase (car operand)
+ (:std-wrapper 'RUNTIME\ STD-WRAPPER)
+ (:fsc-wrapper 'RUNTIME\ FSC-WRAPPER)
+ (:built-in-wrapper 'RUNTIME\ BUILT-IN-WRAPPER)
+ (:structure-wrapper 'RUNTIME\ STRUCTURE-WRAPPER)
+ (:built-in-or-structure-wrapper
+ 'RUNTIME\ BUILT-IN-OR-STRUCTURE-WRAPPER)
+ (:std-slots 'RUNTIME\ STD-SLOTS)
+ (:fsc-slots 'RUNTIME\ FSC-SLOTS)
+ (:wrapper-cache-number-vector
+ 'RUNTIME\ WRAPPER-CACHE-NUMBER-VECTOR))
+ x))
+
+
+ (:i1+ (index) (lap-operands 'RUNTIME\ I1+ index))
+ (:i+ (index1 index2) (lap-operands 'RUNTIME\ I+ index1 index2))
+ (:i- (index1 index2) (lap-operands 'RUNTIME\ I- index1 index2))
+ (:ilogand (index1 index2) (lap-operands 'RUNTIME\ ILOGAND index1 index2))
+ (:ilogxor (index1 index2) (lap-operands 'RUNTIME\ ILOGXOR index1 index2))
+
+ (:iref (vector index) (lap-operands 'RUNTIME\ IREF vector index))
+ (:iset (vector index value) (lap-operands 'RUNTIME\ ISET vector index value))
+
+ (:instance-ref (vector index)
+ (lap-operands 'RUNTIME\ INSTANCE-REF vector index))
+ (:instance-set (vector index value)
+ (lap-operands 'RUNTIME\ INSTANCE-SET vector index value))
+
+ (:cref (vector i) `(RUNTIME\ SVREF ,(lap-operand vector) ,i))
+ (:lisp-variable (symbol) symbol)
+ (:lisp (form) form)
+ ))
+
+(defun lap-operands (fn &rest regs)
+ (cons fn (mapcar #'lap-operand regs)))
+
+(defun lap-reg (n) (intern (format nil "REG~D" n) *the-pcl-package*))
+
+
+;;;
+;;; Runtime Implementations of the operands and opcodes.
+;;;
+;;; In those ports of PCL which choose not to completely re-implement the
+;;; LAP code generator, it may still be provident to consider reimplementing
+;;; one or more of these to get the compiler to produce better code. That
+;;; is why they are split out.
+;;;
+(proclaim '(declaration pcl-fast-call))
+
+(defmacro RUNTIME\ FUNCALL (fn &rest args)
+ #+CMU `(funcall (the function ,fn) ,.args)
+ #-CMU `(funcall ,fn ,.args))
+
+(defmacro RUNTIME\ APPLY (fn &rest args)
+ #+CMU `(apply (the function ,fn) ,.args)
+ #-CMU `(apply ,fn ,.args))
+
+(defmacro RUNTIME\ EMF-CALL (emf restp &rest required-args+rest-arg)
+ `(invoke-effective-method-function ,emf ,restp ,@required-args+rest-arg))
+
+(defmacro RUNTIME\ STD-WRAPPER (x)
+ `(std-instance-wrapper ,x))
+
+(defmacro RUNTIME\ FSC-WRAPPER (x)
+ `(fsc-instance-wrapper ,x))
+
+(defmacro RUNTIME\ BUILT-IN-WRAPPER (x)
+ `(built-in-wrapper-of ,x))
+
+(defmacro RUNTIME\ STRUCTURE-WRAPPER (x)
+ `(built-in-or-structure-wrapper ,x))
+
+(defmacro RUNTIME\ BUILT-IN-OR-STRUCTURE-WRAPPER (x)
+ `(built-in-or-structure-wrapper ,x))
+
+(defmacro RUNTIME\ STRUCTURE-INSTANCE-P (x)
+ `(structure-instance-p ,x))
+
+(defmacro RUNTIME\ STD-SLOTS (x)
+ `(std-instance-slots (the std-instance ,x)))
+
+(defmacro RUNTIME\ FSC-SLOTS (x)
+ `(fsc-instance-slots ,x))
+
+(defmacro RUNTIME\ WRAPPER-CACHE-NUMBER-VECTOR (x)
+ `(wrapper-cache-number-vector ,x))
+
+(defmacro RUNTIME\ STD-INSTANCE-P (x)
+ `(std-instance-p ,x))
+
+(defmacro RUNTIME\ FSC-INSTANCE-P (x)
+ `(fsc-instance-p ,x))
+
+(defmacro RUNTIME\ IZEROP (x)
+ `(zerop (the fixnum ,x)))
+
+(defmacro RUNTIME\ FIX= (x y)
+ `(= (the fixnum ,x) (the fixnum ,y)))
+
+;;;
+;;; These are the implementations of the index operands. The portable
+;;; assembler generates Lisp code that uses these macros. Even though
+;;; the variables holding the arguments and results have type declarations
+;;; on them, we put type declarations in here.
+;;;
+;;; Some compilers are so stupid...
+;;;
+(defmacro RUNTIME\ IREF (vector index)
+ #-structure-wrapper
+ `(svref (the simple-vector ,vector) (the fixnum ,index))
+ #+structure-wrapper
+ `(aref ,vector (the fixnum ,index)))
+
+(defmacro RUNTIME\ ISET (vector index value)
+ `(setf (svref (the simple-vector ,vector) (the fixnum ,index)) ,value))
+
+(defmacro RUNTIME\ INSTANCE-REF (vector index)
+ #-new-kcl-wrapper
+ `(svref (the simple-vector ,vector) (the fixnum ,index))
+ #+new-kcl-wrapper
+ `(%instance-ref ,vector (the fixnum ,index)))
+
+(defmacro RUNTIME\ INSTANCE-SET (vector index value)
+ #-new-kcl-wrapper
+ `(setf (svref (the simple-vector ,vector) (the fixnum ,index)) ,value)
+ #+new-kcl-wrapper
+ `(setf (%instance-ref ,vector (the fixnum ,index)) ,value))
+
+(defmacro RUNTIME\ SVREF (vector fixnum)
+ #-structure-wrapper
+ `(svref (the simple-vector ,vector) (the fixnum ,fixnum))
+ #+structure-wrapper
+ `(aref ,vector (the fixnum ,fixnum)))
+
+(defmacro RUNTIME\ I+ (index1 index2)
+ `(the fixnum (+ (the fixnum ,index1) (the fixnum ,index2))))
+
+(defmacro RUNTIME\ I- (index1 index2)
+ `(the fixnum (- (the fixnum ,index1) (the fixnum ,index2))))
+
+(defmacro RUNTIME\ I1+ (index)
+ `(the fixnum (1+ (the fixnum ,index))))
+
+(defmacro RUNTIME\ ILOGAND (index1 index2)
+ #-Lucid `(the fixnum (logand (the fixnum ,index1) (the fixnum ,index2)))
+ #+Lucid `(%logand ,index1 ,index2))
+
+(defmacro RUNTIME\ ILOGXOR (index1 index2)
+ `(the fixnum (logxor (the fixnum ,index1) (the fixnum ,index2))))
+
+;;;
+;;; In the portable implementation, indexes are just fixnums.
+;;;
+
+(defconstant index-value-limit most-positive-fixnum)
+
+(defun index-value->index (index-value) index-value)
+(defun index->index-value (index) index)
+
+(defun make-index-mask (cache-size line-size)
+ (let ((cache-size-in-bits (floor (log cache-size 2)))
+ (line-size-in-bits (floor (log line-size 2)))
+ (mask 0))
+ (dotimes (i cache-size-in-bits) (setq mask (dpb 1 (byte 1 i) mask)))
+ (dotimes (i line-size-in-bits) (setq mask (dpb 0 (byte 1 i) mask)))
+ mask))
+
+
diff --git a/gcl/pcl/pkg.lisp b/gcl/pcl/pkg.lisp
new file mode 100644
index 000000000..e2e1edf9a
--- /dev/null
+++ b/gcl/pcl/pkg.lisp
@@ -0,0 +1,407 @@
+;;;-*-Mode:LISP; Package:(PCL (LISP WALKER)); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :user)
+
+;;; From defsys.lisp
+(eval-when (compile load eval)
+
+(if (find-package ':walker)
+ (use-package '(:lisp) ':walker)
+ (make-package ':walker :use '(:lisp)))
+
+(if (find-package ':iterate)
+ (use-package '(:lisp :walker) ':iterate)
+ (make-package ':iterate :use '(:lisp :walker)))
+
+(if (find-package ':pcl)
+ (use-package '(:walker :iterate :lisp) ':pcl)
+ (make-package ':pcl :use '(:walker :iterate :lisp)))
+
+(export (intern (symbol-name :iterate) ;Have to do this here,
+ (find-package :iterate)) ;because in the defsystem
+ (find-package :iterate)) ;(later in this file)
+ ;we use the symbol iterate
+ ;to name the file
+)
+
+(in-package :walker)
+
+(export '(define-walker-template
+ walk-form
+ walk-form-expand-macros-p
+ nested-walk-form
+ variable-lexical-p
+ variable-special-p
+ variable-globally-special-p
+ *variable-declarations*
+ variable-declaration
+ macroexpand-all
+ ))
+
+(in-package :iterate)
+
+(export '(iterate iterate* gathering gather with-gathering interval elements
+ list-elements list-tails plist-elements eachtime while until
+ collecting joining maximizing minimizing summing
+ *iterate-warnings*))
+
+(in-package :pcl)
+
+;;;
+;;; Some CommonLisps have more symbols in the Lisp package than the ones that
+;;; are explicitly specified in CLtL. This causes trouble. Any Lisp that has
+;;; extra symbols in the Lisp package should shadow those symbols in the PCL
+;;; package.
+;;;
+#+TI
+(shadow '(string-append once-only destructuring-bind
+ memq assq delq neq true false
+ without-interrupts
+ defmethod)
+ *the-pcl-package*)
+
+#+CMU
+(shadow '(destructuring-bind)
+ *the-pcl-package*)
+#+cmu17
+(shadow '(find-class class-name class-of
+ class built-in-class structure-class
+ standard-class)
+ *the-pcl-package*)
+
+#+GCLisp
+(shadow '(string-append memq assq delq neq make-instance)
+ *the-pcl-package*)
+
+(defun use-package-pcl (&optional (*package* *package*))
+ (shadowing-import
+ (let ((*package* *the-pcl-package*))
+ (mapcar #'intern
+ #+cmu17 '("FIND-CLASS" "CLASS-NAME" "CLASS-OF"
+ "CLASS" "BUILT-IN-CLASS" "STRUCTURE-CLASS"
+ "STANDARD-CLASS")
+ #+TI '("DEFMETHOD")
+ #+GCLisp '("MAKE-INSTANCE")
+ #-(or cmu17 TI GCLisp) '())))
+ (use-package *the-pcl-package*))
+
+#+Genera
+(shadowing-import '(zl:arglist zwei:indentation) *the-pcl-package*)
+
+#+Lucid
+(import '(#-LCL3.0 system:arglist #+LCL3.0 lcl:arglist
+ system:structurep system:structure-type system:structure-length)
+ *the-pcl-package*)
+
+#+lucid
+(#-LCL3.0 progn #+LCL3.0 lcl:handler-bind
+ #+LCL3.0 ((lcl:warning #'(lambda (condition)
+ (declare (ignore condition))
+ (lcl:muffle-warning))))
+(let ((importer
+ #+LCL3.0 #'sys:import-from-lucid-pkg
+ #-LCL3.0 (let ((x (find-symbol "IMPORT-FROM-LUCID-PKG" "LUCID")))
+ (if (and x (fboundp x))
+ (symbol-function x)
+ ;; Only the #'(lambda (x) ...) below is really needed,
+ ;; but when available, the "internal" function
+ ;; 'import-from-lucid-pkg' provides better checking.
+ #'(lambda (name)
+ (import (intern name "LUCID")))))))
+ ;;
+ ;; We need the following "internal", undocumented Lucid goodies:
+ (mapc importer '("%POINTER" "DEFSTRUCT-SIMPLE-PREDICATE"
+ #-LCL3.0 "LOGAND&" "%LOGAND&" #+VAX "LOGAND&-VARIABLE"))
+
+ ;;
+ ;; For without-interrupts.
+ ;;
+ #+LCL3.0
+ (mapc importer '("*SCHEDULER-WAKEUP*" "MAYBE-CALL-SCHEDULER"))
+
+ ;;
+ ;; We import the following symbols, because in 2.1 Lisps they have to be
+ ;; accessed as SYS:<foo>, whereas in 3.0 lisps, they are homed in the
+ ;; LUCID-COMMON-LISP package.
+ (mapc importer '("ARGLIST" "NAMED-LAMBDA" "*PRINT-STRUCTURE*"))
+ ;;
+ ;; We import the following symbols, because in 2.1 Lisps they have to be
+ ;; accessed as LUCID::<foo>, whereas in 3.0 lisps, they have to be
+ ;; accessed as SYS:<foo>
+ (mapc importer '(
+ "NEW-STRUCTURE" "STRUCTURE-REF"
+ "STRUCTUREP" "STRUCTURE-TYPE" "STRUCTURE-LENGTH"
+ "PROCEDUREP" "PROCEDURE-SYMBOL"
+ "PROCEDURE-REF" "SET-PROCEDURE-REF"
+ ))
+; ;;
+; ;; The following is for the "patch" to the general defstruct printer.
+; (mapc importer '(
+; "OUTPUT-STRUCTURE" "DEFSTRUCT-INFO"
+; "OUTPUT-TERSE-OBJECT" "DEFAULT-STRUCTURE-PRINT"
+; "STRUCTURE-TYPE" "*PRINT-OUTPUT*"
+; ))
+ ;;
+ ;; The following is for a "patch" affecting compilation of %logand&.
+ ;; On APOLLO, Domain/CommonLISP 2.10 does not include %logand& whereas
+ ;; Domain/CommonLISP 2.20 does; Domain/CommonLISP 2.20 includes :DOMAIN/OS
+ ;; on *FEATURES*, so this conditionalizes correctly for APOLLO.
+ #-(or (and APOLLO DOMAIN/OS) LCL3.0 VAX)
+ (mapc importer '("COPY-STRUCTURE" "GET-FDESC" "SET-FDESC"))
+
+ nil))
+
+#+kcl
+(progn
+(import '(si:structurep si:structure-def si:structure-ref))
+(shadow 'lisp:dotimes)
+)
+#+kcl
+(in-package "SI")
+#+kcl
+(export '(%structure-name
+ %compiled-function-name
+ %set-compiled-function-name
+ %instance-ref
+ %set-instance-ref))
+#+kcl
+(in-package 'pcl)
+
+#+cmu (shadow 'lisp:dotimes)
+
+#+cmu
+(import '(kernel:funcallable-instance-p)
+ *the-pcl-package*)
+
+
+(shadow 'documentation)
+
+
+;;;
+;;; These come from the index pages of 88-002R.
+;;;
+;;;
+(eval-when (compile load eval)
+
+(defvar *exports* '(add-method
+ built-in-class
+ call-method
+ call-next-method
+ change-class
+ class-name
+ class-of
+ compute-applicable-methods
+ defclass
+ defgeneric
+ define-method-combination
+ defmethod
+ ensure-generic-function
+ find-class
+ find-method
+ function-keywords
+ generic-flet
+ generic-labels
+ initialize-instance
+ invalid-method-error
+ make-instance
+ make-instances-obsolete
+ method-combination-error
+ method-qualifiers
+ next-method-p
+ no-applicable-method
+ no-next-method
+ print-object
+ reinitialize-instance
+ remove-method
+ shared-initialize
+ slot-boundp
+ slot-exists-p
+ slot-makunbound
+ slot-missing
+ slot-unbound
+ slot-value
+ standard
+ standard-class
+ standard-generic-function
+ standard-method
+ standard-object
+ structure-class
+ #-cmu17 symbol-macrolet
+ update-instance-for-different-class
+ update-instance-for-redefined-class
+ with-accessors
+ with-added-methods
+ with-slots
+ ))
+
+);eval-when
+
+#-(or KCL IBCL CMU)
+(export *exports* *the-pcl-package*)
+
+#+CMU
+(export '#.*exports* *the-pcl-package*)
+
+#+(or KCL IBCL)
+(mapc 'export (list *exports*) (list *the-pcl-package*))
+
+
+(eval-when (compile load eval)
+
+(defvar *class-exports*
+ '(standard-instance
+ funcallable-standard-instance
+ generic-function
+ standard-generic-function
+ method
+ standard-method
+ standard-accessor-method
+ standard-reader-method
+ standard-writer-method
+ method-combination
+ slot-definition
+ direct-slot-definition
+ effective-slot-definition
+ standard-slot-definition
+ standard-direct-slot-definition
+ standard-effective-slot-definition
+ specializer
+ eql-specializer
+ built-in-class
+ forward-referenced-class
+ standard-class
+ funcallable-standard-class))
+
+(defvar *chapter-6-exports*
+ '(add-dependent
+ add-direct-method
+ add-direct-subclass
+ add-method
+ allocate-instance
+ class-default-initargs
+ class-direct-default-initargs
+ class-direct-slots
+ class-direct-subclasses
+ class-direct-superclasses
+ class-finalized-p
+ class-precedence-list
+ class-prototype
+ class-slots
+ compute-applicable-methods
+ compute-applicable-methods-using-classes
+ compute-class-precedence-list
+ compute-discriminating-function
+ compute-effective-method
+ compute-effective-slot-definition
+ compute-slots
+ direct-slot-definition-class
+ effective-slot-definition-class
+ ensure-class
+ ensure-class-using-class
+ ensure-generic-function
+ ensure-generic-function-using-class
+ eql-specializer-instance
+ extract-lambda-list
+ extract-specializer-names
+ finalize-inheritance
+ find-method-combination
+ funcallable-standard-instance-access
+ generic-function-argument-precedence-order
+ generic-function-declarations
+ generic-function-lambda-list
+ generic-function-method-class
+ generic-function-method-combination
+ generic-function-methods
+ generic-function-name
+ intern-eql-specializer
+ make-instance
+ make-method-lambda
+ map-dependents
+ method-function
+ method-generic-function
+ method-lambda-list
+ method-specializers
+ method-qualifiers
+ accessor-method-slot-definition
+ reader-method-class
+ remove-dependent
+ remove-direct-method
+ remove-direct-subclass
+ remove-method
+ set-funcallable-instance-function
+ slot-boundp-using-class
+ slot-definition-allocation
+ slot-definition-initargs
+ slot-definition-initform
+ slot-definition-initfunction
+ slot-definition-location
+ slot-definition-name
+ slot-definition-readers
+ slot-definition-writers
+ slot-definition-type
+ slot-makunbound-using-class
+ slot-value-using-class
+ specializer-direct-generic-function
+ specializer-direct-methods
+ standard-instance-access
+ update-dependent
+ validate-superclass
+ writer-method-class
+ ))
+
+);eval-when
+
+#-(or KCL IBCL)
+(export *class-exports* *the-pcl-package*)
+
+#+(or KCL IBCL)
+(mapc 'export (list *class-exports*) (list *the-pcl-package*))
+
+#-(or KCL IBCL)
+(export *chapter-6-exports* *the-pcl-package*)
+
+#+(or KCL IBCL)
+(mapc 'export (list *chapter-6-exports*) (list *the-pcl-package*))
+
+(defvar *slot-accessor-name-package*
+ (or (find-package :slot-accessor-name)
+ (make-package :slot-accessor-name
+ :use '()
+ :nicknames '(:s-a-n))))
+
+#+kcl
+(when (get 'si::basic-wrapper 'si::s-data)
+ (import (mapcar #'(lambda (s) (intern (symbol-name s) "SI"))
+ '(:copy-structure-header :swap-structure-contents :set-structure-def
+ :%instance-ref :%set-instance-ref
+
+ :cache-number-vector :cache-number-vector-length
+ :wrapper-cache-number-adds-ok :wrapper-cache-number-length
+ :wrapper-cache-number-mask :wrapper-cache-number-vector-length
+ :wrapper-layout :wrapper-cache-number-vector
+ :wrapper-state :wrapper-class :wrapper-length))))
diff --git a/gcl/pcl/precom1.lisp b/gcl/pcl/precom1.lisp
new file mode 100644
index 000000000..0c550d95d
--- /dev/null
+++ b/gcl/pcl/precom1.lisp
@@ -0,0 +1,51 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+;;;
+;;; pre-allocate generic function caches. The hope is that this will put
+;;; them nicely together in memory, and that that may be a win. Of course
+;;; the first gc copy will probably blow that out, this really wants to be
+;;; wrapped in something that declares the area static.
+;;;
+;;; This preallocation only creates about 25% more caches than PCL itself
+;;; uses need. Some ports may want to preallocate some more of these.
+;;;
+(eval-when (load)
+ (flet ((allocate (n size)
+ (mapcar #'free-cache-vector
+ (mapcar #'get-cache-vector
+ (make-list n :initial-element size)))))
+ (allocate 128 4)
+ (allocate 64 8)
+ (allocate 64 9)
+ (allocate 32 16)
+ (allocate 16 17)
+ (allocate 16 32)
+ (allocate 1 64)))
+
diff --git a/gcl/pcl/precom2.lisp b/gcl/pcl/precom2.lisp
new file mode 100644
index 000000000..97ab8f9eb
--- /dev/null
+++ b/gcl/pcl/precom2.lisp
@@ -0,0 +1,31 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+(precompile-random-code-segments pcl)
+
diff --git a/gcl/pcl/precom4.lisp b/gcl/pcl/precom4.lisp
new file mode 100644
index 000000000..fe13ee147
--- /dev/null
+++ b/gcl/pcl/precom4.lisp
@@ -0,0 +1,32 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package 'pcl)
+
+(precompile-function-generators pcl) ;this is half of a call to
+ ;precompile-random-code-segments
+
diff --git a/gcl/pcl/saved_gcl_pcl b/gcl/pcl/saved_gcl_pcl
new file mode 100755
index 000000000..5f1863c89
--- /dev/null
+++ b/gcl/pcl/saved_gcl_pcl
Binary files differ
diff --git a/gcl/pcl/slots-boot.lisp b/gcl/pcl/slots-boot.lisp
new file mode 100644
index 000000000..dadb07cec
--- /dev/null
+++ b/gcl/pcl/slots-boot.lisp
@@ -0,0 +1,404 @@
+;;;-*-Mode:LISP; Package:PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+(defmacro slot-symbol (slot-name type)
+ `(if (and (symbolp ,slot-name) (symbol-package ,slot-name))
+ (or (get ,slot-name ',(ecase type
+ (reader 'reader-symbol)
+ (writer 'writer-symbol)
+ (boundp 'boundp-symbol)))
+ (intern (format nil "~A ~A slot ~a"
+ (package-name (symbol-package ,slot-name))
+ (symbol-name ,slot-name)
+ ,(symbol-name type))
+ *slot-accessor-name-package*))
+ (progn
+ (error "non-symbol and non-interned symbol slot name accessors~
+ are not yet implemented")
+ ;;(make-symbol (format nil "~a ~a" ,slot-name ,type))
+ )))
+
+(defun slot-reader-symbol (slot-name)
+ (slot-symbol slot-name reader))
+
+(defun slot-writer-symbol (slot-name)
+ (slot-symbol slot-name writer))
+
+(defun slot-boundp-symbol (slot-name)
+ (slot-symbol slot-name boundp))
+
+(defmacro asv-funcall (sym slot-name type &rest args)
+ (declare (ignore type))
+ `(if (#-akcl fboundp #+akcl %fboundp ',sym)
+ (,sym ,@args)
+ (no-slot ',sym ',slot-name)))
+
+(defun no-slot (sym slot-name)
+ (error "No class has a slot named ~S (~s has no function binding)."
+ slot-name sym))
+
+(defmacro accessor-slot-value (object slot-name)
+ (unless (constantp slot-name)
+ (error "~s requires its slot-name argument to be a constant"
+ 'accessor-slot-value))
+ (let* ((slot-name (eval slot-name))
+ (sym (slot-reader-symbol slot-name)))
+ `(asv-funcall ,sym ,slot-name reader ,object)))
+
+(defmacro accessor-set-slot-value (object slot-name new-value &environment env)
+ (unless (constantp slot-name)
+ (error "~s requires its slot-name argument to be a constant"
+ 'accessor-set-slot-value))
+ (setq object (macroexpand object env))
+ (setq slot-name (macroexpand slot-name env))
+ (let* ((slot-name (eval slot-name))
+ (bindings (unless (or (constantp new-value) (atom new-value))
+ (let ((object-var (gensym)))
+ (prog1 `((,object-var ,object))
+ (setq object object-var)))))
+ (sym (slot-writer-symbol slot-name))
+ (form `(asv-funcall ,sym ,slot-name writer ,new-value ,object)))
+ (if bindings
+ `(let ,bindings ,form)
+ form)))
+
+(defconstant *optimize-slot-boundp* nil)
+
+(defmacro accessor-slot-boundp (object slot-name)
+ (unless (constantp slot-name)
+ (error "~s requires its slot-name argument to be a constant"
+ 'accessor-slot-boundp))
+ (let* ((slot-name (eval slot-name))
+ (sym (slot-boundp-symbol slot-name)))
+ (if (not *optimize-slot-boundp*)
+ `(slot-boundp-normal ,object ',slot-name)
+ `(asv-funcall ,sym ,slot-name boundp ,object))))
+
+
+(defun structure-slot-boundp (object)
+ (declare (ignore object))
+ t)
+
+(defun make-structure-slot-boundp-function (slotd)
+ (let* ((reader (slot-definition-internal-reader-function slotd))
+ (fun #'(lambda (object)
+ (not (eq (funcall reader object) *slot-unbound*)))))
+ (declare (type function reader))
+ #+(and kcl turbo-closure) (si:turbo-closure fun)
+ fun))
+
+(defun get-optimized-std-accessor-method-function (class slotd name)
+ (if (structure-class-p class)
+ (ecase name
+ (reader (slot-definition-internal-reader-function slotd))
+ (writer (slot-definition-internal-writer-function slotd))
+ (boundp (make-structure-slot-boundp-function slotd)))
+ (let* ((fsc-p (cond ((standard-class-p class) nil)
+ ((funcallable-standard-class-p class) t)
+ (t (error "~S is not a standard-class" class))))
+ (slot-name (slot-definition-name slotd))
+ (index (slot-definition-location slotd))
+ (function (ecase name
+ (reader #'make-optimized-std-reader-method-function)
+ (writer #'make-optimized-std-writer-method-function)
+ (boundp #'make-optimized-std-boundp-method-function)))
+ (value (funcall function fsc-p slot-name index)))
+ (declare (type function function))
+ (values value index))))
+
+(defun make-optimized-std-reader-method-function (fsc-p slot-name index)
+ (declare #.*optimize-speed*)
+ (set-function-name
+ (etypecase index
+ (fixnum (if fsc-p
+ #'(lambda (instance)
+ (let ((value (%instance-ref (fsc-instance-slots instance) index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound (class-of instance) instance slot-name)
+ value)))
+ #'(lambda (instance)
+ (let ((value (%instance-ref (std-instance-slots instance) index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound (class-of instance) instance slot-name)
+ value)))))
+ (cons #'(lambda (instance)
+ (let ((value (cdr index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound (class-of instance) instance slot-name)
+ value)))))
+ `(reader ,slot-name)))
+
+(defun make-optimized-std-writer-method-function (fsc-p slot-name index)
+ (declare #.*optimize-speed*)
+ (set-function-name
+ (etypecase index
+ (fixnum (if fsc-p
+ #'(lambda (nv instance)
+ (setf (%instance-ref (fsc-instance-slots instance) index) nv))
+ #'(lambda (nv instance)
+ (setf (%instance-ref (std-instance-slots instance) index) nv))))
+ (cons #'(lambda (nv instance)
+ (declare (ignore instance))
+ (setf (cdr index) nv))))
+ `(writer ,slot-name)))
+
+(defun make-optimized-std-boundp-method-function (fsc-p slot-name index)
+ (declare #.*optimize-speed*)
+ (set-function-name
+ (etypecase index
+ (fixnum (if fsc-p
+ #'(lambda (instance)
+ (not (eq *slot-unbound*
+ (%instance-ref (fsc-instance-slots instance) index))))
+ #'(lambda (instance)
+ (not (eq *slot-unbound*
+ (%instance-ref (std-instance-slots instance) index))))))
+ (cons #'(lambda (instance)
+ (declare (ignore instance))
+ (not (eq *slot-unbound* (cdr index))))))
+ `(boundp ,slot-name)))
+
+(defun make-optimized-structure-slot-value-using-class-method-function (function)
+ #+cmu (declare (type function function))
+ #'(lambda (class object slotd)
+ (let ((value (funcall function object)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound class object (slot-definition-name slotd))
+ value))))
+
+(defun make-optimized-structure-setf-slot-value-using-class-method-function (function)
+ #+cmu (declare (type function function))
+ #'(lambda (nv class object slotd)
+ (declare (ignore class slotd))
+ (funcall function nv object)))
+
+(defun make-optimized-structure-slot-boundp-using-class-method-function (function)
+ #+cmu (declare (type function function))
+ #'(lambda (class object slotd)
+ (declare (ignore class slotd))
+ (not (eq (funcall function object) *slot-unbound*))))
+
+(defun get-optimized-std-slot-value-using-class-method-function (class slotd name)
+ (if (structure-class-p class)
+ (ecase name
+ (reader (make-optimized-structure-slot-value-using-class-method-function
+ (slot-definition-internal-reader-function slotd)))
+ (writer (make-optimized-structure-setf-slot-value-using-class-method-function
+ (slot-definition-internal-writer-function slotd)))
+ (boundp (make-optimized-structure-slot-boundp-using-class-method-function
+ (slot-definition-internal-writer-function slotd))))
+ (let* ((fsc-p (cond ((standard-class-p class) nil)
+ ((funcallable-standard-class-p class) t)
+ (t (error "~S is not a standard-class" class))))
+ (slot-name (slot-definition-name slotd))
+ (index (slot-definition-location slotd))
+ (function
+ (ecase name
+ (reader
+ #'make-optimized-std-slot-value-using-class-method-function)
+ (writer
+ #'make-optimized-std-setf-slot-value-using-class-method-function)
+ (boundp
+ #'make-optimized-std-slot-boundp-using-class-method-function))))
+ #+cmu (declare (type function function))
+ (values (funcall function fsc-p slot-name index) index))))
+
+(defun make-optimized-std-slot-value-using-class-method-function
+ (fsc-p slot-name index)
+ (declare #.*optimize-speed*)
+ (etypecase index
+ (fixnum (if fsc-p
+ #'(lambda (class instance slotd)
+ (declare (ignore slotd))
+ (unless (fsc-instance-p instance) (error "not fsc"))
+ (let ((value (%instance-ref (fsc-instance-slots instance) index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound class instance slot-name)
+ value)))
+ #'(lambda (class instance slotd)
+ (declare (ignore slotd))
+ (unless (std-instance-p instance) (error "not std"))
+ (let ((value (%instance-ref (std-instance-slots instance) index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound class instance slot-name)
+ value)))))
+ (cons #'(lambda (class instance slotd)
+ (declare (ignore slotd))
+ (let ((value (cdr index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound class instance slot-name)
+ value))))))
+
+(defun make-optimized-std-setf-slot-value-using-class-method-function
+ (fsc-p slot-name index)
+ (declare #.*optimize-speed*)
+ (declare (ignore slot-name))
+ (etypecase index
+ (fixnum (if fsc-p
+ #'(lambda (nv class instance slotd)
+ (declare (ignore class slotd))
+ (setf (%instance-ref (fsc-instance-slots instance) index) nv))
+ #'(lambda (nv class instance slotd)
+ (declare (ignore class slotd))
+ (setf (%instance-ref (std-instance-slots instance) index) nv))))
+ (cons #'(lambda (nv class instance slotd)
+ (declare (ignore class instance slotd))
+ (setf (cdr index) nv)))))
+
+(defun make-optimized-std-slot-boundp-using-class-method-function
+ (fsc-p slot-name index)
+ (declare #.*optimize-speed*)
+ (declare (ignore slot-name))
+ (etypecase index
+ (fixnum (if fsc-p
+ #'(lambda (class instance slotd)
+ (declare (ignore class slotd))
+ (not (eq *slot-unbound*
+ (%instance-ref (fsc-instance-slots instance) index))))
+ #'(lambda (class instance slotd)
+ (declare (ignore class slotd))
+ (not (eq *slot-unbound*
+ (%instance-ref (std-instance-slots instance) index))))))
+ (cons #'(lambda (class instance slotd)
+ (declare (ignore class instance slotd))
+ (not (eq *slot-unbound* (cdr index)))))))
+
+(defun get-accessor-from-svuc-method-function (class slotd sdfun name)
+ (macrolet ((emf-funcall (emf &rest args)
+ `(invoke-effective-method-function ,emf nil ,@args)))
+ (set-function-name
+ (case name
+ (reader #'(lambda (instance) (emf-funcall sdfun class instance slotd)))
+ (writer #'(lambda (nv instance) (emf-funcall sdfun nv class instance slotd)))
+ (boundp #'(lambda (instance) (emf-funcall sdfun class instance slotd))))
+ `(,name ,(class-name class) ,(slot-definition-name slotd)))))
+
+(defun make-internal-reader-method-function (class-name slot-name)
+ (list* ':method-spec `(internal-reader-method ,class-name ,slot-name)
+ (make-method-function
+ (lambda (instance)
+ (let ((wrapper (get-instance-wrapper-or-nil instance)))
+ (if wrapper
+ (let* ((class (wrapper-class* wrapper))
+ (index (or (instance-slot-index wrapper slot-name)
+ (assq slot-name (wrapper-class-slots wrapper)))))
+ (typecase index
+ (fixnum
+ (let ((value (%instance-ref (get-slots instance) index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound (class-of instance) instance slot-name)
+ value)))
+ (cons
+ (let ((value (cdr index)))
+ (if (eq value *slot-unbound*)
+ (slot-unbound (class-of instance) instance slot-name)
+ value)))
+ (t
+ (error "The wrapper for class ~S does not have the slot ~S"
+ class slot-name))))
+ (slot-value instance slot-name)))))))
+
+
+(defun make-std-reader-method-function (class-name slot-name)
+ (let* ((pv-table-symbol (gensym))
+ (initargs (copy-tree
+ (make-method-function
+ (lambda (instance)
+ (pv-binding1 (.pv. .calls.
+ (symbol-value pv-table-symbol)
+ (instance) (instance-slots))
+ (instance-read-internal
+ .pv. instance-slots 1
+ (slot-value instance slot-name))))))))
+ (setf (getf (getf initargs ':plist) ':slot-name-lists)
+ (list (list nil slot-name)))
+ (setf (getf (getf initargs ':plist) ':pv-table-symbol) pv-table-symbol)
+ (list* ':method-spec `(reader-method ,class-name ,slot-name)
+ initargs)))
+
+(defun make-std-writer-method-function (class-name slot-name)
+ (let* ((pv-table-symbol (gensym))
+ (initargs (copy-tree
+ (make-method-function
+ (lambda (nv instance)
+ (pv-binding1 (.pv. .calls.
+ (symbol-value pv-table-symbol)
+ (instance) (instance-slots))
+ (instance-write-internal
+ .pv. instance-slots 1 nv
+ (setf (slot-value instance slot-name) nv))))))))
+ (setf (getf (getf initargs ':plist) ':slot-name-lists)
+ (list nil (list nil slot-name)))
+ (setf (getf (getf initargs ':plist) ':pv-table-symbol) pv-table-symbol)
+ (list* ':method-spec `(writer-method ,class-name ,slot-name)
+ initargs)))
+
+(defun make-std-boundp-method-function (class-name slot-name)
+ (let* ((pv-table-symbol (gensym))
+ (initargs (copy-tree
+ (make-method-function
+ (lambda (instance)
+ (pv-binding1 (.pv. .calls.
+ (symbol-value pv-table-symbol)
+ (instance) (instance-slots))
+ (instance-boundp-internal
+ .pv. instance-slots 1
+ (slot-boundp instance slot-name))))))))
+ (setf (getf (getf initargs ':plist) ':slot-name-lists)
+ (list (list nil slot-name)))
+ (setf (getf (getf initargs ':plist) ':pv-table-symbol) pv-table-symbol)
+ (list* ':method-spec `(boundp-method ,class-name ,slot-name)
+ initargs)))
+
+(defun initialize-internal-slot-gfs (slot-name &optional type)
+ (when (or (null type) (eq type 'reader))
+ (let* ((name (slot-reader-symbol slot-name))
+ (gf (ensure-generic-function name)))
+ (unless (generic-function-methods gf)
+ (add-reader-method *the-class-slot-object* gf slot-name))))
+ (when (or (null type) (eq type 'writer))
+ (let* ((name (slot-writer-symbol slot-name))
+ (gf (ensure-generic-function name)))
+ (unless (generic-function-methods gf)
+ (add-writer-method *the-class-slot-object* gf slot-name))))
+ (when (and *optimize-slot-boundp*
+ (or (null type) (eq type 'boundp)))
+ (let* ((name (slot-boundp-symbol slot-name))
+ (gf (ensure-generic-function name)))
+ (unless (generic-function-methods gf)
+ (add-boundp-method *the-class-slot-object* gf slot-name))))
+ nil)
+
+(defun initialize-internal-slot-gfs* (readers writers boundps)
+ (dolist (reader readers)
+ (initialize-internal-slot-gfs reader 'reader))
+ (dolist (writer writers)
+ (initialize-internal-slot-gfs writer 'writer))
+ (dolist (boundp boundps)
+ (initialize-internal-slot-gfs boundp 'boundp)))
diff --git a/gcl/pcl/slots.lisp b/gcl/pcl/slots.lisp
new file mode 100644
index 000000000..6cb3c866e
--- /dev/null
+++ b/gcl/pcl/slots.lisp
@@ -0,0 +1,385 @@
+;;;-*-Mode:LISP; Package: PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+(defmethod wrapper-fetcher ((class standard-class))
+ 'std-instance-wrapper)
+
+(defmethod slots-fetcher ((class standard-class))
+ 'std-instance-slots)
+
+(defmethod raw-instance-allocator ((class standard-class))
+ 'allocate-standard-instance)
+
+;;;
+;;; These four functions work on std-instances and fsc-instances. These are
+;;; instances for which it is possible to change the wrapper and the slots.
+;;;
+;;; For these kinds of instances, most specified methods from the instance
+;;; structure protocol are promoted to the implementation-specific class
+;;; std-class. Many of these methods call these four functions.
+;;;
+
+(defun set-wrapper (inst new)
+ (cond ((std-instance-p inst)
+ #+new-kcl-wrapper
+ (set-structure-def inst new)
+ #-new-kcl-wrapper
+ (setf (std-instance-wrapper inst) new))
+ ((fsc-instance-p inst)
+ (setf (fsc-instance-wrapper inst) new))
+ (t
+ (error "What kind of instance is this?"))))
+
+#+ignore ; can't do this when using #+new-kcl-wrapper
+(defun set-slots (inst new)
+ (cond ((std-instance-p inst)
+ (setf (std-instance-slots inst) new))
+ ((fsc-instance-p inst)
+ (setf (fsc-instance-slots inst) new))
+ (t
+ (error "What kind of instance is this?"))))
+
+(defun swap-wrappers-and-slots (i1 i2)
+ (without-interrupts
+ (cond ((std-instance-p i1)
+ #+new-kcl-wrapper
+ (swap-structure-contents i1 i2)
+ #-new-kcl-wrapper
+ (let ((w1 (std-instance-wrapper i1))
+ (s1 (std-instance-slots i1)))
+ (setf (std-instance-wrapper i1) (std-instance-wrapper i2))
+ (setf (std-instance-slots i1) (std-instance-slots i2))
+ (setf (std-instance-wrapper i2) w1)
+ (setf (std-instance-slots i2) s1)))
+ ((fsc-instance-p i1)
+ (let ((w1 (fsc-instance-wrapper i1))
+ (s1 (fsc-instance-slots i1)))
+ (setf (fsc-instance-wrapper i1) (fsc-instance-wrapper i2))
+ (setf (fsc-instance-slots i1) (fsc-instance-slots i2))
+ (setf (fsc-instance-wrapper i2) w1)
+ (setf (fsc-instance-slots i2) s1)))
+ (t
+ (error "What kind of instance is this?")))))
+
+
+
+
+
+
+(defun get-class-slot-value-1 (object wrapper slot-name)
+ (let ((entry (assoc slot-name (wrapper-class-slots wrapper))))
+ (if (null entry)
+ (slot-missing (wrapper-class wrapper) object slot-name 'slot-value)
+ (if (eq (cdr entry) *slot-unbound*)
+ (slot-unbound (wrapper-class wrapper) object slot-name)
+ (cdr entry)))))
+
+(defun set-class-slot-value-1 (new-value object wrapper slot-name)
+ (let ((entry (assoc slot-name (wrapper-class-slots wrapper))))
+ (if (null entry)
+ (slot-missing (wrapper-class wrapper)
+ object
+ slot-name
+ 'setf
+ new-value)
+ (setf (cdr entry) new-value))))
+
+(defmethod class-slot-value ((class std-class) slot-name)
+ (let ((wrapper (class-wrapper class))
+ (prototype (class-prototype class)))
+ (get-class-slot-value-1 prototype wrapper slot-name)))
+
+(defmethod (setf class-slot-value) (nv (class std-class) slot-name)
+ (let ((wrapper (class-wrapper class))
+ (prototype (class-prototype class)))
+ (set-class-slot-value-1 nv prototype wrapper slot-name)))
+
+
+
+(defun find-slot-definition (class slot-name)
+ (dolist (slot (class-slots class) nil)
+ (when (eql slot-name (slot-definition-name slot))
+ (return slot))))
+
+(defun slot-value (object slot-name)
+ (let* ((class (class-of object))
+ (slot-definition (find-slot-definition class slot-name)))
+ (if (null slot-definition)
+ (slot-missing class object slot-name 'slot-value)
+ (slot-value-using-class class object slot-definition))))
+
+(setf (gdefinition 'slot-value-normal) #'slot-value)
+
+(define-compiler-macro slot-value (object-form slot-name-form)
+ (if (and (constantp slot-name-form)
+ (let ((slot-name (eval slot-name-form)))
+ (and (symbolp slot-name) (symbol-package slot-name))))
+ `(accessor-slot-value ,object-form ,slot-name-form)
+ `(slot-value-normal ,object-form ,slot-name-form)))
+
+(defun set-slot-value (object slot-name new-value)
+ (let* ((class (class-of object))
+ (slot-definition (find-slot-definition class slot-name)))
+ (if (null slot-definition)
+ (slot-missing class object slot-name 'setf)
+ (setf (slot-value-using-class class object slot-definition)
+ new-value))))
+
+(setf (gdefinition 'set-slot-value-normal) #'set-slot-value)
+
+(define-compiler-macro set-slot-value (object-form slot-name-form new-value-form)
+ (if (and (constantp slot-name-form)
+ (let ((slot-name (eval slot-name-form)))
+ (and (symbolp slot-name) (symbol-package slot-name))))
+ `(accessor-set-slot-value ,object-form ,slot-name-form ,new-value-form)
+ `(set-slot-value-normal ,object-form ,slot-name-form ,new-value-form)))
+
+(defconstant *optimize-slot-boundp* nil)
+
+(defun slot-boundp (object slot-name)
+ (let* ((class (class-of object))
+ (slot-definition (find-slot-definition class slot-name)))
+ (if (null slot-definition)
+ (slot-missing class object slot-name 'slot-boundp)
+ (slot-boundp-using-class class object slot-definition))))
+
+(setf (gdefinition 'slot-boundp-normal) #'slot-boundp)
+
+(define-compiler-macro slot-boundp (object-form slot-name-form)
+ (if (and (constantp slot-name-form)
+ (let ((slot-name (eval slot-name-form)))
+ (and (symbolp slot-name) (symbol-package slot-name))))
+ `(accessor-slot-boundp ,object-form ,slot-name-form)
+ `(slot-boundp-normal ,object-form ,slot-name-form)))
+
+(defun slot-makunbound (object slot-name)
+ (let* ((class (class-of object))
+ (slot-definition (find-slot-definition class slot-name)))
+ (if (null slot-definition)
+ (slot-missing class object slot-name 'slot-makunbound)
+ (slot-makunbound-using-class class object slot-definition))))
+
+(defun slot-exists-p (object slot-name)
+ (let ((class (class-of object)))
+ (not (null (find-slot-definition class slot-name)))))
+
+;;;
+;;; This isn't documented, but is used within PCL in a number of print
+;;; object methods (see named-object-print-function).
+;;;
+(defun slot-value-or-default (object slot-name &optional (default "unbound"))
+ (if (slot-boundp object slot-name)
+ (slot-value object slot-name)
+ default))
+
+
+;;;
+;;;
+;;;
+(defun standard-instance-access (instance location)
+ (%instance-ref (std-instance-slots instance) location))
+
+(defun funcallable-standard-instance-access (instance location)
+ (%instance-ref (fsc-instance-slots instance) location))
+
+(defmethod slot-value-using-class ((class std-class)
+ (object standard-object)
+ (slotd standard-effective-slot-definition))
+ (let* ((location (slot-definition-location slotd))
+ (value (typecase location
+ (fixnum
+ (cond ((std-instance-p object)
+ (unless (eq 't (wrapper-state (std-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (%instance-ref (std-instance-slots object) location))
+ ((fsc-instance-p object)
+ (unless (eq 't (wrapper-state (fsc-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (%instance-ref (fsc-instance-slots object) location))
+ (t (error "What kind of instance is this?"))))
+ (cons
+ (cdr location))
+ (t
+ (error "The slot ~s has neither :instance nor :class allocation, ~@
+ so it can't be read by the default ~s method."
+ slotd 'slot-value-using-class)))))
+ (if (eq value *slot-unbound*)
+ (slot-unbound class object (slot-definition-name slotd))
+ value)))
+
+(defmethod (setf slot-value-using-class)
+ (new-value (class std-class)
+ (object standard-object)
+ (slotd standard-effective-slot-definition))
+ (let ((location (slot-definition-location slotd)))
+ (typecase location
+ (fixnum
+ (cond ((std-instance-p object)
+ (unless (eq 't (wrapper-state (std-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (setf (%instance-ref (std-instance-slots object) location) new-value))
+ ((fsc-instance-p object)
+ (unless (eq 't (wrapper-state (fsc-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (setf (%instance-ref (fsc-instance-slots object) location) new-value))
+ (t (error "What kind of instance is this?"))))
+ (cons
+ (setf (cdr location) new-value))
+ (t
+ (error "The slot ~s has neither :instance nor :class allocation, ~@
+ so it can't be written by the default ~s method."
+ slotd '(setf slot-value-using-class))))))
+
+(defmethod slot-boundp-using-class
+ ((class std-class)
+ (object standard-object)
+ (slotd standard-effective-slot-definition))
+ (let* ((location (slot-definition-location slotd))
+ (value (typecase location
+ (fixnum
+ (cond ((std-instance-p object)
+ (unless (eq 't (wrapper-state (std-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (%instance-ref (std-instance-slots object) location))
+ ((fsc-instance-p object)
+ (unless (eq 't (wrapper-state (fsc-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (%instance-ref (fsc-instance-slots object) location))
+ (t (error "What kind of instance is this?"))))
+ (cons
+ (cdr location))
+ (t
+ (error "The slot ~s has neither :instance nor :class allocation, ~@
+ so it can't be read by the default ~s method."
+ slotd 'slot-boundp-using-class)))))
+ (not (eq value *slot-unbound*))))
+
+(defmethod slot-makunbound-using-class
+ ((class std-class)
+ (object standard-object)
+ (slotd standard-effective-slot-definition))
+ (let ((location (slot-definition-location slotd)))
+ (typecase location
+ (fixnum
+ (cond ((std-instance-p object)
+ (unless (eq 't (wrapper-state (std-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (setf (%instance-ref (std-instance-slots object) location) *slot-unbound*))
+ ((fsc-instance-p object)
+ (unless (eq 't (wrapper-state (fsc-instance-wrapper object)))
+ (check-wrapper-validity object))
+ (setf (%instance-ref (fsc-instance-slots object) location) *slot-unbound*))
+ (t (error "What kind of instance is this?"))))
+ (cons
+ (setf (cdr location) *slot-unbound*))
+ (t
+ (error "The slot ~s has neither :instance nor :class allocation, ~@
+ so it can't be written by the default ~s method."
+ slotd 'slot-makunbound-using-class))))
+ nil)
+
+(defmethod slot-value-using-class
+ ((class structure-class)
+ (object structure-object)
+ (slotd structure-effective-slot-definition))
+ (let* ((function (slot-definition-internal-reader-function slotd))
+ (value (funcall function object)))
+ #+cmu (declare (type function function))
+ (if (eq value *slot-unbound*)
+ (slot-unbound class object (slot-definition-name slotd))
+ value)))
+
+(defmethod (setf slot-value-using-class)
+ (new-value (class structure-class)
+ (object structure-object)
+ (slotd structure-effective-slot-definition))
+ (let ((function (slot-definition-internal-writer-function slotd)))
+ #+cmu (declare (type function function))
+ (funcall function new-value object)))
+
+(defmethod slot-boundp-using-class
+ ((class structure-class)
+ (object structure-object)
+ (slotd structure-effective-slot-definition))
+ #-new-kcl-wrapper t
+ #+new-kcl-wrapper
+ (let* ((function (slot-definition-internal-reader-function slotd))
+ (value (funcall function object)))
+ #+cmu (declare (type function function))
+ (not (eq value *slot-unbound*))))
+
+(defmethod slot-makunbound-using-class
+ ((class structure-class)
+ (object structure-object)
+ (slotd structure-effective-slot-definition))
+ (error "Structure slots can't be unbound"))
+
+
+(defmethod slot-missing
+ ((class t) instance slot-name operation &optional new-value)
+ (error "When attempting to ~A,~%the slot ~S is missing from the object ~S."
+ (ecase operation
+ (slot-value "read the slot's value (slot-value)")
+ (setf (format nil
+ "set the slot's value to ~S (setf of slot-value)"
+ new-value))
+ (slot-boundp "test to see if slot is bound (slot-boundp)")
+ (slot-makunbound "make the slot unbound (slot-makunbound)"))
+ slot-name
+ instance))
+
+(defmethod slot-unbound ((class t) instance slot-name)
+ (error "The slot ~S is unbound in the object ~S." slot-name instance))
+
+(defun slot-unbound-internal (instance position)
+ (slot-unbound (class-of instance) instance
+ (etypecase position
+ (fixnum
+ (nth position
+ (wrapper-instance-slots-layout (wrapper-of instance))))
+ (cons
+ (car position)))))
+
+
+(defmethod allocate-instance ((class standard-class) &rest initargs)
+ (declare (ignore initargs))
+ (unless (class-finalized-p class) (finalize-inheritance class))
+ (allocate-standard-instance (class-wrapper class)))
+
+(defmethod allocate-instance ((class structure-class) &rest initargs)
+ (declare (ignore initargs))
+ #-new-kcl-wrapper
+ (let ((constructor (class-defstruct-constructor class)))
+ (if constructor
+ (funcall constructor)
+ (error "Can't allocate an instance of class ~S" (class-name class))))
+ #+new-kcl-wrapper
+ (allocate-standard-instance (class-wrapper class)))
+
+
diff --git a/gcl/pcl/std-class.lisp b/gcl/pcl/std-class.lisp
new file mode 100644
index 000000000..4c4838722
--- /dev/null
+++ b/gcl/pcl/std-class.lisp
@@ -0,0 +1,1321 @@
+;;;-*-Mode:LISP; Package:PCL; Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+
+(in-package :pcl)
+
+(defmethod slot-accessor-function ((slotd effective-slot-definition) type)
+ (ecase type
+ (reader (slot-definition-reader-function slotd))
+ (writer (slot-definition-writer-function slotd))
+ (boundp (slot-definition-boundp-function slotd))))
+
+(defmethod (setf slot-accessor-function) (function
+ (slotd effective-slot-definition) type)
+ (ecase type
+ (reader (setf (slot-definition-reader-function slotd) function))
+ (writer (setf (slot-definition-writer-function slotd) function))
+ (boundp (setf (slot-definition-boundp-function slotd) function))))
+
+(defconstant *slotd-reader-function-std-p* 1)
+(defconstant *slotd-writer-function-std-p* 2)
+(defconstant *slotd-boundp-function-std-p* 4)
+(defconstant *slotd-all-function-std-p* 7)
+
+(defmethod slot-accessor-std-p ((slotd effective-slot-definition) type)
+ (let ((flags (slot-value slotd 'accessor-flags)))
+ (declare (type fixnum flags))
+ (if (eq type 'all)
+ (eql *slotd-all-function-std-p* flags)
+ (let ((mask (ecase type
+ (reader *slotd-reader-function-std-p*)
+ (writer *slotd-writer-function-std-p*)
+ (boundp *slotd-boundp-function-std-p*))))
+ (declare (type fixnum mask))
+ (not (zerop (the fixnum (logand mask flags))))))))
+
+(defmethod (setf slot-accessor-std-p) (value (slotd effective-slot-definition) type)
+ (let ((mask (ecase type
+ (reader *slotd-reader-function-std-p*)
+ (writer *slotd-writer-function-std-p*)
+ (boundp *slotd-boundp-function-std-p*)))
+ (flags (slot-value slotd 'accessor-flags)))
+ (declare (type fixnum mask flags))
+ (setf (slot-value slotd 'accessor-flags)
+ (if value
+ (the fixnum (logior mask flags))
+ (the fixnum (logand (the fixnum (lognot mask)) flags)))))
+ value)
+
+(defmethod initialize-internal-slot-functions ((slotd effective-slot-definition))
+ (let* ((name (slot-value slotd 'name))
+ (class (slot-value slotd 'class)))
+ (let ((table (or (gethash name *name->class->slotd-table*)
+ (setf (gethash name *name->class->slotd-table*)
+ (make-hash-table :test 'eq :size 5)))))
+ (setf (gethash class table) slotd))
+ (dolist (type '(reader writer boundp))
+ (let* ((gf-name (ecase type
+ (reader 'slot-value-using-class)
+ (writer '(setf slot-value-using-class))
+ (boundp 'slot-boundp-using-class)))
+ (gf (gdefinition gf-name)))
+ (compute-slot-accessor-info slotd type gf)))
+ (initialize-internal-slot-gfs name)))
+
+(defmethod compute-slot-accessor-info ((slotd effective-slot-definition) type gf)
+ (let* ((name (slot-value slotd 'name))
+ (class (slot-value slotd 'class))
+ (old-slotd (find-slot-definition class name))
+ (old-std-p (and old-slotd (slot-accessor-std-p old-slotd 'all))))
+ (multiple-value-bind (function std-p)
+ (if (eq *boot-state* 'complete)
+ (get-accessor-method-function gf type class slotd)
+ (get-optimized-std-accessor-method-function class slotd type))
+ #+kcl (si:turbo-closure function)
+ (setf (slot-accessor-std-p slotd type) std-p)
+ (setf (slot-accessor-function slotd type) function))
+ (when (and old-slotd (not (eq old-std-p (slot-accessor-std-p slotd 'all))))
+ (push (cons class name) *pv-table-cache-update-info*))))
+
+(defmethod slot-definition-allocation ((slotd structure-slot-definition))
+ :instance)
+
+
+
+(defmethod shared-initialize :after ((object documentation-mixin)
+ slot-names
+ &key (documentation nil documentation-p))
+ (declare (ignore slot-names))
+ (when documentation-p
+ (setf (plist-value object 'documentation) documentation)))
+
+(defmethod documentation (object &optional doc-type)
+ (lisp:documentation object doc-type))
+
+(defmethod (setf documentation) (new-value object &optional doc-type)
+ (declare (ignore new-value doc-type))
+ (error "Can't change the documentation of ~S." object))
+
+
+(defmethod documentation ((object documentation-mixin) &optional doc-type)
+ (declare (ignore doc-type))
+ (plist-value object 'documentation))
+
+(defmethod (setf documentation) (new-value (object documentation-mixin) &optional doc-type)
+ (declare (ignore doc-type))
+ (setf (plist-value object 'documentation) new-value))
+
+
+(defmethod documentation ((slotd standard-slot-definition) &optional doc-type)
+ (declare (ignore doc-type))
+ (slot-value slotd 'documentation))
+
+(defmethod (setf documentation) (new-value (slotd standard-slot-definition) &optional doc-type)
+ (declare (ignore doc-type))
+ (setf (slot-value slotd 'documentation) new-value))
+
+
+;;;
+;;; Various class accessors that are a little more complicated than can be
+;;; done with automatically generated reader methods.
+;;;
+(defmethod class-finalized-p ((class pcl-class))
+ (with-slots (wrapper) class
+ (not (null wrapper))))
+
+(defmethod class-prototype ((class std-class))
+ (with-slots (prototype) class
+ (or prototype (setq prototype (allocate-instance class)))))
+
+(defmethod class-prototype ((class structure-class))
+ (with-slots (prototype wrapper defstruct-constructor) class
+ (or prototype
+ (setq prototype
+ (if #-new-kcl-wrapper defstruct-constructor #+new-kcl-wrapper nil
+ (allocate-instance class)
+ (allocate-standard-instance wrapper))))))
+
+(defmethod class-direct-default-initargs ((class slot-class))
+ (plist-value class 'direct-default-initargs))
+
+(defmethod class-default-initargs ((class slot-class))
+ (plist-value class 'default-initargs))
+
+(defmethod class-constructors ((class slot-class))
+ (plist-value class 'constructors))
+
+(defmethod class-slot-cells ((class std-class))
+ (plist-value class 'class-slot-cells))
+
+
+;;;
+;;; Class accessors that are even a little bit more complicated than those
+;;; above. These have a protocol for updating them, we must implement that
+;;; protocol.
+;;;
+
+;;;
+;;; Maintaining the direct subclasses backpointers. The update methods are
+;;; here, the values are read by an automatically generated reader method.
+;;;
+(defmethod add-direct-subclass ((class class) (subclass class))
+ (with-slots (direct-subclasses) class
+ (pushnew subclass direct-subclasses)
+ subclass))
+
+(defmethod remove-direct-subclass ((class class) (subclass class))
+ (with-slots (direct-subclasses) class
+ (setq direct-subclasses (remove subclass direct-subclasses))
+ subclass))
+
+;;;
+;;; Maintaining the direct-methods and direct-generic-functions backpointers.
+;;;
+;;; There are four generic functions involved, each has one method for the
+;;; class case and another method for the damned EQL specializers. All of
+;;; these are specified methods and appear in their specified place in the
+;;; class graph.
+;;;
+;;; ADD-DIRECT-METHOD
+;;; REMOVE-DIRECT-METHOD
+;;; SPECIALIZER-DIRECT-METHODS
+;;; SPECIALIZER-DIRECT-GENERIC-FUNCTIONS
+;;;
+;;; In each case, we maintain one value which is a cons. The car is the list
+;;; methods. The cdr is a list of the generic functions. The cdr is always
+;;; computed lazily.
+;;;
+
+(defmethod add-direct-method ((specializer class) (method method))
+ (with-slots (direct-methods) specializer
+ (setf (car direct-methods) (adjoin method (car direct-methods)) ;PUSH
+ (cdr direct-methods) ()))
+ method)
+
+(defmethod remove-direct-method ((specializer class) (method method))
+ (with-slots (direct-methods) specializer
+ (setf (car direct-methods) (remove method (car direct-methods))
+ (cdr direct-methods) ()))
+ method)
+
+(defmethod specializer-direct-methods ((specializer class))
+ (with-slots (direct-methods) specializer
+ (car direct-methods)))
+
+(defmethod specializer-direct-generic-functions ((specializer class))
+ (with-slots (direct-methods) specializer
+ (or (cdr direct-methods)
+ (setf (cdr direct-methods)
+ (gathering1 (collecting-once)
+ (dolist (m (car direct-methods))
+ (gather1 (method-generic-function m))))))))
+
+
+
+;;;
+;;; This hash table is used to store the direct methods and direct generic
+;;; functions of EQL specializers. Each value in the table is the cons.
+;;;
+(defvar *eql-specializer-methods* (make-hash-table :test #'eql))
+(defvar *class-eq-specializer-methods* (make-hash-table :test #'eq))
+
+(defmethod specializer-method-table ((specializer eql-specializer))
+ *eql-specializer-methods*)
+
+(defmethod specializer-method-table ((specializer class-eq-specializer))
+ *class-eq-specializer-methods*)
+
+(defmethod add-direct-method ((specializer specializer-with-object) (method method))
+ (let* ((object (specializer-object specializer))
+ (table (specializer-method-table specializer))
+ (entry (gethash object table)))
+ (unless entry
+ (setq entry
+ (setf (gethash object table)
+ (cons nil nil))))
+ (setf (car entry) (adjoin method (car entry))
+ (cdr entry) ())
+ method))
+
+(defmethod remove-direct-method ((specializer specializer-with-object) (method method))
+ (let* ((object (specializer-object specializer))
+ (entry (gethash object (specializer-method-table specializer))))
+ (when entry
+ (setf (car entry) (remove method (car entry))
+ (cdr entry) ()))
+ method))
+
+(defmethod specializer-direct-methods ((specializer specializer-with-object))
+ (car (gethash (specializer-object specializer)
+ (specializer-method-table specializer))))
+
+(defmethod specializer-direct-generic-functions ((specializer specializer-with-object))
+ (let* ((object (specializer-object specializer))
+ (entry (gethash object (specializer-method-table specializer))))
+ (when entry
+ (or (cdr entry)
+ (setf (cdr entry)
+ (gathering1 (collecting-once)
+ (dolist (m (car entry))
+ (gather1 (method-generic-function m)))))))))
+
+(defun map-specializers (function)
+ (declare (type function function))
+ (map-all-classes #'(lambda (class)
+ (funcall function (class-eq-specializer class))
+ (funcall function class)))
+ (maphash #'(lambda (object methods)
+ (declare (ignore methods))
+ (intern-eql-specializer object))
+ *eql-specializer-methods*)
+ (maphash #'(lambda (object specl)
+ (declare (ignore object))
+ (funcall function specl))
+ *eql-specializer-table*)
+ nil)
+
+(defun map-all-generic-functions (function)
+ (declare (type function function))
+ (let ((all-generic-functions (make-hash-table :test 'eq)))
+ (map-specializers #'(lambda (specl)
+ (dolist (gf (specializer-direct-generic-functions specl))
+ (unless (gethash gf all-generic-functions)
+ (setf (gethash gf all-generic-functions) t)
+ (funcall function gf))))))
+ nil)
+
+(defmethod shared-initialize :after ((specl class-eq-specializer) slot-names &key)
+ (declare (ignore slot-names))
+ (setf (slot-value specl 'type) `(class-eq ,(specializer-class specl))))
+
+(defmethod shared-initialize :after ((specl eql-specializer) slot-names &key)
+ (declare (ignore slot-names))
+ (setf (slot-value specl 'type) `(eql ,(specializer-object specl))))
+
+
+
+(defun real-load-defclass (name metaclass-name supers slots other accessors)
+ (do-standard-defsetfs-for-defclass accessors) ;***
+ (let ((res (apply #'ensure-class name :metaclass metaclass-name
+ :direct-superclasses supers
+ :direct-slots slots
+ :definition-source `((defclass ,name)
+ ,(load-truename))
+ other)))
+ #+cmu17 (kernel:layout-class (class-wrapper res))
+ #-cmu17 res))
+
+(setf (gdefinition 'load-defclass) #'real-load-defclass)
+
+(defun ensure-class (name &rest all)
+ (apply #'ensure-class-using-class name (find-class name nil) all))
+
+(defmethod ensure-class-using-class (name (class null) &rest args &key)
+ (multiple-value-bind (meta initargs)
+ (ensure-class-values class args)
+ (inform-type-system-about-class (class-prototype meta) name);***
+ (setf class (apply #'make-instance meta :name name initargs)
+ (find-class name) class)
+ (inform-type-system-about-class class name) ;***
+ class))
+
+(defmethod ensure-class-using-class (name (class pcl-class) &rest args &key)
+ (multiple-value-bind (meta initargs)
+ (ensure-class-values class args)
+ (unless (eq (class-of class) meta) (change-class class meta))
+ (apply #'reinitialize-instance class initargs)
+ (setf (find-class name) class)
+ (inform-type-system-about-class class name) ;***
+ class))
+
+(defmethod class-predicate-name ((class t))
+ 'function-returning-nil)
+
+(defun ensure-class-values (class args)
+ (let* ((initargs (copy-list args))
+ (unsupplied (list 1))
+ (supplied-meta (getf initargs :metaclass unsupplied))
+ (supplied-supers (getf initargs :direct-superclasses unsupplied))
+ (supplied-slots (getf initargs :direct-slots unsupplied))
+ (meta
+ (cond ((neq supplied-meta unsupplied)
+ (find-class supplied-meta))
+ ((or (null class)
+ (forward-referenced-class-p class))
+ *the-class-standard-class*)
+ (t
+ (class-of class)))))
+ (flet ((fix-super (s)
+ (cond ((classp s) s)
+ ((not (legal-class-name-p s))
+ (error "~S is not a class or a legal class name." s))
+ (t
+ (or (find-class s nil)
+ (setf (find-class s)
+ (make-instance 'forward-referenced-class
+ :name s)))))))
+ (loop (unless (remf initargs :metaclass) (return)))
+ (loop (unless (remf initargs :direct-superclasses) (return)))
+ (loop (unless (remf initargs :direct-slots) (return)))
+ (values meta
+ (list* :direct-superclasses
+ (and (neq supplied-supers unsupplied)
+ (mapcar #'fix-super supplied-supers))
+ :direct-slots
+ (and (neq supplied-slots unsupplied) supplied-slots)
+ initargs)))))
+
+
+;;;
+;;;
+;;;
+#|| ; since it doesn't do anything
+(defmethod shared-initialize :before ((class std-class)
+ slot-names
+ &key direct-superclasses)
+ (declare (ignore slot-names))
+ ;; *** error checking
+ )
+||#
+
+(defmethod shared-initialize :after
+ ((class std-class)
+ slot-names
+ &key (direct-superclasses nil direct-superclasses-p)
+ (direct-slots nil direct-slots-p)
+ (direct-default-initargs nil direct-default-initargs-p)
+ (predicate-name nil predicate-name-p))
+ (declare (ignore slot-names))
+ (if direct-superclasses-p
+ (progn
+ (setq direct-superclasses (or direct-superclasses
+ (list *the-class-standard-object*)))
+ (dolist (superclass direct-superclasses)
+ (unless (validate-superclass class superclass)
+ (error "The class ~S was specified as a~%super-class of the class ~S;~%~
+ but the meta-classes ~S and~%~S are incompatible.~%
+ Define a method for ~S to avoid this error."
+ superclass class (class-of superclass) (class-of class)
+ 'validate-superclass)))
+ (setf (slot-value class 'direct-superclasses) direct-superclasses))
+ (setq direct-superclasses (slot-value class 'direct-superclasses)))
+ (setq direct-slots
+ (if direct-slots-p
+ (setf (slot-value class 'direct-slots)
+ (mapcar #'(lambda (pl) (make-direct-slotd class pl)) direct-slots))
+ (slot-value class 'direct-slots)))
+ (if direct-default-initargs-p
+ (setf (plist-value class 'direct-default-initargs) direct-default-initargs)
+ (setq direct-default-initargs (plist-value class 'direct-default-initargs)))
+ (setf (plist-value class 'class-slot-cells)
+ (gathering1 (collecting)
+ (dolist (dslotd direct-slots)
+ (when (eq (slot-definition-allocation dslotd) class)
+ (let ((initfunction (slot-definition-initfunction dslotd)))
+ (gather1 (cons (slot-definition-name dslotd)
+ (if initfunction
+ (funcall initfunction)
+ *slot-unbound*))))))))
+ (setq predicate-name (if predicate-name-p
+ (setf (slot-value class 'predicate-name)
+ (car predicate-name))
+ (or (slot-value class 'predicate-name)
+ (setf (slot-value class 'predicate-name)
+ (make-class-predicate-name (class-name class))))))
+ (add-direct-subclasses class direct-superclasses)
+ (update-class class nil)
+ (make-class-predicate class predicate-name)
+ (add-slot-accessors class direct-slots))
+
+(defmethod shared-initialize :before ((class class) slot-names &key name)
+ (declare (ignore slot-names name))
+ (setf (slot-value class 'type) `(class ,class))
+ (setf (slot-value class 'class-eq-specializer)
+ (make-instance 'class-eq-specializer :class class)))
+
+(defmethod reinitialize-instance :before ((class slot-class) &key)
+ (remove-direct-subclasses class (class-direct-superclasses class))
+ (remove-slot-accessors class (class-direct-slots class)))
+
+(defmethod reinitialize-instance :after ((class slot-class)
+ &rest initargs
+ &key)
+ (map-dependents class
+ #'(lambda (dependent)
+ (apply #'update-dependent class dependent initargs))))
+
+(defmethod shared-initialize :after
+ ((class structure-class)
+ slot-names
+ &key (direct-superclasses nil direct-superclasses-p)
+ (direct-slots nil direct-slots-p)
+ direct-default-initargs
+ (predicate-name nil predicate-name-p))
+ (declare (ignore slot-names direct-default-initargs))
+ (if direct-superclasses-p
+ (setf (slot-value class 'direct-superclasses)
+ (or direct-superclasses
+ (setq direct-superclasses
+ (and (not (eq (class-name class) 'structure-object))
+ (list *the-class-structure-object*)))))
+ (setq direct-superclasses (slot-value class 'direct-superclasses)))
+ (let* ((name (class-name class))
+ (from-defclass-p (slot-value class 'from-defclass-p))
+ (defstruct-p (or from-defclass-p (not (structure-type-p name)))))
+ (if direct-slots-p
+ (setf (slot-value class 'direct-slots)
+ (setq direct-slots
+ (mapcar #'(lambda (pl)
+ (when defstruct-p
+ (let* ((slot-name (getf pl :name))
+ (acc-name (format nil "~s structure class ~a"
+ name slot-name))
+ (accessor (intern acc-name)))
+ (setq pl (list* :defstruct-accessor-symbol accessor
+ pl))))
+ (make-direct-slotd class pl))
+ direct-slots)))
+ (setq direct-slots (slot-value class 'direct-slots)))
+ (when defstruct-p
+ (let* ((include (car (slot-value class 'direct-superclasses)))
+ (conc-name (intern (format nil "~s structure class " name)))
+ (constructor (intern (format nil "~a constructor" conc-name)))
+ (defstruct `(defstruct (,name
+ ,@(when include
+ `((:include ,(class-name include))))
+ (:print-function print-std-instance)
+ (:predicate nil)
+ (:conc-name ,conc-name)
+ (:constructor ,constructor ()))
+ ,@(mapcar #'(lambda (slot)
+ `(,(slot-definition-name slot)
+ *slot-unbound*))
+ direct-slots)))
+ (reader-names (mapcar #'(lambda (slotd)
+ (intern (format nil "~A~A reader" conc-name
+ (slot-definition-name slotd))))
+ direct-slots))
+ (writer-names (mapcar #'(lambda (slotd)
+ (intern (format nil "~A~A writer" conc-name
+ (slot-definition-name slotd))))
+ direct-slots))
+ (readers-init
+ (mapcar #'(lambda (slotd reader-name)
+ (let ((accessor
+ (slot-definition-defstruct-accessor-symbol slotd)))
+ `(defun ,reader-name (obj)
+ (declare (type ,name obj))
+ (,accessor obj))))
+ direct-slots reader-names))
+ (writers-init
+ (mapcar #'(lambda (slotd writer-name)
+ (let ((accessor
+ (slot-definition-defstruct-accessor-symbol slotd)))
+ `(defun ,writer-name (nv obj)
+ (declare (type ,name obj))
+ (setf (,accessor obj) nv))))
+ direct-slots writer-names))
+ (defstruct-form
+ `(progn
+ ,defstruct
+ ,@readers-init ,@writers-init
+ (declare-structure ',name nil nil))))
+ (unless (structure-type-p name) (eval defstruct-form))
+ (mapc #'(lambda (dslotd reader-name writer-name)
+ (let* ((reader (gdefinition reader-name))
+ (writer (when (gboundp writer-name)
+ (gdefinition writer-name))))
+ (setf (slot-value dslotd 'internal-reader-function) reader)
+ (setf (slot-value dslotd 'internal-writer-function) writer)))
+ direct-slots reader-names writer-names)
+ (setf (slot-value class 'defstruct-form) defstruct-form)
+ (setf (slot-value class 'defstruct-constructor) constructor))))
+ (add-direct-subclasses class direct-superclasses)
+ (setf (slot-value class 'class-precedence-list)
+ (compute-class-precedence-list class))
+ (setf (slot-value class 'slots) (compute-slots class))
+ #-(or cmu17 new-kcl-wrapper)
+ (unless (slot-value class 'wrapper)
+ (setf (slot-value class 'wrapper) (make-wrapper 0 class)))
+ #+cmu17
+ (let ((lclass (lisp:find-class (class-name class))))
+ (setf (kernel:class-pcl-class lclass) class)
+ (setf (slot-value class 'wrapper) (kernel:class-layout lclass)))
+ #+new-kcl-wrapper
+ (let ((wrapper (get (class-name class) 'si::s-data)))
+ (setf (slot-value class 'wrapper) wrapper)
+ (setf (wrapper-class wrapper) class))
+ (update-pv-table-cache-info class)
+ (setq predicate-name (if predicate-name-p
+ (setf (slot-value class 'predicate-name)
+ (car predicate-name))
+ (or (slot-value class 'predicate-name)
+ (setf (slot-value class 'predicate-name)
+ (make-class-predicate-name (class-name class))))))
+ (make-class-predicate class predicate-name)
+ (add-slot-accessors class direct-slots))
+
+(defmethod direct-slot-definition-class ((class structure-class) initargs)
+ (declare (ignore initargs))
+ (find-class 'structure-direct-slot-definition))
+
+(defmethod finalize-inheritance ((class structure-class))
+ nil) ; always finalized
+
+(defun add-slot-accessors (class dslotds)
+ (fix-slot-accessors class dslotds 'add))
+
+(defun remove-slot-accessors (class dslotds)
+ (fix-slot-accessors class dslotds 'remove))
+
+(defun fix-slot-accessors (class dslotds add/remove)
+ (flet ((fix (gfspec name r/w)
+ (let ((gf (ensure-generic-function gfspec)))
+ (case r/w
+ (r (if (eq add/remove 'add)
+ (add-reader-method class gf name)
+ (remove-reader-method class gf)))
+ (w (if (eq add/remove 'add)
+ (add-writer-method class gf name)
+ (remove-writer-method class gf)))))))
+ (dolist (dslotd dslotds)
+ (let ((slot-name (slot-definition-name dslotd)))
+ (dolist (r (slot-definition-readers dslotd)) (fix r slot-name 'r))
+ (dolist (w (slot-definition-writers dslotd)) (fix w slot-name 'w))))))
+
+
+(defun add-direct-subclasses (class new)
+ (dolist (n new)
+ (unless (memq class (class-direct-subclasses class))
+ (add-direct-subclass n class))))
+
+(defun remove-direct-subclasses (class new)
+ (let ((old (class-direct-superclasses class)))
+ (dolist (o (set-difference old new))
+ (remove-direct-subclass o class))))
+
+
+;;;
+;;;
+;;;
+(defmethod finalize-inheritance ((class std-class))
+ (update-class class t))
+
+
+(defun class-has-a-forward-referenced-superclass-p (class)
+ (or (forward-referenced-class-p class)
+ (some #'class-has-a-forward-referenced-superclass-p
+ (class-direct-superclasses class))))
+
+;;;
+;;; Called by :after shared-initialize whenever a class is initialized or
+;;; reinitialized. The class may or may not be finalized.
+;;;
+(defun update-class (class finalizep)
+ (when (or finalizep (class-finalized-p class)
+ (not (class-has-a-forward-referenced-superclass-p class)))
+ (update-cpl class (compute-class-precedence-list class))
+ (update-slots class (compute-slots class))
+ (update-gfs-of-class class)
+ (update-inits class (compute-default-initargs class))
+ (update-make-instance-function-table class))
+ (unless finalizep
+ (dolist (sub (class-direct-subclasses class)) (update-class sub nil))))
+
+(defun update-cpl (class cpl)
+ (when (class-finalized-p class)
+ (unless (equal (class-precedence-list class) cpl)
+ (force-cache-flushes class)))
+ (setf (slot-value class 'class-precedence-list) cpl)
+ (update-class-can-precede-p cpl))
+
+(defun update-class-can-precede-p (cpl)
+ (when cpl
+ (let ((first (car cpl)))
+ (dolist (c (cdr cpl))
+ (pushnew c (slot-value first 'can-precede-list))))
+ (update-class-can-precede-p (cdr cpl))))
+
+(defun class-can-precede-p (class1 class2)
+ (member class2 (class-can-precede-list class1)))
+
+(defun update-slots (class eslotds)
+ (let ((instance-slots ())
+ (class-slots ()))
+ (dolist (eslotd eslotds)
+ (let ((alloc (slot-definition-allocation eslotd)))
+ (cond ((eq alloc :instance) (push eslotd instance-slots))
+ ((classp alloc) (push eslotd class-slots)))))
+ ;;
+ ;; If there is a change in the shape of the instances then the
+ ;; old class is now obsolete.
+ ;;
+ (let* ((nlayout (mapcar #'slot-definition-name
+ (sort instance-slots #'< :key #'slot-definition-location)))
+ (nslots (length nlayout))
+ (nwrapper-class-slots (compute-class-slots class-slots))
+ (owrapper (class-wrapper class))
+ (olayout (and owrapper (wrapper-instance-slots-layout owrapper)))
+ (owrapper-class-slots (and owrapper (wrapper-class-slots owrapper)))
+ (nwrapper
+ (cond ((null owrapper)
+ (make-wrapper nslots class))
+ ((and (equal nlayout olayout)
+ (not
+ (iterate ((o (list-elements owrapper-class-slots))
+ (n (list-elements nwrapper-class-slots)))
+ (unless (eq (car o) (car n)) (return t)))))
+ owrapper)
+ (t
+ ;;
+ ;; This will initialize the new wrapper to have the same
+ ;; state as the old wrapper. We will then have to change
+ ;; that. This may seem like wasted work (it is), but the
+ ;; spec requires that we call make-instances-obsolete.
+ ;;
+ (make-instances-obsolete class)
+ (class-wrapper class)))))
+
+ (with-slots (wrapper slots) class
+ #+new-kcl-wrapper
+ (setf (si::s-data-name nwrapper) (class-name class))
+ #+cmu17
+ (update-lisp-class-layout class nwrapper)
+ (setf slots eslotds
+ (wrapper-instance-slots-layout nwrapper) nlayout
+ (wrapper-class-slots nwrapper) nwrapper-class-slots
+ (wrapper-no-of-instance-slots nwrapper) nslots
+ wrapper nwrapper))
+
+ (unless (eq owrapper nwrapper)
+ (update-pv-table-cache-info class)))))
+
+(defun compute-class-slots (eslotds)
+ (gathering1 (collecting)
+ (dolist (eslotd eslotds)
+ (gather1
+ (assoc (slot-definition-name eslotd)
+ (class-slot-cells (slot-definition-allocation eslotd)))))))
+
+(defun compute-layout (cpl instance-eslotds)
+ (let* ((names
+ (gathering1 (collecting)
+ (dolist (eslotd instance-eslotds)
+ (when (eq (slot-definition-allocation eslotd) :instance)
+ (gather1 (slot-definition-name eslotd))))))
+ (order ()))
+ (labels ((rwalk (tail)
+ (when tail
+ (rwalk (cdr tail))
+ (dolist (ss (class-slots (car tail)))
+ (let ((n (slot-definition-name ss)))
+ (when (member n names)
+ (setq order (cons n order)
+ names (remove n names))))))))
+ (rwalk (if (slot-boundp (car cpl) 'slots)
+ cpl
+ (cdr cpl)))
+ (reverse (append names order)))))
+
+(defun update-gfs-of-class (class)
+ (when (and (class-finalized-p class)
+ (let ((cpl (class-precedence-list class)))
+ (or (member *the-class-slot-class* cpl)
+ (member *the-class-standard-effective-slot-definition* cpl))))
+ (let ((gf-table (make-hash-table :test 'eq)))
+ (labels ((collect-gfs (class)
+ (dolist (gf (specializer-direct-generic-functions class))
+ (setf (gethash gf gf-table) t))
+ (mapc #'collect-gfs (class-direct-superclasses class))))
+ (collect-gfs class)
+ (maphash #'(lambda (gf ignore)
+ (declare (ignore ignore))
+ (update-gf-dfun class gf))
+ gf-table)))))
+
+(defun update-inits (class inits)
+ (setf (plist-value class 'default-initargs) inits))
+
+
+;;;
+;;;
+;;;
+(defmethod compute-default-initargs ((class slot-class))
+ (let ((cpl (class-precedence-list class))
+ (direct (class-direct-default-initargs class)))
+ (labels ((walk (tail)
+ (if (null tail)
+ nil
+ (let ((c (pop tail)))
+ (append (if (eq c class)
+ direct
+ (class-direct-default-initargs c))
+ (walk tail))))))
+ (let ((initargs (walk cpl)))
+ (delete-duplicates initargs :test #'eq :key #'car :from-end t)))))
+
+
+;;;
+;;; Protocols for constructing direct and effective slot definitions.
+;;;
+;;;
+;;;
+;;;
+(defmethod direct-slot-definition-class ((class std-class) initargs)
+ (declare (ignore initargs))
+ (find-class 'standard-direct-slot-definition))
+
+(defun make-direct-slotd (class initargs)
+ (let ((initargs (list* :class class initargs)))
+ (apply #'make-instance (direct-slot-definition-class class initargs) initargs)))
+
+;;;
+;;;
+;;;
+(defmethod compute-slots ((class std-class))
+ ;;
+ ;; As specified, we must call COMPUTE-EFFECTIVE-SLOT-DEFINITION once
+ ;; for each different slot name we find in our superclasses. Each
+ ;; call receives the class and a list of the dslotds with that name.
+ ;; The list is in most-specific-first order.
+ ;;
+ (let ((name-dslotds-alist ()))
+ (dolist (c (class-precedence-list class))
+ (let ((dslotds (class-direct-slots c)))
+ (dolist (d dslotds)
+ (let* ((name (slot-definition-name d))
+ (entry (assq name name-dslotds-alist)))
+ (if entry
+ (push d (cdr entry))
+ (push (list name d) name-dslotds-alist))))))
+ (mapcar #'(lambda (direct)
+ (compute-effective-slot-definition class
+ (nreverse (cdr direct))))
+ name-dslotds-alist)))
+
+(defmethod compute-slots :around ((class std-class))
+ (let ((eslotds (call-next-method))
+ (cpl (class-precedence-list class))
+ (instance-slots ())
+ (class-slots ()))
+ (dolist (eslotd eslotds)
+ (let ((alloc (slot-definition-allocation eslotd)))
+ (cond ((eq alloc :instance) (push eslotd instance-slots))
+ ((classp alloc) (push eslotd class-slots)))))
+ (let ((nlayout (compute-layout cpl instance-slots)))
+ (dolist (eslotd instance-slots)
+ (setf (slot-definition-location eslotd)
+ (position (slot-definition-name eslotd) nlayout))))
+ (dolist (eslotd class-slots)
+ (setf (slot-definition-location eslotd)
+ (assoc (slot-definition-name eslotd)
+ (class-slot-cells (slot-definition-allocation eslotd)))))
+ (mapc #'initialize-internal-slot-functions eslotds)
+ eslotds))
+
+(defmethod compute-slots ((class structure-class))
+ (mapcan #'(lambda (superclass)
+ (mapcar #'(lambda (dslotd)
+ (compute-effective-slot-definition class
+ (list dslotd)))
+ (class-direct-slots superclass)))
+ (reverse (slot-value class 'class-precedence-list))))
+
+(defmethod compute-slots :around ((class structure-class))
+ (let ((eslotds (call-next-method)))
+ (mapc #'initialize-internal-slot-functions eslotds)
+ eslotds))
+
+(defmethod compute-effective-slot-definition ((class slot-class) dslotds)
+ (let* ((initargs (compute-effective-slot-definition-initargs class dslotds))
+ (class (effective-slot-definition-class class initargs)))
+ (apply #'make-instance class initargs)))
+
+(defmethod effective-slot-definition-class ((class std-class) initargs)
+ (declare (ignore initargs))
+ (find-class 'standard-effective-slot-definition))
+
+(defmethod effective-slot-definition-class ((class structure-class) initargs)
+ (declare (ignore initargs))
+ (find-class 'structure-effective-slot-definition))
+
+(defmethod compute-effective-slot-definition-initargs
+ ((class slot-class) direct-slotds)
+ (let* ((name nil)
+ (initfunction nil)
+ (initform nil)
+ (initargs nil)
+ (allocation nil)
+ (type t)
+ (namep nil)
+ (initp nil)
+ (allocp nil))
+
+ (dolist (slotd direct-slotds)
+ (when slotd
+ (unless namep
+ (setq name (slot-definition-name slotd)
+ namep t))
+ (unless initp
+ (when (slot-definition-initfunction slotd)
+ (setq initform (slot-definition-initform slotd)
+ initfunction (slot-definition-initfunction slotd)
+ initp t)))
+ (unless allocp
+ (setq allocation (slot-definition-allocation slotd)
+ allocp t))
+ (setq initargs (append (slot-definition-initargs slotd) initargs))
+ (let ((slotd-type (slot-definition-type slotd)))
+ (setq type (cond ((eq type 't) slotd-type)
+ ((*subtypep type slotd-type) type)
+ (t `(and ,type ,slotd-type)))))))
+ (list :name name
+ :initform initform
+ :initfunction initfunction
+ :initargs initargs
+ :allocation allocation
+ :type type
+ :class class)))
+
+(defmethod compute-effective-slot-definition-initargs :around
+ ((class structure-class) direct-slotds)
+ (let ((slotd (car direct-slotds)))
+ (list* :defstruct-accessor-symbol (slot-definition-defstruct-accessor-symbol slotd)
+ :internal-reader-function (slot-definition-internal-reader-function slotd)
+ :internal-writer-function (slot-definition-internal-writer-function slotd)
+ (call-next-method))))
+
+;;;
+;;; NOTE: For bootstrapping considerations, these can't use make-instance
+;;; to make the method object. They have to use make-a-method which
+;;; is a specially bootstrapped mechanism for making standard methods.
+;;;
+(defmethod reader-method-class ((class slot-class) direct-slot &rest initargs)
+ (declare (ignore direct-slot initargs))
+ (find-class 'standard-reader-method))
+
+(defmethod add-reader-method ((class slot-class) generic-function slot-name)
+ (add-method generic-function
+ (make-a-method 'standard-reader-method
+ ()
+ (list (or (class-name class) 'object))
+ (list class)
+ (make-reader-method-function class slot-name)
+ "automatically generated reader method"
+ slot-name)))
+
+(defmethod writer-method-class ((class slot-class) direct-slot &rest initargs)
+ (declare (ignore direct-slot initargs))
+ (find-class 'standard-writer-method))
+
+(defmethod add-writer-method ((class slot-class) generic-function slot-name)
+ (add-method generic-function
+ (make-a-method 'standard-writer-method
+ ()
+ (list 'new-value (or (class-name class) 'object))
+ (list *the-class-t* class)
+ (make-writer-method-function class slot-name)
+ "automatically generated writer method"
+ slot-name)))
+
+(defmethod add-boundp-method ((class slot-class) generic-function slot-name)
+ (add-method generic-function
+ (make-a-method 'standard-boundp-method
+ ()
+ (list (or (class-name class) 'object))
+ (list class)
+ (make-boundp-method-function class slot-name)
+ "automatically generated boundp method"
+ slot-name)))
+
+(defmethod remove-reader-method ((class slot-class) generic-function)
+ (let ((method (get-method generic-function () (list class) nil)))
+ (when method (remove-method generic-function method))))
+
+(defmethod remove-writer-method ((class slot-class) generic-function)
+ (let ((method
+ (get-method generic-function () (list *the-class-t* class) nil)))
+ (when method (remove-method generic-function method))))
+
+(defmethod remove-boundp-method ((class slot-class) generic-function)
+ (let ((method (get-method generic-function () (list class) nil)))
+ (when method (remove-method generic-function method))))
+
+
+;;;
+;;; make-reader-method-function and make-write-method function are NOT part of
+;;; the standard protocol. They are however useful, PCL makes uses makes use
+;;; of them internally and documents them for PCL users.
+;;;
+;;; *** This needs work to make type testing by the writer functions which
+;;; *** do type testing faster. The idea would be to have one constructor
+;;; *** for each possible type test. In order to do this it would be nice
+;;; *** to have help from inform-type-system-about-class and friends.
+;;;
+;;; *** There is a subtle bug here which is going to have to be fixed.
+;;; *** Namely, the simplistic use of the template has to be fixed. We
+;;; *** have to give the optimize-slot-value method the user might have
+;;; *** defined for this metclass a chance to run.
+;;;
+(defmethod make-reader-method-function ((class slot-class) slot-name)
+ (make-std-reader-method-function (class-name class) slot-name))
+
+(defmethod make-writer-method-function ((class slot-class) slot-name)
+ (make-std-writer-method-function (class-name class) slot-name))
+
+(defmethod make-boundp-method-function ((class slot-class) slot-name)
+ (make-std-boundp-method-function (class-name class) slot-name))
+
+
+;;;; inform-type-system-about-class
+;;;; make-type-predicate
+;;;
+;;; These are NOT part of the standard protocol. They are internal mechanism
+;;; which PCL uses to *try* and tell the type system about class definitions.
+;;; In a more fully integrated implementation of CLOS, the type system would
+;;; know about class objects and class names in a more fundamental way and
+;;; the mechanism used to inform the type system about new classes would be
+;;; different.
+;;;
+(defmethod inform-type-system-about-class ((class std-class) name)
+ (inform-type-system-about-std-class name))
+
+
+(defmethod compatible-meta-class-change-p (class proto-new-class)
+ (eq (class-of class) (class-of proto-new-class)))
+
+(defmethod validate-superclass ((class class) (new-super class))
+ (or (eq new-super *the-class-t*)
+ (eq (class-of class) (class-of new-super))))
+
+
+
+;;;
+;;;
+;;;
+(defun force-cache-flushes (class)
+ (let* ((owrapper (class-wrapper class))
+ (state (wrapper-state owrapper)))
+ ;;
+ ;; We only need to do something if the state is still T. If the
+ ;; state isn't T, it will be FLUSH or OBSOLETE, and both of those
+ ;; will already be doing what we want. In particular, we must be
+ ;; sure we never change an OBSOLETE into a FLUSH since OBSOLETE
+ ;; means do what FLUSH does and then some.
+ ;;
+ (when (eq state 't)
+ (let ((nwrapper (make-wrapper (wrapper-no-of-instance-slots owrapper)
+ class)))
+ (setf (wrapper-instance-slots-layout nwrapper)
+ (wrapper-instance-slots-layout owrapper))
+ (setf (wrapper-class-slots nwrapper)
+ (wrapper-class-slots owrapper))
+ (without-interrupts
+ #+cmu17
+ (update-lisp-class-layout class nwrapper)
+ (setf (slot-value class 'wrapper) nwrapper)
+ (invalidate-wrapper owrapper ':flush nwrapper))))))
+
+(defun flush-cache-trap (owrapper nwrapper instance)
+ (declare (ignore owrapper))
+ (set-wrapper instance nwrapper))
+
+
+
+;;;
+;;; make-instances-obsolete can be called by user code. It will cause the
+;;; next access to the instance (as defined in 88-002R) to trap through the
+;;; update-instance-for-redefined-class mechanism.
+;;;
+(defmethod make-instances-obsolete ((class std-class))
+ (let* ((owrapper (class-wrapper class))
+ (nwrapper (make-wrapper (wrapper-no-of-instance-slots owrapper)
+ class)))
+ (setf (wrapper-instance-slots-layout nwrapper)
+ (wrapper-instance-slots-layout owrapper))
+ (setf (wrapper-class-slots nwrapper)
+ (wrapper-class-slots owrapper))
+ (without-interrupts
+ #+cmu17
+ (update-lisp-class-layout class nwrapper)
+ (setf (slot-value class 'wrapper) nwrapper)
+ (invalidate-wrapper owrapper ':obsolete nwrapper)
+ class)))
+
+(defmethod make-instances-obsolete ((class symbol))
+ (make-instances-obsolete (find-class class)))
+
+
+;;;
+;;; obsolete-instance-trap is the internal trap that is called when we see
+;;; an obsolete instance. The times when it is called are:
+;;; - when the instance is involved in method lookup
+;;; - when attempting to access a slot of an instance
+;;;
+;;; It is not called by class-of, wrapper-of, or any of the low-level instance
+;;; access macros.
+;;;
+;;; Of course these times when it is called are an internal implementation
+;;; detail of PCL and are not part of the documented description of when the
+;;; obsolete instance update happens. The documented description is as it
+;;; appears in 88-002R.
+;;;
+;;; This has to return the new wrapper, so it counts on all the methods on
+;;; obsolete-instance-trap-internal to return the new wrapper. It also does
+;;; a little internal error checking to make sure that the traps are only
+;;; happening when they should, and that the trap methods are computing
+;;; apropriate new wrappers.
+;;;
+
+;;; obsolete-instance-trap might be called on structure instances
+;;; after a structure is redefined. In most cases, obsolete-instance-trap
+;;; will not be able to fix the old instance, so it must signal an
+;;; error. The hard part of this is that the error system and debugger
+;;; might cause obsolete-instance-trap to be called again, so in that
+;;; case, we have to return some reasonable wrapper, instead.
+
+(defvar *in-obsolete-instance-trap* nil)
+(defvar *the-wrapper-of-structure-object*
+ (class-wrapper (find-class 'structure-object)))
+
+#+cmu17
+(define-condition obsolete-structure (error)
+ ((datum :reader obsolete-structure-datum :initarg :datum))
+ (:report
+ (lambda (condition stream)
+ ;; Don't try to print the structure, since it probably
+ ;; won't work.
+ (format stream "Obsolete structure error in ~S:~@
+ For a structure of type: ~S"
+ (conditions::condition-function-name condition)
+ (type-of (obsolete-structure-datum condition))))))
+
+(defun obsolete-instance-trap (owrapper nwrapper instance)
+ (if (not #-(or cmu17 new-kcl-wrapper)
+ (or (std-instance-p instance) (fsc-instance-p instance))
+ #+cmu17
+ (pcl-instance-p instance)
+ #+new-kcl-wrapper
+ nil)
+ (if *in-obsolete-instance-trap*
+ *the-wrapper-of-structure-object*
+ (let ((*in-obsolete-instance-trap* t))
+ #-cmu17
+ (error "The structure ~S is obsolete." instance)
+ #+cmu17
+ (error 'obsolete-structure :datum instance)))
+ (let* ((class (wrapper-class* nwrapper))
+ (copy (allocate-instance class)) ;??? allocate-instance ???
+ (olayout (wrapper-instance-slots-layout owrapper))
+ (nlayout (wrapper-instance-slots-layout nwrapper))
+ (oslots (get-slots instance))
+ (nslots (get-slots copy))
+ (oclass-slots (wrapper-class-slots owrapper))
+ (added ())
+ (discarded ())
+ (plist ()))
+ ;; local --> local transfer
+ ;; local --> shared discard
+ ;; local --> -- discard
+ ;; shared --> local transfer
+ ;; shared --> shared discard
+ ;; shared --> -- discard
+ ;; -- --> local add
+ ;; -- --> shared --
+ ;;
+ ;; Go through all the old local slots.
+ ;;
+ (iterate ((name (list-elements olayout))
+ (opos (interval :from 0)))
+ (let* ((opos opos)
+ (npos (posq name nlayout)))
+ (declare (fixnum opos))
+ (if npos
+ (setf (instance-ref nslots npos) (instance-ref oslots opos))
+ (progn
+ (push name discarded)
+ (unless (eq (instance-ref oslots opos) *slot-unbound*)
+ (setf (getf plist name) (instance-ref oslots opos)))))))
+ ;;
+ ;; Go through all the old shared slots.
+ ;;
+ (iterate ((oclass-slot-and-val (list-elements oclass-slots)))
+ (let ((name (car oclass-slot-and-val))
+ (val (cdr oclass-slot-and-val)))
+ (let ((npos (posq name nlayout)))
+ (if npos
+ (setf (instance-ref nslots npos) (cdr oclass-slot-and-val))
+ (progn (push name discarded)
+ (unless (eq val *slot-unbound*)
+ (setf (getf plist name) val)))))))
+ ;;
+ ;; Go through all the new local slots to compute the added slots.
+ ;;
+ (dolist (nlocal nlayout)
+ (unless (or (memq nlocal olayout)
+ (assq nlocal oclass-slots))
+ (push nlocal added)))
+
+ (swap-wrappers-and-slots instance copy)
+
+ (update-instance-for-redefined-class instance
+ added
+ discarded
+ plist)
+ nwrapper)))
+
+
+;;;
+;;;
+;;;
+(defmacro copy-instance-internal (instance)
+ `(#+new-kcl-wrapper if #-new-kcl-wrapper progn
+ #+new-kcl-wrapper (not (std-instance-p ,instance))
+ (let* ((class (class-of instance))
+ (copy (allocate-instance class)))
+ (if (std-instance-p ,instance)
+ (setf (std-instance-slots ,instance) (std-instance-slots ,instance))
+ (setf (fsc-instance-slots ,instance) (fsc-instance-slots ,instance)))
+ copy)
+ #+new-kcl-wrapper
+ (copy-structure-header ,instance)))
+
+(defun change-class-internal (instance new-class)
+ (let* ((old-class (class-of instance))
+ (copy (allocate-instance new-class))
+ (new-wrapper (get-wrapper copy))
+ (old-wrapper (class-wrapper old-class))
+ (old-layout (wrapper-instance-slots-layout old-wrapper))
+ (new-layout (wrapper-instance-slots-layout new-wrapper))
+ (old-slots (get-slots instance))
+ (new-slots (get-slots copy))
+ (old-class-slots (wrapper-class-slots old-wrapper)))
+
+ ;;
+ ;; "The values of local slots specified by both the class Cto and
+ ;; Cfrom are retained. If such a local slot was unbound, it remains
+ ;; unbound."
+ ;;
+ (iterate ((new-slot (list-elements new-layout))
+ (new-position (interval :from 0)))
+ (let* ((new-position new-position)
+ (old-position (posq new-slot old-layout)))
+ (declare (fixnum new-position))
+ (when old-position
+ (setf (instance-ref new-slots new-position)
+ (instance-ref old-slots old-position)))))
+
+ ;;
+ ;; "The values of slots specified as shared in the class Cfrom and
+ ;; as local in the class Cto are retained."
+ ;;
+ (iterate ((slot-and-val (list-elements old-class-slots)))
+ (let ((position (posq (car slot-and-val) new-layout)))
+ (when position
+ (setf (instance-ref new-slots position) (cdr slot-and-val)))))
+
+ ;; Make the copy point to the old instance's storage, and make the
+ ;; old instance point to the new storage.
+ (swap-wrappers-and-slots instance copy)
+
+ (update-instance-for-different-class copy instance)
+ instance))
+
+(defmethod change-class ((instance standard-object)
+ (new-class standard-class))
+ (unless (std-instance-p instance)
+ (error "Can't change the class of ~S to ~S~@
+ because it isn't already an instance with metaclass~%~S."
+ instance
+ new-class
+ 'standard-class))
+ (change-class-internal instance new-class))
+
+(defmethod change-class ((instance standard-object)
+ (new-class funcallable-standard-class))
+ (unless (fsc-instance-p instance)
+ (error "Can't change the class of ~S to ~S~@
+ because it isn't already an instance with metaclass~%~S."
+ instance
+ new-class
+ 'funcallable-standard-class))
+ (change-class-internal instance new-class))
+
+(defmethod change-class ((instance t) (new-class-name symbol))
+ (change-class instance (find-class new-class-name)))
+
+
+
+;;;
+;;; The metaclass BUILT-IN-CLASS
+;;;
+;;; This metaclass is something of a weird creature. By this point, all
+;;; instances of it which will exist have been created, and no instance
+;;; is ever created by calling MAKE-INSTANCE.
+;;;
+;;; But, there are other parts of the protcol we must follow and those
+;;; definitions appear here.
+;;;
+(defmethod shared-initialize :before
+ ((class built-in-class) slot-names &rest initargs)
+ (declare (ignore slot-names initargs))
+ (error "Attempt to initialize or reinitialize a built in class."))
+
+(defmethod class-direct-slots ((class built-in-class)) ())
+(defmethod class-slots ((class built-in-class)) ())
+(defmethod class-direct-default-initargs ((class built-in-class)) ())
+(defmethod class-default-initargs ((class built-in-class)) ())
+
+(defmethod validate-superclass ((c class) (s built-in-class))
+ (eq s *the-class-t*))
+
+
+
+;;;
+;;;
+;;;
+
+(defmethod validate-superclass ((c slot-class)
+ (f forward-referenced-class))
+ 't)
+
+
+;;;
+;;;
+;;;
+
+(defmethod add-dependent ((metaobject dependent-update-mixin) dependent)
+ (pushnew dependent (plist-value metaobject 'dependents)))
+
+(defmethod remove-dependent ((metaobject dependent-update-mixin) dependent)
+ (setf (plist-value metaobject 'dependents)
+ (delete dependent (plist-value metaobject 'dependents))))
+
+(defmethod map-dependents ((metaobject dependent-update-mixin) function)
+ (dolist (dependent (plist-value metaobject 'dependents))
+ (funcall function dependent)))
+
diff --git a/gcl/pcl/test/bench-precompile.lisp b/gcl/pcl/test/bench-precompile.lisp
new file mode 100644
index 000000000..66e7042be
--- /dev/null
+++ b/gcl/pcl/test/bench-precompile.lisp
@@ -0,0 +1,3 @@
+(in-package :bench)
+#+pcl
+(pcl::precompile-random-code-segments bench)
diff --git a/gcl/pcl/test/bench.lisp b/gcl/pcl/test/bench.lisp
new file mode 100644
index 000000000..a8b73eae7
--- /dev/null
+++ b/gcl/pcl/test/bench.lisp
@@ -0,0 +1,575 @@
+;;;-*- Mode: Lisp; Syntax: Common-lisp; Package: user -*-
+
+(in-package :bench :use '(:lisp #-pcl :clos))
+
+#+(and kcl pcl)
+(eval-when (compile load eval)
+ (shadowing-import 'pcl::dotimes)
+)
+
+#+pcl
+(eval-when (compile load eval) (pcl::use-package-pcl))
+
+#-cmu
+(defmacro declaim (arg)
+ `(proclaim ',arg))
+
+;;;Here are a few homebrew benchmarks for testing out Lisp performance.
+;;; BENCH-THIS-LISP: benchmarks for common lisp.
+;;; BENCH-THIS-CLOS: benchmarks for CLOS.
+;;; BENCH-FLAVORS: ditto for Symbolics flavors.
+;;; BE SURE TO CHANGE THE PACKAGE DEFINITION TO GET THE CLOS + LISP
+;;; YOU WANT TO TEST.
+;;;
+;;;Each benchmark is reported as operations per second. Without-interrupts is
+;;; used, so the scheduler isn't supposed to get in the way. Accuracy is
+;;; generally between one and five percent.
+;;;
+;;;Elapsed time is measured using get-internal-run-time. Because the accuracy
+;;; of this number is fairly crude, it is important to use a large number of
+;;; iterations to get an accurate benchmark. The function median-time may
+;;; complain to you if you didn't pick enough iterations.
+;;;
+;;;July 1992. Watch out! In some cases the instruction being timed will be
+;;; optimized away by a clever compiler. Beware of benchmarks that are
+;;; nearly as fast as *speed-of-empty-loop*.
+;;;
+;;;Thanks to Ken Anderson for much of this code.
+;;;
+;;; jeff morrill
+;;; jmorrill@bbn.com
+
+#+Genera
+(eval-when (compile load eval)
+ (import '(clos-internals::allocate-instance)))
+
+(declaim (optimize (speed 3) (safety 1) (space 0)
+ #+lucid (compilation-speed 0)))
+
+;;;*********************************************************************
+
+(deftype positive-integer () '(integer 0 *))
+(deftype positive-fixnum () '(and fixnum positive-integer))
+
+(defun repeat (fn n)
+ (declare (type function fn) (type positive-integer n))
+ (multiple-value-bind (ngroups last)
+ (floor n most-positive-fixnum)
+ (declare (type positive-fixnum ngroups last))
+ (dotimes (i ngroups)
+ (declare (type positive-fixnum i))
+ (dotimes (j most-positive-fixnum)
+ (declare (fixnum j))
+ (funcall fn)))
+ (dotimes (j last)
+ (declare (type positive-fixnum j))
+ (funcall fn)))
+ n)
+
+;; Most compilers other than KCL have optimizers that make this technique
+;; unreliable for simple forms.
+(eval-when (compile load eval)
+(declaim (fixnum *simple-repeat-count* *simple-iteration-count*
+ *total-simple-iterations*))
+(defparameter *simple-repeat-count* #-kcl 1 #+kcl 10)
+(defparameter *simple-iteration-count* #-kcl 1 #+kcl 10)
+(defparameter *total-simple-iterations*
+ (* *simple-repeat-count* *simple-iteration-count*))
+)
+
+(defmacro simple-repeat (form)
+ (if (eql *simple-iteration-count* 1)
+ form
+ (let ((result (make-symbol "RESULT")))
+ `(let ((,result nil))
+ (dotimes (.i. ,*simple-iteration-count* ,result)
+ (declare (fixnum .i.))
+ ,@(let ((forms nil))
+ (dotimes (i *simple-repeat-count* forms)
+ (push `(setq ,result ,form) forms))))))))
+
+(defvar *use-gc-p* t)
+(defvar *estimated-bytes-per-call* 0)
+(defvar *bytes-per-word* 4)
+(declaim (type (and (integer 0 *) fixnum)
+ *bytes-per-word* *estimated-bytes-per-call*))
+
+(defmacro with-optional-gc-control (&body body)
+ `(let (#+cmu
+ (ext:*bytes-consed-between-gcs*
+ (if *use-gc-p*
+ (+ ext:*bytes-consed-between-gcs*
+ (* *estimated-bytes-per-call* n))
+ ext:*bytes-consed-between-gcs*)))
+ ,@body))
+
+(declaim (single-float *min-time* *one-percent-of-min-time*))
+
+(defvar *min-time* (max 1.0 (/ 400.0 (float internal-time-units-per-second)))
+ "At least 2 orders of magnitude larger than our time resolution.")
+
+(defparameter *one-percent-of-min-time* (* *min-time* 0.01))
+
+(defvar *elapsed-time-result*)
+
+(defun elapsed-time (function n)
+ "Returns the time (seconds) it takes to call function n times."
+ (declare (type function function) (integer n))
+ (when (and *use-gc-p* (plusp *estimated-bytes-per-call*))
+ #+cmu (lisp::gc nil))
+ (let ((start-time (get-internal-run-time)))
+ (setq *elapsed-time-result* (repeat function n))
+ (let ((end-time (get-internal-run-time)))
+ (/ (float (abs (- end-time start-time)))
+ (float internal-time-units-per-second)))))
+
+(defmacro without-interruption (&body forms)
+ #+genera `(scl:without-interrupts ,@forms)
+ #+lucid `(lcl::with-scheduling-inhibited ,@forms)
+ #+allegro `(excl:without-interrupts ,@forms)
+ #+(and (not genera) (not lucid) (not allegro)) `(progn ,@forms))
+
+(declaim (type (function (t function &optional fixnum t) single-float)
+ median-time-internal))
+
+(defvar *warn-if-too-fast-p* nil)
+
+(defun median-time-internal (form function n &optional (I 5)
+ (warn-p *warn-if-too-fast-p*))
+ "Return the median time it takes to evaluate form."
+ ;; I: number of samples to take.
+ (declare (type function function) (fixnum i))
+ (without-interruption
+ (funcall function)
+ (let ((results nil))
+ (dotimes (ignore I)
+ (declare (fixnum ignore))
+ (let ((time (elapsed-time function n)))
+ (declare (single-float time))
+ (when (and (< time *min-time*) warn-p)
+ (format t "~% Warning. Evaluating ~S took only ~S seconds.~
+ ~% You should probably use more iterations."
+ form time))
+ (push time results)))
+ (nth (truncate I 2) (sort results #'<)))))
+
+(defmacro median-time (form n &optional (I 5)
+ (warn-p *warn-if-too-fast-p*))
+ "Return the median time it takes to evaluate form n times."
+ ;; I: number of samples to take.
+ `(median-time-internal
+ ',form
+ #'(lambda () (simple-repeat ,form))
+ (ceiling ,n ,*total-simple-iterations*)
+ ,i
+ ,warn-p))
+
+#+debug
+(defun test () (median-time (sleep 1.0) 5))
+
+
+;;;*********************************************************************
+
+;;; OPERATIONS-PER-SECOND actually does the work of computing a benchmark.
+;;; The amount of time it takes to execute the form N times is recorded,
+;;; minus the time it takes to execute the empty loop. OP/S = N/time.
+;;; This quantity is recomputed five times and the median value is returned.
+;;; Variance in the numbers increases when memory is being allocated (cons,
+;;; make-instance, etc).
+
+(declaim (type (function (t function &optional fixnum integer) single-float)
+ time-form-internal))
+
+(defun time-form-internal (form function &optional (i 5) (default 100))
+ (declare (integer default) (fixnum i))
+ (with-optional-gc-control
+ (let ((time (median-time-internal form function default i nil)))
+ (declare (single-float time))
+ (loop (when (> time *one-percent-of-min-time*)
+ (return nil))
+ (setq default (* default 10))
+ (setq time (median-time-internal form function default i nil)))
+ (when (< time *min-time*)
+ (setq default (ceiling default (/ time *min-time*)))
+ (setq time (median-time-internal form function default i nil)))
+ (/ time (float default)))))
+
+(defmacro time-form (form &optional (i 5))
+ `(/ (time-form-internal ',form #'(lambda () (simple-repeat ,form)) ,i)
+ ,(float *total-simple-iterations*)))
+
+(defun compute-speed-of-empty-loop () (time-form nil))
+
+(declaim (single-float *speed-of-empty-loop*))
+(defparameter *speed-of-empty-loop* (compute-speed-of-empty-loop))
+
+(format t "~%Empty loops per second: ~40T~8,3E~%"
+ (/ 1.0 *speed-of-empty-loop*))
+
+(defmacro operations-per-second (form &optional (i 5))
+ "Return the number of times FORM can evaluate in one second."
+ `(/ 1.0 (- (time-form ,form ,i) *speed-of-empty-loop*)))
+
+(defmacro defun-timer (name args &body body)
+ `(defun ,name ,args
+ ,@body))
+
+(defmacro bench (pretty-name name)
+ `(progn
+ (format t "~%~A: " ,pretty-name) (force-output)
+ (format t "~40T~8,3E" (,name))))
+
+;;;****************************************************************************
+
+;;;BENCH-THIS-LISP
+
+;#+bench-this-lisp
+(progn
+
+(defun-timer Nmult ()
+ (let ((a 2.1))
+ (operations-per-second (* a a))))
+
+(defun-timer Nadd ()
+ (let ((a 2.1))
+ (operations-per-second (+ a a))))
+
+(defun square (x) (* x x))
+
+(defun-timer funcall-1 ()
+ ;; inlined
+ (let ((x 2.1))
+ (operations-per-second (funcall #'(lambda (a) (* a a)) x))))
+
+(defun f1 (n) n)
+
+(defun-timer funcall-2 ()
+ (let ((f #'f1)
+ (x 2.1))
+ (operations-per-second (funcall f x))))
+
+(defun-timer funcall-3 ()
+ (let ((x 2.1))
+ (operations-per-second (f1 x))))
+
+(defun-timer funcall-4 ()
+ (let ((x 2.1))
+ (operations-per-second (funcall #'square x))))
+
+(defun-timer funcall-5 ()
+ (let ((x 2.1)
+ (f #'square))
+ (let ((g #'(lambda (x)
+ (operations-per-second (funcall f x)))))
+ (funcall g x))))
+
+(defun-timer Nsetf ()
+ (let ((array (make-array 15)))
+ (operations-per-second (setf (aref array 5) t))))
+
+(defun-timer Nsymeval () (operations-per-second (eval T)))
+
+(defun-timer Repeatuations () (operations-per-second (eval '(* 2.1 2.1))))
+
+(defun-timer n-cons () (let ((a 1)) (operations-per-second (cons a a))))
+
+(defvar *object* t)
+(defun-timer nspecial () (operations-per-second (null *object*)))
+
+(defun-timer nlexical ()
+ (let ((o t))
+ (operations-per-second (null o))))
+
+(defun-timer nfree ()
+ (let ((o t))
+ (let ((g #'(lambda ()
+ #+genera (declare (sys:downward-function))
+ (operations-per-second (null o)))))
+ (funcall g))))
+
+(defun-timer nfree2 ()
+ (let ((o t))
+ (let ((g #'(lambda ()
+ (let ((f #'(lambda ()
+ #+genera (declare (sys:downward-function))
+ (operations-per-second (null o)))))
+ (funcall f)))))
+ (funcall g))))
+
+(defun-timer ncompilations ()
+ (let ((lambda-expression
+ '(lambda (bar) (let ((baz t)) (if baz (cons bar nil))))))
+ (operations-per-second (compile 'bob lambda-expression))))
+
+(defun bench-this-lisp ()
+ (bench "(* 2.1 2.1)" nmult)
+ (bench "(+ 2.1 2.1)" nadd)
+ (bench "funcall & (* 2.1 2.1)" funcall-3)
+ (bench "special reference" nspecial)
+ (bench "lexical reference" nlexical)
+ ;; (bench "ivar reference" n-ivar-ref)
+ (bench "(setf (aref array 5) t)" nsetf)
+ (bench "(funcall lexical-f x)" funcall-2)
+ (bench "(f x)" funcall-3)
+ ;; (Bench "(eval t)" nsymeval)
+ ;; (bench "(eval '(* 2.1 2.1))" repeatuations)
+ ;; (bench "(cons 1 2)" n-cons)
+ ;; (bench "compile simple function" ncompilations)
+ )
+
+;(bench-this-lisp)
+)
+
+;;;**************************************************************
+
+#+genera
+(progn
+
+(scl:defflavor bar (a b) ()
+ :initable-instance-variables
+ :writable-instance-variables)
+
+(scl:defflavor frob (c) (bar)
+ :initable-instance-variables
+ :writable-instance-variables)
+
+(scl:defmethod (hop bar) ()
+ a)
+
+(scl:defmethod (set-hop bar) ()
+ (setq a n))
+
+(scl:defmethod (nohop bar) ()
+ 5)
+
+(defun n-ivar-ref ()
+ (let ((i (scl:make-instance 'bar :a 0 :b 0)))
+ (ivar-ref i N)))
+
+(scl:defmethod (ivar-ref bar) ()
+ (operations-per-second b))
+
+
+(defun-timer Ninstances ()
+ (operations-per-second (flavor:make-instance 'bar)))
+
+(defun-timer n-svref ()
+ (let ((instance (flavor:make-instance 'bar :a 1)))
+ (operations-per-second (scl:symbol-value-in-instance instance 'a))))
+(defun-timer n-hop ()
+ (let ((instance (flavor:make-instance 'bar :a 1)))
+ (operations-per-second (hop instance))))
+(defun-timer n-gf ()
+ (let ((instance (flavor:make-instance 'bar :a 1)))
+ (operations-per-second (nohop instance))))
+(defun-timer n-set-hop ()
+ (let ((instance (flavor:make-instance 'bar :a 1)))
+ (operations-per-second (set-hop instance))))
+(defun-timer n-type-of ()
+ (let ((instance (flavor:make-instance 'bar)))
+ (operations-per-second (flavor::%instance-flavor instance))))
+
+(defun-timer n-bar-b ()
+ (let ((instance (flavor:make-instance 'bar :a 0 :b 0)))
+ (operations-per-second (bar-b instance))))
+
+(defun-timer n-frob-bar-b ()
+ (let ((instance (flavor:make-instance 'frob :a 0 :b 0)))
+ (operations-per-second (bar-b instance))))
+
+(defun bench-flavors ()
+ (bench "flavor:make-instance (2 slots)" ninstances)
+ (bench "flavor:symbol-value-in-instance" n-svref)
+ (bench "1 method, 1 dispatch" n-gf)
+ (bench "slot symbol in method (access)" n-hop)
+ (bench "slot symbol in method (modify)" n-hop)
+ (bench "slot accessor bar" n-bar-b)
+ (bench "slot accessor frob" n-frob-bar-b)
+ (bench "instance-flavor" n-type-of))
+
+) ; end of #+genera
+
+;;;**************************************************************
+
+;;;BENCH-THIS-CLOS
+;;; (evolved from Ken Anderson's tests of Symbolics CLOS)
+
+#+pcl
+(let ((*default-pathname-defaults* pcl::*pcl-directory*))
+ (load "bench-precompile"))
+
+(defmethod strange ((x t)) t) ; default method
+(defmethod area ((x number)) 'green) ; builtin class
+
+(defclass point
+ ()
+ ((x :initform 0 :accessor x :initarg :x)
+ (y :initform 0 :accessor y :initarg :y)))
+
+(defmethod color ((thing point)) 'red)
+(defmethod address ((thing point)) 'boston)
+(defmethod area ((thing point)) 0)
+(defmethod move-to ((p1 point) (p2 point)) 0)
+
+(defmethod x-offset ((thing point))
+ (with-slots (x y) thing x))
+
+(defmethod set-x-offset ((thing point) new-x)
+ (with-slots (x y) thing (setq x new-x)))
+
+(defclass box
+ (point)
+ ((width :initform 10 :accessor width :initarg :width)
+ (height :initform 10 :accessor height :initarg :height)))
+
+(defmethod area ((thing box)) 0)
+(defmethod move-to ((box box) (point point)) 0)
+(defmethod address :around ((thing box)) (call-next-method))
+
+(defvar p (make-instance 'point))
+(defvar b (make-instance 'box))
+
+(defun-timer n-strange () (operations-per-second (strange 5)))
+(defun-timer n-accesses ()
+ (operations-per-second (x p)))
+(defun-timer n-color ()
+ (operations-per-second (color p)))
+(defun-timer n-call-next-method ()
+ (let ((p b))
+ (operations-per-second (address p))))
+(defun-timer n-area-1 ()
+ (operations-per-second (area p)))
+(defun-timer n-area-2 ()
+ (operations-per-second (area 5)))
+(defun-timer n-move-1 ()
+ (operations-per-second (move-to p p)))
+(defun-timer n-move-2 ()
+ (let ((x p) (y b))
+ (operations-per-second (move-to x y))))
+(defun-timer n-off ()
+ (operations-per-second (x-offset p)))
+(defun-timer n-setoff ()
+ (operations-per-second (set-x-offset p 500)))
+(defun-timer n-slot-value ()
+ (operations-per-second (slot-value p 'x)))
+
+(defun-timer n-class-of-1 ()
+ (operations-per-second (class-of p)))
+#| ; cmucl can't compile this.
+(defun-timer n-class-of-2 ()
+ (operations-per-second (class-of 5)))
+|#
+(defvar nco2 5)
+(defun-timer n-class-of-2 ()
+ (operations-per-second (class-of nco2)))
+
+(defvar *size-of-point* (* *bytes-per-word* 8))
+
+(defun-timer n-alloc ()
+ (let ((*estimated-bytes-per-call* *size-of-point*)
+ (c (find-class 'point)))
+ (operations-per-second (allocate-instance c))))
+
+(defun-timer n-make ()
+ (let ((*estimated-bytes-per-call* *size-of-point*))
+ (operations-per-second (make-instance 'point))))
+
+(defun-timer n-make-initargs ()
+ (let ((*estimated-bytes-per-call* (+ *size-of-point*
+ (* *bytes-per-word* 4))))
+ (operations-per-second (make-instance 'point :x 0 :y 5))))
+
+(defun-timer n-make-variable-initargs ()
+ (let ((*estimated-bytes-per-call* (+ *size-of-point*
+ (* *bytes-per-word* 4)))
+ (x 0) (y 5))
+ (operations-per-second (make-instance 'point :x x :y y))))
+
+#+pcl
+(#+pcl pcl::expanding-make-instance-top-level #-pcl progn
+
+(defun-timer n-make1 ()
+ (let ((*estimated-bytes-per-call* *size-of-point*))
+ (operations-per-second (make-instance 'point))))
+
+(defun-timer n-make-initargs1 ()
+ (let ((*estimated-bytes-per-call* (+ *size-of-point*
+ (* *bytes-per-word* 4))))
+ (operations-per-second (make-instance 'point :x 0 :y 5))))
+
+(defun-timer n-make-variable-initargs1 ()
+ (let ((*estimated-bytes-per-call* (+ *size-of-point*
+ (* *bytes-per-word* 4)))
+ (x 0) (y 5))
+ (operations-per-second (make-instance 'point :x x :y y))))
+
+)
+
+#+pcl
+(defun compile-and-load-file-if-newer (file &rest other-files)
+ #-cmu (declare (ignore other-files))
+ #-cmu (load (compile-file (make-pathname :defaults file :type "lisp")))
+ #+cmu ; uses compile-file-pathname
+ (labels ((type-fwd (file &optional type)
+ (let ((path (if type
+ (make-pathname :defaults file :type type)
+ file)))
+ (if (probe-file path)
+ (file-write-date path)
+ 0)))
+ (fwd (file)
+ (max (type-fwd file "lisp")
+ (type-fwd (compile-file-pathname file)))))
+ (let ((other-fwd 0))
+ (dolist (other other-files)
+ (setq other-fwd (max other-fwd (fwd (merge-pathnames other)))))
+ (setq file (merge-pathnames file))
+ (when (< (type-fwd (compile-file-pathname file))
+ (max (type-fwd file "lisp") other-fwd))
+ (compile-file file)
+ (load file)))))
+
+#+pcl
+(let ((*default-pathname-defaults* pcl::*pcl-directory*))
+ (compile-and-load-file-if-newer "bench-precompile" "bench"))
+
+#+(and lucid (not pcl))
+(lcl::precompile-generic-functions)
+
+(defun bench-this-clos ()
+ (bench "1 default method" n-strange)
+ (bench "1 dispatch, 1 method" n-color)
+ (bench "1 dispatch, :around + primary" n-call-next-method)
+ (bench "1 dispatch, 3 methods, instance" n-area-1)
+ (bench "1 dispatch, 3 methods, noninstance" n-area-2)
+ (bench "2 dispatch, 2 methods" n-move-1)
+ (bench "slot reader method" n-accesses)
+ (bench "with-slots (1 access)" n-off)
+ (bench "with-slots (1 modify)" n-setoff)
+ (bench "naked slot-value" n-slot-value)
+ (bench "class-of instance" n-class-of-1)
+ (bench "class-of noninstance" n-class-of-2)
+ (bench "allocate-instance (2 slots)" n-alloc)
+
+ (let ((two-c-i #-pcl "make-instance (2 constant initargs)"
+ #+pcl "make-instance (2 initargs)"))
+ (let ((opt #+(and pcl (not cmu)) ""
+ #+(and pcl cmu) " (opt)"
+ #-pcl ""))
+ (flet ((c (s) (concatenate 'string s opt)))
+ (bench (c "make-instance (2 slots)") n-make)
+ (bench (c two-c-i) n-make-initargs)
+ #-pcl
+ (bench (c "make-instance (2 variable initargs)")
+ n-make-variable-initargs)))
+
+ #+(and pcl (not cmu))
+ (let ((opt " (opt)"))
+ (flet ((c (s) (concatenate 'string s opt)))
+ (bench (c "make-instance (2 slots)") n-make1)
+ (bench (c two-c-i) n-make-initargs1)
+ #-pcl
+ (bench (c "make-instance (2 variable initargs)")
+ n-make-variable-initargs1)))))
+
+(bench-this-clos)
diff --git a/gcl/pcl/test/bench.out b/gcl/pcl/test/bench.out
new file mode 100644
index 000000000..19139a386
--- /dev/null
+++ b/gcl/pcl/test/bench.out
@@ -0,0 +1,21 @@
+
+ cmucl17f cmucl17g lucid411g lucid411c
+1 default method: 1.810e+6 1.810e+6 1.250E+6 1.000E+7
+1 dispatch, 1 method: 7.394e+5 1.173e+6 9.091E+5 1.429E+6
+1 dispatch, :around + primary: 5.398e+5 6.441e+5 2.174E+5 1.093E+5
+1 dispatch, 3 methods, instance: 7.394e+5 7.130e+5 9.091E+5 1.429E+6
+1 dispatch, 3 methods, noninstance: 6.768e+5 1.023e+6 3.509E+5 1.429E+6
+2 dispatch, 2 methods: 5.890e+4 9.070e+5 4.255E+5 8.333E+5
+slot reader method: 1.533e+6 1.476e+6 1.111E+6 1.429E+6
+with-slots (1 access): 2.738e+5 4.994e+5 2.198E+5 6.452E+5
+with-slots (1 modify): 4.872e+5 5.961e+5 4.082E+5 5.882E+5
+naked slot-value: 1.215e+5 1.687e+5 6.061E+5 8.696E+5
+class-of instance: 4.938e+6 4.938e+6 3.333E+6 1.000E+7
+class-of noninstance: 1.896e+6 9.070e+5 7.407E+5 2.857E+6
+allocate-instance (2 slots): 8.867e+4 6.813e+4 2.475E+4 1.250E+5
+make-instance (2 slots) (opt): 5.798e+3 1.002e+5 2.174E+5 1.266E+5
+make-instance (2 initargs) (opt): 5.657e+3 7.206e+4 1.099E+5 1.613E+5
+make-instance (2 slots): 5.798e+3 1.002e+5 6.969E+3 1.266E+5
+make-instance (2 initargs): 5.657e+3 7.206e+4 5.249E+3 1.613E+5
+make-instance (2 variable initargs): 1.754E+5
+
diff --git a/gcl/pcl/test/list-functions.lisp b/gcl/pcl/test/list-functions.lisp
new file mode 100644
index 000000000..f4601a439
--- /dev/null
+++ b/gcl/pcl/test/list-functions.lisp
@@ -0,0 +1,141 @@
+
+(in-package :pcl)
+
+(defvar *defun-list* nil)
+(defvar *defmethod-list* nil)
+(defvar *defmacro-list* nil)
+(defvar *defgeneric-list* nil)
+
+(defun list-functions (&optional print-p)
+ (let ((eof '(eof))
+ (*package* *package*))
+ (setq *defun-list* nil
+ *defmethod-list* nil
+ *defmacro-list* nil)
+ (labels ((process-form (form)
+ (when (consp form)
+ (case (car form)
+ ((in-package export import shadow shadowing-import) (eval form))
+ #+lcl3.0 (lcl:handler-bind (eval form))
+ (let (when print-p (print form)))
+ (defun (push (list (cadr form) (caddr form))
+ *defun-list*))
+ (defmethod (push (list (cadr form) (caddr form))
+ *defmethod-list*))
+ (defmacro (push (list (cadr form) (caddr form))
+ *defmacro-list*))
+ (defgeneric (push (list (cadr form) (caddr form))
+ *defgeneric-list*))
+ (eval-when (mapc #'process-form (cddr form)))
+ (progn (mapc #'process-form (cdr form)))
+ ((defvar defparameter defconstant proclaim
+ defsetf defstruct deftype define-compiler-macro))
+ ((define-walker-template defopcode defoperand
+ define-method-combination define-constructor-code-type
+ defclass))
+ (t (when print-p (print form)))))))
+ (dolist (file (system-source-files 'pcl))
+ (with-open-file (in file :direction :input)
+ (loop (let ((form (read in nil eof)))
+ (when (eq form eof) (return nil))
+ (process-form form))))))
+ (values (length *defun-list*)
+ (length *defmethod-list*)
+ (length *defmacro-list*)
+ (length *defgeneric-list*))))
+
+(defun list-all-gfs (&key all-p (show-methods-p t) san-p (name "generic-functions"))
+ (let ((keys nil) (opt nil)
+ (gf-vector (make-array 10 :initial-element nil))
+ (readers nil) (writers nil) (cv nil)
+ (*package* *the-pcl-package*)
+ (*print-pretty* nil)
+ (s-a-n (find-package "SLOT-ACCESSOR-NAME"))
+ (lisp-sans (mapcar #'slot-reader-symbol '(function type))))
+ ;; This one has no predefined methods.
+ (defgeneric update-dependent (metaobject dependent &rest initargs))
+ (map-all-generic-functions
+ #'(lambda (gf)
+ (when (or all-p
+ (let ((name (generic-function-name gf)))
+ (when (consp name) (setq name (cadr name)))
+ (and (not (find #\: (symbol-name name)))
+ (or (eq (symbol-package name) *the-pcl-package*)
+ (and san-p
+ (memq name lisp-sans)
+ (and (eq (symbol-package name) s-a-n)
+ (string= "PCL " (symbol-name name)
+ :end2 4)))))))
+ (let ((ll (generic-function-lambda-list gf)))
+ (multiple-value-bind (nrequired noptional
+ keysp restp allow-other-keys-p keywords)
+ (analyze-lambda-list ll)
+ (cond ((use-constant-value-dfun-p gf t)
+ (push gf cv))
+ ((or keysp restp allow-other-keys-p keywords)
+ (push gf keys))
+ ((plusp noptional)
+ (push gf opt))
+ ((and (= nrequired 1)
+ (let ((m (generic-function-methods gf)))
+ (and m
+ (every #'standard-reader-method-p m))))
+ (push gf readers))
+ ((and (= nrequired 2)
+ (let ((m (generic-function-methods gf)))
+ (and m
+ (every #'standard-writer-method-p m))))
+ (push gf writers))
+ (t
+ (push gf (aref gf-vector nrequired)))))))))
+ (with-open-file (out (let* ((system (get-system 'pcl))
+ (*system-directory* (funcall (car system))))
+ (make-pathname :defaults
+ (truename (make-source-pathname "defsys"))
+ :name name))
+ :direction :output)
+ (format out ";;;-*-Mode:LISP; Package:PCL; Base:10; Syntax:Common-lisp -*-~2%")
+ (format out "(in-package :pcl)~%")
+ (flet ((print-gf-list (list)
+ (setq list
+ (sort (mapcar #'generic-function-name list)
+ #'(lambda (sym1 sym2)
+ (let* ((s1 (if (consp sym1) (cadr sym1) sym1))
+ (s2 (if (consp sym2) (cadr sym2) sym2))
+ (p1 (symbol-package s1))
+ (p2 (symbol-package s2)))
+ (if (eq p1 p2)
+ (string< (symbol-name s1) (symbol-name s2))
+ (string< (package-name p1) (package-name p2)))))))
+ (dolist (sym list)
+ (let* ((*print-case* :downcase)
+ (gf (gdefinition sym))
+ (lambda-list (generic-function-lambda-list gf)))
+ (format out "~&~S~%" `(defgeneric ,sym ,lambda-list))
+ (when show-methods-p
+ (dolist (m (generic-function-methods gf))
+ (let* ((q (method-qualifiers m))
+ (qs (if (null q)
+ ""
+ (format nil "~{~S~^ ~}" q)))
+ (s (unparse-specializers m)))
+ (format out "~&; ~7A ~S~%" qs s)))
+ (terpri out))))))
+ (when cv
+ (format out "~%;;; class predicates~%")
+ (print-gf-list cv))
+ (when readers
+ (format out "~%;;; readers~%")
+ (print-gf-list readers))
+ (when writers
+ (format out "~%;;; writers~%")
+ (print-gf-list writers))
+ (dotimes (i 10)
+ (when (aref gf-vector i)
+ (format out "~%;;; ~D argument~:P ~%" i)
+ (print-gf-list (aref gf-vector i))))
+ (format out "~%;;; optional arguments ~%")
+ (print-gf-list opt)
+ (format out "~%;;; keyword arguments ~%")
+ (print-gf-list keys))
+ (terpri out))))
diff --git a/gcl/pcl/test/make-test.lisp b/gcl/pcl/test/make-test.lisp
new file mode 100644
index 000000000..a80a006e1
--- /dev/null
+++ b/gcl/pcl/test/make-test.lisp
@@ -0,0 +1,47 @@
+(in-package :pcl)
+
+(defun top-level-form-form (form)
+ #+cmu
+ (if (and (consp form) (eq (car form) 'eval-when))
+ (third form)
+ form)
+ #+kcl
+ (fourth (third form))
+ #+lcl3.0
+ (third (third form)))
+
+(defun make-test ()
+ (let ((table (make-hash-table :test 'eq))
+ (count 0))
+ (labels ((fixup (form)
+ (if (consp form)
+ (cons (fixup (car form)) (fixup (cdr form)))
+ (if (and (symbolp form) (null (symbol-package form)))
+ (or (gethash form table)
+ (setf (gethash form table)
+ (intern (format nil "~A-%-~D" (symbol-name form)
+ (incf count))
+ *the-pcl-package*)))
+ form))))
+ (with-open-file (out "test.lisp"
+ :direction :output :if-exists :supersede)
+ (declare (type stream out))
+ (let ((*print-case* :downcase)
+ (*print-pretty* t)
+ (*package* *the-pcl-package*))
+ (format out "~S~%" '(in-package :pcl))
+ (let ((i 0)
+ (f (macroexpand '(PRECOMPILE-FUNCTION-GENERATORS PCL))))
+ (dolist (form (cdr (top-level-form-form f)))
+ (let ((name (intern (format nil "FGEN-~D" (incf i)))))
+ (format out "~S~%" `(defun ,name () ,(fixup form))))))
+ (let ((i 0)
+ (f (macroexpand '(PRECOMPILE-DFUN-CONSTRUCTORS PCL))))
+ (dolist (form (cdr f))
+ (let ((name (intern (format nil "DFUN-CONSTR-~D" (incf i))))
+ (form (top-level-form-form form)))
+ (format out "~S~%" `(defun ,name ()
+ (list ,(second form)
+ ,(third form)
+ ,(fixup (macroexpand (fifth form))))))))))))))
+
diff --git a/gcl/pcl/test/makediff b/gcl/pcl/test/makediff
new file mode 100644
index 000000000..19e46b273
--- /dev/null
+++ b/gcl/pcl/test/makediff
Binary files differ
diff --git a/gcl/pcl/test/time.lisp b/gcl/pcl/test/time.lisp
new file mode 100644
index 000000000..06aefc4ca
--- /dev/null
+++ b/gcl/pcl/test/time.lisp
@@ -0,0 +1,156 @@
+(in-package "PCL")
+
+(proclaim '(optimize (speed 3)(safety 0)(compilation-speed 0)))
+
+(defvar *tests*)
+(setq *tests* nil)
+
+(defvar m (car (generic-function-methods #'shared-initialize)))
+(defvar gf #'shared-initialize)
+(defvar c (find-class 'standard-class))
+
+(defclass str ()
+ ((slot :initform nil :reader str-slot))
+ (:metaclass structure-class))
+
+(defvar str (make-instance 'str))
+
+
+(push (cons "Time unoptimized slot-value. This is case (1) from notes.text. (standard)"
+ '(time-slot-value m 'plist 10000))
+ *tests*)
+(push (cons "Time unoptimized slot-value. This is case (1) from notes.text. (standard)"
+ '(time-slot-value m 'generic-function 10000))
+ *tests*)
+(push (cons "Time unoptimized slot-value. This is case (1) from notes.text. (structure)"
+ '(time-slot-value str 'slot 10000))
+ *tests*)
+(defun time-slot-value (object slot-name n)
+ (time (dotimes (i n) (slot-value object slot-name))))
+
+
+(push (cons "Time optimized slot-value outside of a defmethod. Case (2). (standard)"
+ '(time-slot-value-function m 10000))
+ *tests*)
+(defun time-slot-value-function (object n)
+ (time (dotimes (i n) (slot-value object 'function))))
+
+
+(push (cons "Time optimized slot-value outside of a defmethod. Case (2). (structure)"
+ '(time-slot-value-slot str 10000))
+ *tests*)
+(defun time-slot-value-slot (object n)
+ (time (dotimes (i n) (slot-value object 'slot))))
+
+
+(push (cons "Time one-class dfun."
+ '(time-generic-function-methods gf 10000))
+ *tests*)
+(defun time-generic-function-methods (object n)
+ (time (dotimes (i n) (generic-function-methods object))))
+
+
+(push (cons "Time one-index dfun."
+ '(time-class-precedence-list c 10000))
+ *tests*)
+(defun time-class-precedence-list (object n)
+ (time (dotimes (i n) (class-precedence-list object))))
+
+
+(push (cons "Time n-n dfun."
+ '(time-method-function m 10000))
+ *tests*)
+(defun time-method-function (object n)
+ (time (dotimes (i n) (method-function object))))
+
+
+(push (cons "Time caching dfun."
+ '(time-class-slots c 10000))
+ *tests*)
+(defun time-class-slots (object n)
+ (time (dotimes (i n) (class-slots object))))
+
+
+(push (cons "Time typep for classes."
+ '(time-typep-standard-object m 10000))
+ *tests*)
+(defun time-typep-standard-object (object n)
+ (time (dotimes (i n) (typep object 'standard-object))))
+
+
+(push (cons "Time default-initargs."
+ '(time-default-initargs (find-class 'plist-mixin) 1000))
+ *tests*)
+(defun time-default-initargs (class n)
+ (time (dotimes (i n) (default-initargs class nil))))
+
+
+(push (cons "Time make-instance."
+ '(time-make-instance (find-class 'plist-mixin) 1000))
+ *tests*)
+(defun time-make-instance (class n)
+ (time (dotimes (i n) (make-instance class))))
+
+(push (cons "Time constant-keys make-instance."
+ '(time-constant-keys-make-instance 1000))
+ *tests*)
+
+(expanding-make-instance-top-level
+(defun constant-keys-make-instance (n)
+ (dotimes (i n) (make-instance 'plist-mixin))))
+
+(precompile-random-code-segments)
+
+(defun time-constant-keys-make-instance (n)
+ (time (constant-keys-make-instance n)))
+
+(defun expand-all-macros (form)
+ (walk-form form nil #'(lambda (form context env)
+ (if (and (eq context :eval)
+ (consp form)
+ (symbolp (car form))
+ (not (special-form-p (car form)))
+ (macro-function (car form)))
+ (values (macroexpand form env))
+ form))))
+
+(push (cons "Macroexpand meth-structure-slot-value"
+ '(pprint (multiple-value-bind (pgf pm)
+ (prototypes-for-make-method-lambda
+ 'meth-structure-slot-value)
+ (expand-defmethod
+ 'meth-structure-slot-value pgf pm
+ nil '((object str))
+ '(#'(lambda () (slot-value object 'slot)))
+ nil))))
+ *tests*)
+
+#-kcl
+(push (cons "Show code for slot-value inside a defmethod for a structure-class. Case (3)."
+ '(disassemble (meth-structure-slot-value str)))
+ *tests*)
+(defmethod meth-structure-slot-value ((object str))
+ #'(lambda () (slot-value object 'slot)))
+
+
+#|| ; interesting, but long. (produces 100 lines of output)
+(push (cons "Macroexpand meth-standard-slot-value"
+ '(pprint (expand-all-macros
+ (expand-defmethod-internal 'meth-standard-slot-value
+ nil '((object standard-method))
+ '(#'(lambda () (slot-value object 'function)))
+ nil))))
+ *tests*)
+(push (cons "Show code for slot-value inside a defmethod for a standard-class. Case (4)."
+ '(disassemble (meth-standard-slot-value m)))
+ *tests*)
+(defmethod meth-standard-slot-value ((object standard-method))
+ #'(lambda () (slot-value object 'function)))
+||#
+
+
+(defun do-tests ()
+ (dolist (doc+form (reverse *tests*))
+ (format t "~&~%~A~%" (car doc+form))
+ (pprint (cdr doc+form))
+ (eval (cdr doc+form))))
diff --git a/gcl/pcl/vector.lisp b/gcl/pcl/vector.lisp
new file mode 100644
index 000000000..bdaae6681
--- /dev/null
+++ b/gcl/pcl/vector.lisp
@@ -0,0 +1,1104 @@
+;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; Permutation vectors.
+;;;
+
+(in-package :pcl)
+
+(defmacro instance-slot-index (wrapper slot-name)
+ `(let ((pos 0))
+ (declare (fixnum pos))
+ (block loop
+ (dolist (sn (wrapper-instance-slots-layout ,wrapper))
+ (when (eq ,slot-name sn) (return-from loop pos))
+ (incf pos)))))
+
+
+;;;
+;;;
+;;;
+(defun pv-cache-limit-fn (nlines)
+ (default-limit-fn nlines))
+
+(defstruct (pv-table
+ (:predicate pv-tablep)
+ (:constructor make-pv-table-internal
+ (slot-name-lists call-list)))
+ (cache nil :type (or cache null))
+ (pv-size 0 :type fixnum)
+ (slot-name-lists nil :type list)
+ (call-list nil :type list))
+
+#+cmu
+(declaim (ext:freeze-type pv-table))
+
+(defvar *initial-pv-table* (make-pv-table-internal nil nil))
+
+; help new slot-value-using-class methods affect fast iv access
+(defvar *all-pv-table-list* nil)
+
+(defun make-pv-table (&key slot-name-lists call-list)
+ (let ((pv-table (make-pv-table-internal slot-name-lists call-list)))
+ (push pv-table *all-pv-table-list*)
+ pv-table))
+
+(defun make-pv-table-type-declaration (var)
+ `(type pv-table ,var))
+
+(defvar *slot-name-lists-inner* (make-hash-table :test #'equal))
+(defvar *slot-name-lists-outer* (make-hash-table :test #'equal))
+
+;entries in this are lists of (table . pv-offset-list)
+(defvar *pv-key-to-pv-table-table* (make-hash-table :test 'equal))
+
+(defun intern-pv-table (&key slot-name-lists call-list)
+ (let ((new-p nil))
+ (flet ((inner (x)
+ (or (gethash x *slot-name-lists-inner*)
+ (setf (gethash x *slot-name-lists-inner*) (copy-list x))))
+ (outer (x)
+ (or (gethash x *slot-name-lists-outer*)
+ (setf (gethash x *slot-name-lists-outer*)
+ (let ((snl (copy-list (cdr x)))
+ (cl (car x)))
+ (setq new-p t)
+ (make-pv-table :slot-name-lists snl
+ :call-list cl))))))
+ (let ((pv-table (outer (mapcar #'inner (cons call-list slot-name-lists)))))
+ (when new-p
+ (let ((pv-index 1))
+ (declare (fixnum pv-index))
+ (dolist (slot-name-list slot-name-lists)
+ (dolist (slot-name (cdr slot-name-list))
+ (note-pv-table-reference slot-name pv-index pv-table)
+ (incf pv-index)))
+ (dolist (gf-call call-list)
+ (note-pv-table-reference gf-call pv-index pv-table)
+ (incf pv-index))
+ (setf (pv-table-pv-size pv-table) pv-index)))
+ pv-table))))
+
+(defun note-pv-table-reference (ref pv-offset pv-table)
+ (let ((entry (gethash ref *pv-key-to-pv-table-table*)))
+ (when (listp entry)
+ (let ((table-entry (assq pv-table entry)))
+ (when (and (null table-entry)
+ (> (length entry) 8))
+ (let ((new-table-table (make-hash-table :size 16 :test 'eq)))
+ (dolist (table-entry entry)
+ (setf (gethash (car table-entry) new-table-table)
+ (cdr table-entry)))
+ (setf (gethash ref *pv-key-to-pv-table-table*) new-table-table)))
+ (when (listp entry)
+ (if (null table-entry)
+ (let ((new (cons pv-table pv-offset)))
+ (if (consp entry)
+ (push new (cdr entry))
+ (setf (gethash ref *pv-key-to-pv-table-table*) (list new))))
+ (push pv-offset (cdr table-entry)))
+ (return-from note-pv-table-reference nil))))
+ (let ((list (gethash pv-table entry)))
+ (if (consp list)
+ (push pv-offset (cdr list))
+ (setf (gethash pv-table entry) (list pv-offset)))))
+ nil)
+
+(defun map-pv-table-references-of (ref function)
+ (let ((entry (gethash ref *pv-key-to-pv-table-table*)))
+ (if (listp entry)
+ (dolist (table+pv-offset-list entry)
+ (funcall function
+ (car table+pv-offset-list) (cdr table+pv-offset-list)))
+ (maphash function entry)))
+ ref)
+
+
+(defvar *pvs* (make-hash-table :test #'equal))
+
+(defun optimize-slot-value-by-class-p (class slot-name type)
+ (or (not (eq *boot-state* 'complete))
+ (let ((slotd (find-slot-definition class slot-name)))
+ (and slotd
+ (slot-accessor-std-p slotd type)))))
+
+(defun compute-pv-slot (slot-name wrapper class class-slots class-slot-p-cell)
+ (if (symbolp slot-name)
+ (when (optimize-slot-value-by-class-p class slot-name 'all)
+ (or (instance-slot-index wrapper slot-name)
+ (let ((cell (assq slot-name class-slots)))
+ (when cell
+ (setf (car class-slot-p-cell) t)
+ cell))))
+ (when (consp slot-name)
+ (dolist (type '(reader writer) nil)
+ (when (eq (car slot-name) type)
+ (return
+ (let* ((gf-name (cadr slot-name))
+ (gf (gdefinition gf-name))
+ (location
+ (when (eq *boot-state* 'complete)
+ (accessor-values1 gf type class))))
+ (when (consp location)
+ (setf (car class-slot-p-cell) t))
+ location)))))))
+
+(defun compute-pv (slot-name-lists wrappers)
+ (unless (listp wrappers) (setq wrappers (list wrappers)))
+ (let* ((not-simple-p-cell (list nil))
+ (elements
+ (gathering1 (collecting)
+ (iterate ((slot-names (list-elements slot-name-lists)))
+ (when slot-names
+ (let* ((wrapper (pop wrappers))
+ (std-p #+cmu17 (typep wrapper 'wrapper)
+ #-cmu17 t)
+ (class (wrapper-class* wrapper))
+ (class-slots (and std-p (wrapper-class-slots wrapper))))
+ (dolist (slot-name (cdr slot-names))
+ (gather1
+ (when std-p
+ (compute-pv-slot slot-name wrapper class
+ class-slots not-simple-p-cell))))))))))
+ (if (car not-simple-p-cell)
+ (make-permutation-vector (cons t elements))
+ (or (gethash elements *pvs*)
+ (setf (gethash elements *pvs*)
+ (make-permutation-vector (cons nil elements)))))))
+
+(defun compute-calls (call-list wrappers)
+ (declare (ignore call-list wrappers))
+ #||
+ (map 'vector
+ #'(lambda (call)
+ (compute-emf-from-wrappers call wrappers))
+ call-list)
+ ||#
+ '#())
+
+#|| ; Need to finish this, then write the maintenance functions.
+(defun compute-emf-from-wrappers (call wrappers)
+ (when call
+ (destructuring-bind (gf-name nreq restp arg-info) call
+ (if (eq gf-name 'make-instance)
+ (error "should not get here") ; there is another mechanism for this.
+ #'(lambda (&rest args)
+ (if (not (eq *boot-state* 'complete))
+ (apply (gdefinition gf-name) args)
+ (let* ((gf (gdefinition gf-name))
+ (arg-info (arg-info-reader gf))
+ (classes '?)
+ (types '?)
+ (emf (cache-miss-values-internal gf arg-info
+ wrappers classes types
+ 'caching)))
+ (update-all-pv-tables call wrappers emf)
+ #+copy-&rest-arg (setq args (copy-list args))
+ (invoke-emf emf args))))))))
+||#
+
+(defun make-permutation-vector (indexes)
+ (make-array (length indexes) :initial-contents indexes))
+
+(defun pv-table-lookup (pv-table pv-wrappers)
+ (let* ((slot-name-lists (pv-table-slot-name-lists pv-table))
+ (call-list (pv-table-call-list pv-table))
+ (cache (or (pv-table-cache pv-table)
+ (setf (pv-table-cache pv-table)
+ (get-cache (- (length slot-name-lists)
+ (count nil slot-name-lists))
+ t
+ #'pv-cache-limit-fn
+ 2)))))
+ (or (probe-cache cache pv-wrappers)
+ (let* ((pv (compute-pv slot-name-lists pv-wrappers))
+ (calls (compute-calls call-list pv-wrappers))
+ (pv-cell (cons pv calls))
+ (new-cache (fill-cache cache pv-wrappers pv-cell)))
+ (unless (eq new-cache cache)
+ (setf (pv-table-cache pv-table) new-cache)
+ (free-cache cache))
+ pv-cell))))
+
+(defun make-pv-type-declaration (var)
+ `(type simple-vector ,var))
+
+(defvar *empty-pv* #())
+
+(defmacro pvref (pv index)
+ `(svref ,pv ,index))
+
+(defmacro copy-pv (pv)
+ `(copy-seq ,pv))
+
+(defun make-calls-type-declaration (var)
+ `(type simple-vector ,var))
+
+(defmacro callsref (calls index)
+ `(svref ,calls ,index))
+
+(defvar *pv-table-cache-update-info* nil)
+
+;called by:
+;(method shared-initialize :after (structure-class t))
+;update-slots
+(defun update-pv-table-cache-info (class)
+ (let ((slot-names-for-pv-table-update nil)
+ (new-icui nil))
+ (dolist (icu *pv-table-cache-update-info*)
+ (if (eq (car icu) class)
+ (pushnew (cdr icu) slot-names-for-pv-table-update)
+ (push icu new-icui)))
+ (setq *pv-table-cache-update-info* new-icui)
+ (when slot-names-for-pv-table-update
+ (update-all-pv-table-caches class slot-names-for-pv-table-update))))
+
+(defun update-all-pv-table-caches (class slot-names)
+ (let* ((cwrapper (class-wrapper class))
+ (std-p #+cmu17 (typep cwrapper 'wrapper) #-cmu17 t)
+ (class-slots (and std-p (wrapper-class-slots cwrapper)))
+ (class-slot-p-cell (list nil))
+ (new-values (mapcar #'(lambda (slot-name)
+ (cons slot-name
+ (when std-p
+ (compute-pv-slot
+ slot-name cwrapper class
+ class-slots class-slot-p-cell))))
+ slot-names))
+ (pv-tables nil))
+ (dolist (slot-name slot-names)
+ (map-pv-table-references-of
+ slot-name
+ #'(lambda (pv-table pv-offset-list)
+ (declare (ignore pv-offset-list))
+ (pushnew pv-table pv-tables))))
+ (dolist (pv-table pv-tables)
+ (let* ((cache (pv-table-cache pv-table))
+ (slot-name-lists (pv-table-slot-name-lists pv-table))
+ (pv-size (pv-table-pv-size pv-table))
+ (pv-map (make-array pv-size :initial-element nil)))
+ (let ((map-index 1)(param-index 0))
+ (declare (fixnum map-index param-index))
+ (dolist (slot-name-list slot-name-lists)
+ (dolist (slot-name (cdr slot-name-list))
+ (let ((a (assoc slot-name new-values)))
+ (setf (svref pv-map map-index)
+ (and a (cons param-index (cdr a)))))
+ (incf map-index))
+ (incf param-index)))
+ (when cache
+ (map-cache #'(lambda (wrappers pv-cell)
+ (setf (car pv-cell)
+ (update-slots-in-pv wrappers (car pv-cell)
+ cwrapper pv-size pv-map)))
+ cache))))))
+
+(defun update-slots-in-pv (wrappers pv cwrapper pv-size pv-map)
+ (if (not (if (atom wrappers)
+ (eq cwrapper wrappers)
+ (dolist (wrapper wrappers nil)
+ (when (eq wrapper cwrapper)
+ (return t)))))
+ pv
+ (let* ((old-intern-p (listp (pvref pv 0)))
+ (new-pv (if old-intern-p
+ (copy-pv pv)
+ pv))
+ (new-intern-p t))
+ (if (atom wrappers)
+ (dotimes (i pv-size)
+ (when (consp (let ((map (svref pv-map i)))
+ (if map
+ (setf (pvref new-pv i) (cdr map))
+ (pvref new-pv i))))
+ (setq new-intern-p nil)))
+ (let ((param 0))
+ (declare (fixnum param))
+ (dolist (wrapper wrappers)
+ (when (eq wrapper cwrapper)
+ (dotimes (i pv-size)
+ (when (consp (let ((map (svref pv-map i)))
+ (if (and map (= (car map) param))
+ (setf (pvref new-pv i) (cdr map))
+ (pvref new-pv i))))
+ (setq new-intern-p nil))))
+ (incf param))))
+ (when new-intern-p
+ (setq new-pv (let ((list-pv (coerce pv 'list)))
+ (or (gethash (cdr list-pv) *pvs*)
+ (setf (gethash (cdr list-pv) *pvs*)
+ (if old-intern-p
+ new-pv
+ (make-permutation-vector list-pv)))))))
+ new-pv)))
+
+
+(defun maybe-expand-accessor-form (form required-parameters slots env)
+ (let* ((fname (car form))
+ #||(len (length form))||#
+ (gf (if (symbolp fname)
+ (unencapsulated-fdefinition fname)
+ (gdefinition fname))))
+ (macrolet ((maybe-optimize-reader ()
+ `(let ((parameter
+ (can-optimize-access1 (cadr form)
+ required-parameters env)))
+ (when parameter
+ (optimize-reader slots parameter gf-name form))))
+ (maybe-optimize-writer ()
+ `(let ((parameter
+ (can-optimize-access1 (caddr form)
+ required-parameters env)))
+ (when parameter
+ (optimize-writer slots parameter gf-name form)))))
+ (unless (and (consp (cadr form))
+ (eq 'instance-accessor-parameter (caadr form)))
+ (or #||
+ (cond ((and (= len 2) (symbolp fname))
+ (let ((gf-name (gethash fname *gf-declared-reader-table*)))
+ (when gf-name
+ (maybe-optimize-reader))))
+ ((= len 3)
+ (let ((gf-name (gethash fname *gf-declared-writer-table*)))
+ (when gf-name
+ (maybe-optimize-writer)))))
+ ||#
+ (when (and (eq *boot-state* 'complete)
+ (generic-function-p gf))
+ (let ((methods (generic-function-methods gf)))
+ (when methods
+ (let* ((gf-name (generic-function-name gf))
+ (arg-info (gf-arg-info gf))
+ (metatypes (arg-info-metatypes arg-info))
+ (nreq (length metatypes))
+ (applyp (arg-info-applyp arg-info)))
+ (when (null applyp)
+ (cond ((= nreq 1)
+ (when (some #'standard-reader-method-p methods)
+ (maybe-optimize-reader)))
+ ((and (= nreq 2)
+ (consp gf-name)
+ (eq (car gf-name) 'setf))
+ (when (some #'standard-writer-method-p methods)
+ (maybe-optimize-writer))))))))))))))
+
+(defun optimize-generic-function-call (form required-parameters env slots calls)
+ (declare (ignore required-parameters env slots calls))
+ (or (and (eq (car form) 'make-instance)
+ (expand-make-instance-form form))
+ #||
+ (maybe-expand-accessor-form form required-parameters slots env)
+ (let* ((fname (car form))
+ (len (length form))
+ (gf (if (symbolp fname)
+ (and (fboundp fname)
+ (unencapsulated-fdefinition fname))
+ (and (gboundp fname)
+ (gdefinition fname))))
+ (gf-name (and (fsc-instance-p gf)
+ (if (early-gf-p gf)
+ (early-gf-name gf)
+ (generic-function-name gf)))))
+ (when gf-name
+ (multiple-value-bind (nreq restp)
+ (get-generic-function-info gf)
+ (optimize-gf-call slots calls form nreq restp env))))
+ ||#
+ form))
+
+
+
+(defun can-optimize-access (form required-parameters env)
+ (let ((type (ecase (car form)
+ (slot-value 'reader)
+ (set-slot-value 'writer)
+ (slot-boundp 'boundp)))
+ (var (cadr form))
+ (slot-name (eval (caddr form)))) ; known to be constant
+ (can-optimize-access1 var required-parameters env type slot-name)))
+
+(defun can-optimize-access1 (var required-parameters env &optional type slot-name)
+ (when (and (consp var) (eq 'the (car var)))
+ (setq var (caddr var)))
+ (when (symbolp var)
+ (let* ((rebound? (caddr (variable-declaration 'variable-rebinding var env)))
+ (parameter-or-nil (car (memq (or rebound? var) required-parameters))))
+ (when parameter-or-nil
+ (let* ((class-name (caddr (variable-declaration
+ 'class parameter-or-nil env)))
+ (class (find-class class-name nil)))
+ (when (or (not (eq *boot-state* 'complete))
+ (and class (not (class-finalized-p class))))
+ (setq class nil))
+ (when (and class-name (not (eq class-name 't)))
+ (when (or (null type)
+ (not (and class
+ (memq *the-class-structure-object*
+ (class-precedence-list class))))
+ (optimize-slot-value-by-class-p class slot-name type))
+ (cons parameter-or-nil (or class class-name)))))))))
+
+(defun optimize-slot-value (slots sparameter form)
+ (if sparameter
+ (destructuring-bind (ignore ignore slot-name-form) form
+ (let ((slot-name (eval slot-name-form)))
+ (optimize-instance-access slots :read sparameter slot-name nil)))
+ `(accessor-slot-value ,@(cdr form))))
+
+(defun optimize-set-slot-value (slots sparameter form)
+ (if sparameter
+ (destructuring-bind (ignore ignore slot-name-form new-value) form
+ (let ((slot-name (eval slot-name-form)))
+ (optimize-instance-access slots :write sparameter slot-name new-value)))
+ `(accessor-set-slot-value ,@(cdr form))))
+
+(defun optimize-slot-boundp (slots sparameter form)
+ (if sparameter
+ (destructuring-bind (ignore ignore slot-name-form new-value) form
+ (let ((slot-name (eval slot-name-form)))
+ (optimize-instance-access slots :boundp sparameter slot-name new-value)))
+ `(accessor-slot-boundp ,@(cdr form))))
+
+(defun optimize-reader (slots sparameter gf-name form)
+ (if sparameter
+ (optimize-accessor-call slots :read sparameter gf-name nil)
+ form))
+
+(defun optimize-writer (slots sparameter gf-name form)
+ (if sparameter
+ (destructuring-bind (ignore ignore new-value) form
+ (optimize-accessor-call slots :write sparameter gf-name new-value))
+ form))
+;;;
+;;; The <slots> argument is an alist, the CAR of each entry is the name of
+;;; a required parameter to the function. The alist is in order, so the
+;;; position of an entry in the alist corresponds to the argument's position
+;;; in the lambda list.
+;;;
+(defun optimize-instance-access (slots read/write sparameter slot-name new-value)
+ (let ((class (if (consp sparameter) (cdr sparameter) *the-class-t*))
+ (parameter (if (consp sparameter) (car sparameter) sparameter)))
+ (if (and (eq *boot-state* 'complete)
+ (classp class)
+ (memq *the-class-structure-object* (class-precedence-list class)))
+ (let ((slotd (find-slot-definition class slot-name)))
+ (ecase read/write
+ (:read
+ `(,(slot-definition-defstruct-accessor-symbol slotd) ,parameter))
+ (:write
+ `(setf (,(slot-definition-defstruct-accessor-symbol slotd) ,parameter)
+ ,new-value))
+ (:boundp
+ 'T)))
+ (let* ((parameter-entry (assq parameter slots))
+ (slot-entry (assq slot-name (cdr parameter-entry)))
+ (position (posq parameter-entry slots))
+ (pv-offset-form (list 'pv-offset ''.PV-OFFSET.)))
+ (unless parameter-entry
+ (error "Internal error in slot optimization."))
+ (unless slot-entry
+ (setq slot-entry (list slot-name))
+ (push slot-entry (cdr parameter-entry)))
+ (push pv-offset-form (cdr slot-entry))
+ (ecase read/write
+ (:read
+ `(instance-read ,pv-offset-form ,parameter ,position
+ ',slot-name ',class))
+ (:write
+ `(let ((.new-value. ,new-value))
+ (instance-write ,pv-offset-form ,parameter ,position
+ ',slot-name ',class .new-value.)))
+ (:boundp
+ `(instance-boundp ,pv-offset-form ,parameter ,position
+ ',slot-name ',class)))))))
+
+(defun optimize-accessor-call (slots read/write sparameter gf-name new-value)
+ (let* ((class (if (consp sparameter) (cdr sparameter) *the-class-t*))
+ (parameter (if (consp sparameter) (car sparameter) sparameter))
+ (parameter-entry (assq parameter slots))
+ (name (case read/write
+ (:read `(reader ,gf-name))
+ (:write `(writer ,gf-name))))
+ (slot-entry (assoc name (cdr parameter-entry) :test #'equal))
+ (position (posq parameter-entry slots))
+ (pv-offset-form (list 'pv-offset ''.PV-OFFSET.)))
+ (unless parameter-entry
+ (error "Internal error in slot optimization."))
+ (unless slot-entry
+ (setq slot-entry (list name))
+ (push slot-entry (cdr parameter-entry)))
+ (push pv-offset-form (cdr slot-entry))
+ (ecase read/write
+ (:read
+ `(instance-reader ,pv-offset-form ,parameter ,position ,gf-name ',class))
+ (:write
+ `(let ((.new-value. ,new-value))
+ (instance-writer ,pv-offset-form ,parameter ,position ,gf-name ',class
+ .new-value.))))))
+
+(defvar *unspecific-arg* '..unspecific-arg..)
+
+(defun optimize-gf-call-internal (form slots env)
+ (when (and (consp form)
+ (eq (car form) 'the))
+ (setq form (caddr form)))
+ (or (and (symbolp form)
+ (let* ((rebound? (caddr (variable-declaration 'variable-rebinding
+ form env)))
+ (parameter-or-nil (car (assq (or rebound? form) slots))))
+ (when parameter-or-nil
+ (let* ((class-name (caddr (variable-declaration
+ 'class parameter-or-nil env))))
+ (when (and class-name (not (eq class-name 't)))
+ (position parameter-or-nil slots :key #'car))))))
+ (if (constantp form)
+ (let ((form (eval form)))
+ (if (symbolp form)
+ form
+ *unspecific-arg*))
+ *unspecific-arg*)))
+
+(defun optimize-gf-call (slots calls gf-call-form nreq restp env)
+ (unless (eq (car gf-call-form) 'make-instance) ; needs more work
+ (let* ((args (cdr gf-call-form))
+ (all-args-p (eq (car gf-call-form) 'make-instance))
+ (non-required-args (nthcdr nreq args))
+ (required-args (ldiff args non-required-args))
+ (call-spec (list (car gf-call-form) nreq restp
+ (mapcar #'(lambda (form)
+ (optimize-gf-call-internal form slots env))
+ (if all-args-p
+ args
+ required-args))))
+ (call-entry (assoc call-spec calls :test #'equal))
+ (pv-offset-form (list 'pv-offset ''.PV-OFFSET.)))
+ (unless (some #'integerp
+ (let ((spec-args (cdr call-spec)))
+ (if all-args-p
+ (ldiff spec-args (nthcdr nreq spec-args))
+ spec-args)))
+ (return-from optimize-gf-call nil))
+ (unless call-entry
+ (setq call-entry (list call-spec))
+ (push call-entry (cdr calls)))
+ (push pv-offset-form (cdr call-entry))
+ (if (eq (car call-spec) 'make-instance)
+ `(funcall (pv-ref .pv. ,pv-offset-form) ,@(cdr gf-call-form))
+ `(let ((.emf. (pv-ref .pv. ,pv-offset-form)))
+ (invoke-effective-method-function .emf. ,restp
+ ,@required-args ,@(when restp `((list ,@non-required-args)))))))))
+
+
+(define-walker-template pv-offset) ; These forms get munged by mutate slots.
+(defmacro pv-offset (arg) arg)
+(define-walker-template instance-accessor-parameter)
+(defmacro instance-accessor-parameter (x) x)
+
+;; It is safe for these two functions to be wrong.
+;; They just try to guess what the most likely case will be.
+(defun generate-fast-class-slot-access-p (class-form slot-name-form)
+ (let ((class (and (constantp class-form) (eval class-form)))
+ (slot-name (and (constantp slot-name-form) (eval slot-name-form))))
+ (and (eq *boot-state* 'complete)
+ (standard-class-p class)
+ (not (eq class *the-class-t*)) ; shouldn't happen, though.
+ (let ((slotd (find-slot-definition class slot-name)))
+ (and slotd (classp (slot-definition-allocation slotd)))))))
+
+(defun skip-fast-slot-access-p (class-form slot-name-form type)
+ (let ((class (and (constantp class-form) (eval class-form)))
+ (slot-name (and (constantp slot-name-form) (eval slot-name-form))))
+ (and (eq *boot-state* 'complete)
+ (standard-class-p class)
+ (not (eq class *the-class-t*)) ; shouldn't happen, though.
+ (let ((slotd (find-slot-definition class slot-name)))
+ (and slotd (skip-optimize-slot-value-by-class-p class slot-name type))))))
+
+(defun skip-optimize-slot-value-by-class-p (class slot-name type)
+ (let ((slotd (find-slot-definition class slot-name)))
+ (and slotd
+ (eq *boot-state* 'complete)
+ (not (slot-accessor-std-p slotd type)))))
+
+(defmacro instance-read-internal (pv slots pv-offset default &optional type)
+ (unless (member type '(nil :instance :class :default))
+ (error "Illegal type argument to ~S: ~S" 'instance-read-internal type))
+ (if (eq type ':default)
+ default
+ (let* ((index (gensym))
+ (value index))
+ `(locally (declare #.*optimize-speed*)
+ (let ((,index (pvref ,pv ,pv-offset)))
+ (setq ,value (typecase ,index
+ ,@(when (or (null type) (eq type ':instance))
+ `((fixnum (%instance-ref ,slots ,index))))
+ ,@(when (or (null type) (eq type ':class))
+ `((cons (cdr ,index))))
+ (t ',*slot-unbound*)))
+ (if (eq ,value ',*slot-unbound*)
+ ,default
+ ,value))))))
+
+(defmacro instance-read (pv-offset parameter position slot-name class)
+ (if (skip-fast-slot-access-p class slot-name 'reader)
+ `(accessor-slot-value ,parameter ,slot-name)
+ `(instance-read-internal .pv. ,(slot-vector-symbol position)
+ ,pv-offset (accessor-slot-value ,parameter ,slot-name)
+ ,(if (generate-fast-class-slot-access-p class slot-name)
+ ':class ':instance))))
+
+(defmacro instance-reader (pv-offset parameter position gf-name class)
+ (declare (ignore class))
+ `(instance-read-internal .pv. ,(slot-vector-symbol position)
+ ,pv-offset
+ (,gf-name (instance-accessor-parameter ,parameter))
+ :instance))
+
+(defmacro instance-write-internal (pv slots pv-offset new-value default
+ &optional type)
+ (unless (member type '(nil :instance :class :default))
+ (error "Illegal type argument to ~S: ~S" 'instance-write-internal type))
+ (if (eq type ':default)
+ default
+ (let* ((index (gensym)))
+ `(locally (declare #.*optimize-speed*)
+ (let ((,index (pvref ,pv ,pv-offset)))
+ (typecase ,index
+ ,@(when (or (null type) (eq type ':instance))
+ `((fixnum (setf (%instance-ref ,slots ,index) ,new-value))))
+ ,@(when (or (null type) (eq type ':class))
+ `((cons (setf (cdr ,index) ,new-value))))
+ (t ,default)))))))
+
+(defmacro instance-write (pv-offset parameter position slot-name class new-value)
+ (if (skip-fast-slot-access-p class slot-name 'writer)
+ `(accessor-set-slot-value ,parameter ,slot-name ,new-value)
+ `(instance-write-internal .pv. ,(slot-vector-symbol position)
+ ,pv-offset ,new-value
+ (accessor-set-slot-value ,parameter ,slot-name ,new-value)
+ ,(if (generate-fast-class-slot-access-p class slot-name)
+ ':class ':instance))))
+
+(defmacro instance-writer (pv-offset parameter position gf-name class new-value)
+ (declare (ignore class))
+ `(instance-write-internal .pv. ,(slot-vector-symbol position)
+ ,pv-offset ,new-value
+ (,(if (consp gf-name)
+ (get-setf-function-name gf-name)
+ gf-name)
+ (instance-accessor-parameter ,parameter)
+ ,new-value)
+ :instance))
+
+(defmacro instance-boundp-internal (pv slots pv-offset default
+ &optional type)
+ (unless (member type '(nil :instance :class :default))
+ (error "Illegal type argument to ~S: ~S" 'instance-boundp-internal type))
+ (if (eq type ':default)
+ default
+ (let* ((index (gensym)))
+ `(locally (declare #.*optimize-speed*)
+ (let ((,index (pvref ,pv ,pv-offset)))
+ (typecase ,index
+ ,@(when (or (null type) (eq type ':instance))
+ `((fixnum (not (eq (%instance-ref ,slots ,index) ',*slot-unbound*)))))
+ ,@(when (or (null type) (eq type ':class))
+ `((cons (not (eq (cdr ,index) ',*slot-unbound*)))))
+ (t ,default)))))))
+
+(defmacro instance-boundp (pv-offset parameter position slot-name class)
+ (if (skip-fast-slot-access-p class slot-name 'boundp)
+ `(accessor-slot-boundp ,parameter ,slot-name)
+ `(instance-boundp-internal .pv. ,(slot-vector-symbol position)
+ ,pv-offset (accessor-slot-boundp ,parameter ,slot-name)
+ ,(if (generate-fast-class-slot-access-p class slot-name)
+ ':class ':instance))))
+
+;;;
+;;; This magic function has quite a job to do indeed.
+;;;
+;;; The careful reader will recall that <slots> contains all of the optimized
+;;; slot access forms produced by OPTIMIZE-INSTANCE-ACCESS. Each of these is
+;;; a call to either INSTANCE-READ or INSTANCE-WRITE.
+;;;
+;;; At the time these calls were produced, the first argument was specified as
+;;; the symbol .PV-OFFSET.; what we have to do now is convert those pv-offset
+;;; arguments into the actual number that is the correct offset into the pv.
+;;;
+;;; But first, oh but first, we sort <slots> a bit so that for each argument
+;;; we have the slots in alphabetical order. This canonicalizes the PV-TABLE's a
+;;; bit and will hopefully lead to having fewer PV's floating around. Even
+;;; if the gain is only modest, it costs nothing.
+;;;
+(defun slot-name-lists-from-slots (slots calls)
+ (multiple-value-bind (slots calls)
+ (mutate-slots-and-calls slots calls)
+ (let* ((slot-name-lists
+ (mapcar #'(lambda (parameter-entry)
+ (cons nil (mapcar #'car (cdr parameter-entry))))
+ slots))
+ (call-list
+ (mapcar #'car calls)))
+ (dolist (call call-list)
+ (dolist (arg (cdr call))
+ (when (integerp arg)
+ (setf (car (nth arg slot-name-lists)) t))))
+ (setq slot-name-lists (mapcar #'(lambda (r+snl)
+ (when (or (car r+snl) (cdr r+snl))
+ r+snl))
+ slot-name-lists))
+ (let ((cvt (apply #'vector
+ (let ((i -1))
+ (declare (fixnum i))
+ (mapcar #'(lambda (r+snl)
+ (when r+snl (incf i)))
+ slot-name-lists)))))
+ (setq call-list (mapcar #'(lambda (call)
+ (cons (car call)
+ (mapcar #'(lambda (arg)
+ (if (integerp arg)
+ (svref cvt arg)
+ arg))
+ (cdr call))))
+ call-list)))
+ (values slot-name-lists call-list))))
+
+(defun mutate-slots-and-calls (slots calls)
+ (let ((sorted-slots (sort-slots slots))
+ (sorted-calls (sort-calls (cdr calls)))
+ (pv-offset 0)) ; index 0 is for info
+ (declare (fixnum pv-offset))
+ (dolist (parameter-entry sorted-slots)
+ (dolist (slot-entry (cdr parameter-entry))
+ (incf pv-offset)
+ (dolist (form (cdr slot-entry))
+ (setf (cadr form) pv-offset))))
+ (dolist (call-entry sorted-calls)
+ (incf pv-offset)
+ (dolist (form (cdr call-entry))
+ (setf (cadr form) pv-offset)))
+ (values sorted-slots sorted-calls)))
+
+(defun symbol-pkg-name (sym)
+ (let ((pkg (symbol-package sym)))
+ (if pkg (package-name pkg) "")))
+
+(defun symbol-lessp (a b)
+ (if (eq (symbol-package a)
+ (symbol-package b))
+ (string-lessp (symbol-name a)
+ (symbol-name b))
+ (string-lessp (symbol-pkg-name a)
+ (symbol-pkg-name b))))
+
+(defun symbol-or-cons-lessp (a b)
+ (etypecase a
+ (symbol (etypecase b
+ (symbol (symbol-lessp a b))
+ (cons t)))
+ (cons (etypecase b
+ (symbol nil)
+ (cons (if (eq (car a) (car b))
+ (symbol-or-cons-lessp (cdr a) (cdr b))
+ (symbol-or-cons-lessp (car a) (car b))))))))
+
+(defun sort-slots (slots)
+ (mapcar #'(lambda (parameter-entry)
+ (cons (car parameter-entry)
+ (sort (cdr parameter-entry) ;slot entries
+ #'symbol-or-cons-lessp
+ :key #'car)))
+ slots))
+
+(defun sort-calls (calls)
+ (sort calls #'symbol-or-cons-lessp :key #'car))
+
+
+;;;
+;;; This needs to work in terms of metatypes and also needs to work for
+;;; automatically generated reader and writer functions.
+;;; -- Automatically generated reader and writer functions use this stuff too.
+
+(defmacro pv-binding ((required-parameters slot-name-lists pv-table-symbol)
+ &body body)
+ (with-gathering ((slot-vars (collecting))
+ (pv-parameters (collecting)))
+ (iterate ((slots (list-elements slot-name-lists))
+ (required-parameter (list-elements required-parameters))
+ (i (interval :from 0)))
+ (when slots
+ (gather required-parameter pv-parameters)
+ (gather (slot-vector-symbol i) slot-vars)))
+ `(pv-binding1 (.pv. .calls. ,pv-table-symbol ,pv-parameters ,slot-vars)
+ ,@body)))
+
+(defmacro pv-binding1 ((pv calls pv-table-symbol pv-parameters slot-vars)
+ &body body)
+ `(pv-env (,pv ,calls ,pv-table-symbol ,pv-parameters)
+ (let (,@(mapcar #'(lambda (slot-var p) `(,slot-var (get-slots-or-nil ,p)))
+ slot-vars pv-parameters))
+ ,@body)))
+
+;This gets used only when the default make-method-lambda is overriden.
+(defmacro pv-env ((pv calls pv-table-symbol pv-parameters)
+ &rest forms)
+ `(let* ((.pv-table. ,pv-table-symbol)
+ (.pv-cell. (pv-table-lookup-pv-args .pv-table. ,@pv-parameters))
+ (,pv (car .pv-cell.))
+ (,calls (cdr .pv-cell.)))
+ (declare ,(make-pv-type-declaration pv))
+ (declare ,(make-calls-type-declaration calls))
+ ,@(when (symbolp pv-table-symbol)
+ `((declare (special ,pv-table-symbol))))
+ ,@(progn
+ #-cmu `(,pv ,calls)
+ #+cmu `(declare (ignorable ,pv ,calls)))
+ ,@forms))
+
+(defvar *non-variable-declarations*
+ '(method-name method-lambda-list
+ optimize ftype inline notinline))
+
+(defvar *variable-declarations-with-argument*
+ '(class
+ type))
+
+(defvar *variable-declarations-without-argument*
+ '(ignore special dynamic-extent
+ array atom base-char bignum bit bit-vector character common compiled-function
+ complex cons double-float extended-char fixnum float function hash-table integer
+ keyword list long-float nil null number package pathname random-state ratio
+ rational readtable sequence short-float signed-byte simple-array
+ simple-bit-vector simple-string simple-vector single-float standard-char
+ stream string-char symbol t unsigned-byte vector))
+
+(defun split-declarations (body args)
+ (let ((inner-decls nil) (outer-decls nil) decl)
+ (loop (when (null body) (return nil))
+ (setq decl (car body))
+ (unless (and (consp decl)
+ (eq (car decl) 'declare))
+ (return nil))
+ (dolist (form (cdr decl))
+ (when (consp form)
+ (let ((declaration-name (car form)))
+ (if (member declaration-name *non-variable-declarations*)
+ (push `(declare ,form) outer-decls)
+ (let ((arg-p
+ (member declaration-name
+ *variable-declarations-with-argument*))
+ (non-arg-p
+ (member declaration-name
+ *variable-declarations-without-argument*))
+ (dname (list (pop form)))
+ (inners nil) (outers nil))
+ (unless (or arg-p non-arg-p)
+ (warn "The declaration ~S is not understood by ~S.~@
+ Please put ~S on one of the lists ~S,~%~S, or~%~S.~@
+ (Assuming it is a variable declarations without argument)."
+ declaration-name 'split-declarations
+ declaration-name
+ '*non-variable-declarations*
+ '*variable-declarations-with-argument*
+ '*variable-declarations-without-argument*)
+ (push declaration-name
+ *variable-declarations-without-argument*))
+ (when arg-p
+ (setq dname (append dname (list (pop form)))))
+ (dolist (var form)
+ (if (member var args)
+ (push var outers)
+ (push var inners)))
+ (when outers
+ (push `(declare (,@dname ,@outers)) outer-decls))
+ (when inners
+ (push `(declare (,@dname ,@inners)) inner-decls)))))))
+ (setq body (cdr body)))
+ (values outer-decls inner-decls body)))
+
+(defun make-method-initargs-form-internal (method-lambda initargs env)
+ (declare (ignore env))
+ (let (method-lambda-args lmf lmf-params)
+ (if (not (and (= 3 (length method-lambda))
+ (= 2 (length (setq method-lambda-args (cadr method-lambda))))
+ (consp (setq lmf (third method-lambda)))
+ (eq 'simple-lexical-method-functions (car lmf))
+ (eq (car method-lambda-args) (cadr (setq lmf-params (cadr lmf))))
+ (eq (cadr method-lambda-args) (caddr lmf-params))))
+ `(list* :function #',method-lambda
+ ',initargs)
+ (let* ((lambda-list (car lmf-params))
+ (nreq 0)(restp nil)(args nil))
+ (dolist (arg lambda-list)
+ (when (member arg '(&optional &rest &key))
+ (setq restp t)(return nil))
+ (when (eq arg '&aux) (return nil))
+ (incf nreq)(push arg args))
+ (setq args (nreverse args))
+ (setf (getf (getf initargs ':plist) ':arg-info) (cons nreq restp))
+ (make-method-initargs-form-internal1
+ initargs (cddr lmf) args lmf-params restp)))))
+
+(defun make-method-initargs-form-internal1
+ (initargs body req-args lmf-params restp)
+ (multiple-value-bind (outer-decls inner-decls body)
+ (split-declarations body req-args)
+ (let* ((rest-arg (when restp '.rest-arg.))
+ (args+rest-arg (if restp (append req-args (list rest-arg)) req-args)))
+ `(list* :fast-function
+ #'(lambda (.pv-cell. .next-method-call. ,@args+rest-arg)
+ ,@outer-decls
+ .pv-cell. .next-method-call.
+ (macrolet ((pv-env ((pv calls pv-table-symbol pv-parameters)
+ &rest forms)
+ (declare (ignore pv-table-symbol pv-parameters))
+ `(let ((,pv (car .pv-cell.))
+ (,calls (cdr .pv-cell.)))
+ (declare ,(make-pv-type-declaration pv)
+ ,(make-calls-type-declaration calls))
+ ,pv ,calls
+ ,@forms)))
+ (fast-lexical-method-functions
+ (,(car lmf-params) .next-method-call. ,req-args ,rest-arg
+ ,@(cdddr lmf-params))
+ ,@inner-decls
+ ,@body)))
+ ',initargs))))
+
+;use arrays and hash tables and the fngen stuff to make this much better.
+;It doesn't really matter, though, because a function returned by this
+;will get called only when the user explicitly funcalls a result of method-function.
+;BUT, this is needed to make early methods work.
+(defun method-function-from-fast-function (fmf)
+ (declare (type function fmf))
+ (let* ((method-function nil) (pv-table nil)
+ (arg-info (method-function-get fmf ':arg-info))
+ (nreq (car arg-info))
+ (restp (cdr arg-info)))
+ (setq method-function
+ #'(lambda (method-args next-methods)
+ (unless pv-table
+ (setq pv-table (method-function-pv-table fmf)))
+ (let* ((pv-cell (when pv-table
+ (get-method-function-pv-cell
+ method-function method-args pv-table)))
+ (nm (car next-methods))
+ (nms (cdr next-methods))
+ (nmc (when nm
+ (make-method-call :function (if (std-instance-p nm)
+ (method-function nm)
+ nm)
+ :call-method-args (list nms)))))
+ (if restp
+ (let* ((rest (nthcdr nreq method-args))
+ (args (ldiff method-args rest)))
+ (apply fmf pv-cell nmc (nconc args (list rest))))
+ (apply fmf pv-cell nmc method-args)))))
+ (let* ((fname (method-function-get fmf :name))
+ (name `(,(or (get (car fname) 'method-sym)
+ (setf (get (car fname) 'method-sym)
+ (let ((str (symbol-name (car fname))))
+ (if (string= "FAST-" str :end2 5)
+ (intern (subseq str 5) *the-pcl-package*)
+ (car fname)))))
+ ,@(cdr fname))))
+ (set-function-name method-function name))
+ (setf (method-function-get method-function :fast-function) fmf)
+ method-function))
+
+(defun get-method-function-pv-cell (method-function method-args &optional pv-table)
+ (let ((pv-table (or pv-table (method-function-pv-table method-function))))
+ (when pv-table
+ (let ((pv-wrappers (pv-wrappers-from-all-args pv-table method-args)))
+ (when pv-wrappers
+ (pv-table-lookup pv-table pv-wrappers))))))
+
+(defun pv-table-lookup-pv-args (pv-table &rest pv-parameters)
+ (pv-table-lookup pv-table (pv-wrappers-from-pv-args pv-parameters)))
+
+(defun pv-wrappers-from-pv-args (&rest args)
+ (let* ((nkeys (length args))
+ (pv-wrappers (make-list nkeys))
+ w (w-t pv-wrappers))
+ (declare (fixnum nkeys))
+ (dolist (arg args)
+ (setq w
+ #+cmu17 (wrapper-of arg)
+ #-cmu17
+ (cond ((std-instance-p arg)
+ (std-instance-wrapper arg))
+ ((fsc-instance-p arg)
+ (fsc-instance-wrapper arg))
+ (t
+ #+new-kcl-wrapper
+ (built-in-wrapper-of arg)
+ #-new-kcl-wrapper
+ (built-in-or-structure-wrapper arg))))
+ (unless (eq 't (wrapper-state w))
+ (setq w (check-wrapper-validity arg)))
+ (setf (car w-t) w))
+ (setq w-t (cdr w-t))
+ (when (= nkeys 1) (setq pv-wrappers (car pv-wrappers)))
+ pv-wrappers))
+
+(defun pv-wrappers-from-all-args (pv-table args)
+ (let ((nkeys 0)
+ (slot-name-lists (pv-table-slot-name-lists pv-table)))
+ (declare (fixnum nkeys))
+ (dolist (sn slot-name-lists)
+ (when sn (incf nkeys)))
+ (let* ((pv-wrappers (make-list nkeys))
+ (pv-w-t pv-wrappers))
+ (dolist (sn slot-name-lists)
+ (when sn
+ (let* ((arg (car args))
+ (w (wrapper-of arg)))
+ (unless w ; can-optimize-access prevents this from happening.
+ (error "error in pv-wrappers-from-all-args"))
+ (setf (car pv-w-t) w)
+ (setq pv-w-t (cdr pv-w-t))))
+ (setq args (cdr args)))
+ (when (= nkeys 1) (setq pv-wrappers (car pv-wrappers)))
+ pv-wrappers)))
+
+(defun pv-wrappers-from-all-wrappers (pv-table wrappers)
+ (let ((nkeys 0)
+ (slot-name-lists (pv-table-slot-name-lists pv-table)))
+ (declare (fixnum nkeys))
+ (dolist (sn slot-name-lists)
+ (when sn (incf nkeys)))
+ (let* ((pv-wrappers (make-list nkeys))
+ (pv-w-t pv-wrappers))
+ (dolist (sn slot-name-lists)
+ (when sn
+ (let ((w (car wrappers)))
+ (unless w ; can-optimize-access prevents this from happening.
+ (error "error in pv-wrappers-from-all-wrappers"))
+ (setf (car pv-w-t) w)
+ (setq pv-w-t (cdr pv-w-t))))
+ (setq wrappers (cdr wrappers)))
+ (when (= nkeys 1) (setq pv-wrappers (car pv-wrappers)))
+ pv-wrappers)))
diff --git a/gcl/pcl/walk.lisp b/gcl/pcl/walk.lisp
new file mode 100644
index 000000000..7f2cf6a9a
--- /dev/null
+++ b/gcl/pcl/walk.lisp
@@ -0,0 +1,2198 @@
+;;;-*- Mode:LISP; Package:(WALKER LISP 1000); Base:10; Syntax:Common-lisp -*-
+;;;
+;;; *************************************************************************
+;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
+;;; All rights reserved.
+;;;
+;;; Use and copying of this software and preparation of derivative works
+;;; based upon this software are permitted. Any distribution of this
+;;; software or derivative works must comply with all applicable United
+;;; States export control laws.
+;;;
+;;; This software is made available AS IS, and Xerox Corporation makes no
+;;; warranty about the software, its performance or its conformity to any
+;;; specification.
+;;;
+;;; Any person obtaining a copy of this software is requested to send their
+;;; name and post office or electronic mail address to:
+;;; CommonLoops Coordinator
+;;; Xerox PARC
+;;; 3333 Coyote Hill Rd.
+;;; Palo Alto, CA 94304
+;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
+;;;
+;;; Suggestions, comments and requests for improvements are also welcome.
+;;; *************************************************************************
+;;;
+;;; A simple code walker, based IN PART on: (roll the credits)
+;;; Larry Masinter's Masterscope
+;;; Moon's Common Lisp code walker
+;;; Gary Drescher's code walker
+;;; Larry Masinter's simple code walker
+;;; .
+;;; .
+;;; boy, thats fair (I hope).
+;;;
+;;; For now at least, this code walker really only does what PCL needs it to
+;;; do. Maybe it will grow up someday.
+;;;
+
+;;;
+;;; This code walker used to be completely portable. Now it is just "Real
+;;; easy to port". This change had to happen because the hack that made it
+;;; completely portable kept breaking in different releases of different
+;;; Common Lisps, and in addition it never worked entirely anyways. So,
+;;; its now easy to port. To port this walker, all you have to write is one
+;;; simple macro and two simple functions. These macros and functions are
+;;; used by the walker to manipluate the macroexpansion environments of
+;;; the Common Lisp it is running in.
+;;;
+;;; The code which implements the macroexpansion environment manipulation
+;;; mechanisms is in the first part of the file, the real walker follows it.
+;;;
+
+(in-package :walker)
+
+;;;
+;;; The user entry points are walk-form and nested-walked-form. In addition,
+;;; it is legal for user code to call the variable information functions:
+;;; variable-lexical-p, variable-special-p and variable-class. Some users
+;;; will need to call define-walker-template, they will have to figure that
+;;; out for themselves.
+;;;
+(export '(define-walker-template
+ walk-form
+ walk-form-expand-macros-p
+ nested-walk-form
+ variable-lexical-p
+ variable-special-p
+ variable-globally-special-p
+ *variable-declarations*
+ variable-declaration
+ macroexpand-all
+ ))
+
+
+
+;;;
+;;; On the following pages are implementations of the implementation specific
+;;; environment hacking functions for each of the implementations this walker
+;;; has been ported to. If you add a new one, so this walker can run in a new
+;;; implementation of Common Lisp, please send the changes back to us so that
+;;; others can also use this walker in that implementation of Common Lisp.
+;;;
+;;; This code just hacks 'macroexpansion environments'. That is, it is only
+;;; concerned with the function binding of symbols in the environment. The
+;;; walker needs to be able to tell if the symbol names a lexical macro or
+;;; function, and it needs to be able to build environments which contain
+;;; lexical macro or function bindings. It must be able, when walking a
+;;; macrolet, flet or labels form to construct an environment which reflects
+;;; the bindings created by that form. Note that the environment created
+;;; does NOT have to be sufficient to evaluate the body, merely to walk its
+;;; body. This means that definitions do not have to be supplied for lexical
+;;; functions, only the fact that that function is bound is important. For
+;;; macros, the macroexpansion function must be supplied.
+;;;
+;;; This code is organized in a way that lets it work in implementations that
+;;; stack cons their environments. That is reflected in the fact that the
+;;; only operation that lets a user build a new environment is a with-body
+;;; macro which executes its body with the specified symbol bound to the new
+;;; environment. No code in this walker or in PCL will hold a pointer to
+;;; these environments after the body returns. Other user code is free to do
+;;; so in implementations where it works, but that code is not considered
+;;; portable.
+;;;
+;;; There are 3 environment hacking tools. One macro which is used for
+;;; creating new environments, and two functions which are used to access the
+;;; bindings of existing environments.
+;;;
+;;; WITH-AUGMENTED-ENVIRONMENT
+;;;
+;;; ENVIRONMENT-FUNCTION
+;;;
+;;; ENVIRONMENT-MACRO
+;;;
+
+(defun unbound-lexical-function (&rest args)
+ (declare (ignore args))
+ (error "The evaluator was called to evaluate a form in a macroexpansion~%~
+ environment constructed by the PCL portable code walker. These~%~
+ environments are only useful for macroexpansion, they cannot be~%~
+ used for evaluation.~%~
+ This error should never occur when using PCL.~%~
+ This most likely source of this error is a program which tries to~%~
+ to use the PCL portable code walker to build its own evaluator."))
+
+
+;;;
+;;; In Coral Common Lisp, the macroexpansion environment is just a list
+;;; of environment entries. The cadr of each element specifies the type
+;;; of the element. The only types that interest us are CCL::MACRO and
+;;; FUNCTION. In these cases the element is interpreted as follows.
+;;;
+;;; (<function-name> CCL::MACRO . macroexpansion-function)
+;;;
+;;; (<function-name> FUNCTION . <fn>)
+;;;
+;;; When in the compiler, <fn> is a gensym which will be
+;;; a variable which bound at run-time to the function.
+;;; When in the interpreter, <fn> is the actual function.
+;;;
+;;;
+#+:Coral
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+(defun with-augmented-environment-internal (env functions macros)
+ (dolist (f functions)
+ (push (list* f 'function (gensym)) env))
+ (dolist (m macros)
+ (push (list* (car m) 'ccl::macro (cadr m)) env))
+ env)
+
+(defun environment-function (env fn)
+ (let ((entry (assoc fn env :test #'equal)))
+ (and entry
+ (eq (cadr entry) 'function)
+ (cddr entry))))
+
+(defun environment-macro (env macro)
+ (let ((entry (assoc macro env :test #'equal)))
+ (and entry
+ (eq (cadr entry) 'ccl::macro)
+ (cddr entry))))
+
+);#+:Coral
+
+
+;;;
+;;; Franz Common Lisp is a lot like Coral Lisp. The macroexpansion
+;;; environment is just a list of entries. The cadr of each element
+;;; specifies the type of the element. The types that interest us
+;;; are FUNCTION, EXCL::MACRO, and COMPILER::FUNCTION-VALUE. These
+;;; are interpreted as follows:
+;;;
+;;; (<function-name> FUNCTION . <a lexical closure>)
+;;;
+;;; This happens in the interpreter with lexically
+;;; bound functions.
+;;;
+;;; (<function-name> COMPILER::FUNCTION-VALUE . <gensym>)
+;;;
+;;; This happens in the compiler. The gensym represents
+;;; a variable which will be bound at run time to the
+;;; function object.
+;;;
+;;; (<function-name> EXCL::MACRO . <a lambda>)
+;;;
+;;; In both interpreter and compiler, this is the
+;;; representation used for macro definitions.
+;;;
+;;;
+#+:ExCL
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+(defun with-augmented-environment-internal (env functions macros)
+ (let (#+allegro-v4.1 (env-tail (cdr env)) #+allegro-v4.1 (env (car env)))
+ (dolist (f functions)
+ (push (list* f 'function #'unbound-lexical-function) env))
+ (dolist (m macros)
+ (push (list* (car m) 'excl::macro (cadr m)) env))
+ #-allegro-v4.1 env #+allegro-v4.1 (cons env env-tail)))
+
+(defun environment-function (env fn)
+ (let* (#+allegro-v4.1 (env (car env))
+ (entry (assoc fn env :test #'equal)))
+ (and entry
+ (or (eq (cadr entry) 'function)
+ (eq (cadr entry) 'compiler::function-value))
+ (cddr entry))))
+
+(defun environment-macro (env macro)
+ (let* (#+allegro-v4.1 (env (car env))
+ (entry (assoc macro env :test #'equal)))
+ (and entry
+ (eq (cadr entry) 'excl::macro)
+ (cddr entry))))
+
+);#+:ExCL
+
+
+#+Lucid
+(progn
+
+(proclaim '(inline
+ %alphalex-p
+ add-contour-to-env-shape
+ make-function-variable
+ make-sfc-contour
+ sfc-contour-type
+ sfc-contour-elements
+ add-sfc-contour
+ add-function-contour
+ add-macrolet-contour
+ find-variable-in-contour
+ find-alist-element-in-contour
+ find-macrolet-in-contour))
+
+(defun %alphalex-p (object)
+ #-Prime
+ (eq (cadddr (cddddr object)) 'lucid::%alphalex)
+ #+Prime
+ (eq (caddr (cddddr object)) 'lucid::%alphalex))
+
+#+Prime
+(defun lucid::augment-lexenv-fvars-dummy (lexical vars)
+ (lucid::augment-lexenv-fvars-aux lexical vars '() '() 'flet '()))
+
+#-lcl4.0 ; Maybe this should be #-lcl4.1
+(progn
+(defconstant function-contour 1)
+(defconstant macrolet-contour 5))
+#+lcl4.0 ; Maybe this should be #+lcl4.1
+(progn
+(defconstant function-contour 2)
+(defconstant macrolet-contour 6))
+
+(defstruct lucid::contour
+ type
+ elements)
+
+(defun add-contour-to-env-shape (contour-type elements env-shape)
+ (cons (make-contour :type contour-type
+ :elements elements)
+ env-shape))
+
+(defstruct (variable (:constructor make-variable (name source-type)))
+ name
+ (identifier nil)
+ source-type)
+
+(defconstant function-sfc-contour 1)
+(defconstant macrolet-sfc-contour 8)
+(defconstant function-variable-type 1)
+
+(defun make-function-variable (name)
+ (make-variable name function-variable-type))
+
+(defun make-sfc-contour (type elements)
+ (cons type elements))
+
+(defun sfc-contour-type (sfc-contour)
+ (car sfc-contour))
+
+(defun sfc-contour-elements (sfc-contour)
+ (cdr sfc-contour))
+
+(defun add-sfc-contour (element-list environment type)
+ (cons (make-sfc-contour type element-list) environment))
+
+(defun add-function-contour (variable-list environment)
+ (add-sfc-contour variable-list environment function-sfc-contour))
+
+(defun add-macrolet-contour (alist environment)
+ (add-sfc-contour alist environment macrolet-sfc-contour))
+
+(defun find-variable-in-contour (name contour)
+ (dolist (element (sfc-contour-elements contour) nil)
+ (when (eq (variable-name element) name)
+ (return element))))
+
+(defun find-alist-element-in-contour (name contour)
+ (cdr (assoc name (sfc-contour-elements contour))))
+
+(defun find-macrolet-in-contour (name contour)
+ (find-alist-element-in-contour name contour))
+
+(defmacro do-sfc-contours ((contour-var environment &optional result)
+ &body body)
+ `(dolist (,contour-var ,environment ,result) ,@body))
+
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let* ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+;;;
+;;; with-augmented-environment-internal is where the real work of augmenting
+;;; the environment happens.
+;;;
+(defun with-augmented-environment-internal (env functions macros)
+ (let ((function-names (mapcar #'first functions))
+ (macro-names (mapcar #'first macros))
+ (macro-functions (mapcar #'second macros)))
+ (cond ((or (null env)
+ (contour-p (first env)))
+ (when function-names
+ (setq env (add-contour-to-env-shape function-contour
+ function-names
+ env)))
+ (when macro-names
+ (setq env (add-contour-to-env-shape macrolet-contour
+ (pairlis macro-names
+ macro-functions)
+ env))))
+ ((%alphalex-p env)
+ (when function-names
+ (setq env (lucid::augment-lexenv-fvars-dummy env function-names)))
+ (when macro-names
+ (setq env (lucid::augment-lexenv-mvars env
+ macro-names
+ macro-functions))))
+ (t
+ (when function-names
+ (setq env (add-function-contour
+ (mapcar #'make-function-variable function-names)
+ env)))
+ (when macro-names
+ (setq env (add-macrolet-contour
+ (pairlis macro-names macro-functions)
+ env)))))
+ env))
+
+
+(defun environment-function (env fn)
+ (cond ((null env) nil)
+ ((contour-p (first env))
+ (if (lucid::find-lexical-function fn env)
+ t
+ nil))
+ ((%alphalex-p env)
+ (if (lucid::lexenv-fvar fn env)
+ t
+ nil))
+ (t (do-sfc-contours (contour env nil)
+ (let ((type (sfc-contour-type contour)))
+ (cond ((eql type function-sfc-contour)
+ (when (find-variable-in-contour fn contour)
+ (return t)))
+ ((eql type macrolet-sfc-contour)
+ (when (find-macrolet-in-contour fn contour)
+ (return nil)))))))))
+
+(defun environment-macro (env macro)
+ (cond ((null env) nil)
+ ((contour-p (first env))
+ (lucid::find-lexical-macro macro env))
+ ((%alphalex-p env)
+ (lucid::lexenv-mvar macro env))
+ (t (do-sfc-contours (contour env nil)
+ (let ((type (sfc-contour-type contour)))
+ (cond ((eql type function-sfc-contour)
+ (when (find-variable-in-contour macro contour)
+ (return nil)))
+ ((eql type macrolet-sfc-contour)
+ (let ((fn (find-macrolet-in-contour macro contour)))
+ (when fn
+ (return fn))))))))))
+
+
+);#+Lucid
+
+
+
+;;;
+;;; On the 3600, the documentation for how the environments are represented
+;;; is in sys:sys;eval.lisp. That total information is not repeated here.
+;;; The important points are that:
+;;; si:env-variables returns a list of which each element is:
+;;;
+;;; (symbol value)
+;;; or (symbol . locative)
+;;;
+;;; The first form is for lexical variables, the second for
+;;; special and instance variables. In either case CADR of
+;;; the entry is the value and SETF of CADR is used to change
+;;; the value. Variables are looked up with ASSQ.
+;;;
+;;; si:env-functions returns a list of which each element is:
+;;;
+;;; (symbol definition)
+;;;
+;;; where definition is anything that could go in a function cell.
+;;; This is used for both local functions and local macros.
+;;;
+;;; The 3600 stack conses its environments (at least in the interpreter).
+;;; This means that code written using this walker and running on the 3600
+;;; must not hold on to the environment after the walk-function returns.
+;;; No code in this walker or in PCL does that.
+;;;
+#+Genera
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ (let ((funs (make-symbol "FNS"))
+ (macs (make-symbol "MACROS"))
+ (new (make-symbol "NEW")))
+ `(let ((,funs ,functions)
+ (,macs ,macros)
+ (,new ()))
+ (dolist (f ,funs)
+ (push `(,(car f) ,#'unbound-lexical-function) ,new))
+ (dolist (m ,macs)
+ (push `(,(car m) (special ,(cadr m))) ,new))
+ (let* ((.old-env. ,old-env)
+ (.old-vars. (pop .old-env.))
+ (.old-funs. (pop .old-env.))
+ (.old-blks. (pop .old-env.))
+ (.old-tags. (pop .old-env.))
+ (.old-dcls. (pop .old-env.)))
+ (si:with-interpreter-environment (,new-env
+ .old-env.
+ .old-vars.
+ (append ,new .old-funs.)
+ .old-blks.
+ .old-tags.
+ .old-dcls.)
+ ,@body)))))
+
+
+(defun environment-function (env fn)
+ (if (null env)
+ (values nil nil)
+ (let ((entry (assoc fn (si:env-functions env) :test #'equal)))
+ (if (and entry
+ (or (not (listp (cadr entry)))
+ (not (eq (caadr entry) 'special))))
+ (values (cadr entry) t)
+ (environment-function (si:env-parent env) fn)))))
+
+(defun environment-macro (env macro)
+ (if (null env)
+ (values nil nil)
+ (let ((entry (assoc macro (si:env-functions env) :test #'equal)))
+ (if (and entry
+ (listp (cadr entry))
+ (eq (caadr entry) 'special))
+ (values (cadadr entry) t)
+ (environment-macro (si:env-parent env) macro)))))
+
+);#+Genera
+
+#+Cloe-Runtime
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env ,functions ,macros)))
+ ,@body))
+
+(defun with-augmented-environment-internal (env functions macros)
+ functions
+ (dolist (m macros)
+ (setf env `(,(first m) (compiler::macro . ,(second m)) ,@env)))
+ env)
+
+(defun environment-function (env fn)
+ nil)
+
+(defun environment-macro (env macro)
+ (let ((entry (getf env macro)))
+ (if (and (consp entry)
+ (eq (car entry) 'compiler::macro))
+ (values (cdr entry) t)
+ (values nil nil))))
+
+);#+Cloe-Runtime
+
+
+;;;
+;;; In Xerox Lisp, the compiler and interpreter use different structures for
+;;; the environment. This doesn't cause a serious problem, the parts of the
+;;; environments we are concerned with are fairly similar.
+;;;
+#+:Xerox
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let* ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+;;;
+;;; with-augmented-environment-internal is where the real work of augmenting
+;;; the environment happens. Before it gets there, env had better not be NIL
+;;; anymore because we have to know what kind of environment we are supposed
+;;; to be building up. This is probably never a real concern in practice.
+;;; It better not be because we don't do anything about it.
+;;;
+(defun with-augmented-environment-internal (env functions macros)
+ (cond
+ ((compiler::env-p env)
+ (dolist (f functions)
+ (setq env (compiler::copy-env-with-function
+ env f :function)))
+ (dolist (m macros)
+ (setq env (compiler::copy-env-with-function
+ env (car m) :macro (cadr m)))))
+ (t (setq env (if (il:environment-p env)
+ (il:\\copy-environment env)
+ (il:\\make-environment)))
+ ;; The functions field of the environment is a plist of function names
+ ;; and conses like (:function . fn) or (:macro . expansion-fn).
+ ;; Note that we can't smash existing entries in this plist since these
+ ;; are likely shared with older environments.
+ (dolist (f functions)
+ (setf (il:environment-functions env)
+ (list* f (cons :function #'unbound-lexical-function)
+ (il:environment-functions env))))
+ (dolist (m macros)
+ (setf (il:environment-functions env)
+ (list* (car m) (cons :macro (cadr m))
+ (il:environment-functions env))))))
+ env)
+
+(defun environment-function (env fn)
+ (cond ((compiler::env-p env) (eq (compiler:env-fboundp env fn) :function))
+ ((il:environment-p env) (eq (getf (il:environment-functions env) fn)
+ :function))
+ (t nil)))
+
+(defun environment-macro (env macro)
+ (cond ((compiler::env-p env)
+ (multiple-value-bind (type def)
+ (compiler:env-fboundp env macro)
+ (when (eq type :macro) def)))
+ ((il:environment-p env)
+ (xcl:destructuring-bind (type . def)
+ (getf (il:environment-functions env) macro)
+ (when (eq type :macro) def)))
+ (t nil)))
+
+);#+:Xerox
+
+
+;;;
+;;; In IBUKI Common Lisp, the macroexpansion environment is a three element
+;;; list. The second element describes lexical functions and macros. The
+;;; function entries in this list have the form
+;;; (<name> . (FUNCTION . (<function-value> . nil))
+;;; The macro entries have the form
+;;; (<name> . (MACRO . (<macro-value> . nil)).
+;;;
+;;;
+#+(or KCL IBCL)
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+(defun with-augmented-environment-internal (env functions macros)
+ (let ((first (first env))
+ (lexicals (second env))
+ (third (third env)))
+ (dolist (f functions)
+ (push `(,(car f) . (function . (,#'unbound-lexical-function . nil)))
+ lexicals))
+ (dolist (m macros)
+ (push `(,(car m) . (macro . ( ,(cadr m) . nil)))
+ lexicals))
+ (list first lexicals third)))
+
+(defun environment-function (env fn)
+ (when env
+ (let ((entry (assoc fn (second env))))
+ (and entry
+ (eq (cadr entry) 'function)
+ (caddr entry)))))
+
+(defun environment-macro (env macro)
+ (when env
+ (let ((entry (assoc macro (second env))))
+ (and entry
+ (eq (cadr entry) 'macro)
+ (caddr entry)))))
+);#+(or KCL IBCL)
+
+
+;;; --- TI Explorer --
+
+;;; An environment is a two element list, whose car we can ignore and
+;;; whose cadr is list of the local-definitions-frames. Each
+;;; local-definitions-frame holds either macros or functions, but not
+;;; both. Each frame is a plist of <name> <def> <name> <def> ... where
+;;; <name> is a locative to the function cell of the symbol that names
+;;; the function or macro, and <def> is the new def or NIL if this is function
+;;; redefinition or (cons 'ticl:macro <macro-expansion-function>) if this is a macro
+;;; redefinition.
+;;;
+;;; Here's an example. For the form:
+;;; (defun foo ()
+;;; (macrolet ((bar (a b) (list a b))
+;;; (bar2 (a b) (list a b)))
+;;; (flet ((some-local-fn (c d) (print (list c d)))
+;;; (another (c d) (print (list c d))))
+;;; (bar (some-local-fn 1 2) 3))))
+
+;;; the environment arg to macroexpand-1 when called on
+;;; (bar (some-local-fn 1 2) 3)
+;;;is
+;;;(NIL ((#<DTP-LOCATIVE 4710602> NIL
+;;; #<DTP-LOCATIVE 4710671> NIL)
+;;; (#<DTP-LOCATIVE 7346562>
+;;; (TICL:MACRO TICL:NAMED-LAMBDA (BAR (:DESCRIPTIVE-ARGLIST (A B)))
+;;; (SYS::*MACROARG* &OPTIONAL SYS::*MACROENVIRONMENT*)
+;;; (BLOCK BAR ....))
+;;; #<DTP-LOCATIVE 4710664>
+;;; (TICL:MACRO TICL:NAMED-LAMBDA (BAR2 (:DESCRIPTIVE-ARGLIST (A B)))
+;;; (SYS::*MACROARG* &OPTIONAL SYS::*MACROENVIRONMENT*)
+;;; (BLOCK BAR2 ....))))
+#+TI
+(progn
+
+;;; from sys:site;macros.lisp
+(eval-when (compile load eval)
+
+(DEFMACRO MACRO-DEF? (thing)
+ `(AND (CONSP ,thing) (EQ (CAR ,thing) 'TICL::MACRO)))
+
+;; the following macro generates code to check the 'local' environment
+;; for a macro definition for THE SYMBOL <name>. Such a definition would
+;; be set up only by a MACROLET. If a macro definition for <name> is
+;; found, its expander function is returned.
+
+(DEFMACRO FIND-LOCAL-DEFINITION (name local-function-environment)
+ `(IF ,local-function-environment
+ (LET ((vcell (ticl::LOCF (SYMBOL-FUNCTION ,name))))
+ (DOLIST (frame ,local-function-environment)
+ ;; <value> is nil or a locative
+ (LET ((value (sys::GET-LOCATION-OR-NIL (ticl::LOCF frame)
+ vcell)))
+ (When value (RETURN (CAR value))))))
+ nil)))
+
+
+;;;Edited by Reed Hastings 13 Jan 88 16:29
+(defun environment-macro (env macro)
+ "returns what macro-function would, ie. the expansion function"
+ ;;some code picked off macroexpand-1
+ (let* ((local-definitions (cadr env))
+ (local-def (find-local-definition macro local-definitions)))
+ (if (macro-def? local-def)
+ (cdr local-def))))
+
+;;;Edited by Reed Hastings 13 Jan 88 16:29
+;;;Edited by Reed Hastings 7 Mar 88 19:07
+(defun environment-function (env fn)
+ (let* ((local-definitions (cadr env)))
+ (dolist (frame local-definitions)
+ (let ((val (getf frame
+ (ticl::locf (symbol-function fn))
+ :not-found-marker)))
+ (cond ((eq val :not-found-marker))
+ ((functionp val) (return t))
+ ((and (listp val)
+ (eq (car val) 'ticl::macro))
+ (return nil))
+ (t
+ (error "we are confused")))))))
+
+
+;;;Edited by Reed Hastings 13 Jan 88 16:29
+;;;Edited by Reed Hastings 7 Mar 88 19:07
+(defun with-augmented-environment-internal (env functions macros)
+ (let ((local-definitions (cadr env))
+ (new-local-fns-frame
+ (mapcan #'(lambda (fn)
+ (list (ticl:locf (symbol-function (car fn)))
+ #'unbound-lexical-function))
+ functions))
+ (new-local-macros-frame
+ (mapcan #'(lambda (m)
+ (list (ticl:locf (symbol-function (car m))) (cons 'ticl::macro (cadr m))))
+ macros)))
+ (when new-local-fns-frame
+ (push new-local-fns-frame local-definitions))
+ (when new-local-macros-frame
+ (push new-local-macros-frame local-definitions))
+ `(,(car env) ,local-definitions)))
+
+
+;;;Edited by Reed Hastings 7 Mar 88 19:07
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+);#+TI
+
+
+#+(and dec vax common)
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+(defun with-augmented-environment-internal (env functions macros)
+ #'(lambda (op &optional (arg nil arg-p))
+ (cond ((eq op :macro-function)
+ (unless arg-p (error "Invalid environment use."))
+ (lookup-macro-function arg env functions macros))
+ (arg-p
+ (error "Invalid environment operation: ~S ~S" op arg))
+ (t
+ (lookup-macro-function op env functions macros)))))
+
+(defun lookup-macro-function (name env fns macros)
+ (let ((m (assoc name macros)))
+ (cond (m (cadr m))
+ ((assoc name fns) :function)
+ (env (funcall env name))
+ (t nil))))
+
+(defun environment-macro (env macro)
+ (let ((m (and env (funcall env macro))))
+ (and (not (eq m :function))
+ m)))
+
+;;; Nobody calls environment-function. What would it return, anyway?
+);#+(and dec vax common)
+
+
+;;;
+;;; In Golden Common Lisp, the macroexpansion environment is just a list
+;;; of environment entries. Unless the car of the list is :compiler-menv
+;;; it is an interpreted environment. The cadr of each element specifies
+;;; the type of the element. The only types that interest us are GCL:MACRO
+;;; and FUNCTION. In these cases the element is interpreted as follows.
+;;;
+;;; Compiled:
+;;; (<function-name> <gensym> macroexpansion-function)
+;;; (<function-name> <fn>)
+;;;
+;;; Interpreted:
+;;; (<function-name> GCL:MACRO macroexpansion-function)
+;;; (<function-name> <fn>)
+;;;
+;;; When in the compiler, <fn> is a gensym which will be
+;;; a variable which bound at run-time to the function.
+;;; When in the interpreter, <fn> is the actual function.
+;;;
+;;;
+#+gclisp
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+(defun with-augmented-environment-internal (env functions macros)
+ (let ((new-entries nil))
+ (dolist (f functions)
+ (push (cons (car f) nil) new-entries))
+ (dolist (m macros)
+ (push (cons (car m)
+ (if (eq :compiler-menv (car env))
+ (if (eq (caadr m) 'lisp::lambda)
+ `(,(gensym) ,(cadr m))
+ `(,(gensym) ,@(cadr m)))
+ `(gclisp:MACRO ,@(cadr m))))
+ new-entries))
+ (if (eq :compiler-menv (car env))
+ `(:compiler-menv ,@new-entries ,@(cdr env))
+ (append new-entries env))))
+
+(defun environment-function (env fn)
+ (let ((entry (lisp::lexical-function fn env)))
+ (and entry
+ (eq entry 'lisp::lexical-function)
+ fn)))
+
+(defun environment-macro (env macro)
+ (let ((entry (assoc macro (if (eq :compiler-menv (first env))
+ (rest env)
+ env))))
+ (and entry
+ (consp entry)
+ (symbolp (car entry)) ;name
+ (symbolp (cadr entry)) ;gcl:macro or gensym
+ (nthcdr 2 entry))))
+
+);#+gclisp
+
+
+;;;; CMU Common Lisp version of environment frobbing stuff.
+
+;;; In CMU Common Lisp, the environment is represented with a structure
+;;; that holds alists for the functional things, variables, blocks, etc.
+;;; Only the c::lexenv-functions slot is relevent. It holds:
+;;; Alist (name . what), where What is either a Functional (a local function)
+;;; or a list (MACRO . <function>) (a local macro, with the specifier
+;;; expander.) Note that Name may be a (SETF <name>) function.
+
+#+:CMU
+(progn
+
+(defmacro with-augmented-environment
+ ((new-env old-env &key functions macros) &body body)
+ `(let ((,new-env (with-augmented-environment-internal ,old-env
+ ,functions
+ ,macros)))
+ ,@body))
+
+(defun with-augmented-environment-internal (env functions macros)
+ ;; Note: In order to record the correct function definition, we would
+ ;; have to create an interpreted closure, but the with-new-definition
+ ;; macro down below makes no distinction between flet and labels, so
+ ;; we have no idea what to use for the environment. So we just blow it
+ ;; off, 'cause anything real we do would be wrong. We still have to
+ ;; make an entry so we can tell functions from macros.
+ (let ((env (or env (c::make-null-environment))))
+ (c::make-lexenv
+ :default env
+ :functions
+ (append (mapcar #'(lambda (f)
+ (cons (car f) (c::make-functional :lexenv env)))
+ functions)
+ (mapcar #'(lambda (m)
+ (list* (car m) 'c::macro
+ (coerce (cadr m) 'function)))
+ macros)))))
+
+(defun environment-function (env fn)
+ (when env
+ (let ((entry (assoc fn (c::lexenv-functions env) :test #'equal)))
+ (and entry
+ (c::functional-p (cdr entry))
+ (cdr entry)))))
+
+(defun environment-macro (env macro)
+ (when env
+ (let ((entry (assoc macro (c::lexenv-functions env) :test #'eq)))
+ (and entry
+ (eq (cadr entry) 'c::macro)
+ (function-lambda-expression (cddr entry))))))
+
+); end of #+:CMU
+
+
+
+(defmacro with-new-definition-in-environment
+ ((new-env old-env macrolet/flet/labels-form) &body body)
+ (let ((functions (make-symbol "Functions"))
+ (macros (make-symbol "Macros")))
+ `(let ((,functions ())
+ (,macros ()))
+ (ecase (car ,macrolet/flet/labels-form)
+ ((flet labels)
+ (dolist (fn (cadr ,macrolet/flet/labels-form))
+ (push fn ,functions)))
+ ((macrolet)
+ (dolist (mac (cadr ,macrolet/flet/labels-form))
+ (push (list (car mac)
+ (convert-macro-to-lambda (cadr mac)
+ (cddr mac)
+ (string (car mac))))
+ ,macros))))
+ (with-augmented-environment
+ (,new-env ,old-env :functions ,functions :macros ,macros)
+ ,@body))))
+
+#-Genera
+(defun convert-macro-to-lambda (llist body &optional (name "Dummy Macro"))
+ (let ((gensym (make-symbol name)))
+ (eval `(defmacro ,gensym ,llist ,@body))
+ (macro-function gensym)))
+
+#+Genera
+(defun convert-macro-to-lambda (llist body &optional (name "Dummy Macro"))
+ (si:defmacro-1
+ 'sys:named-lambda 'sys:special (make-symbol name) llist body))
+
+
+
+
+
+;;;
+;;; Now comes the real walker.
+;;;
+;;; As the walker walks over the code, it communicates information to itself
+;;; about the walk. This information includes the walk function, variable
+;;; bindings, declarations in effect etc. This information is inherently
+;;; lexical, so the walker passes it around in the actual environment the
+;;; walker passes to macroexpansion functions. This is what makes the
+;;; nested-walk-form facility work properly.
+;;;
+(defmacro walker-environment-bind ((var env &rest key-args)
+ &body body)
+ `(with-augmented-environment
+ (,var ,env :macros (walker-environment-bind-1 ,env ,.key-args))
+ .,body))
+
+(defvar *key-to-walker-environment* (gensym))
+
+(defun env-lock (env)
+ (environment-macro env *key-to-walker-environment*))
+
+(defun walker-environment-bind-1 (env &key (walk-function nil wfnp)
+ (walk-form nil wfop)
+ (declarations nil decp)
+ (lexical-variables nil lexp))
+ (let ((lock (environment-macro env *key-to-walker-environment*)))
+ (list
+ (list *key-to-walker-environment*
+ (list (if wfnp walk-function (car lock))
+ (if wfop walk-form (cadr lock))
+ (if decp declarations (caddr lock))
+ (if lexp lexical-variables (cadddr lock)))))))
+
+(defun env-walk-function (env)
+ (car (env-lock env)))
+
+(defun env-walk-form (env)
+ (cadr (env-lock env)))
+
+(defun env-declarations (env)
+ (caddr (env-lock env)))
+
+(defun env-lexical-variables (env)
+ (cadddr (env-lock env)))
+
+
+(defun note-declaration (declaration env)
+ (push declaration (caddr (env-lock env))))
+
+(defun note-lexical-binding (thing env)
+ (push (list thing :lexical-var) (cadddr (env-lock env))))
+
+(defun VARIABLE-LEXICAL-P (var env)
+ (let ((entry (member var (env-lexical-variables env) :key #'car)))
+ (when (eq (cadar entry) :lexical-var)
+ entry)))
+
+(defun variable-symbol-macro-p (var env)
+ (let ((entry (member var (env-lexical-variables env) :key #'car)))
+ (when (eq (cadar entry) :macro)
+ entry)))
+
+
+(defvar *VARIABLE-DECLARATIONS* '(special))
+
+(defun VARIABLE-DECLARATION (declaration var env)
+ (if (not (member declaration *variable-declarations*))
+ (error "~S is not a recognized variable declaration." declaration)
+ (let ((id (or (variable-lexical-p var env) var)))
+ (dolist (decl (env-declarations env))
+ (when (and (eq (car decl) declaration)
+ (eq (cadr decl) id))
+ (return decl))))))
+
+(defun VARIABLE-SPECIAL-P (var env)
+ (or (not (null (variable-declaration 'special var env)))
+ (variable-globally-special-p var)))
+
+;;;
+;;; VARIABLE-GLOBALLY-SPECIAL-P is used to ask if a variable has been
+;;; declared globally special. Any particular CommonLisp implementation
+;;; should customize this function accordingly and send their customization
+;;; back.
+;;;
+;;; The default version of variable-globally-special-p is probably pretty
+;;; slow, so it uses *globally-special-variables* as a cache to remember
+;;; variables that it has already figured out are globally special.
+;;;
+;;; This would need to be reworked if an unspecial declaration got added to
+;;; Common Lisp.
+;;;
+;;; Common Lisp nit:
+;;; variable-globally-special-p should be defined in Common Lisp.
+;;;
+#-(or Genera Cloe-Runtime Lucid Xerox Excl KCL IBCL (and dec vax common) :CMU HP-HPLabs
+ GCLisp TI pyramid)
+(defvar *globally-special-variables* ())
+
+(defun variable-globally-special-p (symbol)
+ #+Genera (si:special-variable-p symbol)
+ #+Cloe-Runtime (compiler::specialp symbol)
+ #+Lucid (lucid::proclaimed-special-p symbol)
+ #+TI (get symbol 'special)
+ #+Xerox (il:variable-globally-special-p symbol)
+ #+(and dec vax common) (get symbol 'system::globally-special)
+ #+(or KCL IBCL) (si:specialp symbol)
+ #+excl (get symbol 'excl::.globally-special.)
+ #+:CMU (eq (ext:info variable kind symbol) :special)
+ #+HP-HPLabs (member (get symbol 'impl:vartype)
+ '(impl:fluid impl:global)
+ :test #'eq)
+ #+:GCLISP (gclisp::special-p symbol)
+ #+pyramid (or (get symbol 'lisp::globally-special)
+ (get symbol
+ 'clc::globally-special-in-compiler))
+ #+:CORAL (ccl::proclaimed-special-p symbol)
+ #-(or Genera Cloe-Runtime Lucid Xerox Excl KCL IBCL (and dec vax common) :CMU HP-HPLabs
+ GCLisp TI pyramid :CORAL)
+ (or (not (null (member symbol *globally-special-variables* :test #'eq)))
+ (when (eval `(flet ((ref () ,symbol))
+ (let ((,symbol '#,(list nil)))
+ (and (boundp ',symbol) (eq ,symbol (ref))))))
+ (push symbol *globally-special-variables*)
+ t)))
+
+
+ ;;
+;;;;;; Handling of special forms (the infamous 24).
+ ;;
+;;;
+;;; and I quote...
+;;;
+;;; The set of special forms is purposely kept very small because
+;;; any program analyzing program (read code walker) must have
+;;; special knowledge about every type of special form. Such a
+;;; program needs no special knowledge about macros...
+;;;
+;;; So all we have to do here is a define a way to store and retrieve
+;;; templates which describe how to walk the 24 special forms and we are all
+;;; set...
+;;;
+;;; Well, its a nice concept, and I have to admit to being naive enough that
+;;; I believed it for a while, but not everyone takes having only 24 special
+;;; forms as seriously as might be nice. There are (at least) 3 ways to
+;;; lose:
+;;
+;;; 1 - Implementation x implements a Common Lisp special form as a macro
+;;; which expands into a special form which:
+;;; - Is a common lisp special form (not likely)
+;;; - Is not a common lisp special form (on the 3600 IF --> COND).
+;;;
+;;; * We can safe ourselves from this case (second subcase really) by
+;;; checking to see if there is a template defined for something
+;;; before we check to see if we we can macroexpand it.
+;;;
+;;; 2 - Implementation x implements a Common Lisp macro as a special form.
+;;;
+;;; * This is a screw, but not so bad, we save ourselves from it by
+;;; defining extra templates for the macros which are *likely* to
+;;; be implemented as special forms. (DO, DO* ...)
+;;;
+;;; 3 - Implementation x has a special form which is not on the list of
+;;; Common Lisp special forms.
+;;;
+;;; * This is a bad sort of a screw and happens more than I would like
+;;; to think, especially in the implementations which provide more
+;;; than just Common Lisp (3600, Xerox etc.).
+;;; The fix is not terribly staisfactory, but will have to do for
+;;; now. There is a hook in get walker-template which can get a
+;;; template from the implementation's own walker. That template
+;;; has to be converted, and so it may be that the right way to do
+;;; this would actually be for that implementation to provide an
+;;; interface to its walker which looks like the interface to this
+;;; walker.
+;;;
+
+(eval-when (compile load eval)
+
+(defmacro get-walker-template-internal (x) ;Has to be inside eval-when because
+ `(get ,x 'walker-template)) ;Golden Common Lisp doesn't hack
+ ;compile time definition of macros
+ ;right for setf.
+
+(defmacro define-walker-template
+ (name &optional (template '(nil repeat (eval))))
+ `(eval-when (load eval)
+ (setf (get-walker-template-internal ',name) ',template)))
+)
+
+(defun get-walker-template (x)
+ (cond ((symbolp x)
+ (or (get-walker-template-internal x)
+ (get-implementation-dependent-walker-template x)))
+ ((and (listp x)
+ (or (eq (car x) 'lambda)
+ #+cmu17 (eq (car x) 'kernel:instance-lambda)))
+ '(lambda repeat (eval)))
+ (t
+ (error "Can't get template for ~S" x))))
+
+(defun get-implementation-dependent-walker-template (x)
+ (declare (ignore x))
+ ())
+
+
+ ;;
+;;;;;; The actual templates
+ ;;
+
+(define-walker-template BLOCK (NIL NIL REPEAT (EVAL)))
+(define-walker-template CATCH (NIL EVAL REPEAT (EVAL)))
+(define-walker-template COMPILER-LET walk-compiler-let)
+(define-walker-template DECLARE walk-unexpected-declare)
+(define-walker-template EVAL-WHEN (NIL QUOTE REPEAT (EVAL)))
+(define-walker-template FLET walk-flet)
+(define-walker-template FUNCTION (NIL CALL))
+(define-walker-template GO (NIL QUOTE))
+(define-walker-template IF walk-if)
+(define-walker-template LABELS walk-labels)
+(define-walker-template LAMBDA walk-lambda)
+(define-walker-template LET walk-let)
+(define-walker-template LET* walk-let*)
+(define-walker-template LOCALLY walk-locally)
+(define-walker-template MACROLET walk-macrolet)
+(define-walker-template MULTIPLE-VALUE-CALL (NIL EVAL REPEAT (EVAL)))
+(define-walker-template MULTIPLE-VALUE-PROG1 (NIL RETURN REPEAT (EVAL)))
+(define-walker-template MULTIPLE-VALUE-SETQ walk-multiple-value-setq)
+(define-walker-template MULTIPLE-VALUE-BIND walk-multiple-value-bind)
+(define-walker-template PROGN (NIL REPEAT (EVAL)))
+(define-walker-template PROGV (NIL EVAL EVAL REPEAT (EVAL)))
+(define-walker-template QUOTE (NIL QUOTE))
+(define-walker-template RETURN-FROM (NIL QUOTE REPEAT (RETURN)))
+(define-walker-template SETQ walk-setq)
+(define-walker-template SYMBOL-MACROLET walk-symbol-macrolet)
+(define-walker-template TAGBODY walk-tagbody)
+(define-walker-template THE (NIL QUOTE EVAL))
+#+cmu(define-walker-template EXT:TRULY-THE (NIL QUOTE EVAL))
+(define-walker-template THROW (NIL EVAL EVAL))
+(define-walker-template UNWIND-PROTECT (NIL RETURN REPEAT (EVAL)))
+
+;;; The new special form.
+;(define-walker-template pcl::LOAD-TIME-EVAL (NIL EVAL))
+
+;;;
+;;; And the extra templates...
+;;;
+(define-walker-template DO walk-do)
+(define-walker-template DO* walk-do*)
+(define-walker-template PROG walk-prog)
+(define-walker-template PROG* walk-prog*)
+(define-walker-template COND (NIL REPEAT ((TEST REPEAT (EVAL)))))
+
+#+Genera
+(progn
+ (define-walker-template zl::named-lambda walk-named-lambda)
+ (define-walker-template SCL:LETF walk-let)
+ (define-walker-template SCL:LETF* walk-let*)
+ )
+
+#+Lucid
+(progn
+ (define-walker-template #+LCL3.0 lucid-common-lisp:named-lambda
+ #-LCL3.0 sys:named-lambda walk-named-lambda)
+ )
+
+#+(or KCL IBCL)
+(progn
+ (define-walker-template lambda-block walk-named-lambda);Not really right,
+ ;we don't hack block
+ ;names anyways.
+ )
+
+#+TI
+(progn
+ (define-walker-template TICL::LET-IF walk-let-if)
+ )
+
+#+:Coral
+(progn
+ (define-walker-template ccl:%stack-block walk-let)
+ )
+
+#+cmu17
+(progn
+ (define-walker-template kernel:instance-lambda walk-lambda)
+ )
+
+
+
+(defvar walk-form-expand-macros-p nil)
+
+(defun macroexpand-all (form &optional environment)
+ (let ((walk-form-expand-macros-p t))
+ (walk-form form environment)))
+
+(defun WALK-FORM (form
+ &optional environment
+ (walk-function
+ #'(lambda (subform context env)
+ (declare (ignore context env))
+ subform)))
+ (walker-environment-bind (new-env environment :walk-function walk-function)
+ (walk-form-internal form :eval new-env)))
+
+;;;
+;;; nested-walk-form provides an interface that allows nested macros, each
+;;; of which must walk their body to just do one walk of the body of the
+;;; inner macro. That inner walk is done with a walk function which is the
+;;; composition of the two walk functions.
+;;;
+;;; This facility works by having the walker annotate the environment that
+;;; it passes to macroexpand-1 to know which form is being macroexpanded.
+;;; If then the &whole argument to the macroexpansion function is eq to
+;;; the env-walk-form of the environment, nested-walk-form can be certain
+;;; that there are no intervening layers and that a nested walk is alright.
+;;;
+;;; There are some semantic problems with this facility. In particular, if
+;;; the outer walk function returns T as its walk-no-more-p value, this will
+;;; prevent the inner walk function from getting a chance to walk the subforms
+;;; of the form. This is almost never what you want, since it destroys the
+;;; equivalence between this nested-walk-form function and two seperate
+;;; walk-forms.
+;;;
+(defun NESTED-WALK-FORM (whole
+ form
+ &optional environment
+ (walk-function
+ #'(lambda (subform context env)
+ (declare (ignore context env))
+ subform)))
+ (if (eq whole (env-walk-form environment))
+ (let ((outer-walk-function (env-walk-function environment)))
+ (throw whole
+ (walk-form
+ form
+ environment
+ #'(lambda (f c e)
+ ;; First loop to make sure the inner walk function
+ ;; has done all it wants to do with this form.
+ ;; Basically, what we are doing here is providing
+ ;; the same contract walk-form-internal normally
+ ;; provides to the inner walk function.
+ (let ((inner-result nil)
+ (inner-no-more-p nil)
+ (outer-result nil)
+ (outer-no-more-p nil))
+ (loop
+ (multiple-value-setq (inner-result inner-no-more-p)
+ (funcall walk-function f c e))
+ (cond (inner-no-more-p (return))
+ ((not (eq inner-result f)))
+ ((not (consp inner-result)) (return))
+ ((get-walker-template (car inner-result)) (return))
+ (t
+ (multiple-value-bind (expansion macrop)
+ (walker-environment-bind
+ (new-env e :walk-form inner-result)
+ (macroexpand-1 inner-result new-env))
+ (if macrop
+ (setq inner-result expansion)
+ (return)))))
+ (setq f inner-result))
+ (multiple-value-setq (outer-result outer-no-more-p)
+ (funcall outer-walk-function
+ inner-result
+ c
+ e))
+ (values outer-result
+ (and inner-no-more-p outer-no-more-p)))))))
+ (walk-form form environment walk-function)))
+
+;;;
+;;; WALK-FORM-INTERNAL is the main driving function for the code walker. It
+;;; takes a form and the current context and walks the form calling itself or
+;;; the appropriate template recursively.
+;;;
+;;; "It is recommended that a program-analyzing-program process a form
+;;; that is a list whose car is a symbol as follows:
+;;;
+;;; 1. If the program has particular knowledge about the symbol,
+;;; process the form using special-purpose code. All of the
+;;; standard special forms should fall into this category.
+;;; 2. Otherwise, if macro-function is true of the symbol apply
+;;; either macroexpand or macroexpand-1 and start over.
+;;; 3. Otherwise, assume it is a function call. "
+;;;
+
+(defun walk-form-internal (form context env)
+ ;; First apply the walk-function to perform whatever translation
+ ;; the user wants to this form. If the second value returned
+ ;; by walk-function is T then we don't recurse...
+ (catch form
+ (multiple-value-bind (newform walk-no-more-p)
+ (funcall (env-walk-function env) form context env)
+ (catch newform
+ (cond
+ (walk-no-more-p newform)
+ ((not (eq form newform))
+ (walk-form-internal newform context env))
+ ((not (consp newform))
+ (let ((symmac (car (variable-symbol-macro-p newform env))))
+ (if symmac
+ (let ((newnewform (walk-form-internal (cddr symmac)
+ context env)))
+ (if (eq newnewform (cddr symmac))
+ (if walk-form-expand-macros-p newnewform newform)
+ newnewform))
+ newform)))
+ (t
+ (let* ((fn (car newform))
+ (template (get-walker-template fn)))
+ (if template
+ (if (symbolp template)
+ (funcall template newform context env)
+ (walk-template newform template context env))
+ (multiple-value-bind
+ (newnewform macrop)
+ (walker-environment-bind
+ (new-env env :walk-form newform)
+ (macroexpand-1 newform new-env))
+ (cond
+ (macrop
+ (let ((newnewnewform (walk-form-internal newnewform context
+ env)))
+ (if (eq newnewnewform newnewform)
+ (if walk-form-expand-macros-p newnewform newform)
+ newnewnewform)))
+ ((and (symbolp fn)
+ (not (fboundp fn))
+ #+cmu17
+ (special-operator-p fn)
+ #-cmu17
+ (special-form-p fn))
+ (error
+ "~S is a special form, not defined in the CommonLisp.~%~
+ manual This code walker doesn't know how to walk it.~%~
+ Define a template for this special form and try again."
+ fn))
+ (t
+ ;; Otherwise, walk the form as if its just a standard
+ ;; functioncall using a template for standard function
+ ;; call.
+ (walk-template
+ newnewform '(call repeat (eval)) context env))))))))))))
+
+(defun walk-template (form template context env)
+ (if (atom template)
+ (ecase template
+ ((EVAL FUNCTION TEST EFFECT RETURN)
+ (walk-form-internal form :EVAL env))
+ ((QUOTE NIL) form)
+ (SET
+ (walk-form-internal form :SET env))
+ ((LAMBDA CALL)
+ (cond ((or (symbolp form)
+ (and (listp form)
+ (= (length form) 2)
+ (eq (car form) 'setf)))
+ form)
+ #+Lispm
+ ((sys:validate-function-spec form) form)
+ (t (walk-form-internal form context env)))))
+ (case (car template)
+ (REPEAT
+ (walk-template-handle-repeat form
+ (cdr template)
+ ;; For the case where nothing happens
+ ;; after the repeat optimize out the
+ ;; call to length.
+ (if (null (cddr template))
+ ()
+ (nthcdr (- (length form)
+ (length
+ (cddr template)))
+ form))
+ context
+ env))
+ (IF
+ (walk-template form
+ (if (if (listp (cadr template))
+ (eval (cadr template))
+ (funcall (cadr template) form))
+ (caddr template)
+ (cadddr template))
+ context
+ env))
+ (REMOTE
+ (walk-template form (cadr template) context env))
+ (otherwise
+ (cond ((atom form) form)
+ (t (recons form
+ (walk-template
+ (car form) (car template) context env)
+ (walk-template
+ (cdr form) (cdr template) context env))))))))
+
+(defun walk-template-handle-repeat (form template stop-form context env)
+ (if (eq form stop-form)
+ (walk-template form (cdr template) context env)
+ (walk-template-handle-repeat-1 form
+ template
+ (car template)
+ stop-form
+ context
+ env)))
+
+(defun walk-template-handle-repeat-1 (form template repeat-template
+ stop-form context env)
+ (cond ((null form) ())
+ ((eq form stop-form)
+ (if (null repeat-template)
+ (walk-template stop-form (cdr template) context env)
+ (error "While handling repeat:
+ ~%~Ran into stop while still in repeat template.")))
+ ((null repeat-template)
+ (walk-template-handle-repeat-1
+ form template (car template) stop-form context env))
+ (t
+ (recons form
+ (walk-template (car form) (car repeat-template) context env)
+ (walk-template-handle-repeat-1 (cdr form)
+ template
+ (cdr repeat-template)
+ stop-form
+ context
+ env)))))
+
+(defun walk-repeat-eval (form env)
+ (and form
+ (recons form
+ (walk-form-internal (car form) :eval env)
+ (walk-repeat-eval (cdr form) env))))
+
+(defun recons (x car cdr)
+ (if (or (not (eq (car x) car))
+ (not (eq (cdr x) cdr)))
+ (cons car cdr)
+ x))
+
+(defun relist (x &rest args)
+ (if (null args)
+ nil
+ (relist-internal x args nil)))
+
+(defun relist* (x &rest args)
+ (relist-internal x args 't))
+
+(defun relist-internal (x args *p)
+ (if (null (cdr args))
+ (if *p
+ (car args)
+ (recons x (car args) nil))
+ (recons x
+ (car args)
+ (relist-internal (cdr x) (cdr args) *p))))
+
+
+ ;;
+;;;;;; Special walkers
+ ;;
+
+(defun walk-declarations (body fn env
+ &optional doc-string-p declarations old-body
+ &aux (form (car body)) macrop new-form)
+ (cond ((and (stringp form) ;might be a doc string
+ (cdr body) ;isn't the returned value
+ (null doc-string-p) ;no doc string yet
+ (null declarations)) ;no declarations yet
+ (recons body
+ form
+ (walk-declarations (cdr body) fn env t)))
+ ((and (listp form) (eq (car form) 'declare))
+ ;; Got ourselves a real live declaration. Record it, look for more.
+ (dolist (declaration (cdr form))
+ (let ((type (car declaration))
+ (name (cadr declaration))
+ (args (cddr declaration)))
+ (if (member type *variable-declarations*)
+ (note-declaration `(,type
+ ,(or (variable-lexical-p name env) name)
+ ,.args)
+ env)
+ (note-declaration declaration env))
+ (push declaration declarations)))
+ (recons body
+ form
+ (walk-declarations
+ (cdr body) fn env doc-string-p declarations)))
+ ((and form
+ (listp form)
+ (null (get-walker-template (car form)))
+ (progn
+ (multiple-value-setq (new-form macrop)
+ (macroexpand-1 form env))
+ macrop))
+ ;; This form was a call to a macro. Maybe it expanded
+ ;; into a declare? Recurse to find out.
+ (walk-declarations (recons body new-form (cdr body))
+ fn env doc-string-p declarations
+ (or old-body body)))
+ (t
+ ;; Now that we have walked and recorded the declarations,
+ ;; call the function our caller provided to expand the body.
+ ;; We call that function rather than passing the real-body
+ ;; back, because we are RECONSING up the new body.
+ (funcall fn (or old-body body) env))))
+
+
+(defun walk-unexpected-declare (form context env)
+ (declare (ignore context env))
+ (warn "Encountered declare ~S in a place where a declare was not expected."
+ form)
+ form)
+
+(defun walk-arglist (arglist context env &optional (destructuringp nil)
+ &aux arg)
+ (cond ((null arglist) ())
+ ((symbolp (setq arg (car arglist)))
+ (or (member arg lambda-list-keywords)
+ (note-lexical-binding arg env))
+ (recons arglist
+ arg
+ (walk-arglist (cdr arglist)
+ context
+ env
+ (and destructuringp
+ (not (member arg
+ lambda-list-keywords))))))
+ ((consp arg)
+ (prog1 (recons arglist
+ (if destructuringp
+ (walk-arglist arg context env destructuringp)
+ (relist* arg
+ (car arg)
+ (walk-form-internal (cadr arg) :eval env)
+ (cddr arg)))
+ (walk-arglist (cdr arglist) context env nil))
+ (if (symbolp (car arg))
+ (note-lexical-binding (car arg) env)
+ (note-lexical-binding (cadar arg) env))
+ (or (null (cddr arg))
+ (not (symbolp (caddr arg)))
+ (note-lexical-binding (caddr arg) env))))
+ (t
+ (error "Can't understand something in the arglist ~S" arglist))))
+
+(defun walk-let (form context env)
+ (walk-let/let* form context env nil))
+
+(defun walk-let* (form context env)
+ (walk-let/let* form context env t))
+
+(defun walk-prog (form context env)
+ (walk-prog/prog* form context env nil))
+
+(defun walk-prog* (form context env)
+ (walk-prog/prog* form context env t))
+
+(defun walk-do (form context env)
+ (walk-do/do* form context env nil))
+
+(defun walk-do* (form context env)
+ (walk-do/do* form context env t))
+
+(defun walk-let/let* (form context old-env sequentialp)
+ (walker-environment-bind (new-env old-env)
+ (let* ((let/let* (car form))
+ (bindings (cadr form))
+ (body (cddr form))
+ (walked-bindings
+ (walk-bindings-1 bindings
+ old-env
+ new-env
+ context
+ sequentialp))
+ (walked-body
+ (walk-declarations body #'walk-repeat-eval new-env)))
+ (relist*
+ form let/let* walked-bindings walked-body))))
+
+(defun walk-locally (form context env)
+ (declare (ignore context))
+ (let* ((locally (car form))
+ (body (cdr form))
+ (walked-body
+ (walk-declarations body #'walk-repeat-eval env)))
+ (relist*
+ form locally walked-body)))
+
+(defun walk-prog/prog* (form context old-env sequentialp)
+ (walker-environment-bind (new-env old-env)
+ (let* ((possible-block-name (second form))
+ (blocked-prog (and (symbolp possible-block-name)
+ (not (eq possible-block-name 'nil)))))
+ (multiple-value-bind (let/let* block-name bindings body)
+ (if blocked-prog
+ (values (car form) (cadr form) (caddr form) (cdddr form))
+ (values (car form) nil (cadr form) (cddr form)))
+ (let* ((walked-bindings
+ (walk-bindings-1 bindings
+ old-env
+ new-env
+ context
+ sequentialp))
+ (walked-body
+ (walk-declarations
+ body
+ #'(lambda (real-body real-env)
+ (walk-tagbody-1 real-body context real-env))
+ new-env)))
+ (if block-name
+ (relist*
+ form let/let* block-name walked-bindings walked-body)
+ (relist*
+ form let/let* walked-bindings walked-body)))))))
+
+(defun walk-do/do* (form context old-env sequentialp)
+ (walker-environment-bind (new-env old-env)
+ (let* ((do/do* (car form))
+ (bindings (cadr form))
+ (end-test (caddr form))
+ (body (cdddr form))
+ (walked-bindings (walk-bindings-1 bindings
+ old-env
+ new-env
+ context
+ sequentialp))
+ (walked-body
+ (walk-declarations body #'walk-repeat-eval new-env)))
+ (relist* form
+ do/do*
+ (walk-bindings-2 bindings walked-bindings context new-env)
+ (walk-template end-test '(test repeat (eval)) context new-env)
+ walked-body))))
+
+(defun walk-let-if (form context env)
+ (let ((test (cadr form))
+ (bindings (caddr form))
+ (body (cdddr form)))
+ (walk-form-internal
+ `(let ()
+ (declare (special ,@(mapcar #'(lambda (x) (if (listp x) (car x) x))
+ bindings)))
+ (flet ((.let-if-dummy. () ,@body))
+ (if ,test
+ (let ,bindings (.let-if-dummy.))
+ (.let-if-dummy.))))
+ context
+ env)))
+
+(defun walk-multiple-value-setq (form context env)
+ (let ((vars (cadr form)))
+ (if (some #'(lambda (var)
+ (variable-symbol-macro-p var env))
+ vars)
+ (let* ((temps (mapcar #'(lambda (var) (declare (ignore var)) (gensym)) vars))
+ (sets (mapcar #'(lambda (var temp) `(setq ,var ,temp)) vars temps))
+ (expanded `(multiple-value-bind ,temps
+ ,(caddr form)
+ ,@sets))
+ (walked (walk-form-internal expanded context env)))
+ (if (eq walked expanded)
+ form
+ walked))
+ (walk-template form '(nil (repeat (set)) eval) context env))))
+
+(defun walk-multiple-value-bind (form context old-env)
+ (walker-environment-bind (new-env old-env)
+ (let* ((mvb (car form))
+ (bindings (cadr form))
+ (mv-form (walk-template (caddr form) 'eval context old-env))
+ (body (cdddr form))
+ walked-bindings
+ (walked-body
+ (walk-declarations
+ body
+ #'(lambda (real-body real-env)
+ (setq walked-bindings
+ (walk-bindings-1 bindings
+ old-env
+ new-env
+ context
+ nil))
+ (walk-repeat-eval real-body real-env))
+ new-env)))
+ (relist* form mvb walked-bindings mv-form walked-body))))
+
+(defun walk-bindings-1 (bindings old-env new-env context sequentialp)
+ (and bindings
+ (let ((binding (car bindings)))
+ (recons bindings
+ (if (symbolp binding)
+ (prog1 binding
+ (note-lexical-binding binding new-env))
+ (prog1 (relist* binding
+ (car binding)
+ (walk-form-internal (cadr binding)
+ context
+ (if sequentialp
+ new-env
+ old-env))
+ (cddr binding)) ;save cddr for DO/DO*
+ ;it is the next value
+ ;form. Don't walk it
+ ;now though.
+ (note-lexical-binding (car binding) new-env)))
+ (walk-bindings-1 (cdr bindings)
+ old-env
+ new-env
+ context
+ sequentialp)))))
+
+(defun walk-bindings-2 (bindings walked-bindings context env)
+ (and bindings
+ (let ((binding (car bindings))
+ (walked-binding (car walked-bindings)))
+ (recons bindings
+ (if (symbolp binding)
+ binding
+ (relist* binding
+ (car walked-binding)
+ (cadr walked-binding)
+ (walk-template (cddr binding)
+ '(eval)
+ context
+ env)))
+ (walk-bindings-2 (cdr bindings)
+ (cdr walked-bindings)
+ context
+ env)))))
+
+(defun walk-lambda (form context old-env)
+ (walker-environment-bind (new-env old-env)
+ (let* ((arglist (cadr form))
+ (body (cddr form))
+ (walked-arglist (walk-arglist arglist context new-env))
+ (walked-body
+ (walk-declarations body #'walk-repeat-eval new-env)))
+ (relist* form
+ (car form)
+ walked-arglist
+ walked-body))))
+
+(defun walk-named-lambda (form context old-env)
+ (walker-environment-bind (new-env old-env)
+ (let* ((name (cadr form))
+ (arglist (caddr form))
+ (body (cdddr form))
+ (walked-arglist (walk-arglist arglist context new-env))
+ (walked-body
+ (walk-declarations body #'walk-repeat-eval new-env)))
+ (relist* form
+ (car form)
+ name
+ walked-arglist
+ walked-body))))
+
+(defun walk-setq (form context env)
+ (if (cdddr form)
+ (let* ((expanded (let ((rforms nil)
+ (tail (cdr form)))
+ (loop (when (null tail) (return (nreverse rforms)))
+ (let ((var (pop tail)) (val (pop tail)))
+ (push `(setq ,var ,val) rforms)))))
+ (walked (walk-repeat-eval expanded env)))
+ (if (eq expanded walked)
+ form
+ `(progn ,@walked)))
+ (let* ((var (cadr form))
+ (val (caddr form))
+ (symmac (car (variable-symbol-macro-p var env))))
+ (if symmac
+ (let* ((expanded `(setf ,(cddr symmac) ,val))
+ (walked (walk-form-internal expanded context env)))
+ (if (eq expanded walked)
+ form
+ walked))
+ (relist form 'setq
+ (walk-form-internal var :set env)
+ (walk-form-internal val :eval env))))))
+
+(defun walk-symbol-macrolet (form context old-env)
+ (declare (ignore context))
+ (let* ((bindings (cadr form)))
+ (walker-environment-bind
+ (new-env old-env
+ :lexical-variables
+ (append (mapcar #'(lambda (binding)
+ `(,(car binding)
+ :macro . ,(cadr binding)))
+ bindings)
+ (env-lexical-variables old-env)))
+ (relist* form 'symbol-macrolet bindings
+ (walk-repeat-eval (cddr form) new-env)))))
+
+(defun walk-tagbody (form context env)
+ (recons form (car form) (walk-tagbody-1 (cdr form) context env)))
+
+(defun walk-tagbody-1 (form context env)
+ (and form
+ (recons form
+ (walk-form-internal (car form)
+ (if (symbolp (car form)) 'quote context)
+ env)
+ (walk-tagbody-1 (cdr form) context env))))
+
+(defun walk-compiler-let (form context old-env)
+ (declare (ignore context))
+ (let ((vars ())
+ (vals ()))
+ (dolist (binding (cadr form))
+ (cond ((symbolp binding) (push binding vars) (push nil vals))
+ (t
+ (push (car binding) vars)
+ (push (eval (cadr binding)) vals))))
+ (relist* form
+ (car form)
+ (cadr form)
+ (progv vars vals (walk-repeat-eval (cddr form) old-env)))))
+
+(defun walk-macrolet (form context old-env)
+ (walker-environment-bind (macro-env
+ nil
+ :walk-function (env-walk-function old-env))
+ (labels ((walk-definitions (definitions)
+ (and definitions
+ (let ((definition (car definitions)))
+ (recons definitions
+ (relist* definition
+ (car definition)
+ (walk-arglist (cadr definition)
+ context
+ macro-env
+ t)
+ (walk-declarations (cddr definition)
+ #'walk-repeat-eval
+ macro-env))
+ (walk-definitions (cdr definitions)))))))
+ (with-new-definition-in-environment (new-env old-env form)
+ (relist* form
+ (car form)
+ (walk-definitions (cadr form))
+ (walk-declarations (cddr form)
+ #'walk-repeat-eval
+ new-env))))))
+
+(defun walk-flet (form context old-env)
+ (labels ((walk-definitions (definitions)
+ (if (null definitions)
+ ()
+ (recons definitions
+ (walk-lambda (car definitions) context old-env)
+ (walk-definitions (cdr definitions))))))
+ (recons form
+ (car form)
+ (recons (cdr form)
+ (walk-definitions (cadr form))
+ (with-new-definition-in-environment (new-env old-env form)
+ (walk-declarations (cddr form)
+ #'walk-repeat-eval
+ new-env))))))
+
+(defun walk-labels (form context old-env)
+ (with-new-definition-in-environment (new-env old-env form)
+ (labels ((walk-definitions (definitions)
+ (if (null definitions)
+ ()
+ (recons definitions
+ (walk-lambda (car definitions) context new-env)
+ (walk-definitions (cdr definitions))))))
+ (recons form
+ (car form)
+ (recons (cdr form)
+ (walk-definitions (cadr form))
+ (walk-declarations (cddr form)
+ #'walk-repeat-eval
+ new-env))))))
+
+(defun walk-if (form context env)
+ (let ((predicate (cadr form))
+ (arm1 (caddr form))
+ (arm2
+ (if (cddddr form)
+ (progn
+ (warn "In the form:~%~S~%~
+ IF only accepts three arguments, you are using ~D.~%~
+ It is true that some Common Lisps support this, but ~
+ it is not~%~
+ truly legal Common Lisp. For now, this code ~
+ walker is interpreting ~%~
+ the extra arguments as extra else clauses. ~
+ Even if this is what~%~
+ you intended, you should fix your source code."
+ form
+ (length (cdr form)))
+ (cons 'progn (cdddr form)))
+ (cadddr form))))
+ (relist form
+ 'if
+ (walk-form-internal predicate context env)
+ (walk-form-internal arm1 context env)
+ (walk-form-internal arm2 context env))))
+
+
+;;;
+;;; Tests tests tests
+;;;
+
+#|
+;;;
+;;; Here are some examples of the kinds of things you should be able to do
+;;; with your implementation of the macroexpansion environment hacking
+;;; mechanism.
+;;;
+;;; with-lexical-macros is kind of like macrolet, but it only takes names
+;;; of the macros and actual macroexpansion functions to use to macroexpand
+;;; them. The win about that is that for macros which want to wrap several
+;;; macrolets around their body, they can do this but have the macroexpansion
+;;; functions be compiled. See the WITH-RPUSH example.
+;;;
+;;; If the implementation had a special way of communicating the augmented
+;;; environment back to the evaluator that would be totally great. It would
+;;; mean that we could just augment the environment then pass control back
+;;; to the implementations own compiler or interpreter. We wouldn't have
+;;; to call the actual walker. That would make this much faster. Since the
+;;; principal client of this is defmethod it would make compiling defmethods
+;;; faster and that would certainly be a win.
+;;;
+(defmacro with-lexical-macros (macros &body body &environment old-env)
+ (with-augmented-environment (new-env old-env :macros macros)
+ (walk-form (cons 'progn body) :environment new-env)))
+
+(defun expand-rpush (form env)
+ `(push ,(caddr form) ,(cadr form)))
+
+(defmacro with-rpush (&body body)
+ `(with-lexical-macros ,(list (list 'rpush #'expand-rpush)) ,@body))
+
+
+;;;
+;;; Unfortunately, I don't have an automatic tester for the walker.
+;;; Instead there is this set of test cases with a description of
+;;; how each one should go.
+;;;
+(defmacro take-it-out-for-a-test-walk (form)
+ `(take-it-out-for-a-test-walk-1 ',form))
+
+(defun take-it-out-for-a-test-walk-1 (form)
+ (terpri)
+ (terpri)
+ (let ((copy-of-form (copy-tree form))
+ (result (walk-form form nil
+ #'(lambda (x y env)
+ (format t "~&Form: ~S ~3T Context: ~A" x y)
+ (when (symbolp x)
+ (let ((lexical (variable-lexical-p x env))
+ (special (variable-special-p x env)))
+ (when lexical
+ (format t ";~3T")
+ (format t "lexically bound"))
+ (when special
+ (format t ";~3T")
+ (format t "declared special"))
+ (when (boundp x)
+ (format t ";~3T")
+ (format t "bound: ~S " (eval x)))))
+ x))))
+ (cond ((not (equal result copy-of-form))
+ (format t "~%Warning: Result not EQUAL to copy of start."))
+ ((not (eq result form))
+ (format t "~%Warning: Result not EQ to copy of start.")))
+ (pprint result)
+ result))
+
+(defmacro foo (&rest ignore) ''global-foo)
+
+(defmacro bar (&rest ignore) ''global-bar)
+
+(take-it-out-for-a-test-walk (list arg1 arg2 arg3))
+(take-it-out-for-a-test-walk (list (cons 1 2) (list 3 4 5)))
+
+(take-it-out-for-a-test-walk (progn (foo) (bar 1)))
+
+(take-it-out-for-a-test-walk (block block-name a b c))
+(take-it-out-for-a-test-walk (block block-name (list a) b c))
+
+(take-it-out-for-a-test-walk (catch catch-tag (list a) b c))
+;;;
+;;; This is a fairly simple macrolet case. While walking the body of the
+;;; macro, x should be lexically bound. In the body of the macrolet form
+;;; itself, x should not be bound.
+;;;
+(take-it-out-for-a-test-walk
+ (macrolet ((foo (x) (list x) ''inner))
+ x
+ (foo 1)))
+
+;;;
+;;; A slightly more complex macrolet case. In the body of the macro x
+;;; should not be lexically bound. In the body of the macrolet form itself
+;;; x should be bound. Note that THIS CASE WILL CAUSE AN ERROR when it
+;;; tries to macroexpand the call to foo.
+;;;
+(take-it-out-for-a-test-walk
+ (let ((x 1))
+ (macrolet ((foo () (list x) ''inner))
+ x
+ (foo))))
+
+;;;
+;;; A truly hairy use of compiler-let and macrolet. In the body of the
+;;; macro x should not be lexically bound. In the body of the macrolet
+;;; itself x should not be lexically bound. But the macro should expand
+;;; into 1.
+;;;
+(take-it-out-for-a-test-walk
+ (compiler-let ((x 1))
+ (let ((x 2))
+ (macrolet ((foo () x))
+ x
+ (foo)))))
+
+
+(take-it-out-for-a-test-walk
+ (flet ((foo (x) (list x y))
+ (bar (x) (list x y)))
+ (foo 1)))
+
+(take-it-out-for-a-test-walk
+ (let ((y 2))
+ (flet ((foo (x) (list x y))
+ (bar (x) (list x y)))
+ (foo 1))))
+
+(take-it-out-for-a-test-walk
+ (labels ((foo (x) (bar x))
+ (bar (x) (foo x)))
+ (foo 1)))
+
+(take-it-out-for-a-test-walk
+ (flet ((foo (x) (foo x)))
+ (foo 1)))
+
+(take-it-out-for-a-test-walk
+ (flet ((foo (x) (foo x)))
+ (flet ((bar (x) (foo x)))
+ (bar 1))))
+
+(take-it-out-for-a-test-walk (compiler-let ((a 1) (b 2)) (foo a) b))
+(take-it-out-for-a-test-walk (prog () (declare (special a b))))
+(take-it-out-for-a-test-walk (let (a b c)
+ (declare (special a b))
+ (foo a) b c))
+(take-it-out-for-a-test-walk (let (a b c)
+ (declare (special a) (special b))
+ (foo a) b c))
+(take-it-out-for-a-test-walk (let (a b c)
+ (declare (special a))
+ (declare (special b))
+ (foo a) b c))
+(take-it-out-for-a-test-walk (let (a b c)
+ (declare (special a))
+ (declare (special b))
+ (let ((a 1))
+ (foo a) b c)))
+(take-it-out-for-a-test-walk (eval-when ()
+ a
+ (foo a)))
+(take-it-out-for-a-test-walk (eval-when (eval when load)
+ a
+ (foo a)))
+
+(take-it-out-for-a-test-walk (multiple-value-bind (a b) (foo a b) (list a b)))
+(take-it-out-for-a-test-walk (multiple-value-bind (a b)
+ (foo a b)
+ (declare (special a))
+ (list a b)))
+(take-it-out-for-a-test-walk (progn (function foo)))
+(take-it-out-for-a-test-walk (progn a b (go a)))
+(take-it-out-for-a-test-walk (if a b c))
+(take-it-out-for-a-test-walk (if a b))
+(take-it-out-for-a-test-walk ((lambda (a b) (list a b)) 1 2))
+(take-it-out-for-a-test-walk ((lambda (a b) (declare (special a)) (list a b))
+ 1 2))
+(take-it-out-for-a-test-walk (let ((a a) (b a) (c b)) (list a b c)))
+(take-it-out-for-a-test-walk (let* ((a a) (b a) (c b)) (list a b c)))
+(take-it-out-for-a-test-walk (let ((a a) (b a) (c b))
+ (declare (special a b))
+ (list a b c)))
+(take-it-out-for-a-test-walk (let* ((a a) (b a) (c b))
+ (declare (special a b))
+ (list a b c)))
+(take-it-out-for-a-test-walk (let ((a 1) (b 2))
+ (foo bar)
+ (declare (special a))
+ (foo a b)))
+(take-it-out-for-a-test-walk (multiple-value-call #'foo a b c))
+(take-it-out-for-a-test-walk (multiple-value-prog1 a b c))
+(take-it-out-for-a-test-walk (progn a b c))
+(take-it-out-for-a-test-walk (progv vars vals a b c))
+(take-it-out-for-a-test-walk (quote a))
+(take-it-out-for-a-test-walk (return-from block-name a b c))
+(take-it-out-for-a-test-walk (setq a 1))
+(take-it-out-for-a-test-walk (setq a (foo 1) b (bar 2) c 3))
+(take-it-out-for-a-test-walk (tagbody a b c (go a)))
+(take-it-out-for-a-test-walk (the foo (foo-form a b c)))
+(take-it-out-for-a-test-walk (throw tag-form a))
+(take-it-out-for-a-test-walk (unwind-protect (foo a b) d e f))
+
+(defmacro flet-1 (a b) ''outer)
+(defmacro labels-1 (a b) ''outer)
+
+(take-it-out-for-a-test-walk
+ (flet ((flet-1 (a b) () (flet-1 a b) (list a b)))
+ (flet-1 1 2)
+ (foo 1 2)))
+(take-it-out-for-a-test-walk
+ (labels ((label-1 (a b) () (label-1 a b)(list a b)))
+ (label-1 1 2)
+ (foo 1 2)))
+(take-it-out-for-a-test-walk (macrolet ((macrolet-1 (a b) (list a b)))
+ (macrolet-1 a b)
+ (foo 1 2)))
+
+(take-it-out-for-a-test-walk (macrolet ((foo (a) `(inner-foo-expanded ,a)))
+ (foo 1)))
+
+(take-it-out-for-a-test-walk (progn (bar 1)
+ (macrolet ((bar (a)
+ `(inner-bar-expanded ,a)))
+ (bar 2))))
+
+(take-it-out-for-a-test-walk (progn (bar 1)
+ (macrolet ((bar (s)
+ (bar s)
+ `(inner-bar-expanded ,s)))
+ (bar 2))))
+
+(take-it-out-for-a-test-walk (cond (a b)
+ ((foo bar) a (foo a))))
+
+
+(let ((the-lexical-variables ()))
+ (walk-form '(let ((a 1) (b 2))
+ #'(lambda (x) (list a b x y)))
+ ()
+ #'(lambda (form context env)
+ (when (and (symbolp form)
+ (variable-lexical-p form env))
+ (push form the-lexical-variables))
+ form))
+ (or (and (= (length the-lexical-variables) 3)
+ (member 'a the-lexical-variables)
+ (member 'b the-lexical-variables)
+ (member 'x the-lexical-variables))
+ (error "Walker didn't do lexical variables of a closure properly.")))
+
+|#
+
+()
+
generated by cgit v1.2.3 (git 2.25.1) at 2025年09月01日 18:22:30 +0000

AltStyle によって変換されたページ (->オリジナル) /