changelog shortlog graph tags branches files raw help

Mercurial > core / changeset: log def macros

changeset 223: b9ebec84fc18
parent 222: 83e823b80219
child 224: fdea20982c25
author: Richard Westhaver <ellis@rwest.io>
date: Thu, 07 Mar 2024 23:06:25 -0500
files: lisp/ffi/nuklear/nuklear.asd lisp/ffi/nuklear/pkg.lisp lisp/lib/log/err.lisp lisp/lib/log/log.asd lisp/lib/log/log.lisp lisp/lib/log/pkg.lisp lisp/lib/log/sink.lisp lisp/lib/log/source.lisp lisp/lib/log/stream.lisp lisp/std/defpkg.lisp lisp/std/util.lisp std
description: log def macros
     1.1--- a/lisp/ffi/nuklear/nuklear.asd	Sun Mar 03 20:50:37 2024 -0500
     1.2+++ b/lisp/ffi/nuklear/nuklear.asd	Thu Mar 07 23:06:25 2024 -0500
     1.3@@ -0,0 +1,24 @@
     1.4+;;; nuklear.asd --- NUKLEAR SYSTEMS
     1.5+(eval-when (:compile-toplevel :load-toplevel :execute)
     1.6+  (require :sb-grovel))
     1.7+
     1.8+(defpackage :nuklear.sys
     1.9+  (:use :cl :asdf :sb-grovel :sb-alien))
    1.10+
    1.11+(in-package :nuklear.sys)
    1.12+
    1.13+(defsystem "nuklear"
    1.14+  :version "0.1.0"
    1.15+  :license (:file "LICENSE")
    1.16+  :maintainer "ellis <ellis@rwest.io>"
    1.17+  :bug-tracker "https://vc.compiler.company/comp/core/issues"
    1.18+  :depends-on (:sb-grovel :std)
    1.19+  :components ((:file "pkg")
    1.20+               (grovel-constants-file "constants"
    1.21+                                      :package :nuklear))
    1.22+  :in-order-to ((test-op (test-op "nuklear/tests"))))
    1.23+
    1.24+(defsystem "nuklear/tests"
    1.25+  :depends-on (:rt :nuklear)
    1.26+  :components ((:file "tests"))
    1.27+  :perform (test-op (op c) (uiop:symbol-call '#:rt '#:do-tests :nuklear)))
     2.1--- a/lisp/ffi/nuklear/pkg.lisp	Sun Mar 03 20:50:37 2024 -0500
     2.2+++ b/lisp/ffi/nuklear/pkg.lisp	Thu Mar 07 23:06:25 2024 -0500
     2.3@@ -1,28 +1,4 @@
     2.4-;;; nuklear.asd --- NUKLEAR SYSTEMS
     2.5-
     2.6-;; NUKLEAR for lisp.
     2.7-
     2.8-;;; Code:
     2.9-(eval-when (:compile-toplevel :load-toplevel :execute)
    2.10-  (require :sb-grovel))
    2.11-
    2.12-(defpackage :nuklear.sys
    2.13-  (:use :cl :asdf :sb-grovel :sb-alien))
    2.14-
    2.15-(in-package :nuklear.sys)
    2.16+(defpackage :nuklear
    2.17+  (:use :cl :std))
    2.18 
    2.19-(defsystem "nuklear"
    2.20-  :version "0.1.0"
    2.21-  :license (:file "LICENSE")
    2.22-  :maintainer "ellis <ellis@rwest.io>"
    2.23-  :bug-tracker "https://vc.compiler.company/comp/core/issues"
    2.24-  :depends-on (:sb-grovel :std)
    2.25-  :components ((:file "pkg")
    2.26-               (grovel-constants-file "constants"
    2.27-                                      :package :nuklear))
    2.28-  :in-order-to ((test-op (test-op "nuklear/tests"))))
    2.29-
    2.30-(defsystem "nuklear/tests"
    2.31-  :depends-on (:rt :nuklear)
    2.32-  :components ((:file "tests"))
    2.33-  :perform (test-op (op c) (uiop:symbol-call '#:rt '#:do-tests :nuklear)))
    2.34+(in-package :nuklear)
     3.1--- a/lisp/lib/log/err.lisp	Sun Mar 03 20:50:37 2024 -0500
     3.2+++ b/lisp/lib/log/err.lisp	Thu Mar 07 23:06:25 2024 -0500
     3.3@@ -1,4 +1,7 @@
     3.4+;; log/err.lisp --- errors which may be signalled durring logging
     3.5+
     3.6+;;; Code:
     3.7 (in-package :log)
     3.8 
     3.9-(define-condition log-error (simple-error program-error) ()
    3.10+(define-condition log-error (std-error simple-error program-error) ()
    3.11   (:documentation "Base class for all LOG errors"))
     4.1--- a/lisp/lib/log/log.asd	Sun Mar 03 20:50:37 2024 -0500
     4.2+++ b/lisp/lib/log/log.asd	Thu Mar 07 23:06:25 2024 -0500
     4.3@@ -5,8 +5,7 @@
     4.4   :components ((:file "pkg")
     4.5                (:file "err")
     4.6                (:file "log")
     4.7-               (:file "source")
     4.8-               (:file "sink"))
     4.9+               (:file "stream"))
    4.10   :in-order-to ((test-op (test-op "log/tests"))))
    4.11 
    4.12 (defsystem :log/tests
     5.1--- a/lisp/lib/log/log.lisp	Sun Mar 03 20:50:37 2024 -0500
     5.2+++ b/lisp/lib/log/log.lisp	Thu Mar 07 23:06:25 2024 -0500
     5.3@@ -2,11 +2,11 @@
     5.4 
     5.5 (deftype log-level-designator () '(member :warn :debug :info :trace))
     5.6 (declaim (type (or boolean log-level-designator) *log-level*))
     5.7-(defparameter *log-level* nil)
     5.8-(defparameter *logger* nil)
     5.9-(defparameter *log-router* nil)
    5.10+(defvar *log-level* nil)
    5.11+(defvar *logger* nil)
    5.12+(defvar *log-router* nil)
    5.13 (declaim (type (or boolean function) *log-timestamp*))
    5.14-(defparameter *log-timestamp* t 
    5.15+(defvar *log-timestamp* t 
    5.16   "If non-nil, print a timestamp with log output. The value may be a
    5.17 function in which case it is used as the function value of
    5.18 `log-timestamp-source'.")
    5.19@@ -39,6 +39,30 @@
    5.20 ;; TODO: (defmacro generate-log-profile)
    5.21 ;; (defmacro with-log-profile)
    5.22 ;; (defmacro with-logger)
    5.23+(defmacro define-log-level (name)
    5.24+  (let ((%name (string-upcase name)))
    5.25+    `(progn
    5.26+       (defun ,(intern (concatenate 'string %name "!")) (&rest args)
    5.27+         (format t ":~A:~A~%"
    5.28+                 ',name
    5.29+                 (if *log-timestamp*
    5.30+                     (format nil "~A ~t" (log-timestamp-source))
    5.31+                     ""))
    5.32+         (map nil (lambda (x) (format t "~X~%" x)) args)
    5.33+         (if (= 1 (length args))
    5.34+             (car args)
    5.35+             args))
    5.36+       (defun ,(intern (concatenate 'string %name "-P")) ()
    5.37+         (eql *log-level* ,(sb-int:keywordicate name)))
    5.38+       (defun ,(intern (concatenate 'string %name "-DESCRIBE")) (&rest args)
    5.39+         (,(intern (concatenate 'string %name "!")) (apply #'describe args))))))
    5.40+
    5.41+(define-log-level info)
    5.42+(define-log-level trace)
    5.43+(define-log-level warn)
    5.44+(define-log-level debug)
    5.45+
    5.46+#+nil (test! "foo")
    5.47 
    5.48 (defmacro info! (opts &rest args))
    5.49 
    5.50@@ -64,4 +88,4 @@
    5.51 
    5.52 (defun debug-describe (&rest args)
    5.53   (debug! (apply #'describe args)))
    5.54-    
    5.55+
     6.1--- a/lisp/lib/log/pkg.lisp	Sun Mar 03 20:50:37 2024 -0500
     6.2+++ b/lisp/lib/log/pkg.lisp	Thu Mar 07 23:06:25 2024 -0500
     6.3@@ -25,6 +25,8 @@
     6.4 ;;; Code:
     6.5 (defpackage :log
     6.6   (:use :cl :std)
     6.7-  (:export :*log-level* :log-level-designator :log-timestamp-source 
     6.8-   :log! :warn! :info! :debug! :trace!  :dbg!
     6.9-   :debug-p))
    6.10+  (:export :*log-level* :*log-router* :*logger*
    6.11+   :*log-timestmap* :log-level-designator :log-timestamp-source  :logger
    6.12+   :define-log-level :log! :warn! :info! :debug! :trace!
    6.13+   :log-p :warn-p :info-p :debug-p :trace-p
    6.14+   :log-describe :warn-describe :info-describe :debug-describe :trace-describe))
     8.1--- a/lisp/lib/log/source.lisp	Sun Mar 03 20:50:37 2024 -0500
     8.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3@@ -1,1 +0,0 @@
     8.4-(in-package :log)
     9.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2+++ b/lisp/lib/log/stream.lisp	Thu Mar 07 23:06:25 2024 -0500
     9.3@@ -0,0 +1,2 @@
     9.4+;;; log/stream.lisp --- Logging streams
     9.5+(in-package :log)
    10.1--- a/lisp/std/defpkg.lisp	Sun Mar 03 20:50:37 2024 -0500
    10.2+++ b/lisp/std/defpkg.lisp	Thu Mar 07 23:06:25 2024 -0500
    10.3@@ -7,4 +7,702 @@
    10.4 ;;; Code:
    10.5 (in-package :std)
    10.6 
    10.7+(eval-when (:load-toplevel :compile-toplevel :execute)
    10.8+  (defun find-package* (package-designator &optional (error t))
    10.9+    (let ((package (find-package package-designator)))
   10.10+      (cond
   10.11+        (package package)
   10.12+        (error (error "No package named ~S" (string package-designator)))
   10.13+        (t nil))))
   10.14+  (defun find-symbol* (name package-designator &optional (error t))
   10.15+    "Find a symbol in a package of given string'ified NAME;
   10.16+unlike CL:FIND-SYMBOL, work well with 'modern' case sensitive syntax
   10.17+by letting you supply a symbol or keyword for the name;
   10.18+also works well when the package is not present.
   10.19+If optional ERROR argument is NIL, return NIL instead of an error
   10.20+when the symbol is not found."
   10.21+    (block nil
   10.22+      (let ((package (find-package* package-designator error)))
   10.23+        (when package ;; package error handled by find-package* already
   10.24+          (multiple-value-bind (symbol status) (find-symbol (string name) package)
   10.25+            (cond
   10.26+              (status (return (values symbol status)))
   10.27+              (error (error "There is no symbol ~S in package ~S" name (package-name package))))))
   10.28+        (values nil nil))))
   10.29+  (defun symbol-call (package name &rest args)
   10.30+    "Call a function associated with symbol of given name in given package,
   10.31+with given ARGS. Useful when the call is read before the package is loaded,
   10.32+or when loading the package is optional."
   10.33+    (apply (find-symbol* name package) args))
   10.34+  (defun intern* (name package-designator &optional (error t))
   10.35+    (intern (string name) (find-package* package-designator error)))
   10.36+  (defun export* (name package-designator)
   10.37+    (let* ((package (find-package* package-designator))
   10.38+           (symbol (intern* name package)))
   10.39+      (export (or symbol (list symbol)) package)))
   10.40+  (defun import* (symbol package-designator)
   10.41+    (import (or symbol (list symbol)) (find-package* package-designator)))
   10.42+  (defun shadowing-import* (symbol package-designator)
   10.43+    (shadowing-import (or symbol (list symbol)) (find-package* package-designator)))
   10.44+  (defun shadow* (name package-designator)
   10.45+    (shadow (list (string name)) (find-package* package-designator)))
   10.46+  (defun make-symbol* (name)
   10.47+    (etypecase name
   10.48+      (string (make-symbol name))
   10.49+      (symbol (copy-symbol name))))
   10.50+  (defun unintern* (name package-designator &optional (error t))
   10.51+    (block nil
   10.52+      (let ((package (find-package* package-designator error)))
   10.53+        (when package
   10.54+          (multiple-value-bind (symbol status) (find-symbol* name package error)
   10.55+            (cond
   10.56+              (status (unintern symbol package)
   10.57+                      (return (values symbol status)))
   10.58+              (error (error "symbol ~A not present in package ~A"
   10.59+                            (string symbol) (package-name package))))))
   10.60+        (values nil nil))))
   10.61+  (defun symbol-shadowing-p (symbol package)
   10.62+    (and (member symbol (package-shadowing-symbols package)) t))
   10.63+  (defun home-package-p (symbol package)
   10.64+    (and package (let ((sp (symbol-package symbol)))
   10.65+                   (and sp (let ((pp (find-package* package)))
   10.66+                             (and pp (eq sp pp))))))))
   10.67 
   10.68+
   10.69+(eval-when (:load-toplevel :compile-toplevel :execute)
   10.70+  (defun symbol-package-name (symbol)
   10.71+    (let ((package (symbol-package symbol)))
   10.72+      (and package (package-name package))))
   10.73+  (defun standard-common-lisp-symbol-p (symbol)
   10.74+    (multiple-value-bind (sym status) (find-symbol* symbol :common-lisp nil)
   10.75+      (and (eq sym symbol) (eq status :external))))
   10.76+  (defun reify-package (package &optional package-context)
   10.77+    (if (eq package package-context) t
   10.78+        (etypecase package
   10.79+          (null nil)
   10.80+          ((eql (find-package :cl)) :cl)
   10.81+          (package (package-name package)))))
   10.82+  (defun unreify-package (package &optional package-context)
   10.83+    (etypecase package
   10.84+      (null nil)
   10.85+      ((eql t) package-context)
   10.86+      ((or symbol string) (find-package package))))
   10.87+  (defun reify-symbol (symbol &optional package-context)
   10.88+    (etypecase symbol
   10.89+      ((or keyword (satisfies standard-common-lisp-symbol-p)) symbol)
   10.90+      (symbol (vector (symbol-name symbol)
   10.91+                      (reify-package (symbol-package symbol) package-context)))))
   10.92+  (defun unreify-symbol (symbol &optional package-context)
   10.93+    (etypecase symbol
   10.94+      (symbol symbol)
   10.95+      ((simple-vector 2)
   10.96+       (let* ((symbol-name (svref symbol 0))
   10.97+              (package-foo (svref symbol 1))
   10.98+              (package (unreify-package package-foo package-context)))
   10.99+         (if package (intern* symbol-name package)
  10.100+             (make-symbol* symbol-name)))))))
  10.101+
  10.102+(eval-when (:load-toplevel :compile-toplevel :execute)
  10.103+  (defvar *all-package-happiness* '())
  10.104+  (defvar *all-package-fishiness* (list t))
  10.105+  (defun record-fishy (info)
  10.106+    ;;(format t "~&FISHY: ~S~%" info)
  10.107+    (push info *all-package-fishiness*))
  10.108+  (defmacro when-package-fishiness (&body body)
  10.109+    `(when *all-package-fishiness* ,@body))
  10.110+  (defmacro note-package-fishiness (&rest info)
  10.111+    `(when-package-fishiness (record-fishy (list ,@info)))))
  10.112+
  10.113+(eval-when (:load-toplevel :compile-toplevel :execute)
  10.114+  #+(or clisp clozure)
  10.115+  (defun get-setf-function-symbol (symbol)
  10.116+    #+clisp (let ((sym (get symbol 'system::setf-function)))
  10.117+              (if sym (values sym :setf-function)
  10.118+                  (let ((sym (get symbol 'system::setf-expander)))
  10.119+                    (if sym (values sym :setf-expander)
  10.120+                        (values nil nil)))))
  10.121+    #+clozure (gethash symbol ccl::%setf-function-names%))
  10.122+  #+(or clisp clozure)
  10.123+  (defun set-setf-function-symbol (new-setf-symbol symbol &optional kind)
  10.124+    #+clisp (assert (member kind '(:setf-function :setf-expander)))
  10.125+    #+clozure (assert (eq kind t))
  10.126+    #+clisp
  10.127+    (cond
  10.128+      ((null new-setf-symbol)
  10.129+       (remprop symbol 'system::setf-function)
  10.130+       (remprop symbol 'system::setf-expander))
  10.131+      ((eq kind :setf-function)
  10.132+       (setf (get symbol 'system::setf-function) new-setf-symbol))
  10.133+      ((eq kind :setf-expander)
  10.134+       (setf (get symbol 'system::setf-expander) new-setf-symbol))
  10.135+      (t (error "invalid kind of setf-function ~S for ~S to be set to ~S"
  10.136+                kind symbol new-setf-symbol)))
  10.137+    #+clozure
  10.138+    (progn
  10.139+      (gethash symbol ccl::%setf-function-names%) new-setf-symbol
  10.140+      (gethash new-setf-symbol ccl::%setf-function-name-inverses%) symbol))
  10.141+  #+(or clisp clozure)
  10.142+  (defun create-setf-function-symbol (symbol)
  10.143+    #+clisp (system::setf-symbol symbol)
  10.144+    #+clozure (ccl::construct-setf-function-name symbol))
  10.145+  (defun set-dummy-symbol (symbol reason other-symbol)
  10.146+    (setf (get symbol 'dummy-symbol) (cons reason other-symbol)))
  10.147+  (defun make-dummy-symbol (symbol)
  10.148+    (let ((dummy (copy-symbol symbol)))
  10.149+      (set-dummy-symbol dummy 'replacing symbol)
  10.150+      (set-dummy-symbol symbol 'replaced-by dummy)
  10.151+      dummy))
  10.152+  (defun dummy-symbol (symbol)
  10.153+    (get symbol 'dummy-symbol))
  10.154+  (defun get-dummy-symbol (symbol)
  10.155+    (let ((existing (dummy-symbol symbol)))
  10.156+      (if existing (values (cdr existing) (car existing))
  10.157+          (make-dummy-symbol symbol))))
  10.158+  (defun nuke-symbol-in-package (symbol package-designator)
  10.159+    (let ((package (find-package* package-designator))
  10.160+          (name (symbol-name symbol)))
  10.161+      (multiple-value-bind (sym stat) (find-symbol name package)
  10.162+        (when (and (member stat '(:internal :external)) (eq symbol sym))
  10.163+          (if (symbol-shadowing-p symbol package)
  10.164+              (shadowing-import* (get-dummy-symbol symbol) package)
  10.165+              (unintern* symbol package))))))
  10.166+  (defun nuke-symbol (symbol &optional (packages (list-all-packages)))
  10.167+    #+(or clisp clozure)
  10.168+    (multiple-value-bind (setf-symbol kind)
  10.169+        (get-setf-function-symbol symbol)
  10.170+      (when kind (nuke-symbol setf-symbol)))
  10.171+    (loop :for p :in packages :do (nuke-symbol-in-package symbol p)))
  10.172+  (defun rehome-symbol (symbol package-designator)
  10.173+    "Changes the home package of a symbol, also leaving it present in its old home if any"
  10.174+    (let* ((name (symbol-name symbol))
  10.175+           (package (find-package* package-designator))
  10.176+           (old-package (symbol-package symbol))
  10.177+           (old-status (and old-package (nth-value 1 (find-symbol name old-package))))
  10.178+           (shadowing (and old-package (symbol-shadowing-p symbol old-package) (make-symbol name))))
  10.179+      (multiple-value-bind (overwritten-symbol overwritten-symbol-status) (find-symbol name package)
  10.180+        (unless (eq package old-package)
  10.181+          (let ((overwritten-symbol-shadowing-p
  10.182+                  (and overwritten-symbol-status
  10.183+                       (symbol-shadowing-p overwritten-symbol package))))
  10.184+            (note-package-fishiness
  10.185+             :rehome-symbol name
  10.186+             (when old-package (package-name old-package)) old-status (and shadowing t)
  10.187+             (package-name package) overwritten-symbol-status overwritten-symbol-shadowing-p)
  10.188+            (when old-package
  10.189+              (if shadowing
  10.190+                  (shadowing-import* shadowing old-package))
  10.191+              (unintern* symbol old-package))
  10.192+            (cond
  10.193+              (overwritten-symbol-shadowing-p
  10.194+               (shadowing-import* symbol package))
  10.195+              (t
  10.196+               (when overwritten-symbol-status
  10.197+                 (unintern* overwritten-symbol package))
  10.198+               (import* symbol package)))
  10.199+            (if shadowing
  10.200+                (shadowing-import* symbol old-package)
  10.201+                (import* symbol old-package))
  10.202+            #+(or clisp clozure)
  10.203+            (multiple-value-bind (setf-symbol kind)
  10.204+                (get-setf-function-symbol symbol)
  10.205+              (when kind
  10.206+                (let* ((setf-function (fdefinition setf-symbol))
  10.207+                       (new-setf-symbol (create-setf-function-symbol symbol)))
  10.208+                  (note-package-fishiness
  10.209+                   :setf-function
  10.210+                   name (package-name package)
  10.211+                   (symbol-name setf-symbol) (symbol-package-name setf-symbol)
  10.212+                   (symbol-name new-setf-symbol) (symbol-package-name new-setf-symbol))
  10.213+                  (when (symbol-package setf-symbol)
  10.214+                    (unintern* setf-symbol (symbol-package setf-symbol)))
  10.215+                  (setf (fdefinition new-setf-symbol) setf-function)
  10.216+                  (set-setf-function-symbol new-setf-symbol symbol kind))))
  10.217+            #+(or clisp clozure)
  10.218+            (multiple-value-bind (overwritten-setf foundp)
  10.219+                (get-setf-function-symbol overwritten-symbol)
  10.220+              (when foundp
  10.221+                (unintern overwritten-setf)))
  10.222+            (when (eq old-status :external)
  10.223+              (export* symbol old-package))
  10.224+            (when (eq overwritten-symbol-status :external)
  10.225+              (export* symbol package))))
  10.226+        (values overwritten-symbol overwritten-symbol-status))))
  10.227+  (defun ensure-package-unused (package)
  10.228+    (loop :for p :in (package-used-by-list package) :do
  10.229+      (unuse-package package p)))
  10.230+  (defun delete-package* (package &key nuke)
  10.231+    (let ((p (find-package package)))
  10.232+      (when p
  10.233+        (when nuke (do-symbols (s p) (when (home-package-p s p) (nuke-symbol s))))
  10.234+        (ensure-package-unused p)
  10.235+        (delete-package package))))
  10.236+  (defun package-names (package)
  10.237+    (cons (package-name package) (package-nicknames package)))
  10.238+  (defun packages-from-names (names)
  10.239+    (remove-duplicates (remove nil (mapcar #'find-package names)) :from-end t))
  10.240+  (defun fresh-package-name (&key (prefix :%TO-BE-DELETED)
  10.241+                               separator
  10.242+                               (index (random most-positive-fixnum)))
  10.243+    (loop :for i :from index
  10.244+          :for n = (format nil "~A~@[~A~D~]" prefix (and (plusp i) (or separator "")) i)
  10.245+            :thereis (and (not (find-package n)) n)))
  10.246+  (defun rename-package-away (p &rest keys &key prefix &allow-other-keys)
  10.247+    (let ((new-name
  10.248+            (apply 'fresh-package-name
  10.249+                   :prefix (or prefix (format nil "__~A__" (package-name p))) keys)))
  10.250+      (record-fishy (list :rename-away (package-names p) new-name))
  10.251+      (rename-package p new-name))))
  10.252+
  10.253+
  10.254+;;; Communicable representation of symbol and package information
  10.255+
  10.256+(eval-when (:load-toplevel :compile-toplevel :execute)
  10.257+  (defun package-definition-form (package-designator
  10.258+                                  &key (nicknamesp t) (usep t)
  10.259+                                    (shadowp t) (shadowing-import-p t)
  10.260+                                    (exportp t) (importp t) internp (error t))
  10.261+    (let* ((package (or (find-package* package-designator error)
  10.262+                        (return-from package-definition-form nil)))
  10.263+           (name (package-name package))
  10.264+           (nicknames (package-nicknames package))
  10.265+           (use (mapcar #'package-name (package-use-list package)))
  10.266+           (shadow ())
  10.267+           (shadowing-import (make-hash-table :test 'equal))
  10.268+           (import (make-hash-table :test 'equal))
  10.269+           (export ())
  10.270+           (intern ()))
  10.271+      (when package
  10.272+        (loop :for sym :being :the :symbols :in package
  10.273+              :for status = (nth-value 1 (find-symbol* sym package)) :do
  10.274+                (ecase status
  10.275+                  ((nil :inherited))
  10.276+                  ((:internal :external)
  10.277+                   (let* ((name (symbol-name sym))
  10.278+                          (external (eq status :external))
  10.279+                          (home (symbol-package sym))
  10.280+                          (home-name (package-name home))
  10.281+                          (imported (not (eq home package)))
  10.282+                          (shadowing (symbol-shadowing-p sym package)))
  10.283+                     (cond
  10.284+                       ((and shadowing imported)
  10.285+                        (push name (gethash home-name shadowing-import)))
  10.286+                       (shadowing
  10.287+                        (push name shadow))
  10.288+                       (imported
  10.289+                        (push name (gethash home-name import))))
  10.290+                     (cond
  10.291+                       (external
  10.292+                        (push name export))
  10.293+                       (imported)
  10.294+                       (t (push name intern)))))))
  10.295+        (labels ((sort-names (names)
  10.296+                   (sort (copy-list names) #'string<))
  10.297+                 (table-keys (table)
  10.298+                   (loop :for k :being :the :hash-keys :of table :collect k))
  10.299+                 (when-relevant (key value)
  10.300+                   (when value (list (cons key value))))
  10.301+                 (import-options (key table)
  10.302+                   (loop :for i :in (sort-names (table-keys table))
  10.303+                         :collect `(,key ,i ,@(sort-names (gethash i table))))))
  10.304+          `(defpackage ,name
  10.305+             ,@(when-relevant :nicknames (and nicknamesp (sort-names nicknames)))
  10.306+             (:use ,@(and usep (sort-names use)))
  10.307+             ,@(when-relevant :shadow (and shadowp (sort-names shadow)))
  10.308+             ,@(import-options :shadowing-import-from (and shadowing-import-p shadowing-import))
  10.309+             ,@(import-options :import-from (and importp import))
  10.310+             ,@(when-relevant :export (and exportp (sort-names export)))
  10.311+             ,@(when-relevant :intern (and internp (sort-names intern)))))))))
  10.312+
  10.313+(eval-when (:load-toplevel :compile-toplevel :execute)
  10.314+  (defun ensure-shadowing-import (name to-package from-package shadowed imported)
  10.315+    (check-type name string)
  10.316+    (check-type to-package package)
  10.317+    (check-type from-package package)
  10.318+    (check-type shadowed hash-table)
  10.319+    (check-type imported hash-table)
  10.320+    (let ((import-me (find-symbol* name from-package)))
  10.321+      (multiple-value-bind (existing status) (find-symbol name to-package)
  10.322+        (cond
  10.323+          ((gethash name shadowed)
  10.324+           (unless (eq import-me existing)
  10.325+             (error "Conflicting shadowings for ~A" name)))
  10.326+          (t
  10.327+           (setf (gethash name shadowed) t)
  10.328+           (setf (gethash name imported) t)
  10.329+           (unless (or (null status)
  10.330+                       (and (member status '(:internal :external))
  10.331+                            (eq existing import-me)
  10.332+                            (symbol-shadowing-p existing to-package)))
  10.333+             (note-package-fishiness
  10.334+              :shadowing-import name
  10.335+              (package-name from-package)
  10.336+              (or (home-package-p import-me from-package) (symbol-package-name import-me))
  10.337+              (package-name to-package) status
  10.338+              (and status (or (home-package-p existing to-package) (symbol-package-name existing)))))
  10.339+           (shadowing-import* import-me to-package))))))
  10.340+  (defun ensure-imported (import-me into-package &optional from-package)
  10.341+    (check-type import-me symbol)
  10.342+    (check-type into-package package)
  10.343+    (check-type from-package (or null package))
  10.344+    (let ((name (symbol-name import-me)))
  10.345+      (multiple-value-bind (existing status) (find-symbol name into-package)
  10.346+        (cond
  10.347+          ((not status)
  10.348+           (import* import-me into-package))
  10.349+          ((eq import-me existing))
  10.350+          (t
  10.351+           (let ((shadowing-p (symbol-shadowing-p existing into-package)))
  10.352+             (note-package-fishiness
  10.353+              :ensure-imported name
  10.354+              (and from-package (package-name from-package))
  10.355+              (or (home-package-p import-me from-package) (symbol-package-name import-me))
  10.356+              (package-name into-package)
  10.357+              status
  10.358+              (and status (or (home-package-p existing into-package) (symbol-package-name existing)))
  10.359+              shadowing-p)
  10.360+             (cond
  10.361+               ((or shadowing-p (eq status :inherited))
  10.362+                (shadowing-import* import-me into-package))
  10.363+               (t
  10.364+                (unintern* existing into-package)
  10.365+                (import* import-me into-package))))))))
  10.366+    (values))
  10.367+  (defun ensure-import (name to-package from-package shadowed imported)
  10.368+    (check-type name string)
  10.369+    (check-type to-package package)
  10.370+    (check-type from-package package)
  10.371+    (check-type shadowed hash-table)
  10.372+    (check-type imported hash-table)
  10.373+    (multiple-value-bind (import-me import-status) (find-symbol name from-package)
  10.374+      (when (null import-status)
  10.375+        (note-package-fishiness
  10.376+         :import-uninterned name (package-name from-package) (package-name to-package))
  10.377+        (setf import-me (intern* name from-package)))
  10.378+      (multiple-value-bind (existing status) (find-symbol name to-package)
  10.379+        (cond
  10.380+          ((and imported (gethash name imported))
  10.381+           (unless (and status (eq import-me existing))
  10.382+             (error "Can't import ~S from both ~S and ~S"
  10.383+                    name (package-name (symbol-package existing)) (package-name from-package))))
  10.384+          ((gethash name shadowed)
  10.385+           (error "Can't both shadow ~S and import it from ~S" name (package-name from-package)))
  10.386+          (t
  10.387+           (setf (gethash name imported) t))))
  10.388+      (ensure-imported import-me to-package from-package)))
  10.389+  (defun ensure-inherited (name symbol to-package from-package mixp shadowed imported inherited)
  10.390+    (check-type name string)
  10.391+    (check-type symbol symbol)
  10.392+    (check-type to-package package)
  10.393+    (check-type from-package package)
  10.394+    (check-type mixp (member nil t)) ; no cl:boolean on Genera
  10.395+    (check-type shadowed hash-table)
  10.396+    (check-type imported hash-table)
  10.397+    (check-type inherited hash-table)
  10.398+    (multiple-value-bind (existing status) (find-symbol name to-package)
  10.399+      (let* ((sp (symbol-package symbol))
  10.400+             (in (gethash name inherited))
  10.401+             (xp (and status (symbol-package existing))))
  10.402+        (when (null sp)
  10.403+          (note-package-fishiness
  10.404+           :import-uninterned name
  10.405+           (package-name from-package) (package-name to-package) mixp)
  10.406+          (import* symbol from-package)
  10.407+          (setf sp (package-name from-package)))
  10.408+        (cond
  10.409+          ((gethash name shadowed))
  10.410+          (in
  10.411+           (unless (equal sp (first in))
  10.412+             (if mixp
  10.413+                 (ensure-shadowing-import name to-package (second in) shadowed imported)
  10.414+                 (error "Can't inherit ~S from ~S, it is inherited from ~S"
  10.415+                        name (package-name sp) (package-name (first in))))))
  10.416+          ((gethash name imported)
  10.417+           (unless (eq symbol existing)
  10.418+             (error "Can't inherit ~S from ~S, it is imported from ~S"
  10.419+                    name (package-name sp) (package-name xp))))
  10.420+          (t
  10.421+           (setf (gethash name inherited) (list sp from-package))
  10.422+           (when (and status (not (eq sp xp)))
  10.423+             (let ((shadowing (symbol-shadowing-p existing to-package)))
  10.424+               (note-package-fishiness
  10.425+                :inherited name
  10.426+                (package-name from-package)
  10.427+                (or (home-package-p symbol from-package) (symbol-package-name symbol))
  10.428+                (package-name to-package)
  10.429+                (or (home-package-p existing to-package) (symbol-package-name existing)))
  10.430+               (if shadowing (ensure-shadowing-import name to-package from-package shadowed imported)
  10.431+                   (unintern* existing to-package)))))))))
  10.432+  (defun ensure-mix (name symbol to-package from-package shadowed imported inherited)
  10.433+    (check-type name string)
  10.434+    (check-type symbol symbol)
  10.435+    (check-type to-package package)
  10.436+    (check-type from-package package)
  10.437+    (check-type shadowed hash-table)
  10.438+    (check-type imported hash-table)
  10.439+    (check-type inherited hash-table)
  10.440+    (unless (gethash name shadowed)
  10.441+      (multiple-value-bind (existing status) (find-symbol name to-package)
  10.442+        (let* ((sp (symbol-package symbol))
  10.443+               (im (gethash name imported))
  10.444+               (in (gethash name inherited)))
  10.445+          (cond
  10.446+            ((or (null status)
  10.447+                 (and status (eq symbol existing))
  10.448+                 (and in (eq sp (first in))))
  10.449+             (ensure-inherited name symbol to-package from-package t shadowed imported inherited))
  10.450+            (in
  10.451+             (remhash name inherited)
  10.452+             (ensure-shadowing-import name to-package (second in) shadowed imported))
  10.453+            (im
  10.454+             (error "Symbol ~S import from ~S~:[~; actually ~:[uninterned~;~:*from ~S~]~] conflicts with existing symbol in ~S~:[~; actually ~:[uninterned~;from ~:*~S~]~]"
  10.455+                    name (package-name from-package)
  10.456+                    (home-package-p symbol from-package) (symbol-package-name symbol)
  10.457+                    (package-name to-package)
  10.458+                    (home-package-p existing to-package) (symbol-package-name existing)))
  10.459+            (t
  10.460+             (ensure-inherited name symbol to-package from-package t shadowed imported inherited)))))))
  10.461+
  10.462+  (defun recycle-symbol (name recycle exported)
  10.463+    ;; Takes a symbol NAME (a string), a list of package designators for RECYCLE
  10.464+    ;; packages, and a hash-table of names (strings) of symbols scheduled to be
  10.465+    ;; EXPORTED from the package being defined. It returns two values, the
  10.466+    ;; symbol found (if any, or else NIL), and a boolean flag indicating whether
  10.467+    ;; a symbol was found. The caller (DEFPKG) will then do the
  10.468+    ;; re-homing of the symbol, etc.
  10.469+    (check-type name string)
  10.470+    (check-type recycle list)
  10.471+    (check-type exported hash-table)
  10.472+    (when (gethash name exported) ;; don't bother recycling private symbols
  10.473+      (let (recycled foundp)
  10.474+        (dolist (r recycle (values recycled foundp))
  10.475+          (multiple-value-bind (symbol status) (find-symbol name r)
  10.476+            (when (and status (home-package-p symbol r))
  10.477+              (cond
  10.478+                (foundp
  10.479+                 ;; (nuke-symbol symbol)) -- even simple variable names like O or C will do that.
  10.480+                 (note-package-fishiness :recycled-duplicate name (package-name foundp) (package-name r)))
  10.481+                (t
  10.482+                 (setf recycled symbol foundp r)))))))))
  10.483+  (defun symbol-recycled-p (sym recycle)
  10.484+    (check-type sym symbol)
  10.485+    (check-type recycle list)
  10.486+    (and (member (symbol-package sym) recycle) t))
  10.487+  (defun ensure-symbol (name package intern recycle shadowed imported inherited exported)
  10.488+    (check-type name string)
  10.489+    (check-type package package)
  10.490+    (check-type intern (member nil t)) ; no cl:boolean on Genera
  10.491+    (check-type shadowed hash-table)
  10.492+    (check-type imported hash-table)
  10.493+    (check-type inherited hash-table)
  10.494+    (unless (or (gethash name shadowed)
  10.495+                (gethash name imported)
  10.496+                (gethash name inherited))
  10.497+      (multiple-value-bind (existing status)
  10.498+          (find-symbol name package)
  10.499+        (multiple-value-bind (recycled previous) (recycle-symbol name recycle exported)
  10.500+          (cond
  10.501+            ((and status (eq existing recycled) (eq previous package)))
  10.502+            (previous
  10.503+             (rehome-symbol recycled package))
  10.504+            ((and status (eq package (symbol-package existing))))
  10.505+            (t
  10.506+             (when status
  10.507+               (note-package-fishiness
  10.508+                :ensure-symbol name
  10.509+                (reify-package (symbol-package existing) package)
  10.510+                status intern)
  10.511+               (unintern existing))
  10.512+             (when intern
  10.513+               (intern* name package))))))))
  10.514+  (declaim (ftype (function (t t t &optional t) t) ensure-exported))
  10.515+  (defun ensure-exported-to-user (name symbol to-package &optional recycle)
  10.516+    (check-type name string)
  10.517+    (check-type symbol symbol)
  10.518+    (check-type to-package package)
  10.519+    (check-type recycle list)
  10.520+    (assert (equal name (symbol-name symbol)))
  10.521+    (multiple-value-bind (existing status) (find-symbol name to-package)
  10.522+      (unless (and status (eq symbol existing))
  10.523+        (let ((accessible
  10.524+                (or (null status)
  10.525+                    (let ((shadowing (symbol-shadowing-p existing to-package))
  10.526+                          (recycled (symbol-recycled-p existing recycle)))
  10.527+                      (unless (and shadowing (not recycled))
  10.528+                        (note-package-fishiness
  10.529+                         :ensure-export name (symbol-package-name symbol)
  10.530+                         (package-name to-package)
  10.531+                         (or (home-package-p existing to-package) (symbol-package-name existing))
  10.532+                         status shadowing)
  10.533+                        (if (or (eq status :inherited) shadowing)
  10.534+                            (shadowing-import* symbol to-package)
  10.535+                            (unintern existing to-package))
  10.536+                        t)))))
  10.537+          (when (and accessible (eq status :external))
  10.538+            (ensure-exported name symbol to-package recycle))))))
  10.539+  (defun ensure-exported (name symbol from-package &optional recycle)
  10.540+    (dolist (to-package (package-used-by-list from-package))
  10.541+      (ensure-exported-to-user name symbol to-package recycle))
  10.542+    (unless (eq from-package (symbol-package symbol))
  10.543+      (ensure-imported symbol from-package))
  10.544+    (export* name from-package))
  10.545+  (defun ensure-export (name from-package &optional recycle)
  10.546+    (multiple-value-bind (symbol status) (find-symbol* name from-package)
  10.547+      (unless (eq status :external)
  10.548+        (ensure-exported name symbol from-package recycle))))
  10.549+
  10.550+  (defun ensure-package (name &key
  10.551+                                nicknames documentation use
  10.552+                                shadow shadowing-import-from
  10.553+                                import-from export intern
  10.554+                                recycle mix reexport
  10.555+                                unintern)
  10.556+    #+genera (declare (ignore documentation))
  10.557+    (let* ((package-name (string name))
  10.558+           (nicknames (mapcar #'string nicknames))
  10.559+           (names (cons package-name nicknames))
  10.560+           (previous (packages-from-names names))
  10.561+           (discarded (cdr previous))
  10.562+           (to-delete ())
  10.563+           (package (or (first previous) (make-package package-name :nicknames nicknames)))
  10.564+           (recycle (packages-from-names recycle))
  10.565+           (use (mapcar 'find-package* use))
  10.566+           (mix (mapcar 'find-package* mix))
  10.567+           (reexport (mapcar 'find-package* reexport))
  10.568+           (shadow (mapcar 'string shadow))
  10.569+           (export (mapcar 'string export))
  10.570+           (intern (mapcar 'string intern))
  10.571+           (unintern (mapcar 'string unintern))
  10.572+           (shadowed (make-hash-table :test 'equal)) ; string to bool
  10.573+           (imported (make-hash-table :test 'equal)) ; string to bool
  10.574+           (exported (make-hash-table :test 'equal)) ; string to bool
  10.575+           ;; string to list home package and use package:
  10.576+           (inherited (make-hash-table :test 'equal)))
  10.577+      (when-package-fishiness (record-fishy package-name))
  10.578+      #-genera
  10.579+      (when documentation (setf (documentation package t) documentation))
  10.580+      (loop :for p :in (set-difference (package-use-list package) (append mix use))
  10.581+            :do (note-package-fishiness :over-use name (package-names p))
  10.582+                (unuse-package p package))
  10.583+      (loop :for p :in discarded
  10.584+            :for n = (remove-if #'(lambda (x) (member x names :test 'equal))
  10.585+                                (package-names p))
  10.586+            :do (note-package-fishiness :nickname name (package-names p))
  10.587+                (cond (n (rename-package p (first n) (rest n)))
  10.588+                      (t (rename-package-away p)
  10.589+                         (push p to-delete))))
  10.590+      (rename-package package package-name nicknames)
  10.591+      (dolist (name unintern)
  10.592+        (multiple-value-bind (existing status) (find-symbol name package)
  10.593+          (when status
  10.594+            (unless (eq status :inherited)
  10.595+              (note-package-fishiness
  10.596+               :unintern (package-name package) name (symbol-package-name existing) status)
  10.597+              (unintern* name package nil)))))
  10.598+      (dolist (name export)
  10.599+        (setf (gethash name exported) t))
  10.600+      (dolist (p reexport)
  10.601+        (do-external-symbols (sym p)
  10.602+          (setf (gethash (string sym) exported) t)))
  10.603+      (do-external-symbols (sym package)
  10.604+        (let ((name (symbol-name sym)))
  10.605+          (unless (gethash name exported)
  10.606+            (note-package-fishiness
  10.607+             :over-export (package-name package) name
  10.608+             (or (home-package-p sym package) (symbol-package-name sym)))
  10.609+            (unexport sym package))))
  10.610+      (dolist (name shadow)
  10.611+        (setf (gethash name shadowed) t)
  10.612+        (multiple-value-bind (existing status) (find-symbol name package)
  10.613+          (multiple-value-bind (recycled previous) (recycle-symbol name recycle exported)
  10.614+            (let ((shadowing (and status (symbol-shadowing-p existing package))))
  10.615+              (cond
  10.616+                ((eq previous package))
  10.617+                (previous
  10.618+                 (rehome-symbol recycled package))
  10.619+                ((or (member status '(nil :inherited))
  10.620+                     (home-package-p existing package)))
  10.621+                (t
  10.622+                 (let ((dummy (make-symbol name)))
  10.623+                   (note-package-fishiness
  10.624+                    :shadow-imported (package-name package) name
  10.625+                    (symbol-package-name existing) status shadowing)
  10.626+                   (shadowing-import* dummy package)
  10.627+                   (import* dummy package)))))))
  10.628+        (shadow* name package))
  10.629+      (loop :for (p . syms) :in shadowing-import-from
  10.630+            :for pp = (find-package* p) :do
  10.631+              (dolist (sym syms) (ensure-shadowing-import (string sym) package pp shadowed imported)))
  10.632+      (loop :for p :in mix
  10.633+            :for pp = (find-package* p) :do
  10.634+              (do-external-symbols (sym pp) (ensure-mix (symbol-name sym) sym package pp shadowed imported inherited)))
  10.635+      (loop :for (p . syms) :in import-from
  10.636+            :for pp = (find-package p) :do
  10.637+              (dolist (sym syms) (ensure-import (symbol-name sym) package pp shadowed imported)))
  10.638+      (dolist (p (append use mix))
  10.639+        (do-external-symbols (sym p) (ensure-inherited (string sym) sym package p nil shadowed imported inherited))
  10.640+        (use-package p package))
  10.641+      (loop :for name :being :the :hash-keys :of exported :do
  10.642+        (ensure-symbol name package t recycle shadowed imported inherited exported)
  10.643+        (ensure-export name package recycle))
  10.644+      (dolist (name intern)
  10.645+        (ensure-symbol name package t recycle shadowed imported inherited exported))
  10.646+      (do-symbols (sym package)
  10.647+        (ensure-symbol (symbol-name sym) package nil recycle shadowed imported inherited exported))
  10.648+      (map () 'delete-package* to-delete)
  10.649+      package)))
  10.650+
  10.651+(eval-when (:load-toplevel :compile-toplevel :execute)
  10.652+  (defun parse-defpkg-form (package clauses)
  10.653+    (loop
  10.654+      :with use-p = nil :with recycle-p = nil
  10.655+      :with documentation = nil
  10.656+      :for (kw . args) :in clauses
  10.657+      :when (eq kw :nicknames) :append args :into nicknames :else
  10.658+        :when (eq kw :documentation)
  10.659+          :do (cond
  10.660+                (documentation (error "defpkg: can't define documentation twice"))
  10.661+                ((or (atom args) (cdr args)) (error "defpkg: bad documentation"))
  10.662+                (t (setf documentation (car args)))) :else
  10.663+      :when (eq kw :use) :append args :into use :and :do (setf use-p t) :else
  10.664+        :when (eq kw :shadow) :append args :into shadow :else
  10.665+          :when (eq kw :shadowing-import-from) :collect args :into shadowing-import-from :else
  10.666+            :when (eq kw :import-from) :collect args :into import-from :else
  10.667+              :when (eq kw :export) :append args :into export :else
  10.668+                :when (eq kw :intern) :append args :into intern :else
  10.669+                  :when (eq kw :recycle) :append args :into recycle :and :do (setf recycle-p t) :else
  10.670+                    :when (eq kw :mix) :append args :into mix :else
  10.671+                      :when (eq kw :reexport) :append args :into reexport :else
  10.672+                        :when (eq kw :use-reexport) :append args :into use :and :append args :into reexport
  10.673+                        :and :do (setf use-p t) :else
  10.674+      :when (eq kw :mix-reexport) :append args :into mix :and :append args :into reexport
  10.675+      :and :do (setf use-p t) :else
  10.676+      :when (eq kw :unintern) :append args :into unintern :else
  10.677+        :do (error "unrecognized defpkg keyword ~S" kw)
  10.678+      :finally (return `(,package
  10.679+                         :nicknames ,nicknames :documentation ,documentation
  10.680+                         :use ,(if use-p use '(:common-lisp))
  10.681+                         :shadow ,shadow :shadowing-import-from ,shadowing-import-from
  10.682+                         :import-from ,import-from :export ,export :intern ,intern
  10.683+                         :recycle ,(if recycle-p recycle (cons package nicknames))
  10.684+                         :mix ,mix :reexport ,reexport :unintern ,unintern)))))
  10.685+
  10.686+(defmacro defpkg (package &rest clauses)
  10.687+  "Richard's Robust DEFPACKAGE macro. Based on UIOP:DEFINE-PACKAGE. ymmv.
  10.688+
  10.689+DEFPKG takes a PACKAGE and a number of CLAUSES, of the form (KEYWORD . ARGS).
  10.690+
  10.691+DEFPKG supports the following keywords:
  10.692+USE, SHADOW, SHADOWING-IMPORT-FROM, IMPORT-FROM, EXPORT, INTERN -- as per CL:DEFPACKAGE.
  10.693+
  10.694+DEFPKG also redefines the following extensions:
  10.695+RECYCLE, MIX, REEXPORT, UNINTERN -- as per UIOP/PACKAGE:DEFINE-PACKAGE
  10.696+
  10.697+REEXPORT -- Takes a list of package designators. For each package in
  10.698+the list, export symbols with the same name as those exported from
  10.699+that package. In the case of shadowing, etc. They may not be EQL."
  10.700+  (let ((ensure-form
  10.701+          `(apply 'ensure-package ',(parse-defpkg-form package clauses))))
  10.702+    `(progn
  10.703+       #+(or clasp ecl gcl mkcl) (defpackage ,package (:use))
  10.704+       (eval-when (:compile-toplevel :load-toplevel :execute)
  10.705+         ,ensure-form))))
    11.1--- a/lisp/std/util.lisp	Sun Mar 03 20:50:37 2024 -0500
    11.2+++ b/lisp/std/util.lisp	Thu Mar 07 23:06:25 2024 -0500
    11.3@@ -184,706 +184,6 @@
    11.4       (setf p (ash p -1)))
    11.5     (nreverse network)))
    11.6 
    11.7-(eval-when (:load-toplevel :compile-toplevel :execute)
    11.8-  (defun find-package* (package-designator &optional (error t))
    11.9-    (let ((package (find-package package-designator)))
   11.10-      (cond
   11.11-        (package package)
   11.12-        (error (error "No package named ~S" (string package-designator)))
   11.13-        (t nil))))
   11.14-  (defun find-symbol* (name package-designator &optional (error t))
   11.15-    "Find a symbol in a package of given string'ified NAME;
   11.16-unlike CL:FIND-SYMBOL, work well with 'modern' case sensitive syntax
   11.17-by letting you supply a symbol or keyword for the name;
   11.18-also works well when the package is not present.
   11.19-If optional ERROR argument is NIL, return NIL instead of an error
   11.20-when the symbol is not found."
   11.21-    (block nil
   11.22-      (let ((package (find-package* package-designator error)))
   11.23-        (when package ;; package error handled by find-package* already
   11.24-          (multiple-value-bind (symbol status) (find-symbol (string name) package)
   11.25-            (cond
   11.26-              (status (return (values symbol status)))
   11.27-              (error (error "There is no symbol ~S in package ~S" name (package-name package))))))
   11.28-        (values nil nil))))
   11.29-  (defun symbol-call (package name &rest args)
   11.30-    "Call a function associated with symbol of given name in given package,
   11.31-with given ARGS. Useful when the call is read before the package is loaded,
   11.32-or when loading the package is optional."
   11.33-    (apply (find-symbol* name package) args))
   11.34-  (defun intern* (name package-designator &optional (error t))
   11.35-    (intern (string name) (find-package* package-designator error)))
   11.36-  (defun export* (name package-designator)
   11.37-    (let* ((package (find-package* package-designator))
   11.38-           (symbol (intern* name package)))
   11.39-      (export (or symbol (list symbol)) package)))
   11.40-  (defun import* (symbol package-designator)
   11.41-    (import (or symbol (list symbol)) (find-package* package-designator)))
   11.42-  (defun shadowing-import* (symbol package-designator)
   11.43-    (shadowing-import (or symbol (list symbol)) (find-package* package-designator)))
   11.44-  (defun shadow* (name package-designator)
   11.45-    (shadow (list (string name)) (find-package* package-designator)))
   11.46-  (defun make-symbol* (name)
   11.47-    (etypecase name
   11.48-      (string (make-symbol name))
   11.49-      (symbol (copy-symbol name))))
   11.50-  (defun unintern* (name package-designator &optional (error t))
   11.51-    (block nil
   11.52-      (let ((package (find-package* package-designator error)))
   11.53-        (when package
   11.54-          (multiple-value-bind (symbol status) (find-symbol* name package error)
   11.55-            (cond
   11.56-              (status (unintern symbol package)
   11.57-                      (return (values symbol status)))
   11.58-              (error (error "symbol ~A not present in package ~A"
   11.59-                            (string symbol) (package-name package))))))
   11.60-        (values nil nil))))
   11.61-  (defun symbol-shadowing-p (symbol package)
   11.62-    (and (member symbol (package-shadowing-symbols package)) t))
   11.63-  (defun home-package-p (symbol package)
   11.64-    (and package (let ((sp (symbol-package symbol)))
   11.65-                   (and sp (let ((pp (find-package* package)))
   11.66-                             (and pp (eq sp pp))))))))
   11.67-
   11.68-
   11.69-(eval-when (:load-toplevel :compile-toplevel :execute)
   11.70-  (defun symbol-package-name (symbol)
   11.71-    (let ((package (symbol-package symbol)))
   11.72-      (and package (package-name package))))
   11.73-  (defun standard-common-lisp-symbol-p (symbol)
   11.74-    (multiple-value-bind (sym status) (find-symbol* symbol :common-lisp nil)
   11.75-      (and (eq sym symbol) (eq status :external))))
   11.76-  (defun reify-package (package &optional package-context)
   11.77-    (if (eq package package-context) t
   11.78-        (etypecase package
   11.79-          (null nil)
   11.80-          ((eql (find-package :cl)) :cl)
   11.81-          (package (package-name package)))))
   11.82-  (defun unreify-package (package &optional package-context)
   11.83-    (etypecase package
   11.84-      (null nil)
   11.85-      ((eql t) package-context)
   11.86-      ((or symbol string) (find-package package))))
   11.87-  (defun reify-symbol (symbol &optional package-context)
   11.88-    (etypecase symbol
   11.89-      ((or keyword (satisfies standard-common-lisp-symbol-p)) symbol)
   11.90-      (symbol (vector (symbol-name symbol)
   11.91-                      (reify-package (symbol-package symbol) package-context)))))
   11.92-  (defun unreify-symbol (symbol &optional package-context)
   11.93-    (etypecase symbol
   11.94-      (symbol symbol)
   11.95-      ((simple-vector 2)
   11.96-       (let* ((symbol-name (svref symbol 0))
   11.97-              (package-foo (svref symbol 1))
   11.98-              (package (unreify-package package-foo package-context)))
   11.99-         (if package (intern* symbol-name package)
  11.100-             (make-symbol* symbol-name)))))))
  11.101-
  11.102-(eval-when (:load-toplevel :compile-toplevel :execute)
  11.103-  (defvar *all-package-happiness* '())
  11.104-  (defvar *all-package-fishiness* (list t))
  11.105-  (defun record-fishy (info)
  11.106-    ;;(format t "~&FISHY: ~S~%" info)
  11.107-    (push info *all-package-fishiness*))
  11.108-  (defmacro when-package-fishiness (&body body)
  11.109-    `(when *all-package-fishiness* ,@body))
  11.110-  (defmacro note-package-fishiness (&rest info)
  11.111-    `(when-package-fishiness (record-fishy (list ,@info)))))
  11.112-
  11.113-(eval-when (:load-toplevel :compile-toplevel :execute)
  11.114-  #+(or clisp clozure)
  11.115-  (defun get-setf-function-symbol (symbol)
  11.116-    #+clisp (let ((sym (get symbol 'system::setf-function)))
  11.117-              (if sym (values sym :setf-function)
  11.118-                  (let ((sym (get symbol 'system::setf-expander)))
  11.119-                    (if sym (values sym :setf-expander)
  11.120-                        (values nil nil)))))
  11.121-    #+clozure (gethash symbol ccl::%setf-function-names%))
  11.122-  #+(or clisp clozure)
  11.123-  (defun set-setf-function-symbol (new-setf-symbol symbol &optional kind)
  11.124-    #+clisp (assert (member kind '(:setf-function :setf-expander)))
  11.125-    #+clozure (assert (eq kind t))
  11.126-    #+clisp
  11.127-    (cond
  11.128-      ((null new-setf-symbol)
  11.129-       (remprop symbol 'system::setf-function)
  11.130-       (remprop symbol 'system::setf-expander))
  11.131-      ((eq kind :setf-function)
  11.132-       (setf (get symbol 'system::setf-function) new-setf-symbol))
  11.133-      ((eq kind :setf-expander)
  11.134-       (setf (get symbol 'system::setf-expander) new-setf-symbol))
  11.135-      (t (error "invalid kind of setf-function ~S for ~S to be set to ~S"
  11.136-                kind symbol new-setf-symbol)))
  11.137-    #+clozure
  11.138-    (progn
  11.139-      (gethash symbol ccl::%setf-function-names%) new-setf-symbol
  11.140-      (gethash new-setf-symbol ccl::%setf-function-name-inverses%) symbol))
  11.141-  #+(or clisp clozure)
  11.142-  (defun create-setf-function-symbol (symbol)
  11.143-    #+clisp (system::setf-symbol symbol)
  11.144-    #+clozure (ccl::construct-setf-function-name symbol))
  11.145-  (defun set-dummy-symbol (symbol reason other-symbol)
  11.146-    (setf (get symbol 'dummy-symbol) (cons reason other-symbol)))
  11.147-  (defun make-dummy-symbol (symbol)
  11.148-    (let ((dummy (copy-symbol symbol)))
  11.149-      (set-dummy-symbol dummy 'replacing symbol)
  11.150-      (set-dummy-symbol symbol 'replaced-by dummy)
  11.151-      dummy))
  11.152-  (defun dummy-symbol (symbol)
  11.153-    (get symbol 'dummy-symbol))
  11.154-  (defun get-dummy-symbol (symbol)
  11.155-    (let ((existing (dummy-symbol symbol)))
  11.156-      (if existing (values (cdr existing) (car existing))
  11.157-          (make-dummy-symbol symbol))))
  11.158-  (defun nuke-symbol-in-package (symbol package-designator)
  11.159-    (let ((package (find-package* package-designator))
  11.160-          (name (symbol-name symbol)))
  11.161-      (multiple-value-bind (sym stat) (find-symbol name package)
  11.162-        (when (and (member stat '(:internal :external)) (eq symbol sym))
  11.163-          (if (symbol-shadowing-p symbol package)
  11.164-              (shadowing-import* (get-dummy-symbol symbol) package)
  11.165-              (unintern* symbol package))))))
  11.166-  (defun nuke-symbol (symbol &optional (packages (list-all-packages)))
  11.167-    #+(or clisp clozure)
  11.168-    (multiple-value-bind (setf-symbol kind)
  11.169-        (get-setf-function-symbol symbol)
  11.170-      (when kind (nuke-symbol setf-symbol)))
  11.171-    (loop :for p :in packages :do (nuke-symbol-in-package symbol p)))
  11.172-  (defun rehome-symbol (symbol package-designator)
  11.173-    "Changes the home package of a symbol, also leaving it present in its old home if any"
  11.174-    (let* ((name (symbol-name symbol))
  11.175-           (package (find-package* package-designator))
  11.176-           (old-package (symbol-package symbol))
  11.177-           (old-status (and old-package (nth-value 1 (find-symbol name old-package))))
  11.178-           (shadowing (and old-package (symbol-shadowing-p symbol old-package) (make-symbol name))))
  11.179-      (multiple-value-bind (overwritten-symbol overwritten-symbol-status) (find-symbol name package)
  11.180-        (unless (eq package old-package)
  11.181-          (let ((overwritten-symbol-shadowing-p
  11.182-                  (and overwritten-symbol-status
  11.183-                       (symbol-shadowing-p overwritten-symbol package))))
  11.184-            (note-package-fishiness
  11.185-             :rehome-symbol name
  11.186-             (when old-package (package-name old-package)) old-status (and shadowing t)
  11.187-             (package-name package) overwritten-symbol-status overwritten-symbol-shadowing-p)
  11.188-            (when old-package
  11.189-              (if shadowing
  11.190-                  (shadowing-import* shadowing old-package))
  11.191-              (unintern* symbol old-package))
  11.192-            (cond
  11.193-              (overwritten-symbol-shadowing-p
  11.194-               (shadowing-import* symbol package))
  11.195-              (t
  11.196-               (when overwritten-symbol-status
  11.197-                 (unintern* overwritten-symbol package))
  11.198-               (import* symbol package)))
  11.199-            (if shadowing
  11.200-                (shadowing-import* symbol old-package)
  11.201-                (import* symbol old-package))
  11.202-            #+(or clisp clozure)
  11.203-            (multiple-value-bind (setf-symbol kind)
  11.204-                (get-setf-function-symbol symbol)
  11.205-              (when kind
  11.206-                (let* ((setf-function (fdefinition setf-symbol))
  11.207-                       (new-setf-symbol (create-setf-function-symbol symbol)))
  11.208-                  (note-package-fishiness
  11.209-                   :setf-function
  11.210-                   name (package-name package)
  11.211-                   (symbol-name setf-symbol) (symbol-package-name setf-symbol)
  11.212-                   (symbol-name new-setf-symbol) (symbol-package-name new-setf-symbol))
  11.213-                  (when (symbol-package setf-symbol)
  11.214-                    (unintern* setf-symbol (symbol-package setf-symbol)))
  11.215-                  (setf (fdefinition new-setf-symbol) setf-function)
  11.216-                  (set-setf-function-symbol new-setf-symbol symbol kind))))
  11.217-            #+(or clisp clozure)
  11.218-            (multiple-value-bind (overwritten-setf foundp)
  11.219-                (get-setf-function-symbol overwritten-symbol)
  11.220-              (when foundp
  11.221-                (unintern overwritten-setf)))
  11.222-            (when (eq old-status :external)
  11.223-              (export* symbol old-package))
  11.224-            (when (eq overwritten-symbol-status :external)
  11.225-              (export* symbol package))))
  11.226-        (values overwritten-symbol overwritten-symbol-status))))
  11.227-  (defun ensure-package-unused (package)
  11.228-    (loop :for p :in (package-used-by-list package) :do
  11.229-      (unuse-package package p)))
  11.230-  (defun delete-package* (package &key nuke)
  11.231-    (let ((p (find-package package)))
  11.232-      (when p
  11.233-        (when nuke (do-symbols (s p) (when (home-package-p s p) (nuke-symbol s))))
  11.234-        (ensure-package-unused p)
  11.235-        (delete-package package))))
  11.236-  (defun package-names (package)
  11.237-    (cons (package-name package) (package-nicknames package)))
  11.238-  (defun packages-from-names (names)
  11.239-    (remove-duplicates (remove nil (mapcar #'find-package names)) :from-end t))
  11.240-  (defun fresh-package-name (&key (prefix :%TO-BE-DELETED)
  11.241-                               separator
  11.242-                               (index (random most-positive-fixnum)))
  11.243-    (loop :for i :from index
  11.244-          :for n = (format nil "~A~@[~A~D~]" prefix (and (plusp i) (or separator "")) i)
  11.245-            :thereis (and (not (find-package n)) n)))
  11.246-  (defun rename-package-away (p &rest keys &key prefix &allow-other-keys)
  11.247-    (let ((new-name
  11.248-            (apply 'fresh-package-name
  11.249-                   :prefix (or prefix (format nil "__~A__" (package-name p))) keys)))
  11.250-      (record-fishy (list :rename-away (package-names p) new-name))
  11.251-      (rename-package p new-name))))
  11.252-
  11.253-
  11.254-;;; Communicable representation of symbol and package information
  11.255-
  11.256-(eval-when (:load-toplevel :compile-toplevel :execute)
  11.257-  (defun package-definition-form (package-designator
  11.258-                                  &key (nicknamesp t) (usep t)
  11.259-                                    (shadowp t) (shadowing-import-p t)
  11.260-                                    (exportp t) (importp t) internp (error t))
  11.261-    (let* ((package (or (find-package* package-designator error)
  11.262-                        (return-from package-definition-form nil)))
  11.263-           (name (package-name package))
  11.264-           (nicknames (package-nicknames package))
  11.265-           (use (mapcar #'package-name (package-use-list package)))
  11.266-           (shadow ())
  11.267-           (shadowing-import (make-hash-table :test 'equal))
  11.268-           (import (make-hash-table :test 'equal))
  11.269-           (export ())
  11.270-           (intern ()))
  11.271-      (when package
  11.272-        (loop :for sym :being :the :symbols :in package
  11.273-              :for status = (nth-value 1 (find-symbol* sym package)) :do
  11.274-                (ecase status
  11.275-                  ((nil :inherited))
  11.276-                  ((:internal :external)
  11.277-                   (let* ((name (symbol-name sym))
  11.278-                          (external (eq status :external))
  11.279-                          (home (symbol-package sym))
  11.280-                          (home-name (package-name home))
  11.281-                          (imported (not (eq home package)))
  11.282-                          (shadowing (symbol-shadowing-p sym package)))
  11.283-                     (cond
  11.284-                       ((and shadowing imported)
  11.285-                        (push name (gethash home-name shadowing-import)))
  11.286-                       (shadowing
  11.287-                        (push name shadow))
  11.288-                       (imported
  11.289-                        (push name (gethash home-name import))))
  11.290-                     (cond
  11.291-                       (external
  11.292-                        (push name export))
  11.293-                       (imported)
  11.294-                       (t (push name intern)))))))
  11.295-        (labels ((sort-names (names)
  11.296-                   (sort (copy-list names) #'string<))
  11.297-                 (table-keys (table)
  11.298-                   (loop :for k :being :the :hash-keys :of table :collect k))
  11.299-                 (when-relevant (key value)
  11.300-                   (when value (list (cons key value))))
  11.301-                 (import-options (key table)
  11.302-                   (loop :for i :in (sort-names (table-keys table))
  11.303-                         :collect `(,key ,i ,@(sort-names (gethash i table))))))
  11.304-          `(defpackage ,name
  11.305-             ,@(when-relevant :nicknames (and nicknamesp (sort-names nicknames)))
  11.306-             (:use ,@(and usep (sort-names use)))
  11.307-             ,@(when-relevant :shadow (and shadowp (sort-names shadow)))
  11.308-             ,@(import-options :shadowing-import-from (and shadowing-import-p shadowing-import))
  11.309-             ,@(import-options :import-from (and importp import))
  11.310-             ,@(when-relevant :export (and exportp (sort-names export)))
  11.311-             ,@(when-relevant :intern (and internp (sort-names intern)))))))))
  11.312-
  11.313-(eval-when (:load-toplevel :compile-toplevel :execute)
  11.314-  (defun ensure-shadowing-import (name to-package from-package shadowed imported)
  11.315-    (check-type name string)
  11.316-    (check-type to-package package)
  11.317-    (check-type from-package package)
  11.318-    (check-type shadowed hash-table)
  11.319-    (check-type imported hash-table)
  11.320-    (let ((import-me (find-symbol* name from-package)))
  11.321-      (multiple-value-bind (existing status) (find-symbol name to-package)
  11.322-        (cond
  11.323-          ((gethash name shadowed)
  11.324-           (unless (eq import-me existing)
  11.325-             (error "Conflicting shadowings for ~A" name)))
  11.326-          (t
  11.327-           (setf (gethash name shadowed) t)
  11.328-           (setf (gethash name imported) t)
  11.329-           (unless (or (null status)
  11.330-                       (and (member status '(:internal :external))
  11.331-                            (eq existing import-me)
  11.332-                            (symbol-shadowing-p existing to-package)))
  11.333-             (note-package-fishiness
  11.334-              :shadowing-import name
  11.335-              (package-name from-package)
  11.336-              (or (home-package-p import-me from-package) (symbol-package-name import-me))
  11.337-              (package-name to-package) status
  11.338-              (and status (or (home-package-p existing to-package) (symbol-package-name existing)))))
  11.339-           (shadowing-import* import-me to-package))))))
  11.340-  (defun ensure-imported (import-me into-package &optional from-package)
  11.341-    (check-type import-me symbol)
  11.342-    (check-type into-package package)
  11.343-    (check-type from-package (or null package))
  11.344-    (let ((name (symbol-name import-me)))
  11.345-      (multiple-value-bind (existing status) (find-symbol name into-package)
  11.346-        (cond
  11.347-          ((not status)
  11.348-           (import* import-me into-package))
  11.349-          ((eq import-me existing))
  11.350-          (t
  11.351-           (let ((shadowing-p (symbol-shadowing-p existing into-package)))
  11.352-             (note-package-fishiness
  11.353-              :ensure-imported name
  11.354-              (and from-package (package-name from-package))
  11.355-              (or (home-package-p import-me from-package) (symbol-package-name import-me))
  11.356-              (package-name into-package)
  11.357-              status
  11.358-              (and status (or (home-package-p existing into-package) (symbol-package-name existing)))
  11.359-              shadowing-p)
  11.360-             (cond
  11.361-               ((or shadowing-p (eq status :inherited))
  11.362-                (shadowing-import* import-me into-package))
  11.363-               (t
  11.364-                (unintern* existing into-package)
  11.365-                (import* import-me into-package))))))))
  11.366-    (values))
  11.367-  (defun ensure-import (name to-package from-package shadowed imported)
  11.368-    (check-type name string)
  11.369-    (check-type to-package package)
  11.370-    (check-type from-package package)
  11.371-    (check-type shadowed hash-table)
  11.372-    (check-type imported hash-table)
  11.373-    (multiple-value-bind (import-me import-status) (find-symbol name from-package)
  11.374-      (when (null import-status)
  11.375-        (note-package-fishiness
  11.376-         :import-uninterned name (package-name from-package) (package-name to-package))
  11.377-        (setf import-me (intern* name from-package)))
  11.378-      (multiple-value-bind (existing status) (find-symbol name to-package)
  11.379-        (cond
  11.380-          ((and imported (gethash name imported))
  11.381-           (unless (and status (eq import-me existing))
  11.382-             (error "Can't import ~S from both ~S and ~S"
  11.383-                    name (package-name (symbol-package existing)) (package-name from-package))))
  11.384-          ((gethash name shadowed)
  11.385-           (error "Can't both shadow ~S and import it from ~S" name (package-name from-package)))
  11.386-          (t
  11.387-           (setf (gethash name imported) t))))
  11.388-      (ensure-imported import-me to-package from-package)))
  11.389-  (defun ensure-inherited (name symbol to-package from-package mixp shadowed imported inherited)
  11.390-    (check-type name string)
  11.391-    (check-type symbol symbol)
  11.392-    (check-type to-package package)
  11.393-    (check-type from-package package)
  11.394-    (check-type mixp (member nil t)) ; no cl:boolean on Genera
  11.395-    (check-type shadowed hash-table)
  11.396-    (check-type imported hash-table)
  11.397-    (check-type inherited hash-table)
  11.398-    (multiple-value-bind (existing status) (find-symbol name to-package)
  11.399-      (let* ((sp (symbol-package symbol))
  11.400-             (in (gethash name inherited))
  11.401-             (xp (and status (symbol-package existing))))
  11.402-        (when (null sp)
  11.403-          (note-package-fishiness
  11.404-           :import-uninterned name
  11.405-           (package-name from-package) (package-name to-package) mixp)
  11.406-          (import* symbol from-package)
  11.407-          (setf sp (package-name from-package)))
  11.408-        (cond
  11.409-          ((gethash name shadowed))
  11.410-          (in
  11.411-           (unless (equal sp (first in))
  11.412-             (if mixp
  11.413-                 (ensure-shadowing-import name to-package (second in) shadowed imported)
  11.414-                 (error "Can't inherit ~S from ~S, it is inherited from ~S"
  11.415-                        name (package-name sp) (package-name (first in))))))
  11.416-          ((gethash name imported)
  11.417-           (unless (eq symbol existing)
  11.418-             (error "Can't inherit ~S from ~S, it is imported from ~S"
  11.419-                    name (package-name sp) (package-name xp))))
  11.420-          (t
  11.421-           (setf (gethash name inherited) (list sp from-package))
  11.422-           (when (and status (not (eq sp xp)))
  11.423-             (let ((shadowing (symbol-shadowing-p existing to-package)))
  11.424-               (note-package-fishiness
  11.425-                :inherited name
  11.426-                (package-name from-package)
  11.427-                (or (home-package-p symbol from-package) (symbol-package-name symbol))
  11.428-                (package-name to-package)
  11.429-                (or (home-package-p existing to-package) (symbol-package-name existing)))
  11.430-               (if shadowing (ensure-shadowing-import name to-package from-package shadowed imported)
  11.431-                   (unintern* existing to-package)))))))))
  11.432-  (defun ensure-mix (name symbol to-package from-package shadowed imported inherited)
  11.433-    (check-type name string)
  11.434-    (check-type symbol symbol)
  11.435-    (check-type to-package package)
  11.436-    (check-type from-package package)
  11.437-    (check-type shadowed hash-table)
  11.438-    (check-type imported hash-table)
  11.439-    (check-type inherited hash-table)
  11.440-    (unless (gethash name shadowed)
  11.441-      (multiple-value-bind (existing status) (find-symbol name to-package)
  11.442-        (let* ((sp (symbol-package symbol))
  11.443-               (im (gethash name imported))
  11.444-               (in (gethash name inherited)))
  11.445-          (cond
  11.446-            ((or (null status)
  11.447-                 (and status (eq symbol existing))
  11.448-                 (and in (eq sp (first in))))
  11.449-             (ensure-inherited name symbol to-package from-package t shadowed imported inherited))
  11.450-            (in
  11.451-             (remhash name inherited)
  11.452-             (ensure-shadowing-import name to-package (second in) shadowed imported))
  11.453-            (im
  11.454-             (error "Symbol ~S import from ~S~:[~; actually ~:[uninterned~;~:*from ~S~]~] conflicts with existing symbol in ~S~:[~; actually ~:[uninterned~;from ~:*~S~]~]"
  11.455-                    name (package-name from-package)
  11.456-                    (home-package-p symbol from-package) (symbol-package-name symbol)
  11.457-                    (package-name to-package)
  11.458-                    (home-package-p existing to-package) (symbol-package-name existing)))
  11.459-            (t
  11.460-             (ensure-inherited name symbol to-package from-package t shadowed imported inherited)))))))
  11.461-
  11.462-  (defun recycle-symbol (name recycle exported)
  11.463-    ;; Takes a symbol NAME (a string), a list of package designators for RECYCLE
  11.464-    ;; packages, and a hash-table of names (strings) of symbols scheduled to be
  11.465-    ;; EXPORTED from the package being defined. It returns two values, the
  11.466-    ;; symbol found (if any, or else NIL), and a boolean flag indicating whether
  11.467-    ;; a symbol was found. The caller (DEFPKG) will then do the
  11.468-    ;; re-homing of the symbol, etc.
  11.469-    (check-type name string)
  11.470-    (check-type recycle list)
  11.471-    (check-type exported hash-table)
  11.472-    (when (gethash name exported) ;; don't bother recycling private symbols
  11.473-      (let (recycled foundp)
  11.474-        (dolist (r recycle (values recycled foundp))
  11.475-          (multiple-value-bind (symbol status) (find-symbol name r)
  11.476-            (when (and status (home-package-p symbol r))
  11.477-              (cond
  11.478-                (foundp
  11.479-                 ;; (nuke-symbol symbol)) -- even simple variable names like O or C will do that.
  11.480-                 (note-package-fishiness :recycled-duplicate name (package-name foundp) (package-name r)))
  11.481-                (t
  11.482-                 (setf recycled symbol foundp r)))))))))
  11.483-  (defun symbol-recycled-p (sym recycle)
  11.484-    (check-type sym symbol)
  11.485-    (check-type recycle list)
  11.486-    (and (member (symbol-package sym) recycle) t))
  11.487-  (defun ensure-symbol (name package intern recycle shadowed imported inherited exported)
  11.488-    (check-type name string)
  11.489-    (check-type package package)
  11.490-    (check-type intern (member nil t)) ; no cl:boolean on Genera
  11.491-    (check-type shadowed hash-table)
  11.492-    (check-type imported hash-table)
  11.493-    (check-type inherited hash-table)
  11.494-    (unless (or (gethash name shadowed)
  11.495-                (gethash name imported)
  11.496-                (gethash name inherited))
  11.497-      (multiple-value-bind (existing status)
  11.498-          (find-symbol name package)
  11.499-        (multiple-value-bind (recycled previous) (recycle-symbol name recycle exported)
  11.500-          (cond
  11.501-            ((and status (eq existing recycled) (eq previous package)))
  11.502-            (previous
  11.503-             (rehome-symbol recycled package))
  11.504-            ((and status (eq package (symbol-package existing))))
  11.505-            (t
  11.506-             (when status
  11.507-               (note-package-fishiness
  11.508-                :ensure-symbol name
  11.509-                (reify-package (symbol-package existing) package)
  11.510-                status intern)
  11.511-               (unintern existing))
  11.512-             (when intern
  11.513-               (intern* name package))))))))
  11.514-  (declaim (ftype (function (t t t &optional t) t) ensure-exported))
  11.515-  (defun ensure-exported-to-user (name symbol to-package &optional recycle)
  11.516-    (check-type name string)
  11.517-    (check-type symbol symbol)
  11.518-    (check-type to-package package)
  11.519-    (check-type recycle list)
  11.520-    (assert (equal name (symbol-name symbol)))
  11.521-    (multiple-value-bind (existing status) (find-symbol name to-package)
  11.522-      (unless (and status (eq symbol existing))
  11.523-        (let ((accessible
  11.524-                (or (null status)
  11.525-                    (let ((shadowing (symbol-shadowing-p existing to-package))
  11.526-                          (recycled (symbol-recycled-p existing recycle)))
  11.527-                      (unless (and shadowing (not recycled))
  11.528-                        (note-package-fishiness
  11.529-                         :ensure-export name (symbol-package-name symbol)
  11.530-                         (package-name to-package)
  11.531-                         (or (home-package-p existing to-package) (symbol-package-name existing))
  11.532-                         status shadowing)
  11.533-                        (if (or (eq status :inherited) shadowing)
  11.534-                            (shadowing-import* symbol to-package)
  11.535-                            (unintern existing to-package))
  11.536-                        t)))))
  11.537-          (when (and accessible (eq status :external))
  11.538-            (ensure-exported name symbol to-package recycle))))))
  11.539-  (defun ensure-exported (name symbol from-package &optional recycle)
  11.540-    (dolist (to-package (package-used-by-list from-package))
  11.541-      (ensure-exported-to-user name symbol to-package recycle))
  11.542-    (unless (eq from-package (symbol-package symbol))
  11.543-      (ensure-imported symbol from-package))
  11.544-    (export* name from-package))
  11.545-  (defun ensure-export (name from-package &optional recycle)
  11.546-    (multiple-value-bind (symbol status) (find-symbol* name from-package)
  11.547-      (unless (eq status :external)
  11.548-        (ensure-exported name symbol from-package recycle))))
  11.549-
  11.550-  (defun ensure-package (name &key
  11.551-                                nicknames documentation use
  11.552-                                shadow shadowing-import-from
  11.553-                                import-from export intern
  11.554-                                recycle mix reexport
  11.555-                                unintern)
  11.556-    #+genera (declare (ignore documentation))
  11.557-    (let* ((package-name (string name))
  11.558-           (nicknames (mapcar #'string nicknames))
  11.559-           (names (cons package-name nicknames))
  11.560-           (previous (packages-from-names names))
  11.561-           (discarded (cdr previous))
  11.562-           (to-delete ())
  11.563-           (package (or (first previous) (make-package package-name :nicknames nicknames)))
  11.564-           (recycle (packages-from-names recycle))
  11.565-           (use (mapcar 'find-package* use))
  11.566-           (mix (mapcar 'find-package* mix))
  11.567-           (reexport (mapcar 'find-package* reexport))
  11.568-           (shadow (mapcar 'string shadow))
  11.569-           (export (mapcar 'string export))
  11.570-           (intern (mapcar 'string intern))
  11.571-           (unintern (mapcar 'string unintern))
  11.572-           (shadowed (make-hash-table :test 'equal)) ; string to bool
  11.573-           (imported (make-hash-table :test 'equal)) ; string to bool
  11.574-           (exported (make-hash-table :test 'equal)) ; string to bool
  11.575-           ;; string to list home package and use package:
  11.576-           (inherited (make-hash-table :test 'equal)))
  11.577-      (when-package-fishiness (record-fishy package-name))
  11.578-      #-genera
  11.579-      (when documentation (setf (documentation package t) documentation))
  11.580-      (loop :for p :in (set-difference (package-use-list package) (append mix use))
  11.581-            :do (note-package-fishiness :over-use name (package-names p))
  11.582-                (unuse-package p package))
  11.583-      (loop :for p :in discarded
  11.584-            :for n = (remove-if #'(lambda (x) (member x names :test 'equal))
  11.585-                                (package-names p))
  11.586-            :do (note-package-fishiness :nickname name (package-names p))
  11.587-                (cond (n (rename-package p (first n) (rest n)))
  11.588-                      (t (rename-package-away p)
  11.589-                         (push p to-delete))))
  11.590-      (rename-package package package-name nicknames)
  11.591-      (dolist (name unintern)
  11.592-        (multiple-value-bind (existing status) (find-symbol name package)
  11.593-          (when status
  11.594-            (unless (eq status :inherited)
  11.595-              (note-package-fishiness
  11.596-               :unintern (package-name package) name (symbol-package-name existing) status)
  11.597-              (unintern* name package nil)))))
  11.598-      (dolist (name export)
  11.599-        (setf (gethash name exported) t))
  11.600-      (dolist (p reexport)
  11.601-        (do-external-symbols (sym p)
  11.602-          (setf (gethash (string sym) exported) t)))
  11.603-      (do-external-symbols (sym package)
  11.604-        (let ((name (symbol-name sym)))
  11.605-          (unless (gethash name exported)
  11.606-            (note-package-fishiness
  11.607-             :over-export (package-name package) name
  11.608-             (or (home-package-p sym package) (symbol-package-name sym)))
  11.609-            (unexport sym package))))
  11.610-      (dolist (name shadow)
  11.611-        (setf (gethash name shadowed) t)
  11.612-        (multiple-value-bind (existing status) (find-symbol name package)
  11.613-          (multiple-value-bind (recycled previous) (recycle-symbol name recycle exported)
  11.614-            (let ((shadowing (and status (symbol-shadowing-p existing package))))
  11.615-              (cond
  11.616-                ((eq previous package))
  11.617-                (previous
  11.618-                 (rehome-symbol recycled package))
  11.619-                ((or (member status '(nil :inherited))
  11.620-                     (home-package-p existing package)))
  11.621-                (t
  11.622-                 (let ((dummy (make-symbol name)))
  11.623-                   (note-package-fishiness
  11.624-                    :shadow-imported (package-name package) name
  11.625-                    (symbol-package-name existing) status shadowing)
  11.626-                   (shadowing-import* dummy package)
  11.627-                   (import* dummy package)))))))
  11.628-        (shadow* name package))
  11.629-      (loop :for (p . syms) :in shadowing-import-from
  11.630-            :for pp = (find-package* p) :do
  11.631-              (dolist (sym syms) (ensure-shadowing-import (string sym) package pp shadowed imported)))
  11.632-      (loop :for p :in mix
  11.633-            :for pp = (find-package* p) :do
  11.634-              (do-external-symbols (sym pp) (ensure-mix (symbol-name sym) sym package pp shadowed imported inherited)))
  11.635-      (loop :for (p . syms) :in import-from
  11.636-            :for pp = (find-package p) :do
  11.637-              (dolist (sym syms) (ensure-import (symbol-name sym) package pp shadowed imported)))
  11.638-      (dolist (p (append use mix))
  11.639-        (do-external-symbols (sym p) (ensure-inherited (string sym) sym package p nil shadowed imported inherited))
  11.640-        (use-package p package))
  11.641-      (loop :for name :being :the :hash-keys :of exported :do
  11.642-        (ensure-symbol name package t recycle shadowed imported inherited exported)
  11.643-        (ensure-export name package recycle))
  11.644-      (dolist (name intern)
  11.645-        (ensure-symbol name package t recycle shadowed imported inherited exported))
  11.646-      (do-symbols (sym package)
  11.647-        (ensure-symbol (symbol-name sym) package nil recycle shadowed imported inherited exported))
  11.648-      (map () 'delete-package* to-delete)
  11.649-      package)))
  11.650-
  11.651-(eval-when (:load-toplevel :compile-toplevel :execute)
  11.652-  (defun parse-defpkg-form (package clauses)
  11.653-    (loop
  11.654-      :with use-p = nil :with recycle-p = nil
  11.655-      :with documentation = nil
  11.656-      :for (kw . args) :in clauses
  11.657-      :when (eq kw :nicknames) :append args :into nicknames :else
  11.658-        :when (eq kw :documentation)
  11.659-          :do (cond
  11.660-                (documentation (error "defpkg: can't define documentation twice"))
  11.661-                ((or (atom args) (cdr args)) (error "defpkg: bad documentation"))
  11.662-                (t (setf documentation (car args)))) :else
  11.663-      :when (eq kw :use) :append args :into use :and :do (setf use-p t) :else
  11.664-        :when (eq kw :shadow) :append args :into shadow :else
  11.665-          :when (eq kw :shadowing-import-from) :collect args :into shadowing-import-from :else
  11.666-            :when (eq kw :import-from) :collect args :into import-from :else
  11.667-              :when (eq kw :export) :append args :into export :else
  11.668-                :when (eq kw :intern) :append args :into intern :else
  11.669-                  :when (eq kw :recycle) :append args :into recycle :and :do (setf recycle-p t) :else
  11.670-                    :when (eq kw :mix) :append args :into mix :else
  11.671-                      :when (eq kw :reexport) :append args :into reexport :else
  11.672-                        :when (eq kw :use-reexport) :append args :into use :and :append args :into reexport
  11.673-                        :and :do (setf use-p t) :else
  11.674-      :when (eq kw :mix-reexport) :append args :into mix :and :append args :into reexport
  11.675-      :and :do (setf use-p t) :else
  11.676-      :when (eq kw :unintern) :append args :into unintern :else
  11.677-        :do (error "unrecognized defpkg keyword ~S" kw)
  11.678-      :finally (return `(,package
  11.679-                         :nicknames ,nicknames :documentation ,documentation
  11.680-                         :use ,(if use-p use '(:common-lisp))
  11.681-                         :shadow ,shadow :shadowing-import-from ,shadowing-import-from
  11.682-                         :import-from ,import-from :export ,export :intern ,intern
  11.683-                         :recycle ,(if recycle-p recycle (cons package nicknames))
  11.684-                         :mix ,mix :reexport ,reexport :unintern ,unintern)))))
  11.685-
  11.686-(defmacro defpkg (package &rest clauses)
  11.687-  "Richard's Robust DEFPACKAGE macro. Based on UIOP:DEFINE-PACKAGE. ymmv.
  11.688-
  11.689-DEFPKG takes a PACKAGE and a number of CLAUSES, of the form (KEYWORD . ARGS).
  11.690-
  11.691-DEFPKG supports the following keywords:
  11.692-USE, SHADOW, SHADOWING-IMPORT-FROM, IMPORT-FROM, EXPORT, INTERN -- as per CL:DEFPACKAGE.
  11.693-
  11.694-DEFPKG also redefines the following extensions:
  11.695-RECYCLE, MIX, REEXPORT, UNINTERN -- as per UIOP/PACKAGE:DEFINE-PACKAGE
  11.696-
  11.697-REEXPORT -- Takes a list of package designators. For each package in
  11.698-the list, export symbols with the same name as those exported from
  11.699-that package. In the case of shadowing, etc. They may not be EQL."
  11.700-  (let ((ensure-form
  11.701-          `(apply 'ensure-package ',(parse-defpkg-form package clauses))))
  11.702-    `(progn
  11.703-       #+(or clasp ecl gcl mkcl) (defpackage ,package (:use))
  11.704-       (eval-when (:compile-toplevel :load-toplevel :execute)
  11.705-         ,ensure-form))))
  11.706-
  11.707 ;; TODO
  11.708 (defun save-lisp-and-live (filename completion-function restart &rest args)
  11.709   (flet ((restart-sbcl ()
    12.1Binary file std has changed