changelog shortlog graph tags branches files raw help

Mercurial > core / changeset: begin :STD refactor

changeset 291: a0dfde3cb3c4
parent 290: 14b0ee8d09c1
child 292: 00d1c8afcdbb
author: Richard Westhaver <ellis@rwest.io>
date: Mon, 22 Apr 2024 23:14:47 -0400
files: lisp/ffi/uring/util.lisp lisp/std/alien.lisp lisp/std/ana.lisp lisp/std/array.lisp lisp/std/bit.lisp lisp/std/bits.lisp lisp/std/defpkg.lisp lisp/std/err.lisp lisp/std/file.lisp lisp/std/fmt.lisp lisp/std/fu.lisp lisp/std/fu/curry.lisp lisp/std/hash-table.lisp lisp/std/list.lisp lisp/std/macs/ana.lisp lisp/std/macs/const.lisp lisp/std/macs/pan.lisp lisp/std/mop.lisp lisp/std/named-readtables.lisp lisp/std/num/float.lisp lisp/std/num/parse.lisp lisp/std/os.lisp lisp/std/pan.lisp lisp/std/path.lisp lisp/std/pkg.lisp lisp/std/readtable.lisp lisp/std/seq.lisp lisp/std/std.asd lisp/std/stream.lisp lisp/std/string.lisp lisp/std/sym.lisp lisp/std/sys.lisp lisp/std/thread.lisp lisp/std/type.lisp lisp/std/types.lisp lisp/std/util.lisp
description: begin :STD refactor
     1.1--- a/lisp/ffi/uring/util.lisp	Sun Apr 21 22:38:49 2024 -0400
     1.2+++ b/lisp/ffi/uring/util.lisp	Mon Apr 22 23:14:47 2024 -0400
     1.3@@ -60,3 +60,10 @@
     1.4 
     1.5 ;; do-mmap
     1.6 ;; map len bytes starting from offset from file-descriptor in mmapped-region
     1.7+
     1.8+;;; CPU Affinity
     1.9+;; it appears this actually crashes SBCL, receiving sig6 from foreign thread
    1.10+;; (define-alien-routine sched-setaffinity int (pid int) (cpusetsize size-t) (set (* (struct cpu-set-t))))
    1.11+;; (define-alien-routine sched-getaffinity int (pid int) (cpusetsize size-t) (set (* (struct cpu-set-t))))
    1.12+;; (sched-getaffinity 0 cpu-setsize (make-alien (struct cpu-set-t)))
    1.13+;; (sched-setaffinity 0 cpu-setsize (make-alien (struct cpu-set-t)))
     2.1--- a/lisp/std/alien.lisp	Sun Apr 21 22:38:49 2024 -0400
     2.2+++ b/lisp/std/alien.lisp	Mon Apr 22 23:14:47 2024 -0400
     2.3@@ -21,7 +21,7 @@
     2.4 ;; represented by objects of type ALIEN-VALUE.
     2.5 
     2.6 ;;; Code:
     2.7-(in-package :std)
     2.8+(in-package :std/alien)
     2.9 (shadowing-import
    2.10  '(sb-unix::syscall sb-unix::syscall* sb-unix::int-syscall
    2.11    sb-unix::with-restarted-syscall sb-unix::void-syscall) :std)
     3.1--- a/lisp/std/ana.lisp	Sun Apr 21 22:38:49 2024 -0400
     3.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3@@ -1,84 +0,0 @@
     3.4-;;; ana.lisp --- anaphoric macros
     3.5-
     3.6-;;; Code:
     3.7-(in-package :std)
     3.8-
     3.9-(in-readtable :std)
    3.10-
    3.11-;; Graham's alambda
    3.12-(defmacro alambda (parms &body body)
    3.13-  `(labels ((self ,parms ,@body))
    3.14-     #'self))
    3.15-
    3.16-;; Graham's aif
    3.17-(defmacro aif (test then &optional else)
    3.18-  `(let ((it ,test))
    3.19-     (if it ,then ,else)))
    3.20-
    3.21-;; ;; TODO 2023-09-05: wrap, document, optimize, hack
    3.22-;; re-exported from SB-INT
    3.23-(defmacro awhen (test &body body)
    3.24-  `(let ((it ,test))
    3.25-     (when it ,@body)))
    3.26-
    3.27-(defmacro acond (&rest clauses)
    3.28-  (if (null clauses)
    3.29-      `()
    3.30-      (destructuring-bind ((test &body body) &rest rest) clauses
    3.31-        (let ((it (copy-symbol 'it)))
    3.32-          `(let ((,it ,test))
    3.33-             (if ,it
    3.34-                 ;; Just like COND - no body means return the tested value.
    3.35-                 ,(if body
    3.36-                      `(let ((it ,it)) (declare (ignorable it)) ,@body)
    3.37-                      it)
    3.38-                 (acond ,@rest)))))))
    3.39-
    3.40-(defmacro! nlet-tail (n letargs &body body)
    3.41-  (let ((gs (loop for i in letargs
    3.42-               collect (gensym))))
    3.43-    `(macrolet
    3.44-         ((,n ,gs
    3.45-            `(progn
    3.46-               (psetq
    3.47-                ,@(apply #'nconc
    3.48-                         (mapcar
    3.49-                          #'list
    3.50-                          ',(mapcar #'car letargs)
    3.51-                          (list ,@gs))))
    3.52-               (go ,',g!n))))
    3.53-       (block ,g!b
    3.54-         (let ,letargs
    3.55-           (tagbody
    3.56-              ,g!n (return-from
    3.57-                    ,g!b (progn ,@body))))))))
    3.58-
    3.59-(defmacro alet% (letargs &rest body)
    3.60-  `(let ((this) ,@letargs)
    3.61-     (setq this ,@(last body))
    3.62-     ,@(butlast body)
    3.63-     this))
    3.64-
    3.65-(defmacro alet (letargs &rest body)
    3.66-  `(let ((this) ,@letargs)
    3.67-     (setq this ,@(last body))
    3.68-     ,@(butlast body)
    3.69-     (lambda (&rest params)
    3.70-       (apply this params))))
    3.71-
    3.72-;; swiped from fiveam. This is just like acond except it assumes that
    3.73-;; the TEST in each element of CLAUSES returns two values as opposed
    3.74-;; to one.
    3.75-(defmacro acond2 (&rest clauses)
    3.76-  (if (null clauses)
    3.77-      nil
    3.78-      (with-gensyms (val foundp)
    3.79-        (destructuring-bind ((test &rest progn) &rest others)
    3.80-            clauses
    3.81-          `(multiple-value-bind (,val ,foundp)
    3.82-               ,test
    3.83-             (if (or ,val ,foundp)
    3.84-                 (let ((it ,val))
    3.85-                   (declare (ignorable it))
    3.86-                   ,@progn)
    3.87-                 (acond2 ,@others)))))))
     4.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2+++ b/lisp/std/array.lisp	Mon Apr 22 23:14:47 2024 -0400
     4.3@@ -0,0 +1,24 @@
     4.4+;;; std/array.lisp --- Standard Arrays
     4.5+
     4.6+;;
     4.7+
     4.8+;;; Code:
     4.9+(in-package :std/array)
    4.10+
    4.11+(defun copy-array (array)
    4.12+  (let ((new-array
    4.13+          (make-array (array-dimensions array)
    4.14+                      :element-type (array-element-type array)
    4.15+                      :adjustable (adjustable-array-p array)
    4.16+                      :fill-pointer (and (array-has-fill-pointer-p array)
    4.17+                                         (fill-pointer array)))))
    4.18+    (loop for i below (array-total-size array)
    4.19+          do (setf (row-major-aref new-array i)
    4.20+                   (row-major-aref array i)))
    4.21+    new-array))
    4.22+
    4.23+(deftype signed-array-length ()
    4.24+  "A (possibly negated) array length."
    4.25+  '#.(let ((limit (1- array-dimension-limit)))
    4.26+       `(integer ,(- limit) ,limit)))
    4.27+
     5.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2+++ b/lisp/std/bit.lisp	Mon Apr 22 23:14:47 2024 -0400
     5.3@@ -0,0 +1,522 @@
     5.4+;;; std/bit.lisp --- Bit manipulation
     5.5+
     5.6+;;; Commentary:
     5.7+
     5.8+;; CMUCL doc: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node132.html
     5.9+
    5.10+;; quick primer: https://cp-algorithms.com/algebra/bit-manipulation.html
    5.11+
    5.12+;;; Code:
    5.13+(in-package :std/bit)
    5.14+
    5.15+;;; Types
    5.16+;; Bytes aren't necessarily 8 bits wide in Lisp. OCTET is always 8
    5.17+;; bits.
    5.18+(deftype octet () '(unsigned-byte 8))
    5.19+(deftype octet-vector (&optional length)
    5.20+  `(simple-array octet (,length)))
    5.21+
    5.22+;;; Bits
    5.23+(defun make-bits (length &rest args)
    5.24+  (apply #'make-array length (nconc (list :element-type 'bit) args)))
    5.25+
    5.26+;; https://graphics.stanford.edu/~seander/bithacks.html
    5.27+;; http://www.azillionmonkeys.com/qed/asmexample.html
    5.28+(defun haipart (n count) 
    5.29+  (declare (fixnum n count))
    5.30+  (let ((x (abs n)))
    5.31+    (if (minusp count) 
    5.32+        (ldb (byte (- count) 0) x)
    5.33+        (ldb (byte count (max 0 (- (integer-length x) count)))
    5.34+             x))))
    5.35+
    5.36+;; minusp = 38 bytes
    5.37+
    5.38+;; 29 bytes
    5.39+(defun sign-bit (n)
    5.40+  "compute the sign bit of a fixnum. If N < 0 return -1 else return 0."
    5.41+  (declare (fixnum n))
    5.42+  (ash n (- 0 (integer-length n))))
    5.43+
    5.44+;; 51 bytes (speed 3)
    5.45+;; 67 bytes (speed 1)
    5.46+(defun different-signs-p (x y)
    5.47+  "Return non-nil iff x and y have opposite signs."
    5.48+  (declare (fixnum x y) (optimize (speed 1)))
    5.49+  (< (expt x y) 0))
    5.50+
    5.51+;; TODO 2024-02-23: 
    5.52+(defun mortify-bits (x y)
    5.53+  "Interleave the bits of two numbers (Mortan numbers)."
    5.54+  (declare (fixnum x y)
    5.55+           (ignore x y))
    5.56+  ;; (loop for i across (integer-length)
    5.57+  ;;       with z = 0
    5.58+  ;;       ;; z |= (x & 1U << i) << i | (y & 1U << i) << (i + 1);
    5.59+  ;;       do ()
    5.60+  ;;       return z)
    5.61+  )
    5.62+
    5.63+(defun int-list-bits (n)
    5.64+  (declare (fixnum n))
    5.65+  (let ((bits '()))
    5.66+    (dotimes (position (integer-length n) bits)
    5.67+      (push (ldb (byte 1 position) n) bits))))
    5.68+
    5.69+(defun int-bit-vector (n)
    5.70+  (declare (fixnum n))
    5.71+  (let ((bits (make-array 0 :element-type 'bit :adjustable t :fill-pointer t)))
    5.72+    (dotimes (position (integer-length n) bits)
    5.73+      (vector-push-extend (ldb (byte 1 position) n) bits))))
    5.74+
    5.75+(defun aref-bit (octets idx)
    5.76+  (declare (octet-vector octets) (fixnum idx))
    5.77+  (multiple-value-bind (octet-idx bit-idx)
    5.78+      (truncate idx 8)
    5.79+    (ldb (byte 1 bit-idx)
    5.80+         (aref octets octet-idx))))
    5.81+
    5.82+(defun make-bit-vector (size &optional (fill 0))
    5.83+  "Make a BIT-VECTOR with SIZE and initial-element FILL which must be a
    5.84+BIT 0|1. Note that this representation is not as useful as you might
    5.85+think - bit-vectors don't have a direct mapping to integers/fixnums --
    5.86+they are vectors (AKA arrays) first, and bits second. Attempting to
    5.87+perform bitwise-ops ends up being very inefficient so whenever
    5.88+possible, stick with fixnums and use LOG* functions."
    5.89+  (declare (bit fill))
    5.90+  (make-array size :initial-element fill :adjustable nil :element-type 'bit))
    5.91+
    5.92+;; simple setter/getter for integer bits
    5.93+(define-setf-expander logbit (index place &environment env)
    5.94+  (multiple-value-bind (temps vals stores store-form access-form)
    5.95+      (get-setf-expansion place env)
    5.96+    (let ((i (gensym))
    5.97+          (store (gensym))
    5.98+          (stemp (first stores)))
    5.99+      (values `(,i ,@temps)
   5.100+              `(,index ,@vals)
   5.101+              `(,store)
   5.102+              `(let ((,stemp (dpb ,store (byte 1 ,i) ,access-form))
   5.103+                     ,@(cdr stores))
   5.104+                 ,store-form
   5.105+                 ,store)
   5.106+              `(logbit ,i ,access-form)))))
   5.107+
   5.108+(defun logbit (idx n)
   5.109+  (declare (fixnum idx n))
   5.110+  (ldb (byte 1 idx) n))
   5.111+
   5.112+;;; Bitfields
   5.113+
   5.114+;; see https://github.com/marcoheisig/bitfield
   5.115+
   5.116+;; A bitfield is a simple, efficient mechanism for storing multiple
   5.117+;; discrete states into a single non-negative integer.
   5.118+
   5.119+(deftype bitfield ()
   5.120+  "A bitfield is a non-negative integer that efficiently encodes
   5.121+information about some booleans, enumerations, or small integers."
   5.122+  'unsigned-byte)
   5.123+
   5.124+;;; Bitfield Slots
   5.125+(defgeneric bitfield-slot-name (bitfield-slot)
   5.126+  (:documentation
   5.127+   "Returns a symbol that is the name of the bitfield slot."))
   5.128+
   5.129+(defgeneric bitfield-slot-start (bitfield-slot)
   5.130+  (:documentation
   5.131+   "Returns the position of the first bit of this slot in the bitfield."))
   5.132+
   5.133+(defgeneric bitfield-slot-end (bitfield-slot)
   5.134+  (:documentation
   5.135+   "Returns the position right after the last bit of this slot in the bitfield."))
   5.136+
   5.137+(defgeneric bitfield-slot-size (bitfield-slot)
   5.138+  (:documentation
   5.139+   "Returns an unsigned byte that is the number of distinct states of the slot."))
   5.140+
   5.141+(defgeneric bitfield-slot-initform (bitfield-slot)
   5.142+  (:documentation
   5.143+   "Returns a form that produces the initial value for that slot."))
   5.144+
   5.145+(defgeneric bitfield-slot-pack (bitfield-slot value-form)
   5.146+  (:documentation
   5.147+   "Takes a form that produces a value and turns it into a form that produces
   5.148+a non-negative integer representing that value."))
   5.149+
   5.150+(defgeneric bitfield-slot-unpack (bitfield-slot value-form)
   5.151+  (:documentation
   5.152+   "Take a form that produces a value that is encoded as a non-negative
   5.153+integer (as produced by BITFIELD-SLOT-PACK), and turn it into a form that
   5.154+produces the decoded value."))
   5.155+
   5.156+(defgeneric parse-atomic-bitfield-slot-specifier
   5.157+    (specifier &key initform)
   5.158+  (:documentation
   5.159+   "Parses an atomic bitfield slot specifier, i.e., a bitfield slot
   5.160+specifier that is not a list.  Returns three values:
   5.161+
   5.162+1. A designator for a bitfield slot class.
   5.163+
   5.164+2. The size of the bitfield slot.
   5.165+
   5.166+3. A list of additional arguments that will be supplied to MAKE-INSTANCE
   5.167+when creating the bitfield slot instance."))
   5.168+
   5.169+(defgeneric parse-compound-bitfield-slot-specifier
   5.170+    (specifier arguments &key initform)
   5.171+  (:documentation
   5.172+   "Parses a compount bitfield slot specifier, i.e., a bitfield slot
   5.173+specifier that is a list.  The SPECIFIER is the CAR of that list and the
   5.174+ARGUMENTS are the CDR of that list.  Returns three values:
   5.175+
   5.176+1. A designator for a bitfield slot class.
   5.177+
   5.178+2. The size of the bitfield slot.
   5.179+
   5.180+3. A list of additional arguments that will be supplied to MAKE-INSTANCE
   5.181+when creating the bitfield slot instance."))
   5.182+
   5.183+(defclass bitfield-slot ()
   5.184+  ((%name :initarg :name :reader bitfield-slot-name)
   5.185+   (%initform :initarg :initform :reader bitfield-slot-initform)
   5.186+   (%start :initarg :start :reader bitfield-slot-start)
   5.187+   (%end :initarg :end :reader bitfield-slot-end)
   5.188+   (%size :initarg :size :reader bitfield-slot-size)))
   5.189+
   5.190+;;; Boolean Slots
   5.191+(defclass bitfield-boolean-slot (bitfield-slot)
   5.192+  ())
   5.193+
   5.194+(defmethod bitfield-slot-pack ((slot bitfield-boolean-slot) value-form)
   5.195+  `(if ,value-form 1 0))
   5.196+
   5.197+(defmethod bitfield-slot-unpack ((slot bitfield-boolean-slot) value-form)
   5.198+  `(ecase ,value-form (0 nil) (1 t)))
   5.199+
   5.200+(defmethod parse-atomic-bitfield-slot-specifier
   5.201+    ((specifier (eql 'boolean)) &key (initform 'nil))
   5.202+  (values 'bitfield-boolean-slot
   5.203+          2
   5.204+          `(:initform ,initform)))
   5.205+
   5.206+;;; Integer Slots
   5.207+(defclass bitfield-integer-slot (bitfield-slot)
   5.208+  ((%offset
   5.209+    :type integer
   5.210+    :initarg :offset
   5.211+    :reader bitfield-integer-slot-offset)))
   5.212+
   5.213+(defmethod bitfield-slot-pack ((slot bitfield-integer-slot) value-form)
   5.214+  (let ((offset (bitfield-integer-slot-offset slot))
   5.215+        (size (bitfield-slot-size slot)))
   5.216+    `(the (integer 0 (,size))
   5.217+          (- (the (integer ,offset (,(+ offset size))) ,value-form)
   5.218+             ,offset))))
   5.219+
   5.220+(defmethod bitfield-slot-unpack ((slot bitfield-integer-slot) value-form)
   5.221+  (let ((offset (bitfield-integer-slot-offset slot))
   5.222+        (size (bitfield-slot-size slot)))
   5.223+    `(the (integer ,offset (,(+ offset size)))
   5.224+          (+ ,value-form ,offset))))
   5.225+
   5.226+(defmethod parse-atomic-bitfield-slot-specifier
   5.227+    ((specifier (eql 'bit)) &key (initform '0))
   5.228+  (values 'bitfield-unsigned-byte-slot
   5.229+          2
   5.230+          `(:offset 0 :initform ,initform)))
   5.231+
   5.232+(defmethod parse-compound-bitfield-slot-specifier
   5.233+    ((specifier (eql 'unsigned-byte)) arguments &key (initform '0))
   5.234+  (destructuring-bind (bits) arguments
   5.235+    (check-type bits unsigned-byte)
   5.236+    (values 'bitfield-integer-slot
   5.237+            (expt 2 bits)
   5.238+            `(:offset 0 :initform ,initform))))
   5.239+
   5.240+(defmethod parse-compound-bitfield-slot-specifier
   5.241+    ((specifier (eql 'signed-byte)) arguments &key (initform '0))
   5.242+  (destructuring-bind (bits) arguments
   5.243+    (check-type bits unsigned-byte)
   5.244+    (values 'bitfield-integer-slot
   5.245+            (expt 2 bits)
   5.246+            `(:offset ,(- (expt 2 (1- bits))) :initform ,initform))))
   5.247+
   5.248+(defmethod parse-compound-bitfield-slot-specifier
   5.249+    ((specifier (eql 'integer)) bounds &key (initform nil initform-supplied-p))
   5.250+  (flet ((fail ()
   5.251+           (error "Invalid integer bitfield slot specifier: ~S"
   5.252+                  `(integer ,@bounds))))
   5.253+    (unless (typep bounds '(cons t (cons t null)))
   5.254+      (fail))
   5.255+    (destructuring-bind (lo hi) bounds
   5.256+      (let* ((start (typecase lo
   5.257+                      (integer lo)
   5.258+                      ((cons integer null)
   5.259+                       (1+ (first lo)))
   5.260+                      (otherwise (fail))))
   5.261+             (end (typecase hi
   5.262+                    (integer (1+ hi))
   5.263+                    ((cons integer null)
   5.264+                     (first hi))
   5.265+                    (otherwise (fail))))
   5.266+             (size (- end start)))
   5.267+        (unless (plusp size)
   5.268+          (fail))
   5.269+        (values 'bitfield-integer-slot
   5.270+                size
   5.271+                `(:offset ,start :initform ,(if initform-supplied-p initform start)))))))
   5.272+
   5.273+;;; Member Slots
   5.274+(defclass bitfield-member-slot (bitfield-slot)
   5.275+  ((%objects
   5.276+    :type list
   5.277+    :initarg :objects
   5.278+    :reader bitfield-member-slot-objects)))
   5.279+
   5.280+(defmethod bitfield-slot-pack ((slot bitfield-member-slot) value-form)
   5.281+  `(ecase ,value-form
   5.282+     ,@(loop for key in (bitfield-member-slot-objects slot)
   5.283+             for value from 0
   5.284+             collect `((,key) ,value))))
   5.285+
   5.286+(defmethod bitfield-slot-unpack ((slot bitfield-member-slot) value-form)
   5.287+  `(ecase ,value-form
   5.288+     ,@(loop for key from 0
   5.289+             for value in (bitfield-member-slot-objects slot)
   5.290+             collect `((,key) ',value))))
   5.291+
   5.292+(defmethod parse-compound-bitfield-slot-specifier
   5.293+    ((specifier (eql 'member)) objects &key (initform `',(first objects)))
   5.294+  (values 'bitfield-member-slot
   5.295+          (length objects)
   5.296+          `(:initform ,initform :objects ,objects)))
   5.297+
   5.298+;;; Parsing
   5.299+;; The position right after the last slot that has been parsed so far.
   5.300+(defvar *bitfield-position*)
   5.301+
   5.302+(defun parse-bitfield-slot (slot)
   5.303+  (destructuring-bind (slot-name slot-specifier &rest rest) slot
   5.304+    (check-type slot-name symbol)
   5.305+    (multiple-value-bind (slot-class size args)
   5.306+        (if (consp slot-specifier)
   5.307+            (apply #'parse-compound-bitfield-slot-specifier
   5.308+                   (car slot-specifier)
   5.309+                   (cdr slot-specifier)
   5.310+                   rest)
   5.311+            (apply #'parse-atomic-bitfield-slot-specifier
   5.312+                   slot-specifier
   5.313+                   rest))
   5.314+      (apply #'make-instance slot-class
   5.315+             :name slot-name
   5.316+             :size size
   5.317+             :start *bitfield-position*
   5.318+             :end (incf *bitfield-position* (integer-length (1- size)))
   5.319+             args))))
   5.320+
   5.321+(defmacro define-bitfield (name &body slots)
   5.322+  "Defines an encoding of enumerable properties like booleans,
   5.323+integers or finite sets as a single non-negative integer.
   5.324+
   5.325+For a supplied bitfield name NAME, and for some slot definitions of the
   5.326+form (SLOT-NAME TYPE &KEY INITFORM &ALLOW-OTHER-KEYS), this macro defines
   5.327+the following functions:
   5.328+
   5.329+1. A constructor named MAKE-{NAME}, that takes one keyword argument per
   5.330+   SLOT-NAME, similar to the default constructor generated by DEFSTRUCT.
   5.331+   It returns a bitfield whose entries have the values indicated by the
   5.332+   keyword arguments, or the supplied initform.
   5.333+
   5.334+2. A clone operation named CLONE-{NAME}, that takes an existing bitfield
   5.335+   and one keyword argument per SLOT-NAME.  It returns a copy of the
   5.336+   existing bitfield, but where each supplied keyword argument supersedes
   5.337+   the value of the corresponding slot.
   5.338+
   5.339+3. A reader function named {NAME}-{SLOT-NAME} for each slot.
   5.340+
   5.341+In addition to these functions, NAME is defined as a suitable subtype of
   5.342+UNSIGNED-BYTE.
   5.343+
   5.344+This macro supports boolean, integer, and member slots.  It is also
   5.345+possible to add new kinds of slots by defining new subclasses of
   5.346+BITFIELD-SLOT and the corresponding methods on BITFIELD-SLOT-PACK,
   5.347+BITFIELD-SLOT-UNPACK and PARSE-ATOMIC-BITFIELD-SLOT-SPECIFIER or
   5.348+PARSE-COMPOUND-BITFIELD-SLOT-SPECIFIER.
   5.349+
   5.350+ Example:
   5.351+
   5.352+ (define-bitfield examplebits
   5.353+   (a boolean)
   5.354+   (b (signed-byte 2))
   5.355+   (c (unsigned-byte 3) :initform 1)
   5.356+   (d (integer -100 100))
   5.357+   (e (member foo bar baz)))
   5.358+
   5.359+ (defun examplebits-values (examplebits)
   5.360+   (list
   5.361+    (examplebits-a examplebits)
   5.362+    (examplebits-b examplebits)
   5.363+    (examplebits-c examplebits)
   5.364+    (examplebits-d examplebits)
   5.365+    (examplebits-e examplebits)))
   5.366+
   5.367+ (defparameter *default* (make-examplebits))
   5.368+
   5.369+ (examplebits-values *default*)
   5.370+ ;; => (nil 0 1 -100 foo)
   5.371+
   5.372+ (defparameter *explicit* (make-examplebits :a t :b -1 :c 7 :d 42 :e 'baz))
   5.373+
   5.374+ (examplebits-values *explicit*)
   5.375+ ;; => (t -1 7 42 baz)
   5.376+
   5.377+ (defparameter *clone* (clone-examplebits *explicit* :a nil :b -1 :c 2 :d -12 :e 'bar))
   5.378+
   5.379+ (examplebits-values *clone*)
   5.380+ ;; => (nil -1 2 -12 bar)
   5.381+"
   5.382+  (let* ((*bitfield-position* 0)
   5.383+         (package (symbol-package name))
   5.384+         (constructor
   5.385+           (intern (concatenate 'string "MAKE-" (symbol-name name)) package))
   5.386+         (cloner
   5.387+           (intern (concatenate 'string "CLONE-" (symbol-name name)) package))
   5.388+         (reader-prefix
   5.389+           (concatenate 'string ))
   5.390+         (slots
   5.391+           (mapcar #'parse-bitfield-slot slots))
   5.392+         (reader-names
   5.393+           (loop for slot in slots
   5.394+                 collect
   5.395+                 (intern (concatenate 'string (symbol-name name) "-" reader-prefix
   5.396+                                      (symbol-name (bitfield-slot-name slot)))
   5.397+                         package))))
   5.398+    `(progn
   5.399+       (deftype ,name () '(unsigned-byte ,*bitfield-position*))
   5.400+       ;; Define all slot readers.
   5.401+       ,@(loop for slot in slots
   5.402+               for reader-name in reader-names
   5.403+               for start = (bitfield-slot-start slot)
   5.404+               for end = (bitfield-slot-end slot)
   5.405+               collect
   5.406+               `(declaim (inline ,reader-name))
   5.407+               collect
   5.408+               `(defun ,reader-name (,name)
   5.409+                  (declare (,name ,name))
   5.410+                  ,(bitfield-slot-unpack
   5.411+                    slot
   5.412+                    `(ldb (byte ,(- end start) ,start) ,name))))
   5.413+       ;; Define the cloner.
   5.414+       (declaim (inline ,cloner))
   5.415+       (defun ,cloner
   5.416+           (,name &key ,@(loop for slot in slots
   5.417+                               for reader-name in reader-names
   5.418+                               collect
   5.419+                               `(,(bitfield-slot-name slot)
   5.420+                                 (,reader-name ,name))))
   5.421+         (declare (,name ,name))
   5.422+         (logior
   5.423+          ,@(loop for slot in slots
   5.424+                  collect
   5.425+                  `(ash ,(bitfield-slot-pack slot (bitfield-slot-name slot))
   5.426+                        ,(bitfield-slot-start slot)))))
   5.427+       ;; Define the constructor.
   5.428+       (declaim (inline ,constructor))
   5.429+       (defun ,constructor
   5.430+           (&key ,@(loop for slot in slots
   5.431+                         collect
   5.432+                         `(,(bitfield-slot-name slot)
   5.433+                           ,(bitfield-slot-initform slot))))
   5.434+         (logior
   5.435+          ,@(loop for slot in slots
   5.436+                  collect
   5.437+                  `(ash ,(bitfield-slot-pack slot (bitfield-slot-name slot))
   5.438+                        ,(bitfield-slot-start slot)))))
   5.439+       ',name)))
   5.440+
   5.441+;;; From bit-smasher
   5.442+(declaim (type (simple-array (simple-bit-vector 4) (16)) *bit-map*))
   5.443+(defvar *bit-map* #(#*0000
   5.444+                    #*0001
   5.445+                    #*0010
   5.446+                    #*0011
   5.447+                    #*0100
   5.448+                    #*0101
   5.449+                    #*0110
   5.450+                    #*0111
   5.451+                    #*1000
   5.452+                    #*1001
   5.453+                    #*1010
   5.454+                    #*1011
   5.455+                    #*1100
   5.456+                    #*1101
   5.457+                    #*1110
   5.458+                    #*1111))
   5.459+
   5.460+(deftype hex-char ()
   5.461+  `(member #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
   5.462+           #\a #\b #\c #\d #\e #\f
   5.463+           #\A #\B #\C #\D #\E #\F))
   5.464+
   5.465+(declaim (ftype (function (hex-char) (integer 0 16)) hexchar->int)
   5.466+         (inline hexchar->int))
   5.467+(defun hexchar-to-int (char)
   5.468+  "Return the bit vector associated with a hex-value character CHAR from *bit-map*."
   5.469+  (declare (optimize (speed 2) (safety 0)))
   5.470+  (cond ((char<= #\0 char #\9) (- (char-code char) #.(char-code #\0)))
   5.471+        ((char<= #\a char #\f) (- (char-code char) #.(- (char-code #\a) 10)))
   5.472+        (t                     (- (char-code char) #.(- (char-code #\A) 10))
   5.473+         ;; always return these results
   5.474+         #+nil (char<= #\A char #\F))))
   5.475+
   5.476+;;; From Ironclad
   5.477+(defun hex-string-to-octet-vector (string &aux (start 0) (end (length string)))
   5.478+  "Parses a substring of STRING delimited by START and END of
   5.479+hexadecimal digits into a byte array."
   5.480+  (declare (type string string))
   5.481+  (let* ((length
   5.482+          (ash (- end start) -1)
   5.483+           #+nil (/ (- end start) 2))
   5.484+         (key (make-array length :element-type '(unsigned-byte 8))))
   5.485+    (declare (type (simple-array (unsigned-byte 8)) key))
   5.486+    (loop for i from 0
   5.487+          for j from start below end by 2
   5.488+          do (setf (aref key i)
   5.489+                   (+ (* (hexchar-to-int (char string j)) 16)
   5.490+                      (hexchar-to-int (char string (1+ j)))))
   5.491+          finally (return key))))
   5.492+
   5.493+(defun octet-vector-to-hex-string (vector)
   5.494+  "Return a string containing the hexadecimal representation of the
   5.495+subsequence of VECTOR between START and END.  ELEMENT-TYPE controls
   5.496+the element-type of the returned string."
   5.497+  (declare (type (vector (unsigned-byte 8)) vector))
   5.498+  (let* ((length (length vector))
   5.499+         (hexdigits #.(coerce "0123456789abcdef" 'simple-base-string)))
   5.500+    (loop with string = (make-string (* length 2) :element-type 'base-char)
   5.501+       for i from 0 below length
   5.502+       for j from 0 by 2
   5.503+       do (let ((byte (aref vector i)))
   5.504+            (declare (optimize (safety 0)))
   5.505+            (setf (aref string j)
   5.506+                  (aref hexdigits (ldb (byte 4 4) byte))
   5.507+                  (aref string (1+ j))
   5.508+                  (aref hexdigits (ldb (byte 4 0) byte))))
   5.509+       finally (return string))))
   5.510+
   5.511+(defun octets-to-integer (octet-vec &optional (end (length octet-vec)))
   5.512+  (declare (type (simple-array (unsigned-byte 8)) octet-vec))
   5.513+  (do ((j 0 (1+ j))
   5.514+       (sum 0))
   5.515+      ((>= j end) sum)
   5.516+    (setf sum (+ (aref octet-vec j) (ash sum 8)))))
   5.517+
   5.518+(defun integer-to-octets (bignum &optional (n-bits (integer-length bignum)))
   5.519+  (let* ((n-bytes (ceiling n-bits 8))
   5.520+         (octet-vec (make-array n-bytes :element-type '(unsigned-byte 8))))
   5.521+    (declare (type (simple-array (unsigned-byte 8)) octet-vec))
   5.522+    (loop for i from (1- n-bytes) downto 0
   5.523+          for index from 0
   5.524+          do (setf (aref octet-vec index) (ldb (byte 8 (* i 8)) bignum))
   5.525+          finally (return octet-vec))))
     6.1--- a/lisp/std/bits.lisp	Sun Apr 21 22:38:49 2024 -0400
     6.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3@@ -1,522 +0,0 @@
     6.4-;;; bits.lisp --- Bit manipulation
     6.5-
     6.6-;;; Commentary:
     6.7-
     6.8-;; CMUCL doc: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node132.html
     6.9-
    6.10-;; quick primer: https://cp-algorithms.com/algebra/bit-manipulation.html
    6.11-
    6.12-;;; Code:
    6.13-(in-package :std)
    6.14-
    6.15-;;; Types
    6.16-;; Bytes aren't necessarily 8 bits wide in Lisp. OCTET is always 8
    6.17-;; bits.
    6.18-(deftype octet () '(unsigned-byte 8))
    6.19-(deftype octet-vector (&optional length)
    6.20-  `(simple-array octet (,length)))
    6.21-
    6.22-;;; Bits
    6.23-(defun make-bits (length &rest args)
    6.24-  (apply #'make-array length (nconc (list :element-type 'bit) args)))
    6.25-
    6.26-;; https://graphics.stanford.edu/~seander/bithacks.html
    6.27-;; http://www.azillionmonkeys.com/qed/asmexample.html
    6.28-(defun haipart (n count) 
    6.29-  (declare (fixnum n count))
    6.30-  (let ((x (abs n)))
    6.31-    (if (minusp count) 
    6.32-        (ldb (byte (- count) 0) x)
    6.33-        (ldb (byte count (max 0 (- (integer-length x) count)))
    6.34-             x))))
    6.35-
    6.36-;; minusp = 38 bytes
    6.37-
    6.38-;; 29 bytes
    6.39-(defun sign-bit (n)
    6.40-  "compute the sign bit of a fixnum. If N < 0 return -1 else return 0."
    6.41-  (declare (fixnum n))
    6.42-  (ash n (- 0 (integer-length n))))
    6.43-
    6.44-;; 51 bytes (speed 3)
    6.45-;; 67 bytes (speed 1)
    6.46-(defun different-signs-p (x y)
    6.47-  "Return non-nil iff x and y have opposite signs."
    6.48-  (declare (fixnum x y) (optimize (speed 1)))
    6.49-  (< (expt x y) 0))
    6.50-
    6.51-;; TODO 2024-02-23: 
    6.52-(defun mortify-bits (x y)
    6.53-  "Interleave the bits of two numbers (Mortan numbers)."
    6.54-  (declare (fixnum x y)
    6.55-           (ignore x y))
    6.56-  ;; (loop for i across (integer-length)
    6.57-  ;;       with z = 0
    6.58-  ;;       ;; z |= (x & 1U << i) << i | (y & 1U << i) << (i + 1);
    6.59-  ;;       do ()
    6.60-  ;;       return z)
    6.61-  )
    6.62-
    6.63-(defun int-list-bits (n)
    6.64-  (declare (fixnum n))
    6.65-  (let ((bits '()))
    6.66-    (dotimes (position (integer-length n) bits)
    6.67-      (push (ldb (byte 1 position) n) bits))))
    6.68-
    6.69-(defun int-bit-vector (n)
    6.70-  (declare (fixnum n))
    6.71-  (let ((bits (make-array 0 :element-type 'bit :adjustable t :fill-pointer t)))
    6.72-    (dotimes (position (integer-length n) bits)
    6.73-      (vector-push-extend (ldb (byte 1 position) n) bits))))
    6.74-
    6.75-(defun aref-bit (octets idx)
    6.76-  (declare (octet-vector octets) (fixnum idx))
    6.77-  (multiple-value-bind (octet-idx bit-idx)
    6.78-      (truncate idx 8)
    6.79-    (ldb (byte 1 bit-idx)
    6.80-         (aref octets octet-idx))))
    6.81-
    6.82-(defun make-bit-vector (size &optional (fill 0))
    6.83-  "Make a BIT-VECTOR with SIZE and initial-element FILL which must be a
    6.84-BIT 0|1. Note that this representation is not as useful as you might
    6.85-think - bit-vectors don't have a direct mapping to integers/fixnums --
    6.86-they are vectors (AKA arrays) first, and bits second. Attempting to
    6.87-perform bitwise-ops ends up being very inefficient so whenever
    6.88-possible, stick with fixnums and use LOG* functions."
    6.89-  (declare (bit fill))
    6.90-  (make-array size :initial-element fill :adjustable nil :element-type 'bit))
    6.91-
    6.92-;; simple setter/getter for integer bits
    6.93-(define-setf-expander logbit (index place &environment env)
    6.94-  (multiple-value-bind (temps vals stores store-form access-form)
    6.95-      (get-setf-expansion place env)
    6.96-    (let ((i (gensym))
    6.97-          (store (gensym))
    6.98-          (stemp (first stores)))
    6.99-      (values `(,i ,@temps)
   6.100-              `(,index ,@vals)
   6.101-              `(,store)
   6.102-              `(let ((,stemp (dpb ,store (byte 1 ,i) ,access-form))
   6.103-                     ,@(cdr stores))
   6.104-                 ,store-form
   6.105-                 ,store)
   6.106-              `(logbit ,i ,access-form)))))
   6.107-
   6.108-(defun logbit (idx n)
   6.109-  (declare (fixnum idx n))
   6.110-  (ldb (byte 1 idx) n))
   6.111-
   6.112-;;; Bitfields
   6.113-
   6.114-;; see https://github.com/marcoheisig/bitfield
   6.115-
   6.116-;; A bitfield is a simple, efficient mechanism for storing multiple
   6.117-;; discrete states into a single non-negative integer.
   6.118-
   6.119-(deftype bitfield ()
   6.120-  "A bitfield is a non-negative integer that efficiently encodes
   6.121-information about some booleans, enumerations, or small integers."
   6.122-  'unsigned-byte)
   6.123-
   6.124-;;; Bitfield Slots
   6.125-(defgeneric bitfield-slot-name (bitfield-slot)
   6.126-  (:documentation
   6.127-   "Returns a symbol that is the name of the bitfield slot."))
   6.128-
   6.129-(defgeneric bitfield-slot-start (bitfield-slot)
   6.130-  (:documentation
   6.131-   "Returns the position of the first bit of this slot in the bitfield."))
   6.132-
   6.133-(defgeneric bitfield-slot-end (bitfield-slot)
   6.134-  (:documentation
   6.135-   "Returns the position right after the last bit of this slot in the bitfield."))
   6.136-
   6.137-(defgeneric bitfield-slot-size (bitfield-slot)
   6.138-  (:documentation
   6.139-   "Returns an unsigned byte that is the number of distinct states of the slot."))
   6.140-
   6.141-(defgeneric bitfield-slot-initform (bitfield-slot)
   6.142-  (:documentation
   6.143-   "Returns a form that produces the initial value for that slot."))
   6.144-
   6.145-(defgeneric bitfield-slot-pack (bitfield-slot value-form)
   6.146-  (:documentation
   6.147-   "Takes a form that produces a value and turns it into a form that produces
   6.148-a non-negative integer representing that value."))
   6.149-
   6.150-(defgeneric bitfield-slot-unpack (bitfield-slot value-form)
   6.151-  (:documentation
   6.152-   "Take a form that produces a value that is encoded as a non-negative
   6.153-integer (as produced by BITFIELD-SLOT-PACK), and turn it into a form that
   6.154-produces the decoded value."))
   6.155-
   6.156-(defgeneric parse-atomic-bitfield-slot-specifier
   6.157-    (specifier &key initform)
   6.158-  (:documentation
   6.159-   "Parses an atomic bitfield slot specifier, i.e., a bitfield slot
   6.160-specifier that is not a list.  Returns three values:
   6.161-
   6.162-1. A designator for a bitfield slot class.
   6.163-
   6.164-2. The size of the bitfield slot.
   6.165-
   6.166-3. A list of additional arguments that will be supplied to MAKE-INSTANCE
   6.167-when creating the bitfield slot instance."))
   6.168-
   6.169-(defgeneric parse-compound-bitfield-slot-specifier
   6.170-    (specifier arguments &key initform)
   6.171-  (:documentation
   6.172-   "Parses a compount bitfield slot specifier, i.e., a bitfield slot
   6.173-specifier that is a list.  The SPECIFIER is the CAR of that list and the
   6.174-ARGUMENTS are the CDR of that list.  Returns three values:
   6.175-
   6.176-1. A designator for a bitfield slot class.
   6.177-
   6.178-2. The size of the bitfield slot.
   6.179-
   6.180-3. A list of additional arguments that will be supplied to MAKE-INSTANCE
   6.181-when creating the bitfield slot instance."))
   6.182-
   6.183-(defclass bitfield-slot ()
   6.184-  ((%name :initarg :name :reader bitfield-slot-name)
   6.185-   (%initform :initarg :initform :reader bitfield-slot-initform)
   6.186-   (%start :initarg :start :reader bitfield-slot-start)
   6.187-   (%end :initarg :end :reader bitfield-slot-end)
   6.188-   (%size :initarg :size :reader bitfield-slot-size)))
   6.189-
   6.190-;;; Boolean Slots
   6.191-(defclass bitfield-boolean-slot (bitfield-slot)
   6.192-  ())
   6.193-
   6.194-(defmethod bitfield-slot-pack ((slot bitfield-boolean-slot) value-form)
   6.195-  `(if ,value-form 1 0))
   6.196-
   6.197-(defmethod bitfield-slot-unpack ((slot bitfield-boolean-slot) value-form)
   6.198-  `(ecase ,value-form (0 nil) (1 t)))
   6.199-
   6.200-(defmethod parse-atomic-bitfield-slot-specifier
   6.201-    ((specifier (eql 'boolean)) &key (initform 'nil))
   6.202-  (values 'bitfield-boolean-slot
   6.203-          2
   6.204-          `(:initform ,initform)))
   6.205-
   6.206-;;; Integer Slots
   6.207-(defclass bitfield-integer-slot (bitfield-slot)
   6.208-  ((%offset
   6.209-    :type integer
   6.210-    :initarg :offset
   6.211-    :reader bitfield-integer-slot-offset)))
   6.212-
   6.213-(defmethod bitfield-slot-pack ((slot bitfield-integer-slot) value-form)
   6.214-  (let ((offset (bitfield-integer-slot-offset slot))
   6.215-        (size (bitfield-slot-size slot)))
   6.216-    `(the (integer 0 (,size))
   6.217-          (- (the (integer ,offset (,(+ offset size))) ,value-form)
   6.218-             ,offset))))
   6.219-
   6.220-(defmethod bitfield-slot-unpack ((slot bitfield-integer-slot) value-form)
   6.221-  (let ((offset (bitfield-integer-slot-offset slot))
   6.222-        (size (bitfield-slot-size slot)))
   6.223-    `(the (integer ,offset (,(+ offset size)))
   6.224-          (+ ,value-form ,offset))))
   6.225-
   6.226-(defmethod parse-atomic-bitfield-slot-specifier
   6.227-    ((specifier (eql 'bit)) &key (initform '0))
   6.228-  (values 'bitfield-unsigned-byte-slot
   6.229-          2
   6.230-          `(:offset 0 :initform ,initform)))
   6.231-
   6.232-(defmethod parse-compound-bitfield-slot-specifier
   6.233-    ((specifier (eql 'unsigned-byte)) arguments &key (initform '0))
   6.234-  (destructuring-bind (bits) arguments
   6.235-    (check-type bits unsigned-byte)
   6.236-    (values 'bitfield-integer-slot
   6.237-            (expt 2 bits)
   6.238-            `(:offset 0 :initform ,initform))))
   6.239-
   6.240-(defmethod parse-compound-bitfield-slot-specifier
   6.241-    ((specifier (eql 'signed-byte)) arguments &key (initform '0))
   6.242-  (destructuring-bind (bits) arguments
   6.243-    (check-type bits unsigned-byte)
   6.244-    (values 'bitfield-integer-slot
   6.245-            (expt 2 bits)
   6.246-            `(:offset ,(- (expt 2 (1- bits))) :initform ,initform))))
   6.247-
   6.248-(defmethod parse-compound-bitfield-slot-specifier
   6.249-    ((specifier (eql 'integer)) bounds &key (initform nil initform-supplied-p))
   6.250-  (flet ((fail ()
   6.251-           (error "Invalid integer bitfield slot specifier: ~S"
   6.252-                  `(integer ,@bounds))))
   6.253-    (unless (typep bounds '(cons t (cons t null)))
   6.254-      (fail))
   6.255-    (destructuring-bind (lo hi) bounds
   6.256-      (let* ((start (typecase lo
   6.257-                      (integer lo)
   6.258-                      ((cons integer null)
   6.259-                       (1+ (first lo)))
   6.260-                      (otherwise (fail))))
   6.261-             (end (typecase hi
   6.262-                    (integer (1+ hi))
   6.263-                    ((cons integer null)
   6.264-                     (first hi))
   6.265-                    (otherwise (fail))))
   6.266-             (size (- end start)))
   6.267-        (unless (plusp size)
   6.268-          (fail))
   6.269-        (values 'bitfield-integer-slot
   6.270-                size
   6.271-                `(:offset ,start :initform ,(if initform-supplied-p initform start)))))))
   6.272-
   6.273-;;; Member Slots
   6.274-(defclass bitfield-member-slot (bitfield-slot)
   6.275-  ((%objects
   6.276-    :type list
   6.277-    :initarg :objects
   6.278-    :reader bitfield-member-slot-objects)))
   6.279-
   6.280-(defmethod bitfield-slot-pack ((slot bitfield-member-slot) value-form)
   6.281-  `(ecase ,value-form
   6.282-     ,@(loop for key in (bitfield-member-slot-objects slot)
   6.283-             for value from 0
   6.284-             collect `((,key) ,value))))
   6.285-
   6.286-(defmethod bitfield-slot-unpack ((slot bitfield-member-slot) value-form)
   6.287-  `(ecase ,value-form
   6.288-     ,@(loop for key from 0
   6.289-             for value in (bitfield-member-slot-objects slot)
   6.290-             collect `((,key) ',value))))
   6.291-
   6.292-(defmethod parse-compound-bitfield-slot-specifier
   6.293-    ((specifier (eql 'member)) objects &key (initform `',(first objects)))
   6.294-  (values 'bitfield-member-slot
   6.295-          (length objects)
   6.296-          `(:initform ,initform :objects ,objects)))
   6.297-
   6.298-;;; Parsing
   6.299-;; The position right after the last slot that has been parsed so far.
   6.300-(defvar *bitfield-position*)
   6.301-
   6.302-(defun parse-bitfield-slot (slot)
   6.303-  (destructuring-bind (slot-name slot-specifier &rest rest) slot
   6.304-    (check-type slot-name symbol)
   6.305-    (multiple-value-bind (slot-class size args)
   6.306-        (if (consp slot-specifier)
   6.307-            (apply #'parse-compound-bitfield-slot-specifier
   6.308-                   (car slot-specifier)
   6.309-                   (cdr slot-specifier)
   6.310-                   rest)
   6.311-            (apply #'parse-atomic-bitfield-slot-specifier
   6.312-                   slot-specifier
   6.313-                   rest))
   6.314-      (apply #'make-instance slot-class
   6.315-             :name slot-name
   6.316-             :size size
   6.317-             :start *bitfield-position*
   6.318-             :end (incf *bitfield-position* (integer-length (1- size)))
   6.319-             args))))
   6.320-
   6.321-(defmacro define-bitfield (name &body slots)
   6.322-  "Defines an encoding of enumerable properties like booleans,
   6.323-integers or finite sets as a single non-negative integer.
   6.324-
   6.325-For a supplied bitfield name NAME, and for some slot definitions of the
   6.326-form (SLOT-NAME TYPE &KEY INITFORM &ALLOW-OTHER-KEYS), this macro defines
   6.327-the following functions:
   6.328-
   6.329-1. A constructor named MAKE-{NAME}, that takes one keyword argument per
   6.330-   SLOT-NAME, similar to the default constructor generated by DEFSTRUCT.
   6.331-   It returns a bitfield whose entries have the values indicated by the
   6.332-   keyword arguments, or the supplied initform.
   6.333-
   6.334-2. A clone operation named CLONE-{NAME}, that takes an existing bitfield
   6.335-   and one keyword argument per SLOT-NAME.  It returns a copy of the
   6.336-   existing bitfield, but where each supplied keyword argument supersedes
   6.337-   the value of the corresponding slot.
   6.338-
   6.339-3. A reader function named {NAME}-{SLOT-NAME} for each slot.
   6.340-
   6.341-In addition to these functions, NAME is defined as a suitable subtype of
   6.342-UNSIGNED-BYTE.
   6.343-
   6.344-This macro supports boolean, integer, and member slots.  It is also
   6.345-possible to add new kinds of slots by defining new subclasses of
   6.346-BITFIELD-SLOT and the corresponding methods on BITFIELD-SLOT-PACK,
   6.347-BITFIELD-SLOT-UNPACK and PARSE-ATOMIC-BITFIELD-SLOT-SPECIFIER or
   6.348-PARSE-COMPOUND-BITFIELD-SLOT-SPECIFIER.
   6.349-
   6.350- Example:
   6.351-
   6.352- (define-bitfield examplebits
   6.353-   (a boolean)
   6.354-   (b (signed-byte 2))
   6.355-   (c (unsigned-byte 3) :initform 1)
   6.356-   (d (integer -100 100))
   6.357-   (e (member foo bar baz)))
   6.358-
   6.359- (defun examplebits-values (examplebits)
   6.360-   (list
   6.361-    (examplebits-a examplebits)
   6.362-    (examplebits-b examplebits)
   6.363-    (examplebits-c examplebits)
   6.364-    (examplebits-d examplebits)
   6.365-    (examplebits-e examplebits)))
   6.366-
   6.367- (defparameter *default* (make-examplebits))
   6.368-
   6.369- (examplebits-values *default*)
   6.370- ;; => (nil 0 1 -100 foo)
   6.371-
   6.372- (defparameter *explicit* (make-examplebits :a t :b -1 :c 7 :d 42 :e 'baz))
   6.373-
   6.374- (examplebits-values *explicit*)
   6.375- ;; => (t -1 7 42 baz)
   6.376-
   6.377- (defparameter *clone* (clone-examplebits *explicit* :a nil :b -1 :c 2 :d -12 :e 'bar))
   6.378-
   6.379- (examplebits-values *clone*)
   6.380- ;; => (nil -1 2 -12 bar)
   6.381-"
   6.382-  (let* ((*bitfield-position* 0)
   6.383-         (package (symbol-package name))
   6.384-         (constructor
   6.385-           (intern (concatenate 'string "MAKE-" (symbol-name name)) package))
   6.386-         (cloner
   6.387-           (intern (concatenate 'string "CLONE-" (symbol-name name)) package))
   6.388-         (reader-prefix
   6.389-           (concatenate 'string ))
   6.390-         (slots
   6.391-           (mapcar #'parse-bitfield-slot slots))
   6.392-         (reader-names
   6.393-           (loop for slot in slots
   6.394-                 collect
   6.395-                 (intern (concatenate 'string (symbol-name name) "-" reader-prefix
   6.396-                                      (symbol-name (bitfield-slot-name slot)))
   6.397-                         package))))
   6.398-    `(progn
   6.399-       (deftype ,name () '(unsigned-byte ,*bitfield-position*))
   6.400-       ;; Define all slot readers.
   6.401-       ,@(loop for slot in slots
   6.402-               for reader-name in reader-names
   6.403-               for start = (bitfield-slot-start slot)
   6.404-               for end = (bitfield-slot-end slot)
   6.405-               collect
   6.406-               `(declaim (inline ,reader-name))
   6.407-               collect
   6.408-               `(defun ,reader-name (,name)
   6.409-                  (declare (,name ,name))
   6.410-                  ,(bitfield-slot-unpack
   6.411-                    slot
   6.412-                    `(ldb (byte ,(- end start) ,start) ,name))))
   6.413-       ;; Define the cloner.
   6.414-       (declaim (inline ,cloner))
   6.415-       (defun ,cloner
   6.416-           (,name &key ,@(loop for slot in slots
   6.417-                               for reader-name in reader-names
   6.418-                               collect
   6.419-                               `(,(bitfield-slot-name slot)
   6.420-                                 (,reader-name ,name))))
   6.421-         (declare (,name ,name))
   6.422-         (logior
   6.423-          ,@(loop for slot in slots
   6.424-                  collect
   6.425-                  `(ash ,(bitfield-slot-pack slot (bitfield-slot-name slot))
   6.426-                        ,(bitfield-slot-start slot)))))
   6.427-       ;; Define the constructor.
   6.428-       (declaim (inline ,constructor))
   6.429-       (defun ,constructor
   6.430-           (&key ,@(loop for slot in slots
   6.431-                         collect
   6.432-                         `(,(bitfield-slot-name slot)
   6.433-                           ,(bitfield-slot-initform slot))))
   6.434-         (logior
   6.435-          ,@(loop for slot in slots
   6.436-                  collect
   6.437-                  `(ash ,(bitfield-slot-pack slot (bitfield-slot-name slot))
   6.438-                        ,(bitfield-slot-start slot)))))
   6.439-       ',name)))
   6.440-
   6.441-;;; From bit-smasher
   6.442-(declaim (type (simple-array (simple-bit-vector 4) (16)) *bit-map*))
   6.443-(defvar *bit-map* #(#*0000
   6.444-                    #*0001
   6.445-                    #*0010
   6.446-                    #*0011
   6.447-                    #*0100
   6.448-                    #*0101
   6.449-                    #*0110
   6.450-                    #*0111
   6.451-                    #*1000
   6.452-                    #*1001
   6.453-                    #*1010
   6.454-                    #*1011
   6.455-                    #*1100
   6.456-                    #*1101
   6.457-                    #*1110
   6.458-                    #*1111))
   6.459-
   6.460-(deftype hex-char ()
   6.461-  `(member #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
   6.462-           #\a #\b #\c #\d #\e #\f
   6.463-           #\A #\B #\C #\D #\E #\F))
   6.464-
   6.465-(declaim (ftype (function (hex-char) (integer 0 16)) hexchar->int)
   6.466-         (inline hexchar->int))
   6.467-(defun hexchar-to-int (char)
   6.468-  "Return the bit vector associated with a hex-value character CHAR from *bit-map*."
   6.469-  (declare (optimize (speed 2) (safety 0)))
   6.470-  (cond ((char<= #\0 char #\9) (- (char-code char) #.(char-code #\0)))
   6.471-        ((char<= #\a char #\f) (- (char-code char) #.(- (char-code #\a) 10)))
   6.472-        (t                     (- (char-code char) #.(- (char-code #\A) 10))
   6.473-         ;; always return these results
   6.474-         #+nil (char<= #\A char #\F))))
   6.475-
   6.476-;;; From Ironclad
   6.477-(defun hex-string-to-octet-vector (string &aux (start 0) (end (length string)))
   6.478-  "Parses a substring of STRING delimited by START and END of
   6.479-hexadecimal digits into a byte array."
   6.480-  (declare (type string string))
   6.481-  (let* ((length
   6.482-          (ash (- end start) -1)
   6.483-           #+nil (/ (- end start) 2))
   6.484-         (key (make-array length :element-type '(unsigned-byte 8))))
   6.485-    (declare (type (simple-array (unsigned-byte 8)) key))
   6.486-    (loop for i from 0
   6.487-          for j from start below end by 2
   6.488-          do (setf (aref key i)
   6.489-                   (+ (* (hexchar-to-int (char string j)) 16)
   6.490-                      (hexchar-to-int (char string (1+ j)))))
   6.491-          finally (return key))))
   6.492-
   6.493-(defun octet-vector-to-hex-string (vector)
   6.494-  "Return a string containing the hexadecimal representation of the
   6.495-subsequence of VECTOR between START and END.  ELEMENT-TYPE controls
   6.496-the element-type of the returned string."
   6.497-  (declare (type (vector (unsigned-byte 8)) vector))
   6.498-  (let* ((length (length vector))
   6.499-         (hexdigits #.(coerce "0123456789abcdef" 'simple-base-string)))
   6.500-    (loop with string = (make-string (* length 2) :element-type 'base-char)
   6.501-       for i from 0 below length
   6.502-       for j from 0 by 2
   6.503-       do (let ((byte (aref vector i)))
   6.504-            (declare (optimize (safety 0)))
   6.505-            (setf (aref string j)
   6.506-                  (aref hexdigits (ldb (byte 4 4) byte))
   6.507-                  (aref string (1+ j))
   6.508-                  (aref hexdigits (ldb (byte 4 0) byte))))
   6.509-       finally (return string))))
   6.510-
   6.511-(defun octets-to-integer (octet-vec &optional (end (length octet-vec)))
   6.512-  (declare (type (simple-array (unsigned-byte 8)) octet-vec))
   6.513-  (do ((j 0 (1+ j))
   6.514-       (sum 0))
   6.515-      ((>= j end) sum)
   6.516-    (setf sum (+ (aref octet-vec j) (ash sum 8)))))
   6.517-
   6.518-(defun integer-to-octets (bignum &optional (n-bits (integer-length bignum)))
   6.519-  (let* ((n-bytes (ceiling n-bits 8))
   6.520-         (octet-vec (make-array n-bytes :element-type '(unsigned-byte 8))))
   6.521-    (declare (type (simple-array (unsigned-byte 8)) octet-vec))
   6.522-    (loop for i from (1- n-bytes) downto 0
   6.523-          for index from 0
   6.524-          do (setf (aref octet-vec index) (ldb (byte 8 (* i 8)) bignum))
   6.525-          finally (return octet-vec))))
     7.1--- a/lisp/std/defpkg.lisp	Sun Apr 21 22:38:49 2024 -0400
     7.2+++ b/lisp/std/defpkg.lisp	Mon Apr 22 23:14:47 2024 -0400
     7.3@@ -5,7 +5,7 @@
     7.4 ;;
     7.5 
     7.6 ;;; Code:
     7.7-(in-package :std)
     7.8+(in-package :std/defpkg)
     7.9 
    7.10 (eval-when (:load-toplevel :compile-toplevel :execute)
    7.11   (defun find-package* (package-designator &optional (error t))
     8.1--- a/lisp/std/err.lisp	Sun Apr 21 22:38:49 2024 -0400
     8.2+++ b/lisp/std/err.lisp	Mon Apr 22 23:14:47 2024 -0400
     8.3@@ -1,7 +1,7 @@
     8.4 ;;; err.lisp --- Conditions and other exception handlers
     8.5 
     8.6 ;;; Code:
     8.7-(in-package :std)
     8.8+(in-package :std/err)
     8.9 
    8.10 (defvar *std-error-message* "An error occured")
    8.11 
     9.1--- a/lisp/std/file.lisp	Sun Apr 21 22:38:49 2024 -0400
     9.2+++ b/lisp/std/file.lisp	Mon Apr 22 23:14:47 2024 -0400
     9.3@@ -3,7 +3,22 @@
     9.4 ;;
     9.5 
     9.6 ;;; Code:
     9.7-(in-package :std)
     9.8+(in-package :std/file)
     9.9+
    9.10+;;; Sexp utils
    9.11+;; (reexport-from :uiop :include '(read-file-form read-file-forms slurp-stream-forms))
    9.12+
    9.13+(defun tmpfile (size)
    9.14+  "Create an anonymous temporary file of the given size. Returns a file descriptor."
    9.15+  (let (done fd pathname)
    9.16+    (unwind-protect
    9.17+         (progn
    9.18+           (setf (values fd pathname) (sb-posix:mkstemp "/dev/shm/tmp.XXXXXXXX"))
    9.19+           (sb-posix:unlink pathname)
    9.20+           (sb-posix:ftruncate fd size)
    9.21+           (setf done t))
    9.22+      (when (and fd (not done)) (sb-posix:close fd)))
    9.23+    fd))
    9.24 
    9.25 (declaim (inline octet-vector=/unsafe))
    9.26 (defun octet-vector=/unsafe (v1 v2 start1 end1 start2 end2)
    10.1--- a/lisp/std/fmt.lisp	Sun Apr 21 22:38:49 2024 -0400
    10.2+++ b/lisp/std/fmt.lisp	Mon Apr 22 23:14:47 2024 -0400
    10.3@@ -1,7 +1,7 @@
    10.4 ;;; std/fmt.lisp --- printer and format utils
    10.5 
    10.6 ;;; Code:
    10.7-(in-package :std)
    10.8+(in-package :std/fmt)
    10.9 
   10.10 (defun iprintln (x &optional (n 2) stream)
   10.11   (println (format nil "~A~A" (make-string n :initial-element #\Space) x) stream))
    11.1--- a/lisp/std/fu.lisp	Sun Apr 21 22:38:49 2024 -0400
    11.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3@@ -1,872 +0,0 @@
    11.4-;;; fu.lisp --- Function utilities
    11.5-
    11.6-;; 
    11.7-
    11.8-;;; Code:
    11.9-(in-package :std)
   11.10-
   11.11-(in-readtable :std)
   11.12-
   11.13-(defmacro! sortf (comparator &rest places)
   11.14-  (if places
   11.15-    `(tagbody
   11.16-       ,@(mapcar
   11.17-           #`(let ((,g!a #1=,(nth (car a1) places))
   11.18-                   (,g!b #2=,(nth (cadr a1) places)))
   11.19-               (if (,comparator ,g!b ,g!a)
   11.20-                 (setf #1# ,g!b
   11.21-                       #2# ,g!a)))
   11.22-           (build-batcher-sn (length places))))))
   11.23-
   11.24-#+cl-ppcre
   11.25-(defun dollar-symbol-p (s)
   11.26-  (and (symbolp s)
   11.27-       (> (length (symbol-name s)) 1)
   11.28-       (string= (symbol-name s)
   11.29-                "$"
   11.30-                :start1 0
   11.31-                :end1 1)
   11.32-       (ignore-errors (parse-integer (subseq (symbol-name s) 1)))))
   11.33-
   11.34-
   11.35-#+cl-ppcre
   11.36-(defmacro! if-match ((match-regex str) then &optional else)
   11.37-  (let* ((dollars (remove-duplicates
   11.38-                   (remove-if-not #'dollar-symbol-p
   11.39-                                  (flatten then))))
   11.40-         (top (or (car (sort (mapcar #'dollar-symbol-p dollars) #'>))
   11.41-                  0)))
   11.42-    `(multiple-value-bind (,g!matches ,g!captures) (,match-regex ,str)
   11.43-       (declare (ignorable ,g!matches ,g!captures))
   11.44-       (let ((,g!captures-len (length ,g!captures)))
   11.45-         (declare (ignorable ,g!captures-len))
   11.46-         (symbol-macrolet ,(mapcar #`(,(symb "$" a1)
   11.47-                                       (if (< ,g!captures-len ,a1)
   11.48-                                           (error "Too few matchs: ~a unbound." ,(mkstr "$" a1))
   11.49-                                           (aref ,g!captures ,(1- a1))))
   11.50-                                   (loop for i from 1 to top collect i))
   11.51-           (if ,g!matches
   11.52-               ,then
   11.53-               ,else))))))
   11.54-
   11.55-#+cl-ppcre
   11.56-(defmacro when-match ((match-regex str) &body forms)
   11.57-  `(if-match (,match-regex ,str)
   11.58-     (progn ,@forms)))
   11.59-
   11.60-(defmacro once-only (specs &body forms)
   11.61-  "Constructs code whose primary goal is to help automate the handling of
   11.62-multiple evaluation within macros. Multiple evaluation is handled by introducing
   11.63-intermediate variables, in order to reuse the result of an expression.
   11.64-
   11.65-The returned value is a list of the form
   11.66-
   11.67-  (let ((<gensym-1> <expr-1>)
   11.68-        ...
   11.69-        (<gensym-n> <expr-n>))
   11.70-    <res>)
   11.71-
   11.72-where GENSYM-1, ..., GENSYM-N are the intermediate variables introduced in order
   11.73-to evaluate EXPR-1, ..., EXPR-N once, only. RES is code that is the result of
   11.74-evaluating the implicit progn FORMS within a special context determined by
   11.75-SPECS. RES should make use of (reference) the intermediate variables.
   11.76-
   11.77-Each element within SPECS is either a symbol SYMBOL or a pair (SYMBOL INITFORM).
   11.78-Bare symbols are equivalent to the pair (SYMBOL SYMBOL).
   11.79-
   11.80-Each pair (SYMBOL INITFORM) specifies a single intermediate variable:
   11.81-
   11.82-- INITFORM is an expression evaluated to produce EXPR-i
   11.83-
   11.84-- SYMBOL is the name of the variable that will be bound around FORMS to the
   11.85-  corresponding gensym GENSYM-i, in order for FORMS to generate RES that
   11.86-  references the intermediate variable
   11.87-
   11.88-The evaluation of INITFORMs and binding of SYMBOLs resembles LET. INITFORMs of
   11.89-all the pairs are evaluated before binding SYMBOLs and evaluating FORMS.
   11.90-
   11.91-Example:
   11.92-
   11.93-  The following expression
   11.94-
   11.95-  (let ((x '(incf y)))
   11.96-    (once-only (x)
   11.97-      `(cons ,x ,x)))
   11.98-
   11.99-  ;;; =>
  11.100-  ;;; (let ((#1=#:X123 (incf y)))
  11.101-  ;;;   (cons #1# #1#))
  11.102-
  11.103-  could be used within a macro to avoid multiple evaluation like so
  11.104-
  11.105-  (defmacro cons1 (x)
  11.106-    (once-only (x)
  11.107-      `(cons ,x ,x)))
  11.108-
  11.109-  (let ((y 0))
  11.110-    (cons1 (incf y)))
  11.111-
  11.112-  ;;; => (1 . 1)
  11.113-
  11.114-Example:
  11.115-
  11.116-  The following expression demonstrates the usage of the INITFORM field
  11.117-
  11.118-  (let ((expr '(incf y)))
  11.119-    (once-only ((var `(1+ ,expr)))
  11.120-      `(list ',expr ,var ,var)))
  11.121-
  11.122-  ;;; =>
  11.123-  ;;; (let ((#1=#:VAR123 (1+ (incf y))))
  11.124-  ;;;   (list '(incf y) #1# #1))
  11.125-
  11.126-  which could be used like so
  11.127-
  11.128-  (defmacro print-succ-twice (expr)
  11.129-    (once-only ((var `(1+ ,expr)))
  11.130-      `(format t \"Expr: ~s, Once: ~s, Twice: ~s~%\" ',expr ,var ,var)))
  11.131-
  11.132-  (let ((y 10))
  11.133-    (print-succ-twice (incf y)))
  11.134-
  11.135-  ;;; >>
  11.136-  ;;; Expr: (INCF Y), Once: 12, Twice: 12"
  11.137-  (let ((gensyms (make-gensym-list (length specs) "ONCE-ONLY"))
  11.138-        (names-and-forms (mapcar (lambda (spec)
  11.139-                                   (etypecase spec
  11.140-                                     (list
  11.141-                                      (destructuring-bind (name form) spec
  11.142-                                        (cons name form)))
  11.143-                                     (symbol
  11.144-                                      (cons spec spec))))
  11.145-                                 specs)))
  11.146-    ;; bind in user-macro
  11.147-    `(let ,(mapcar (lambda (g n) (list g `(gensym ,(string (car n)))))
  11.148-                   gensyms names-and-forms)
  11.149-       ;; bind in final expansion
  11.150-       `(let (,,@(mapcar (lambda (g n)
  11.151-                           ``(,,g ,,(cdr n)))
  11.152-                         gensyms names-and-forms))
  11.153-          ;; bind in user-macro
  11.154-          ,(let ,(mapcar (lambda (n g) (list (car n) g))
  11.155-                         names-and-forms gensyms)
  11.156-             ,@forms)))))
  11.157-
  11.158-;;;; DESTRUCTURING-*CASE
  11.159-
  11.160-(defun expand-destructuring-case (key clauses case)
  11.161-  (once-only (key)
  11.162-    `(if (typep ,key 'cons)
  11.163-         (,case (car ,key)
  11.164-           ,@(mapcar (lambda (clause)
  11.165-                       (destructuring-bind ((keys . lambda-list) &body body) clause
  11.166-                         `(,keys
  11.167-                           (destructuring-bind ,lambda-list (cdr ,key)
  11.168-                             ,@body))))
  11.169-                     clauses))
  11.170-         (error "Invalid key to DESTRUCTURING-~S: ~S" ',case ,key))))
  11.171-
  11.172-(defmacro destructuring-case (keyform &body clauses)
  11.173-  "DESTRUCTURING-CASE, -CCASE, and -ECASE are a combination of CASE and DESTRUCTURING-BIND.
  11.174-KEYFORM must evaluate to a CONS.
  11.175-
  11.176-Clauses are of the form:
  11.177-
  11.178-  ((CASE-KEYS . DESTRUCTURING-LAMBDA-LIST) FORM*)
  11.179-
  11.180-The clause whose CASE-KEYS matches CAR of KEY, as if by CASE, CCASE, or ECASE,
  11.181-is selected, and FORMs are then executed with CDR of KEY is destructured and
  11.182-bound by the DESTRUCTURING-LAMBDA-LIST.
  11.183-
  11.184-Example:
  11.185-
  11.186- (defun dcase (x)
  11.187-   (destructuring-case x
  11.188-     ((:foo a b)
  11.189-      (format nil \"foo: ~S, ~S\" a b))
  11.190-     ((:bar &key a b)
  11.191-      (format nil \"bar: ~S, ~S\" a b))
  11.192-     (((:alt1 :alt2) a)
  11.193-      (format nil \"alt: ~S\" a))
  11.194-     ((t &rest rest)
  11.195-      (format nil \"unknown: ~S\" rest))))
  11.196-
  11.197-  (dcase (list :foo 1 2))        ; => \"foo: 1, 2\"
  11.198-  (dcase (list :bar :a 1 :b 2))  ; => \"bar: 1, 2\"
  11.199-  (dcase (list :alt1 1))         ; => \"alt: 1\"
  11.200-  (dcase (list :alt2 2))         ; => \"alt: 2\"
  11.201-  (dcase (list :quux 1 2 3))     ; => \"unknown: 1, 2, 3\"
  11.202-
  11.203- (defun decase (x)
  11.204-   (destructuring-case x
  11.205-     ((:foo a b)
  11.206-      (format nil \"foo: ~S, ~S\" a b))
  11.207-     ((:bar &key a b)
  11.208-      (format nil \"bar: ~S, ~S\" a b))
  11.209-     (((:alt1 :alt2) a)
  11.210-      (format nil \"alt: ~S\" a))))
  11.211-
  11.212-  (decase (list :foo 1 2))        ; => \"foo: 1, 2\"
  11.213-  (decase (list :bar :a 1 :b 2))  ; => \"bar: 1, 2\"
  11.214-  (decase (list :alt1 1))         ; => \"alt: 1\"
  11.215-  (decase (list :alt2 2))         ; => \"alt: 2\"
  11.216-  (decase (list :quux 1 2 3))     ; =| error
  11.217-"
  11.218-  (expand-destructuring-case keyform clauses 'case))
  11.219-
  11.220-(defmacro destructuring-ccase (keyform &body clauses)
  11.221-  (expand-destructuring-case keyform clauses 'ccase))
  11.222-
  11.223-(defmacro destructuring-ecase (keyform &body clauses)
  11.224-  (expand-destructuring-case keyform clauses 'ecase))
  11.225-
  11.226-(dolist (name '(destructuring-ccase destructuring-ecase))
  11.227-  (setf (documentation name 'function) (documentation 'destructuring-case 'function)))
  11.228-
  11.229-;;; *-let --- control-flow let-binding macros
  11.230-;; based on https://stevelosh.com/blog/2018/07/fun-with-macros-if-let/
  11.231-
  11.232-(defmacro when-let (bindings &body body)
  11.233-  "Bind `bindings` in parallel and execute `body`, short-circuiting on `nil`.
  11.234-
  11.235-  This macro combines `when` and `let`.  It takes a list of bindings and
  11.236-  binds them like `let` before executing `body`, but if any binding's value
  11.237-  evaluates to `nil` the process stops and `nil` is immediately returned.
  11.238-
  11.239-  Examples:
  11.240-
  11.241-    (when-let ((a (progn (print :a) 1))
  11.242-               (b (progn (print :b) 2))
  11.243-      (list a b))
  11.244-    ; =>
  11.245-    :A
  11.246-    :B
  11.247-    (1 2)
  11.248-
  11.249-    (when-let ((a (progn (print :a) nil))
  11.250-               (b (progn (print :b) 2)))
  11.251-      (list a b))
  11.252-    ; =>
  11.253-    :A
  11.254-    NIL
  11.255-
  11.256-  "
  11.257-  (with-gensyms (block)
  11.258-    `(block ,block
  11.259-       (let ,(loop :for (symbol value) :in bindings
  11.260-                   :collect `(,symbol (or ,value
  11.261-                                          (return-from ,block nil))))
  11.262-         ,@body))))
  11.263-
  11.264-(defmacro when-let* (bindings &body body)
  11.265-  "Bind `bindings` serially and execute `body`, short-circuiting on `nil`.
  11.266-
  11.267-  This macro combines `when` and `let*`.  It takes a list of bindings
  11.268-  and binds them like `let*` before executing `body`, but if any
  11.269-  binding's value evaluates to `nil` the process stops and `nil` is
  11.270-  immediately returned.
  11.271-
  11.272-  Examples:
  11.273-
  11.274-    (when-let* ((a (progn (print :a) 1))
  11.275-                (b (progn (print :b) (1+ a)))
  11.276-      (list a b))
  11.277-    ; =>
  11.278-    :A
  11.279-    :B
  11.280-    (1 2)
  11.281-
  11.282-    (when-let* ((a (progn (print :a) nil))
  11.283-                (b (progn (print :b) (1+ a))))
  11.284-      (list a b))
  11.285-    ; =>
  11.286-    :A
  11.287-    NIL
  11.288-
  11.289-  "
  11.290-  (with-gensyms (block)
  11.291-    `(block ,block
  11.292-       (let* ,(loop :for (symbol value) :in bindings
  11.293-                    :collect `(,symbol (or ,value
  11.294-                                           (return-from ,block nil))))
  11.295-         ,@body))))
  11.296-
  11.297-(defmacro if-let (bindings &body body)
  11.298-  "Bind `bindings` in parallel and execute `then` if all are true, or `else` otherwise.
  11.299-
  11.300-  `body` must be of the form `(...optional-declarations... then else)`.
  11.301-
  11.302-  This macro combines `if` and `let`.  It takes a list of bindings and
  11.303-  binds them like `let` before executing the `then` branch of `body`, but
  11.304-  if any binding's value evaluates to `nil` the process stops there and the
  11.305-  `else` branch is immediately executed (with no bindings in effect).
  11.306-
  11.307-  If any `optional-declarations` are included they will only be in effect
  11.308-  for the `then` branch.
  11.309-
  11.310-  Examples:
  11.311-
  11.312-    (if-let ((a (progn (print :a) 1))
  11.313-             (b (progn (print :b) 2)))
  11.314-      (list a b)
  11.315-      'nope)
  11.316-    ; =>
  11.317-    :A
  11.318-    :B
  11.319-    (1 2)
  11.320-
  11.321-    (if-let ((a (progn (print :a) nil))
  11.322-             (b (progn (print :b) 2)))
  11.323-      (list a b)
  11.324-      'nope)
  11.325-    ; =>
  11.326-    :A
  11.327-    NOPE
  11.328-
  11.329-  "
  11.330-  (with-gensyms (outer inner)
  11.331-    (multiple-value-bind (body declarations) (parse-body body)
  11.332-      (destructuring-bind (then else) body
  11.333-        `(block ,outer
  11.334-           (block ,inner
  11.335-             (let ,(loop :for (symbol value) :in bindings
  11.336-                         :collect `(,symbol (or ,value
  11.337-                                                (return-from ,inner nil))))
  11.338-               ,@declarations
  11.339-               (return-from ,outer ,then)))
  11.340-           ,else)))))
  11.341-
  11.342-(defmacro if-let* (bindings then else)
  11.343-  "Bind `bindings` serially and execute `then` if all are true, or `else` otherwise.
  11.344-
  11.345-  This macro combines `if` and `let*`.  It takes a list of bindings and
  11.346-  binds them like `let*` before executing `then`, but if any binding's
  11.347-  value evaluates to `nil` the process stops and the `else` branch is
  11.348-  immediately executed (with no bindings in effect).
  11.349-
  11.350-  Examples:
  11.351-
  11.352-    (if-let* ((a (progn (print :a) 1))
  11.353-              (b (progn (print :b) (1+ a)))
  11.354-      (list a b)
  11.355-      'nope)
  11.356-    ; =>
  11.357-    :A
  11.358-    :B
  11.359-    (1 2)
  11.360-
  11.361-    (if-let* ((a (progn (print :a) nil))
  11.362-              (b (progn (print :b) (1+ a))))
  11.363-      (list a b)
  11.364-      'nope)
  11.365-    ; =>
  11.366-    :A
  11.367-    NOPE
  11.368-
  11.369-  "
  11.370-  (with-gensyms (outer inner)
  11.371-    `(block ,outer
  11.372-       (block ,inner
  11.373-         (let* ,(loop :for (symbol value) :in bindings
  11.374-                      :collect `(,symbol (or ,value
  11.375-                                             (return-from ,inner nil))))
  11.376-           (return-from ,outer ,then)))
  11.377-       ,else)))
  11.378-
  11.379-
  11.380-(defmacro def! (name &body body)
  11.381-  "`defun' without args."
  11.382-  `(defun ,name () ,@body))
  11.383-
  11.384-(defmacro eval-always (&body body)
  11.385-  `(eval-when (:compile-toplevel :load-toplevel :execute) ,@body))
  11.386-
  11.387-;;; TODO 2023-09-04: Env
  11.388-
  11.389-;;; Introspection
  11.390-;; (eval-always (require :sb-introspect))
  11.391-
  11.392-;; (reexport-from :sb-introspect
  11.393-;; 	       :include '(:function-lambda-list :lambda-list-keywords :lambda-parameters-limit
  11.394-;; 			  :method-combination-lambda-list :deftype-lambda-list
  11.395-;; 			  :primitive-object-size :allocation-information
  11.396-;; 			  :function-type
  11.397-;; 			  :who-specializes-directly :who-specializes-generally
  11.398-;; 			  :find-function-callees :find-function-callers))
  11.399-
  11.400-;; ;;; Compiler
  11.401-
  11.402-;; (reexport-from :sb-c
  11.403-;; 	       :include '(:define-source-transformation
  11.404-;; 			  :parse-eval-when-situations
  11.405-;; 			  :source-location))
  11.406-;;; Definitions
  11.407-(defun %reevaluate-constant (name value test)
  11.408-  (if (not (boundp name))
  11.409-      value
  11.410-      (let ((old (symbol-value name))
  11.411-            (new value))
  11.412-        (if (not (constantp name))
  11.413-            (prog1 new
  11.414-              (cerror "Try to redefine the variable as a constant."
  11.415-                      "~@<~S is an already bound non-constant variable ~
  11.416-                       whose value is ~S.~:@>" name old))
  11.417-            (if (funcall test old new)
  11.418-                old
  11.419-                (restart-case
  11.420-                    (error "~@<~S is an already defined constant whose value ~
  11.421-                              ~S is not equal to the provided initial value ~S ~
  11.422-                              under ~S.~:@>" name old new test)
  11.423-                  (ignore ()
  11.424-                    :report "Retain the current value."
  11.425-                    old)
  11.426-                  (continue ()
  11.427-                    :report "Try to redefine the constant."
  11.428-                    new)))))))
  11.429-
  11.430-(defmacro define-constant (name initial-value &key (test #'eql) documentation)
  11.431-  "Ensures that the global variable named by NAME is a constant with a value
  11.432-that is equal under TEST to the result of evaluating INITIAL-VALUE. TEST is a
  11.433-/function designator/ that defaults to EQL. If DOCUMENTATION is given, it
  11.434-becomes the documentation string of the constant.
  11.435-
  11.436-Signals an error if NAME is already a bound non-constant variable.
  11.437-
  11.438-Signals an error if NAME is already a constant variable whose value is not
  11.439-equal under TEST to result of evaluating INITIAL-VALUE."
  11.440-  `(defconstant ,name (%reevaluate-constant ',name ,initial-value ,test)
  11.441-     ,@(when documentation `(,documentation))))
  11.442-
  11.443-;;; Named Lambdas
  11.444-;; (reexport-from :sb-int :include '(:make-macro-lambda :parse-lambda-list))
  11.445-
  11.446-;;; Sexp utils
  11.447-;; (reexport-from :uiop :include '(read-file-form read-file-forms slurp-stream-forms))
  11.448-
  11.449-;;; cl-bench utils
  11.450-;; Destructive merge of two sorted lists.
  11.451-;; From Hansen's MS thesis.
  11.452-(defun merge! (a b predicate)
  11.453-  (labels ((merge-loop (r a b)
  11.454-             (cond ((funcall predicate (car b) (car a))
  11.455-                    (setf (cdr r) b)
  11.456-                    (if (null (cdr b))
  11.457-                        (setf (cdr b) a)
  11.458-                        (merge-loop b a (cdr b))))
  11.459-                   (t ; (car a) <= (car b)
  11.460-                    (setf (cdr r) a)
  11.461-                    (if (null (cdr a))
  11.462-                        (setf (cdr a) b)
  11.463-                        (merge-loop a (cdr a) b))))))
  11.464-    (cond ((null a) b)
  11.465-          ((null b) a)
  11.466-          ((funcall predicate (car b) (car a))
  11.467-           (if (null (cdr b))
  11.468-               (setf (cdr b) a)
  11.469-               (merge-loop b a (cdr b)))
  11.470-           b)
  11.471-          (t                           ; (car a) <= (car b)
  11.472-           (if (null (cdr a))
  11.473-               (setf (cdr a) b)
  11.474-               (merge-loop a (cdr a) b))
  11.475-           a))))
  11.476-
  11.477-;; Stable sort procedure which copies the input list and then sorts
  11.478-;; the new list imperatively.  On the systems we have benchmarked,
  11.479-;; this generic list sort has been at least as fast and usually much
  11.480-;; faster than the library's sort routine.
  11.481-;; Due to Richard O'Keefe; algorithm attributed to D.H.D. Warren.
  11.482-(defun sort! (seq predicate)
  11.483-  (labels ((astep (n)
  11.484-             (cond ((> n 2)
  11.485-                    (let* ((j (truncate n 2))
  11.486-                           (a (astep j))
  11.487-                           (k (- n j))
  11.488-                           (b (astep k)))
  11.489-                      (merge! a b predicate)))
  11.490-                   ((= n 2)
  11.491-                    (let ((x (car seq))
  11.492-                          (y (cadr seq))
  11.493-                          (p seq))
  11.494-                      (setf seq (cddr seq))
  11.495-                      (when (funcall predicate y x)
  11.496-                        (setf (car p) y)
  11.497-                        (setf (cadr p) x))
  11.498-                      (setf (cddr p) nil)
  11.499-                      p))
  11.500-                   ((= n 1)
  11.501-                    (let ((p seq))
  11.502-                      (setf seq (cdr seq))
  11.503-                      (setf (cdr p) nil)
  11.504-                      p))
  11.505-                   (t nil))))
  11.506-    (astep (length seq))))
  11.507-
  11.508-;;; CLOS/MOP
  11.509-(defun list-indirect-class-methods (class)
  11.510-  "List all indirect methods of CLASS."
  11.511-  (remove-duplicates (mapcan #'specializer-direct-generic-functions (compute-class-precedence-list class))))
  11.512-
  11.513-(defun list-class-methods (class methods &optional indirect)
  11.514-  "List all methods specializing on CLASS modulo METHODS. When INDIRECT is
  11.515-non-nil, also include indirect (parent) methods."
  11.516-  (if (eq methods t)
  11.517-      (if indirect
  11.518-	  (list-indirect-class-methods class)
  11.519-	  (specializer-direct-generic-functions class))
  11.520-      (mapcar
  11.521-       (lambda (s)
  11.522-	 (car (member s (specializer-direct-generic-functions class) :key #'generic-function-name)))
  11.523-       methods)))
  11.524-
  11.525-;; FIX 2023-09-13: need exclude param
  11.526-(defun list-class-slots (class slots &optional exclude)
  11.527-  ;; should probably convert slot-definition-name here
  11.528-  (let ((cs (remove-if
  11.529-	     (lambda (s)
  11.530-	       (or
  11.531-		(null s)
  11.532-		(member t (mapcar
  11.533-			   (lambda (x)
  11.534-			     (string= (slot-definition-name s) x))
  11.535-			   exclude))))
  11.536-	     (class-slots class))))
  11.537-    (if (eq slots t)
  11.538-	cs
  11.539-	(loop for s in slots
  11.540-	      with sn = (symb s)
  11.541-	      for c in cs
  11.542-	      with cn = (symb (slot-definition-name c))
  11.543-	      when (eq sn cn)
  11.544-		collect c))))
  11.545-
  11.546-;; TODO 2023-09-09: slot exclusion from dynamic var
  11.547-(defun list-slot-values-using-class (class obj slots &optional nullp unboundp)
  11.548-  (remove-if
  11.549-   #'null
  11.550-   (mapcar
  11.551-    (lambda (s)
  11.552-      (let ((n (slot-definition-name s)))
  11.553-	(let ((ns (make-keyword (symbol-name n))))
  11.554-	  (if (slot-boundp-using-class class obj s)
  11.555-	      (let ((v (slot-value-using-class class obj s)))
  11.556-		(if nullp
  11.557-		    `(,ns ,v)
  11.558-		    (unless (null v)
  11.559-		      `(,ns ,v))))
  11.560-	      (when unboundp (list ns))))))
  11.561-    slots)))
  11.562-
  11.563-;;; Seq utils
  11.564-
  11.565-(deftype signed-array-length ()
  11.566-  "A (possibly negated) array length."
  11.567-  '#.(let ((limit (1- array-dimension-limit)))
  11.568-       `(integer ,(- limit) ,limit)))
  11.569-
  11.570-(defun take (n seq)
  11.571-  "Return, at most, the first N elements of SEQ, as a *new* sequence
  11.572-of the same type as SEQ.
  11.573-
  11.574-If N is longer than SEQ, SEQ is simply copied.
  11.575-
  11.576-If N is negative, then |N| elements are taken (in their original
  11.577-order) from the end of SEQ."
  11.578-  #+sbcl (declare (sb-ext:muffle-conditions style-warning))
  11.579-  (declare (type signed-array-length n))
  11.580-  (seq-dispatch seq
  11.581-    (if (minusp n)
  11.582-        (last seq (abs n))
  11.583-        (firstn n seq))
  11.584-    (if (minusp n)
  11.585-        (subseq seq (max 0 (+ (length seq) n)))
  11.586-        (subseq seq 0 (min n (length seq))))))
  11.587-
  11.588-;;; Hashtable utils
  11.589-(declaim (inline maphash-keys))
  11.590-(defun maphash-keys (function table)
  11.591-  "Like MAPHASH, but calls FUNCTION with each key in the hash table TABLE."
  11.592-  (maphash (lambda (k v)
  11.593-             (declare (ignore v))
  11.594-             (funcall function k))
  11.595-           table))
  11.596-
  11.597-(declaim (inline maphash-values))
  11.598-(defun maphash-values (function table)
  11.599-  "Like MAPHASH, but calls FUNCTION with each value in the hash table TABLE."
  11.600-  (maphash (lambda (k v)
  11.601-             (declare (ignore k))
  11.602-             (funcall function v))
  11.603-           table))
  11.604-
  11.605-(defun hash-table-keys (table)
  11.606-  "Returns a list containing the keys of hash table TABLE."
  11.607-  (let ((keys nil))
  11.608-    (maphash-keys (lambda (k)
  11.609-                    (push k keys))
  11.610-                  table)
  11.611-    keys))
  11.612-
  11.613-(defun hash-table-values (table)
  11.614-  "Returns a list containing the values of hash table TABLE."
  11.615-  (let ((values nil))
  11.616-    (maphash-values (lambda (v)
  11.617-                      (push v values))
  11.618-                    table)
  11.619-    values))
  11.620-
  11.621-(defun current-lisp-implementation ()
  11.622-  "Return the current lisp implemenation as a cons: (TYPE VERSION)"
  11.623-  (list 
  11.624-   (lisp-implementation-type) 
  11.625-   (lisp-implementation-version)
  11.626-   *features*))
  11.627-
  11.628-;;; Franz
  11.629-(defvar if*-keyword-list '("then" "thenret" "else" "elseif"))
  11.630-
  11.631-(defmacro if* (&rest args)
  11.632-   (do ((xx (reverse args) (cdr xx))
  11.633-	(state :init)
  11.634-	(elseseen nil)
  11.635-	(totalcol nil)
  11.636-	(lookat nil nil)
  11.637-	(col nil))
  11.638-       ((null xx)
  11.639-	(cond ((eq state :compl)
  11.640-	       `(cond ,@totalcol))
  11.641-	      (t (error "if*: illegal form ~s" args))))
  11.642-       (cond ((and (symbolp (car xx))
  11.643-		   (member (symbol-name (car xx))
  11.644-			   if*-keyword-list
  11.645-			   :test #'string-equal))
  11.646-	      (setq lookat (symbol-name (car xx)))))
  11.647-
  11.648-       (cond ((eq state :init)
  11.649-	      (cond (lookat (cond ((string-equal lookat "thenret")
  11.650-				   (setq col nil
  11.651-					 state :then))
  11.652-				  (t (error
  11.653-				      "if*: bad keyword ~a" lookat))))
  11.654-		    (t (setq state :col
  11.655-			     col nil)
  11.656-		       (push (car xx) col))))
  11.657-	     ((eq state :col)
  11.658-	      (cond (lookat
  11.659-		     (cond ((string-equal lookat "else")
  11.660-			    (cond (elseseen
  11.661-				   (error
  11.662-				    "if*: multiples elses")))
  11.663-			    (setq elseseen t)
  11.664-			    (setq state :init)
  11.665-			    (push `(t ,@col) totalcol))
  11.666-			   ((string-equal lookat "then")
  11.667-			    (setq state :then))
  11.668-			   (t (error "if*: bad keyword ~s"
  11.669-					      lookat))))
  11.670-		    (t (push (car xx) col))))
  11.671-	     ((eq state :then)
  11.672-	      (cond (lookat
  11.673-		     (error
  11.674-		      "if*: keyword ~s at the wrong place " (car xx)))
  11.675-		    (t (setq state :compl)
  11.676-		       (push `(,(car xx) ,@col) totalcol))))
  11.677-	     ((eq state :compl)
  11.678-	      (cond ((not (string-equal lookat "elseif"))
  11.679-		     (error "if*: missing elseif clause ")))
  11.680-	      (setq state :init)))))
  11.681-
  11.682-(defun tmpfile (size)
  11.683-  "Create an anonymous temporary file of the given size. Returns a file descriptor."
  11.684-  (let (done fd pathname)
  11.685-    (unwind-protect
  11.686-         (progn
  11.687-           (setf (values fd pathname) (sb-posix:mkstemp "/dev/shm/tmp.XXXXXXXX"))
  11.688-           (sb-posix:unlink pathname)
  11.689-           (sb-posix:ftruncate fd size)
  11.690-           (setf done t))
  11.691-      (when (and fd (not done)) (sb-posix:close fd)))
  11.692-    fd))
  11.693-
  11.694-;;; Alexandria Functions
  11.695-(declaim (inline ensure-function))
  11.696-
  11.697-(declaim (ftype (function (t) (values function &optional))
  11.698-                ensure-function))
  11.699-(defun ensure-function (function-designator)
  11.700-  "Returns the function designated by FUNCTION-DESIGNATOR:
  11.701-if FUNCTION-DESIGNATOR is a function, it is returned, otherwise
  11.702-it must be a function name and its FDEFINITION is returned."
  11.703-  (if (functionp function-designator)
  11.704-      function-designator
  11.705-      (fdefinition function-designator)))
  11.706-
  11.707-(define-modify-macro ensure-functionf/1 () ensure-function)
  11.708-
  11.709-(defmacro ensure-functionf (&rest places)
  11.710-  "Multiple-place modify macro for ENSURE-FUNCTION: ensures that each of
  11.711-PLACES contains a function."
  11.712-  `(progn ,@(mapcar (lambda (x) `(ensure-functionf/1 ,x)) places)))
  11.713-
  11.714-(defun disjoin (predicate &rest more-predicates)
  11.715-  "Returns a function that applies each of PREDICATE and MORE-PREDICATE
  11.716-functions in turn to its arguments, returning the primary value of the first
  11.717-predicate that returns true, without calling the remaining predicates.
  11.718-If none of the predicates returns true, NIL is returned."
  11.719-  (declare (optimize (speed 3) (safety 1) (debug 1)))
  11.720-  (let ((predicate (ensure-function predicate))
  11.721-	(more-predicates (mapcar #'ensure-function more-predicates)))
  11.722-    (lambda (&rest arguments)
  11.723-      (or (apply predicate arguments)
  11.724-	  (some (lambda (p)
  11.725-		  (declare (type function p))
  11.726-		  (apply p arguments))
  11.727-		more-predicates)))))
  11.728-
  11.729-(defun conjoin (predicate &rest more-predicates)
  11.730-  "Returns a function that applies each of PREDICATE and MORE-PREDICATE
  11.731-functions in turn to its arguments, returning NIL if any of the predicates
  11.732-returns false, without calling the remaining predicates. If none of the
  11.733-predicates returns false, returns the primary value of the last predicate."
  11.734-  (if (null more-predicates)
  11.735-      predicate
  11.736-      (lambda (&rest arguments)
  11.737-	(and (apply predicate arguments)
  11.738-	     ;; Cannot simply use CL:EVERY because we want to return the
  11.739-	     ;; non-NIL value of the last predicate if all succeed.
  11.740-	     (do ((tail (cdr more-predicates) (cdr tail))
  11.741-		  (head (car more-predicates) (car tail)))
  11.742-		 ((not tail)
  11.743-		  (apply head arguments))
  11.744-	       (unless (apply head arguments)
  11.745-		 (return nil)))))))
  11.746-
  11.747-(defun compose (function &rest more-functions)
  11.748-  "Returns a function composed of FUNCTION and MORE-FUNCTIONS that applies its
  11.749-arguments to to each in turn, starting from the rightmost of MORE-FUNCTIONS,
  11.750-and then calling the next one with the primary value of the last."
  11.751-  (declare (optimize (speed 3) (safety 1) (debug 1)))
  11.752-  (reduce (lambda (f g)
  11.753-	    (let ((f (ensure-function f))
  11.754-		  (g (ensure-function g)))
  11.755-	      (lambda (&rest arguments)
  11.756-		(declare (dynamic-extent arguments))
  11.757-		(funcall f (apply g arguments)))))
  11.758-          more-functions
  11.759-          :initial-value function))
  11.760-
  11.761-(define-compiler-macro compose (function &rest more-functions)
  11.762-  (labels ((compose-1 (funs)
  11.763-             (if (cdr funs)
  11.764-                 `(funcall ,(car funs) ,(compose-1 (cdr funs)))
  11.765-                 `(apply ,(car funs) arguments))))
  11.766-    (let* ((args (cons function more-functions))
  11.767-           (funs (make-gensym-list (length args) "COMPOSE")))
  11.768-      `(let ,(loop for f in funs for arg in args
  11.769-		   collect `(,f (ensure-function ,arg)))
  11.770-         (declare (optimize (speed 3) (safety 1) (debug 1)))
  11.771-         (lambda (&rest arguments)
  11.772-           (declare (dynamic-extent arguments))
  11.773-           ,(compose-1 funs))))))
  11.774-
  11.775-(defun multiple-value-compose (function &rest more-functions)
  11.776-    "Returns a function composed of FUNCTION and MORE-FUNCTIONS that applies
  11.777-its arguments to each in turn, starting from the rightmost of
  11.778-MORE-FUNCTIONS, and then calling the next one with all the return values of
  11.779-the last."
  11.780-  (declare (optimize (speed 3) (safety 1) (debug 1)))
  11.781-  (reduce (lambda (f g)
  11.782-	    (let ((f (ensure-function f))
  11.783-		  (g (ensure-function g)))
  11.784-	      (lambda (&rest arguments)
  11.785-		(declare (dynamic-extent arguments))
  11.786-		(multiple-value-call f (apply g arguments)))))
  11.787-          more-functions
  11.788-          :initial-value function))
  11.789-
  11.790-(define-compiler-macro multiple-value-compose (function &rest more-functions)
  11.791-  (labels ((compose-1 (funs)
  11.792-             (if (cdr funs)
  11.793-                 `(multiple-value-call ,(car funs) ,(compose-1 (cdr funs)))
  11.794-                 `(apply ,(car funs) arguments))))
  11.795-    (let* ((args (cons function more-functions))
  11.796-           (funs (make-gensym-list (length args) "MV-COMPOSE")))
  11.797-      `(let ,(mapcar #'list funs args)
  11.798-         (declare (optimize (speed 3) (safety 1) (debug 1)))
  11.799-         (lambda (&rest arguments)
  11.800-           (declare (dynamic-extent arguments))
  11.801-           ,(compose-1 funs))))))
  11.802-
  11.803-(declaim (inline curry rcurry))
  11.804-
  11.805-(defun curry (function &rest arguments)
  11.806-  "Returns a function that applies ARGUMENTS and the arguments
  11.807-it is called with to FUNCTION."
  11.808-  (declare (optimize (speed 3) (safety 1)))
  11.809-  (let ((fn (ensure-function function)))
  11.810-    (lambda (&rest more)
  11.811-      (declare (dynamic-extent more))
  11.812-      ;; Using M-V-C we don't need to append the arguments.
  11.813-      (multiple-value-call fn (values-list arguments) (values-list more)))))
  11.814-
  11.815-(define-compiler-macro curry (function &rest arguments)
  11.816-  (let ((curries (make-gensym-list (length arguments) "CURRY"))
  11.817-        (fun (gensym "FUN")))
  11.818-    `(let ((,fun (ensure-function ,function))
  11.819-           ,@(mapcar #'list curries arguments))
  11.820-       (declare (optimize (speed 3) (safety 1)))
  11.821-       (lambda (&rest more)
  11.822-         (declare (dynamic-extent more))
  11.823-         (apply ,fun ,@curries more)))))
  11.824-
  11.825-(defun rcurry (function &rest arguments)
  11.826-  "Returns a function that applies the arguments it is called
  11.827-with and ARGUMENTS to FUNCTION."
  11.828-  (declare (optimize (speed 3) (safety 1)))
  11.829-  (let ((fn (ensure-function function)))
  11.830-    (lambda (&rest more)
  11.831-      (declare (dynamic-extent more))
  11.832-      (multiple-value-call fn (values-list more) (values-list arguments)))))
  11.833-
  11.834-(define-compiler-macro rcurry (function &rest arguments)
  11.835-  (let ((rcurries (make-gensym-list (length arguments) "RCURRY"))
  11.836-        (fun (gensym "FUN")))
  11.837-    `(let ((,fun (ensure-function ,function))
  11.838-           ,@(mapcar #'list rcurries arguments))
  11.839-       (declare (optimize (speed 3) (safety 1)))
  11.840-       (lambda (&rest more)
  11.841-         (declare (dynamic-extent more))
  11.842-         (multiple-value-call ,fun (values-list more) ,@rcurries)))))
  11.843-
  11.844-(declaim (notinline curry rcurry))
  11.845-
  11.846-
  11.847-(defmacro named-lambda (name lambda-list &body body)
  11.848-  "Expands into a lambda-expression within whose BODY NAME denotes the
  11.849-corresponding function."
  11.850-  `(labels ((,name ,lambda-list ,@body))
  11.851-     #',name))
  11.852-
  11.853-;;; array utils
  11.854-
  11.855-(defun copy-array (array)
  11.856-  (let ((new-array
  11.857-          (make-array (array-dimensions array)
  11.858-                      :element-type (array-element-type array)
  11.859-                      :adjustable (adjustable-array-p array)
  11.860-                      :fill-pointer (and (array-has-fill-pointer-p array)
  11.861-                                         (fill-pointer array)))))
  11.862-    (loop for i below (array-total-size array)
  11.863-          do (setf (row-major-aref new-array i)
  11.864-                   (row-major-aref array i)))
  11.865-    new-array))
  11.866-
  11.867-;;; hash-table utils
  11.868-(defun hash-table-alist (table)
  11.869-  "Returns an association list containing the keys and values of hash table
  11.870-TABLE."
  11.871-  (let ((alist nil))
  11.872-    (maphash (lambda (k v)
  11.873-               (push (cons k v) alist))
  11.874-             table)
  11.875-    alist))
    12.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2+++ b/lisp/std/fu/curry.lisp	Mon Apr 22 23:14:47 2024 -0400
    12.3@@ -0,0 +1,159 @@
    12.4+;;; std/fu/curry.lisp --- Standard Currying Functors
    12.5+
    12.6+;;
    12.7+
    12.8+;;; Code:
    12.9+(in-package :std/fu)
   12.10+
   12.11+;;; Alexandria Functions
   12.12+(declaim (inline ensure-function))
   12.13+
   12.14+(declaim (ftype (function (t) (values function &optional))
   12.15+                ensure-function))
   12.16+(defun ensure-function (function-designator)
   12.17+  "Returns the function designated by FUNCTION-DESIGNATOR:
   12.18+if FUNCTION-DESIGNATOR is a function, it is returned, otherwise
   12.19+it must be a function name and its FDEFINITION is returned."
   12.20+  (if (functionp function-designator)
   12.21+      function-designator
   12.22+      (fdefinition function-designator)))
   12.23+
   12.24+(define-modify-macro ensure-functionf/1 () ensure-function)
   12.25+
   12.26+(defmacro ensure-functionf (&rest places)
   12.27+  "Multiple-place modify macro for ENSURE-FUNCTION: ensures that each of
   12.28+PLACES contains a function."
   12.29+  `(progn ,@(mapcar (lambda (x) `(ensure-functionf/1 ,x)) places)))
   12.30+
   12.31+(defun disjoin (predicate &rest more-predicates)
   12.32+  "Returns a function that applies each of PREDICATE and MORE-PREDICATE
   12.33+functions in turn to its arguments, returning the primary value of the first
   12.34+predicate that returns true, without calling the remaining predicates.
   12.35+If none of the predicates returns true, NIL is returned."
   12.36+  (declare (optimize (speed 3) (safety 1) (debug 1)))
   12.37+  (let ((predicate (ensure-function predicate))
   12.38+        (more-predicates (mapcar #'ensure-function more-predicates)))
   12.39+    (lambda (&rest arguments)
   12.40+      (or (apply predicate arguments)
   12.41+          (some (lambda (p)
   12.42+                  (declare (type function p))
   12.43+                  (apply p arguments))
   12.44+                more-predicates)))))
   12.45+
   12.46+(defun conjoin (predicate &rest more-predicates)
   12.47+  "Returns a function that applies each of PREDICATE and MORE-PREDICATE
   12.48+functions in turn to its arguments, returning NIL if any of the predicates
   12.49+returns false, without calling the remaining predicates. If none of the
   12.50+predicates returns false, returns the primary value of the last predicate."
   12.51+  (if (null more-predicates)
   12.52+      predicate
   12.53+      (lambda (&rest arguments)
   12.54+        (and (apply predicate arguments)
   12.55+             ;; Cannot simply use CL:EVERY because we want to return the
   12.56+             ;; non-NIL value of the last predicate if all succeed.
   12.57+             (do ((tail (cdr more-predicates) (cdr tail))
   12.58+                  (head (car more-predicates) (car tail)))
   12.59+                 ((not tail)
   12.60+                  (apply head arguments))
   12.61+               (unless (apply head arguments)
   12.62+                 (return nil)))))))
   12.63+
   12.64+(defun compose (function &rest more-functions)
   12.65+  "Returns a function composed of FUNCTION and MORE-FUNCTIONS that applies its
   12.66+arguments to to each in turn, starting from the rightmost of MORE-FUNCTIONS,
   12.67+and then calling the next one with the primary value of the last."
   12.68+  (declare (optimize (speed 3) (safety 1) (debug 1)))
   12.69+  (reduce (lambda (f g)
   12.70+            (let ((f (ensure-function f))
   12.71+                  (g (ensure-function g)))
   12.72+              (lambda (&rest arguments)
   12.73+                (declare (dynamic-extent arguments))
   12.74+                (funcall f (apply g arguments)))))
   12.75+          more-functions
   12.76+          :initial-value function))
   12.77+
   12.78+(define-compiler-macro compose (function &rest more-functions)
   12.79+  (labels ((compose-1 (funs)
   12.80+             (if (cdr funs)
   12.81+                 `(funcall ,(car funs) ,(compose-1 (cdr funs)))
   12.82+                 `(apply ,(car funs) arguments))))
   12.83+    (let* ((args (cons function more-functions))
   12.84+           (funs (make-gensym-list (length args) "COMPOSE")))
   12.85+      `(let ,(loop for f in funs for arg in args
   12.86+                   collect `(,f (ensure-function ,arg)))
   12.87+         (declare (optimize (speed 3) (safety 1) (debug 1)))
   12.88+         (lambda (&rest arguments)
   12.89+           (declare (dynamic-extent arguments))
   12.90+           ,(compose-1 funs))))))
   12.91+
   12.92+(defun multiple-value-compose (function &rest more-functions)
   12.93+    "Returns a function composed of FUNCTION and MORE-FUNCTIONS that applies
   12.94+its arguments to each in turn, starting from the rightmost of
   12.95+MORE-FUNCTIONS, and then calling the next one with all the return values of
   12.96+the last."
   12.97+  (declare (optimize (speed 3) (safety 1) (debug 1)))
   12.98+  (reduce (lambda (f g)
   12.99+            (let ((f (ensure-function f))
  12.100+                  (g (ensure-function g)))
  12.101+              (lambda (&rest arguments)
  12.102+                (declare (dynamic-extent arguments))
  12.103+                (multiple-value-call f (apply g arguments)))))
  12.104+          more-functions
  12.105+          :initial-value function))
  12.106+
  12.107+(define-compiler-macro multiple-value-compose (function &rest more-functions)
  12.108+  (labels ((compose-1 (funs)
  12.109+             (if (cdr funs)
  12.110+                 `(multiple-value-call ,(car funs) ,(compose-1 (cdr funs)))
  12.111+                 `(apply ,(car funs) arguments))))
  12.112+    (let* ((args (cons function more-functions))
  12.113+           (funs (make-gensym-list (length args) "MV-COMPOSE")))
  12.114+      `(let ,(mapcar #'list funs args)
  12.115+         (declare (optimize (speed 3) (safety 1) (debug 1)))
  12.116+         (lambda (&rest arguments)
  12.117+           (declare (dynamic-extent arguments))
  12.118+           ,(compose-1 funs))))))
  12.119+
  12.120+(declaim (inline curry rcurry))
  12.121+
  12.122+(defun curry (function &rest arguments)
  12.123+  "Returns a function that applies ARGUMENTS and the arguments
  12.124+it is called with to FUNCTION."
  12.125+  (declare (optimize (speed 3) (safety 1)))
  12.126+  (let ((fn (ensure-function function)))
  12.127+    (lambda (&rest more)
  12.128+      (declare (dynamic-extent more))
  12.129+      ;; Using M-V-C we don't need to append the arguments.
  12.130+      (multiple-value-call fn (values-list arguments) (values-list more)))))
  12.131+
  12.132+(define-compiler-macro curry (function &rest arguments)
  12.133+  (let ((curries (make-gensym-list (length arguments) "CURRY"))
  12.134+        (fun (gensym "FUN")))
  12.135+    `(let ((,fun (ensure-function ,function))
  12.136+           ,@(mapcar #'list curries arguments))
  12.137+       (declare (optimize (speed 3) (safety 1)))
  12.138+       (lambda (&rest more)
  12.139+         (declare (dynamic-extent more))
  12.140+         (apply ,fun ,@curries more)))))
  12.141+
  12.142+(defun rcurry (function &rest arguments)
  12.143+  "Returns a function that applies the arguments it is called
  12.144+with and ARGUMENTS to FUNCTION."
  12.145+  (declare (optimize (speed 3) (safety 1)))
  12.146+  (let ((fn (ensure-function function)))
  12.147+    (lambda (&rest more)
  12.148+      (declare (dynamic-extent more))
  12.149+      (multiple-value-call fn (values-list more) (values-list arguments)))))
  12.150+
  12.151+(define-compiler-macro rcurry (function &rest arguments)
  12.152+  (let ((rcurries (make-gensym-list (length arguments) "RCURRY"))
  12.153+        (fun (gensym "FUN")))
  12.154+    `(let ((,fun (ensure-function ,function))
  12.155+           ,@(mapcar #'list rcurries arguments))
  12.156+       (declare (optimize (speed 3) (safety 1)))
  12.157+       (lambda (&rest more)
  12.158+         (declare (dynamic-extent more))
  12.159+         (multiple-value-call ,fun (values-list more) ,@rcurries)))))
  12.160+
  12.161+(declaim (notinline curry rcurry))
  12.162+
    13.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2+++ b/lisp/std/hash-table.lisp	Mon Apr 22 23:14:47 2024 -0400
    13.3@@ -0,0 +1,47 @@
    13.4+;;; std/hash-table.lisp --- Standard Hash Tables
    13.5+
    13.6+;;
    13.7+
    13.8+;;; Code:
    13.9+(in-package :std/hash-table)
   13.10+
   13.11+(declaim (inline maphash-keys))
   13.12+(defun maphash-keys (function table)
   13.13+  "Like MAPHASH, but calls FUNCTION with each key in the hash table TABLE."
   13.14+  (maphash (lambda (k v)
   13.15+             (declare (ignore v))
   13.16+             (funcall function k))
   13.17+           table))
   13.18+
   13.19+(declaim (inline maphash-values))
   13.20+(defun maphash-values (function table)
   13.21+  "Like MAPHASH, but calls FUNCTION with each value in the hash table TABLE."
   13.22+  (maphash (lambda (k v)
   13.23+             (declare (ignore k))
   13.24+             (funcall function v))
   13.25+           table))
   13.26+
   13.27+(defun hash-table-keys (table)
   13.28+  "Returns a list containing the keys of hash table TABLE."
   13.29+  (let ((keys nil))
   13.30+    (maphash-keys (lambda (k)
   13.31+                    (push k keys))
   13.32+                  table)
   13.33+    keys))
   13.34+
   13.35+(defun hash-table-values (table)
   13.36+  "Returns a list containing the values of hash table TABLE."
   13.37+  (let ((values nil))
   13.38+    (maphash-values (lambda (v)
   13.39+                      (push v values))
   13.40+                    table)
   13.41+    values))
   13.42+
   13.43+(defun hash-table-alist (table)
   13.44+  "Returns an association list containing the keys and values of hash table
   13.45+TABLE."
   13.46+  (let ((alist nil))
   13.47+    (maphash (lambda (k v)
   13.48+               (push (cons k v) alist))
   13.49+             table)
   13.50+    alist))
    14.1--- a/lisp/std/list.lisp	Sun Apr 21 22:38:49 2024 -0400
    14.2+++ b/lisp/std/list.lisp	Mon Apr 22 23:14:47 2024 -0400
    14.3@@ -1,7 +1,7 @@
    14.4 ;;; std/list.lisp --- List utils
    14.5 
    14.6 ;;; Code:
    14.7-(in-package :std)
    14.8+(in-package :std/list)
    14.9 
   14.10 ;; (reexport-from :sb-int
   14.11 ;; 	       :include '(:recons :memq :assq :ensure-list :proper-list-of-length-p :proper-list-p
   14.12@@ -122,3 +122,60 @@
   14.13                          (car x)
   14.14                          (rec (cdr x) acc))))))
   14.15       (rec x nil))))
   14.16+
   14.17+;;; cl-bench utils
   14.18+;; Destructive merge of two sorted lists.
   14.19+;; From Hansen's MS thesis.
   14.20+(defun merge! (a b predicate)
   14.21+  (labels ((merge-loop (r a b)
   14.22+             (cond ((funcall predicate (car b) (car a))
   14.23+                    (setf (cdr r) b)
   14.24+                    (if (null (cdr b))
   14.25+                        (setf (cdr b) a)
   14.26+                        (merge-loop b a (cdr b))))
   14.27+                   (t ; (car a) <= (car b)
   14.28+                    (setf (cdr r) a)
   14.29+                    (if (null (cdr a))
   14.30+                        (setf (cdr a) b)
   14.31+                        (merge-loop a (cdr a) b))))))
   14.32+    (cond ((null a) b)
   14.33+          ((null b) a)
   14.34+          ((funcall predicate (car b) (car a))
   14.35+           (if (null (cdr b))
   14.36+               (setf (cdr b) a)
   14.37+               (merge-loop b a (cdr b)))
   14.38+           b)
   14.39+          (t                           ; (car a) <= (car b)
   14.40+           (if (null (cdr a))
   14.41+               (setf (cdr a) b)
   14.42+               (merge-loop a (cdr a) b))
   14.43+           a))))
   14.44+
   14.45+;; Stable sort procedure which copies the input list and then sorts
   14.46+;; the new list imperatively. Due to Richard O'Keefe; algorithm
   14.47+;; attributed to D.H.D. Warren.
   14.48+(defun sort! (seq predicate)
   14.49+  (labels ((astep (n)
   14.50+             (cond ((> n 2)
   14.51+                    (let* ((j (truncate n 2))
   14.52+                           (a (astep j))
   14.53+                           (k (- n j))
   14.54+                           (b (astep k)))
   14.55+                      (merge! a b predicate)))
   14.56+                   ((= n 2)
   14.57+                    (let ((x (car seq))
   14.58+                          (y (cadr seq))
   14.59+                          (p seq))
   14.60+                      (setf seq (cddr seq))
   14.61+                      (when (funcall predicate y x)
   14.62+                        (setf (car p) y)
   14.63+                        (setf (cadr p) x))
   14.64+                      (setf (cddr p) nil)
   14.65+                      p))
   14.66+                   ((= n 1)
   14.67+                    (let ((p seq))
   14.68+                      (setf seq (cdr seq))
   14.69+                      (setf (cdr p) nil)
   14.70+                      p))
   14.71+                   (t nil))))
   14.72+    (astep (length seq))))
    15.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2+++ b/lisp/std/macs/ana.lisp	Mon Apr 22 23:14:47 2024 -0400
    15.3@@ -0,0 +1,671 @@
    15.4+;;; ana.lisp --- anaphoric macros
    15.5+
    15.6+;;; Code:
    15.7+(in-package :std/macs)
    15.8+
    15.9+(in-readtable :std)
   15.10+
   15.11+;;; Named Lambdas
   15.12+;; (reexport-from :sb-int :include '(:make-macro-lambda :parse-lambda-list))
   15.13+
   15.14+;; LoL tlist
   15.15+;; (declaim (inline make-tlist tlist-left
   15.16+;;                  tlist-right tlist-empty-p))
   15.17+
   15.18+;; (defun make-tlist () (cons nil nil))
   15.19+;; (defun tlist-left (tl) (caar tl))
   15.20+;; (defun tlist-right (tl) (cadr tl))
   15.21+;; (defun tlist-empty-p (tl) (null (car tl)))
   15.22+
   15.23+;; (declaim (inline tlist-add-left
   15.24+;;                  tlist-add-right))
   15.25+
   15.26+;; (defun tlist-add-left (tl it)
   15.27+;;   (let ((x (cons it (car tl))))
   15.28+;;     (if (tlist-empty-p tl)
   15.29+;;         (setf (cdr tl) x))
   15.30+;;     (setf (car tl) x)))
   15.31+
   15.32+;; (defun tlist-add-right (tl it)
   15.33+;;   (let ((x (cons it nil)))
   15.34+;;     (if (tlist-empty-p tl)
   15.35+;;         (setf (car tl) x)
   15.36+;;         (setf (cddr tl) x))
   15.37+;;     (setf (cdr tl) x)))
   15.38+
   15.39+;; (declaim (inline tlist-rem-left))
   15.40+
   15.41+;; (defun tlist-rem-left (tl)
   15.42+;;   (if (tlist-empty-p tl)
   15.43+;;       (error "Remove from empty tlist")
   15.44+;;       (let ((x (car tl)))
   15.45+;;         (setf (car tl) (cdar tl))
   15.46+;;         (if (tlist-empty-p tl)
   15.47+;;             (setf (cdr tl) nil)) ;; For gc
   15.48+;;         (car x))))
   15.49+
   15.50+;; (declaim (inline tlist-update))
   15.51+
   15.52+;; (defun tlist-update (tl)
   15.53+;;   (setf (cdr tl) (last (car tl))))
   15.54+
   15.55+(defun build-batcher-sn (n)
   15.56+  (let* (network
   15.57+         (tee (ceiling (log n 2)))
   15.58+         (p (ash 1 (- tee 1))))
   15.59+    (loop while (> p 0) do
   15.60+      (let ((q (ash 1 (- tee 1)))
   15.61+            (r 0)
   15.62+            (d p))
   15.63+        (loop while (> d 0) do
   15.64+          (loop for i from 0 to (- n d 1) do
   15.65+            (if (= (logand i p) r)
   15.66+                (push (list i (+ i d))
   15.67+                      network)))
   15.68+          (setf d (- q p)
   15.69+                q (ash q -1)
   15.70+                r p)))
   15.71+      (setf p (ash p -1)))
   15.72+    (nreverse network)))
   15.73+
   15.74+(defmacro! sortf (comparator &rest places)
   15.75+  (if places
   15.76+      `(tagbody
   15.77+          ,@(mapcar
   15.78+             #`(let ((,g!a #1=,(nth (car a1) places))
   15.79+                     (,g!b #2=,(nth (cadr a1) places)))
   15.80+                 (if (,comparator ,g!b ,g!a)
   15.81+                     (setf #1# ,g!b
   15.82+                           #2# ,g!a)))
   15.83+             (build-batcher-sn (length places))))))
   15.84+
   15.85+#+cl-ppcre
   15.86+(defun dollar-symbol-p (s)
   15.87+  (and (symbolp s)
   15.88+       (> (length (symbol-name s)) 1)
   15.89+       (string= (symbol-name s)
   15.90+                "$"
   15.91+                :start1 0
   15.92+                :end1 1)
   15.93+       (ignore-errors (parse-integer (subseq (symbol-name s) 1)))))
   15.94+
   15.95+
   15.96+#+cl-ppcre
   15.97+(defmacro! if-match ((match-regex str) then &optional else)
   15.98+  (let* ((dollars (remove-duplicates
   15.99+                   (remove-if-not #'dollar-symbol-p
  15.100+                                  (flatten then))))
  15.101+         (top (or (car (sort (mapcar #'dollar-symbol-p dollars) #'>))
  15.102+                  0)))
  15.103+    `(multiple-value-bind (,g!matches ,g!captures) (,match-regex ,str)
  15.104+       (declare (ignorable ,g!matches ,g!captures))
  15.105+       (let ((,g!captures-len (length ,g!captures)))
  15.106+         (declare (ignorable ,g!captures-len))
  15.107+         (symbol-macrolet ,(mapcar #`(,(symb "$" a1)
  15.108+                                       (if (< ,g!captures-len ,a1)
  15.109+                                           (error "Too few matchs: ~a unbound." ,(mkstr "$" a1))
  15.110+                                           (aref ,g!captures ,(1- a1))))
  15.111+                                   (loop for i from 1 to top collect i))
  15.112+           (if ,g!matches
  15.113+               ,then
  15.114+               ,else))))))
  15.115+
  15.116+(defun g!-symbol-p (s)
  15.117+  (and (symbolp s)
  15.118+       (> (length (symbol-name s)) 2)
  15.119+       (string= (symbol-name s)
  15.120+                "G!"
  15.121+                :start1 0
  15.122+                :end1 2)))
  15.123+
  15.124+(defun o!-symbol-p (s)
  15.125+  (and (symbolp s)
  15.126+       (> (length (symbol-name s)) 2)
  15.127+       (string= (symbol-name s)
  15.128+                "O!"
  15.129+                :start1 0
  15.130+                :end1 2)))
  15.131+
  15.132+(defun o!-symbol-to-g!-symbol (s)
  15.133+  (symb "G!"
  15.134+        (subseq (symbol-name s) 2)))
  15.135+
  15.136+#+cl-ppcre
  15.137+(defmacro when-match ((match-regex str) &body forms)
  15.138+  `(if-match (,match-regex ,str)
  15.139+             (progn ,@forms)))
  15.140+
  15.141+(defmacro once-only (specs &body forms)
  15.142+  "Constructs code whose primary goal is to help automate the handling of
  15.143+multiple evaluation within macros. Multiple evaluation is handled by introducing
  15.144+intermediate variables, in order to reuse the result of an expression.
  15.145+
  15.146+The returned value is a list of the form
  15.147+
  15.148+  (let ((<gensym-1> <expr-1>)
  15.149+        ...
  15.150+        (<gensym-n> <expr-n>))
  15.151+    <res>)
  15.152+
  15.153+where GENSYM-1, ..., GENSYM-N are the intermediate variables introduced in order
  15.154+to evaluate EXPR-1, ..., EXPR-N once, only. RES is code that is the result of
  15.155+evaluating the implicit progn FORMS within a special context determined by
  15.156+SPECS. RES should make use of (reference) the intermediate variables.
  15.157+
  15.158+Each element within SPECS is either a symbol SYMBOL or a pair (SYMBOL INITFORM).
  15.159+Bare symbols are equivalent to the pair (SYMBOL SYMBOL).
  15.160+
  15.161+Each pair (SYMBOL INITFORM) specifies a single intermediate variable:
  15.162+
  15.163+- INITFORM is an expression evaluated to produce EXPR-i
  15.164+
  15.165+- SYMBOL is the name of the variable that will be bound around FORMS to the
  15.166+  corresponding gensym GENSYM-i, in order for FORMS to generate RES that
  15.167+  references the intermediate variable
  15.168+
  15.169+The evaluation of INITFORMs and binding of SYMBOLs resembles LET. INITFORMs of
  15.170+all the pairs are evaluated before binding SYMBOLs and evaluating FORMS.
  15.171+
  15.172+Example:
  15.173+
  15.174+  The following expression
  15.175+
  15.176+  (let ((x '(incf y)))
  15.177+    (once-only (x)
  15.178+      `(cons ,x ,x)))
  15.179+
  15.180+  ;;; =>
  15.181+  ;;; (let ((#1=#:X123 (incf y)))
  15.182+  ;;;   (cons #1# #1#))
  15.183+
  15.184+  could be used within a macro to avoid multiple evaluation like so
  15.185+
  15.186+  (defmacro cons1 (x)
  15.187+    (once-only (x)
  15.188+      `(cons ,x ,x)))
  15.189+
  15.190+  (let ((y 0))
  15.191+    (cons1 (incf y)))
  15.192+
  15.193+  ;;; => (1 . 1)
  15.194+
  15.195+Example:
  15.196+
  15.197+  The following expression demonstrates the usage of the INITFORM field
  15.198+
  15.199+  (let ((expr '(incf y)))
  15.200+    (once-only ((var `(1+ ,expr)))
  15.201+      `(list ',expr ,var ,var)))
  15.202+
  15.203+  ;;; =>
  15.204+  ;;; (let ((#1=#:VAR123 (1+ (incf y))))
  15.205+  ;;;   (list '(incf y) #1# #1))
  15.206+
  15.207+  which could be used like so
  15.208+
  15.209+  (defmacro print-succ-twice (expr)
  15.210+    (once-only ((var `(1+ ,expr)))
  15.211+      `(format t \"Expr: ~s, Once: ~s, Twice: ~s~%\" ',expr ,var ,var)))
  15.212+
  15.213+  (let ((y 10))
  15.214+    (print-succ-twice (incf y)))
  15.215+
  15.216+  ;;; >>
  15.217+  ;;; Expr: (INCF Y), Once: 12, Twice: 12"
  15.218+  (let ((gensyms (make-gensym-list (length specs) "ONCE-ONLY"))
  15.219+        (names-and-forms (mapcar (lambda (spec)
  15.220+                                   (etypecase spec
  15.221+                                     (list
  15.222+                                      (destructuring-bind (name form) spec
  15.223+                                        (cons name form)))
  15.224+                                     (symbol
  15.225+                                      (cons spec spec))))
  15.226+                                 specs)))
  15.227+    ;; bind in user-macro
  15.228+    `(let ,(mapcar (lambda (g n) (list g `(gensym ,(string (car n)))))
  15.229+            gensyms names-and-forms)
  15.230+       ;; bind in final expansion
  15.231+       `(let (,,@(mapcar (lambda (g n)
  15.232+                           ``(,,g ,,(cdr n)))
  15.233+                         gensyms names-and-forms))
  15.234+          ;; bind in user-macro
  15.235+          ,(let ,(mapcar (lambda (n g) (list (car n) g))
  15.236+                  names-and-forms gensyms)
  15.237+             ,@forms)))))
  15.238+
  15.239+;;;; DESTRUCTURING-*CASE
  15.240+
  15.241+(defun expand-destructuring-case (key clauses case)
  15.242+  (once-only (key)
  15.243+    `(if (typep ,key 'cons)
  15.244+         (,case (car ,key)
  15.245+           ,@(mapcar (lambda (clause)
  15.246+                       (destructuring-bind ((keys . lambda-list) &body body) clause
  15.247+                         `(,keys
  15.248+                           (destructuring-bind ,lambda-list (cdr ,key)
  15.249+                             ,@body))))
  15.250+              clauses))
  15.251+         (error "Invalid key to DESTRUCTURING-~S: ~S" ',case ,key))))
  15.252+
  15.253+(defmacro destructuring-case (keyform &body clauses)
  15.254+  "DESTRUCTURING-CASE, -CCASE, and -ECASE are a combination of CASE and DESTRUCTURING-BIND.
  15.255+KEYFORM must evaluate to a CONS.
  15.256+
  15.257+Clauses are of the form:
  15.258+
  15.259+  ((CASE-KEYS . DESTRUCTURING-LAMBDA-LIST) FORM*)
  15.260+
  15.261+The clause whose CASE-KEYS matches CAR of KEY, as if by CASE, CCASE, or ECASE,
  15.262+is selected, and FORMs are then executed with CDR of KEY is destructured and
  15.263+bound by the DESTRUCTURING-LAMBDA-LIST.
  15.264+
  15.265+Example:
  15.266+
  15.267+ (defun dcase (x)
  15.268+   (destructuring-case x
  15.269+     ((:foo a b)
  15.270+      (format nil \"foo: ~S, ~S\" a b))
  15.271+     ((:bar &key a b)
  15.272+      (format nil \"bar: ~S, ~S\" a b))
  15.273+     (((:alt1 :alt2) a)
  15.274+      (format nil \"alt: ~S\" a))
  15.275+     ((t &rest rest)
  15.276+      (format nil \"unknown: ~S\" rest))))
  15.277+
  15.278+  (dcase (list :foo 1 2))        ; => \"foo: 1, 2\"
  15.279+  (dcase (list :bar :a 1 :b 2))  ; => \"bar: 1, 2\"
  15.280+  (dcase (list :alt1 1))         ; => \"alt: 1\"
  15.281+  (dcase (list :alt2 2))         ; => \"alt: 2\"
  15.282+  (dcase (list :quux 1 2 3))     ; => \"unknown: 1, 2, 3\"
  15.283+
  15.284+ (defun decase (x)
  15.285+   (destructuring-case x
  15.286+     ((:foo a b)
  15.287+      (format nil \"foo: ~S, ~S\" a b))
  15.288+     ((:bar &key a b)
  15.289+      (format nil \"bar: ~S, ~S\" a b))
  15.290+     (((:alt1 :alt2) a)
  15.291+      (format nil \"alt: ~S\" a))))
  15.292+
  15.293+  (decase (list :foo 1 2))        ; => \"foo: 1, 2\"
  15.294+  (decase (list :bar :a 1 :b 2))  ; => \"bar: 1, 2\"
  15.295+  (decase (list :alt1 1))         ; => \"alt: 1\"
  15.296+  (decase (list :alt2 2))         ; => \"alt: 2\"
  15.297+  (decase (list :quux 1 2 3))     ; =| error
  15.298+"
  15.299+  (expand-destructuring-case keyform clauses 'case))
  15.300+
  15.301+(defmacro destructuring-ccase (keyform &body clauses)
  15.302+  (expand-destructuring-case keyform clauses 'ccase))
  15.303+
  15.304+(defmacro destructuring-ecase (keyform &body clauses)
  15.305+  (expand-destructuring-case keyform clauses 'ecase))
  15.306+
  15.307+(dolist (name '(destructuring-ccase destructuring-ecase))
  15.308+  (setf (documentation name 'function) (documentation 'destructuring-case 'function)))
  15.309+
  15.310+;;; *-let --- control-flow let-binding macros
  15.311+;; based on https://stevelosh.com/blog/2018/07/fun-with-macros-if-let/
  15.312+
  15.313+(defmacro when-let (bindings &body body)
  15.314+  "Bind `bindings` in parallel and execute `body`, short-circuiting on `nil`.
  15.315+
  15.316+  This macro combines `when` and `let`.  It takes a list of bindings and
  15.317+  binds them like `let` before executing `body`, but if any binding's value
  15.318+  evaluates to `nil` the process stops and `nil` is immediately returned.
  15.319+
  15.320+  Examples:
  15.321+
  15.322+    (when-let ((a (progn (print :a) 1))
  15.323+               (b (progn (print :b) 2))
  15.324+      (list a b))
  15.325+    ; =>
  15.326+    :A
  15.327+    :B
  15.328+    (1 2)
  15.329+
  15.330+    (when-let ((a (progn (print :a) nil))
  15.331+               (b (progn (print :b) 2)))
  15.332+      (list a b))
  15.333+    ; =>
  15.334+    :A
  15.335+    NIL
  15.336+
  15.337+  "
  15.338+  (with-gensyms (block)
  15.339+    `(block ,block
  15.340+       (let ,(loop :for (symbol value) :in bindings
  15.341+                   :collect `(,symbol (or ,value
  15.342+                                          (return-from ,block nil))))
  15.343+         ,@body))))
  15.344+
  15.345+(defmacro when-let* (bindings &body body)
  15.346+  "Bind `bindings` serially and execute `body`, short-circuiting on `nil`.
  15.347+
  15.348+  This macro combines `when` and `let*`.  It takes a list of bindings
  15.349+  and binds them like `let*` before executing `body`, but if any
  15.350+  binding's value evaluates to `nil` the process stops and `nil` is
  15.351+  immediately returned.
  15.352+
  15.353+  Examples:
  15.354+
  15.355+    (when-let* ((a (progn (print :a) 1))
  15.356+                (b (progn (print :b) (1+ a)))
  15.357+      (list a b))
  15.358+    ; =>
  15.359+    :A
  15.360+    :B
  15.361+    (1 2)
  15.362+
  15.363+    (when-let* ((a (progn (print :a) nil))
  15.364+                (b (progn (print :b) (1+ a))))
  15.365+      (list a b))
  15.366+    ; =>
  15.367+    :A
  15.368+    NIL
  15.369+
  15.370+  "
  15.371+  (with-gensyms (block)
  15.372+    `(block ,block
  15.373+       (let* ,(loop :for (symbol value) :in bindings
  15.374+                    :collect `(,symbol (or ,value
  15.375+                                           (return-from ,block nil))))
  15.376+         ,@body))))
  15.377+
  15.378+(defmacro if-let (bindings &body body)
  15.379+  "Bind `bindings` in parallel and execute `then` if all are true, or `else` otherwise.
  15.380+
  15.381+  `body` must be of the form `(...optional-declarations... then else)`.
  15.382+
  15.383+  This macro combines `if` and `let`.  It takes a list of bindings and
  15.384+  binds them like `let` before executing the `then` branch of `body`, but
  15.385+  if any binding's value evaluates to `nil` the process stops there and the
  15.386+  `else` branch is immediately executed (with no bindings in effect).
  15.387+
  15.388+  If any `optional-declarations` are included they will only be in effect
  15.389+  for the `then` branch.
  15.390+
  15.391+  Examples:
  15.392+
  15.393+    (if-let ((a (progn (print :a) 1))
  15.394+             (b (progn (print :b) 2)))
  15.395+      (list a b)
  15.396+      'nope)
  15.397+    ; =>
  15.398+    :A
  15.399+    :B
  15.400+    (1 2)
  15.401+
  15.402+    (if-let ((a (progn (print :a) nil))
  15.403+             (b (progn (print :b) 2)))
  15.404+      (list a b)
  15.405+      'nope)
  15.406+    ; =>
  15.407+    :A
  15.408+    NOPE
  15.409+
  15.410+  "
  15.411+  (with-gensyms (outer inner)
  15.412+    (multiple-value-bind (body declarations) (parse-body body)
  15.413+      (destructuring-bind (then else) body
  15.414+        `(block ,outer
  15.415+           (block ,inner
  15.416+             (let ,(loop :for (symbol value) :in bindings
  15.417+                         :collect `(,symbol (or ,value
  15.418+                                                (return-from ,inner nil))))
  15.419+               ,@declarations
  15.420+               (return-from ,outer ,then)))
  15.421+           ,else)))))
  15.422+
  15.423+(defmacro if-let* (bindings then else)
  15.424+  "Bind `bindings` serially and execute `then` if all are true, or `else` otherwise.
  15.425+
  15.426+  This macro combines `if` and `let*`.  It takes a list of bindings and
  15.427+  binds them like `let*` before executing `then`, but if any binding's
  15.428+  value evaluates to `nil` the process stops and the `else` branch is
  15.429+  immediately executed (with no bindings in effect).
  15.430+
  15.431+  Examples:
  15.432+
  15.433+    (if-let* ((a (progn (print :a) 1))
  15.434+              (b (progn (print :b) (1+ a)))
  15.435+      (list a b)
  15.436+      'nope)
  15.437+    ; =>
  15.438+    :A
  15.439+    :B
  15.440+    (1 2)
  15.441+
  15.442+    (if-let* ((a (progn (print :a) nil))
  15.443+              (b (progn (print :b) (1+ a))))
  15.444+      (list a b)
  15.445+      'nope)
  15.446+    ; =>
  15.447+    :A
  15.448+    NOPE
  15.449+
  15.450+  "
  15.451+  (with-gensyms (outer inner)
  15.452+    `(block ,outer
  15.453+       (block ,inner
  15.454+         (let* ,(loop :for (symbol value) :in bindings
  15.455+                      :collect `(,symbol (or ,value
  15.456+                                             (return-from ,inner nil))))
  15.457+           (return-from ,outer ,then)))
  15.458+       ,else)))
  15.459+
  15.460+
  15.461+(defmacro def! (name &body body)
  15.462+  "`defun' without args."
  15.463+  `(defun ,name () ,@body))
  15.464+
  15.465+(defmacro eval-always (&body body)
  15.466+  `(eval-when (:compile-toplevel :load-toplevel :execute) ,@body))
  15.467+
  15.468+;;; Franz
  15.469+(defvar if*-keyword-list '("then" "thenret" "else" "elseif"))
  15.470+
  15.471+(defmacro if* (&rest args)
  15.472+  (do ((xx (reverse args) (cdr xx))
  15.473+       (state :init)
  15.474+       (elseseen nil)
  15.475+       (totalcol nil)
  15.476+       (lookat nil nil)
  15.477+       (col nil))
  15.478+      ((null xx)
  15.479+       (cond ((eq state :compl)
  15.480+              `(cond ,@totalcol))
  15.481+             (t (error "if*: illegal form ~s" args))))
  15.482+    (cond ((and (symbolp (car xx))
  15.483+                (member (symbol-name (car xx))
  15.484+                        if*-keyword-list
  15.485+                        :test #'string-equal))
  15.486+           (setq lookat (symbol-name (car xx)))))
  15.487+
  15.488+    (cond ((eq state :init)
  15.489+           (cond (lookat (cond ((string-equal lookat "thenret")
  15.490+                                (setq col nil
  15.491+                                      state :then))
  15.492+                               (t (error
  15.493+                                   "if*: bad keyword ~a" lookat))))
  15.494+                 (t (setq state :col
  15.495+                          col nil)
  15.496+                    (push (car xx) col))))
  15.497+          ((eq state :col)
  15.498+           (cond (lookat
  15.499+                  (cond ((string-equal lookat "else")
  15.500+                         (cond (elseseen
  15.501+                                (error
  15.502+                                 "if*: multiples elses")))
  15.503+                         (setq elseseen t)
  15.504+                         (setq state :init)
  15.505+                         (push `(t ,@col) totalcol))
  15.506+                        ((string-equal lookat "then")
  15.507+                         (setq state :then))
  15.508+                        (t (error "if*: bad keyword ~s"
  15.509+                                  lookat))))
  15.510+                 (t (push (car xx) col))))
  15.511+          ((eq state :then)
  15.512+           (cond (lookat
  15.513+                  (error
  15.514+                   "if*: keyword ~s at the wrong place " (car xx)))
  15.515+                 (t (setq state :compl)
  15.516+                    (push `(,(car xx) ,@col) totalcol))))
  15.517+          ((eq state :compl)
  15.518+           (cond ((not (string-equal lookat "elseif"))
  15.519+                  (error "if*: missing elseif clause ")))
  15.520+           (setq state :init)))))
  15.521+
  15.522+(defmacro named-lambda (name lambda-list &body body)
  15.523+  "Expands into a lambda-expression within whose BODY NAME denotes the
  15.524+corresponding function."
  15.525+  `(labels ((,name ,lambda-list ,@body))
  15.526+     #',name))
  15.527+
  15.528+;;; Misc
  15.529+(defmacro until (condition &body body)
  15.530+  (let ((block-name (gensym)))
  15.531+    `(block ,block-name
  15.532+       (loop
  15.533+         (if ,condition
  15.534+             (return-from ,block-name nil)
  15.535+             (progn ,@body))))))
  15.536+
  15.537+(defmacro defmacro/g! (name args &rest body)
  15.538+  (let ((syms (remove-duplicates
  15.539+               (remove-if-not #'g!-symbol-p
  15.540+                              (flatten body)))))
  15.541+    (multiple-value-bind (body declarations docstring)
  15.542+        (parse-body body :documentation t)
  15.543+      `(defmacro ,name ,args
  15.544+         ,@(when docstring
  15.545+             (list docstring))
  15.546+         ,@declarations
  15.547+         (let ,(mapcar
  15.548+                (lambda (s)
  15.549+                  `(,s (gensym ,(subseq
  15.550+                                 (symbol-name s)
  15.551+                                 2))))
  15.552+                syms)
  15.553+           ,@body)))))
  15.554+
  15.555+(defmacro defmacro! (name args &rest body)
  15.556+  (let* ((os (remove-if-not #'o!-symbol-p (flatten args)))
  15.557+         (gs (mapcar #'o!-symbol-to-g!-symbol os)))
  15.558+    (multiple-value-bind (body declarations docstring)
  15.559+        (parse-body body :documentation t)
  15.560+      `(defmacro/g! ,name ,args
  15.561+         ,@(when docstring
  15.562+             (list docstring))
  15.563+         ,@declarations
  15.564+         `(let ,(mapcar #'list (list ,@gs) (list ,@os))
  15.565+            ,(progn ,@body))))))
  15.566+
  15.567+(defmacro defun! (name args &body body)
  15.568+  (let ((syms (remove-duplicates
  15.569+               (remove-if-not #'g!-symbol-p
  15.570+                              (flatten body)))))
  15.571+    (multiple-value-bind (body declarations docstring)
  15.572+        (parse-body body :documentation t)
  15.573+      `(defun ,name ,args
  15.574+         ,@(when docstring
  15.575+             (list docstring))
  15.576+         ,@declarations
  15.577+         (let ,(mapcar (lambda (s)
  15.578+                         `(,s (gensym ,(subseq (symbol-name s)
  15.579+                                               2))))
  15.580+                syms)
  15.581+           ,@body)))))
  15.582+
  15.583+(defmacro! dlambda (&rest ds)
  15.584+  "Dynamic dispatch lambda."
  15.585+  `(lambda (&rest ,g!args)
  15.586+     (case (car ,g!args)
  15.587+       ,@(mapcar
  15.588+          (lambda (d)
  15.589+            `(,(if (eq t (car d))
  15.590+                   t
  15.591+                   (list (car d)))
  15.592+              (apply (lambda ,@(cdr d))
  15.593+                     ,(if (eq t (car d))
  15.594+                          g!args
  15.595+                          `(cdr ,g!args)))))
  15.596+          ds))))
  15.597+
  15.598+;; Graham's alambda
  15.599+(defmacro alambda (parms &body body)
  15.600+  `(labels ((self ,parms ,@body))
  15.601+     #'self))
  15.602+
  15.603+;; Graham's aif
  15.604+(defmacro aif (test then &optional else)
  15.605+  `(let ((it ,test))
  15.606+     (if it ,then ,else)))
  15.607+
  15.608+;; ;; TODO 2023-09-05: wrap, document, optimize, hack
  15.609+;; re-exported from SB-INT
  15.610+(defmacro awhen (test &body body)
  15.611+  `(let ((it ,test))
  15.612+     (when it ,@body)))
  15.613+
  15.614+(defmacro acond (&rest clauses)
  15.615+  (if (null clauses)
  15.616+      `()
  15.617+      (destructuring-bind ((test &body body) &rest rest) clauses
  15.618+        (let ((it (copy-symbol 'it)))
  15.619+          `(let ((,it ,test))
  15.620+             (if ,it
  15.621+                 ;; Just like COND - no body means return the tested value.
  15.622+                 ,(if body
  15.623+                      `(let ((it ,it)) (declare (ignorable it)) ,@body)
  15.624+                      it)
  15.625+                 (acond ,@rest)))))))
  15.626+
  15.627+(defmacro! nlet-tail (n letargs &body body)
  15.628+  (let ((gs (loop for i in letargs
  15.629+                  collect (gensym))))
  15.630+    `(macrolet
  15.631+         ((,n ,gs
  15.632+            `(progn
  15.633+               (psetq
  15.634+                ,@(apply #'nconc
  15.635+                         (mapcar
  15.636+                          #'list
  15.637+                          ',(mapcar #'car letargs)
  15.638+                          (list ,@gs))))
  15.639+               (go ,',g!n))))
  15.640+       (block ,g!b
  15.641+         (let ,letargs
  15.642+           (tagbody
  15.643+              ,g!n (return-from
  15.644+                    ,g!b (progn ,@body))))))))
  15.645+
  15.646+(defmacro alet% (letargs &rest body)
  15.647+  `(let ((this) ,@letargs)
  15.648+     (setq this ,@(last body))
  15.649+     ,@(butlast body)
  15.650+     this))
  15.651+
  15.652+(defmacro alet (letargs &rest body)
  15.653+  `(let ((this) ,@letargs)
  15.654+     (setq this ,@(last body))
  15.655+     ,@(butlast body)
  15.656+     (lambda (&rest params)
  15.657+       (apply this params))))
  15.658+
  15.659+;; swiped from fiveam. This is just like acond except it assumes that
  15.660+;; the TEST in each element of CLAUSES returns two values as opposed
  15.661+;; to one.
  15.662+(defmacro acond2 (&rest clauses)
  15.663+  (if (null clauses)
  15.664+      nil
  15.665+      (with-gensyms (val foundp)
  15.666+        (destructuring-bind ((test &rest progn) &rest others)
  15.667+            clauses
  15.668+          `(multiple-value-bind (,val ,foundp)
  15.669+               ,test
  15.670+             (if (or ,val ,foundp)
  15.671+                 (let ((it ,val))
  15.672+                   (declare (ignorable it))
  15.673+                   ,@progn)
  15.674+                 (acond2 ,@others)))))))
    16.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2+++ b/lisp/std/macs/const.lisp	Mon Apr 22 23:14:47 2024 -0400
    16.3@@ -0,0 +1,46 @@
    16.4+;;; std/macs/const.lisp --- DEFINE-CONSTANT and friends
    16.5+
    16.6+;;
    16.7+
    16.8+;;; Code:
    16.9+(in-package :std/macs)
   16.10+;; (reexport-from :sb-c
   16.11+;; 	       :include '(:define-source-transformation
   16.12+;; 			  :parse-eval-when-situations
   16.13+;; 			  :source-location))
   16.14+;;; Definitions
   16.15+(defun %reevaluate-constant (name value test)
   16.16+  (if (not (boundp name))
   16.17+      value
   16.18+      (let ((old (symbol-value name))
   16.19+            (new value))
   16.20+        (if (not (constantp name))
   16.21+            (prog1 new
   16.22+              (cerror "Try to redefine the variable as a constant."
   16.23+                      "~@<~S is an already bound non-constant variable ~
   16.24+                       whose value is ~S.~:@>" name old))
   16.25+            (if (funcall test old new)
   16.26+                old
   16.27+                (restart-case
   16.28+                    (error "~@<~S is an already defined constant whose value ~
   16.29+                              ~S is not equal to the provided initial value ~S ~
   16.30+                              under ~S.~:@>" name old new test)
   16.31+                  (ignore ()
   16.32+                    :report "Retain the current value."
   16.33+                    old)
   16.34+                  (continue ()
   16.35+                    :report "Try to redefine the constant."
   16.36+                    new)))))))
   16.37+
   16.38+(defmacro define-constant (name initial-value &key (test #'eql) documentation)
   16.39+  "Ensures that the global variable named by NAME is a constant with a value
   16.40+that is equal under TEST to the result of evaluating INITIAL-VALUE. TEST is a
   16.41+/function designator/ that defaults to EQL. If DOCUMENTATION is given, it
   16.42+becomes the documentation string of the constant.
   16.43+
   16.44+Signals an error if NAME is already a bound non-constant variable.
   16.45+
   16.46+Signals an error if NAME is already a constant variable whose value is not
   16.47+equal under TEST to result of evaluating INITIAL-VALUE."
   16.48+  `(defconstant ,name (%reevaluate-constant ',name ,initial-value ,test)
   16.49+     ,@(when documentation `(,documentation))))
    17.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2+++ b/lisp/std/macs/pan.lisp	Mon Apr 22 23:14:47 2024 -0400
    17.3@@ -0,0 +1,84 @@
    17.4+;;; pan.lisp --- Pandoric macros
    17.5+
    17.6+;;; Code:
    17.7+(in-package :std)
    17.8+(in-readtable :std)
    17.9+
   17.10+(defun pandoriclet-get (letargs)
   17.11+  `(case sym
   17.12+     ,@(mapcar #`(((car a1)) (car a1))
   17.13+        letargs)
   17.14+     (t (error
   17.15+         "Unknown pandoric get: ~a"
   17.16+         sym))))
   17.17+
   17.18+(defun pandoriclet-set (letargs)
   17.19+  `(case sym
   17.20+     ,@(mapcar #`(((car a1))
   17.21+                  (setq (car a1) val))
   17.22+        letargs)
   17.23+     (t (error
   17.24+         "Unknown pandoric set: ~a"
   17.25+         sym))))
   17.26+
   17.27+(defmacro pandoriclet (letargs &rest body)
   17.28+  (let ((letargs (cons
   17.29+                  '(this)
   17.30+                  (let-binding-transform
   17.31+                   letargs))))
   17.32+    `(let (,@letargs)
   17.33+       (setq this ,@(last body))
   17.34+       ,@(butlast body)
   17.35+       (dlambda
   17.36+        (:pandoric-get (sym)
   17.37+                       ,(pandoriclet-get letargs))
   17.38+        (:pandoric-set (sym val)
   17.39+                       ,(pandoriclet-set letargs))
   17.40+        (t (&rest args)
   17.41+           (apply this args))))))
   17.42+
   17.43+(declaim (inline get-pandoric))
   17.44+
   17.45+(defun get-pandoric (box sym)
   17.46+  (funcall box :pandoric-get sym))
   17.47+
   17.48+(defsetf get-pandoric (box sym) (val)
   17.49+  `(progn
   17.50+     (funcall ,box :pandoric-set ,sym ,val)
   17.51+     ,val))
   17.52+
   17.53+(defmacro! with-pandoric (syms o!box &rest body)
   17.54+  `(symbol-macrolet
   17.55+       (,@(mapcar #`(a1 (get-pandoric ,g!box a1))
   17.56+                  syms))
   17.57+     ,@body))
   17.58+
   17.59+;; (defun pandoric-hotpatch (box new)
   17.60+;;   (with-pandoric (this) box
   17.61+;;     (setq this new)))
   17.62+
   17.63+(defmacro pandoric-recode (vars box new)
   17.64+  `(with-pandoric (this ,@vars) ,box
   17.65+     (setq this ,new)))
   17.66+
   17.67+(defmacro plambda (largs pargs &rest body)
   17.68+  (let ((pargs (mapcar #'list pargs)))
   17.69+    `(let (this self)
   17.70+       (setq
   17.71+        this (lambda ,largs ,@body)
   17.72+        self (dlambda
   17.73+              (:pandoric-get (sym)
   17.74+                             ,(pandoriclet-get pargs))
   17.75+              (:pandoric-set (sym val)
   17.76+                             ,(pandoriclet-set pargs))
   17.77+              (t (&rest args)
   17.78+                 (apply this args)))))))
   17.79+
   17.80+(defvar pandoric-eval-tunnel)
   17.81+
   17.82+(defmacro pandoric-eval (vars expr)
   17.83+  `(let ((pandoric-eval-tunnel
   17.84+           (plambda () ,vars t)))
   17.85+     (eval `(with-pandoric
   17.86+              ,',vars pandoric-eval-tunnel
   17.87+              ,,expr))))
    18.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2+++ b/lisp/std/mop.lisp	Mon Apr 22 23:14:47 2024 -0400
    18.3@@ -0,0 +1,60 @@
    18.4+;;; std/mop.lisp --- Standard MOP
    18.5+
    18.6+;;
    18.7+
    18.8+;;; Code:
    18.9+(in-package :std/mop)
   18.10+
   18.11+(defun list-indirect-class-methods (class)
   18.12+  "List all indirect methods of CLASS."
   18.13+  (remove-duplicates (mapcan #'specializer-direct-generic-functions (compute-class-precedence-list class))))
   18.14+
   18.15+(defun list-class-methods (class methods &optional indirect)
   18.16+  "List all methods specializing on CLASS modulo METHODS. When INDIRECT is
   18.17+non-nil, also include indirect (parent) methods."
   18.18+  (if (eq methods t)
   18.19+      (if indirect
   18.20+          (list-indirect-class-methods class)
   18.21+          (specializer-direct-generic-functions class))
   18.22+      (mapcar
   18.23+       (lambda (s)
   18.24+         (car (member s (specializer-direct-generic-functions class) :key #'generic-function-name)))
   18.25+       methods)))
   18.26+
   18.27+;; FIX 2023-09-13: need exclude param
   18.28+(defun list-class-slots (class slots &optional exclude)
   18.29+  ;; should probably convert slot-definition-name here
   18.30+  (let ((cs (remove-if
   18.31+             (lambda (s)
   18.32+               (or
   18.33+                (null s)
   18.34+                (member t (mapcar
   18.35+                           (lambda (x)
   18.36+                             (string= (slot-definition-name s) x))
   18.37+                           exclude))))
   18.38+             (class-slots class))))
   18.39+    (if (eq slots t)
   18.40+        cs
   18.41+        (loop for s in slots
   18.42+              with sn = (symb s)
   18.43+              for c in cs
   18.44+              with cn = (symb (slot-definition-name c))
   18.45+              when (eq sn cn)
   18.46+                collect c))))
   18.47+
   18.48+;; TODO 2023-09-09: slot exclusion from dynamic var
   18.49+(defun list-slot-values-using-class (class obj slots &optional nullp unboundp)
   18.50+  (remove-if
   18.51+   #'null
   18.52+   (mapcar
   18.53+    (lambda (s)
   18.54+      (let ((n (slot-definition-name s)))
   18.55+        (let ((ns (make-keyword (symbol-name n))))
   18.56+          (if (slot-boundp-using-class class obj s)
   18.57+              (let ((v (slot-value-using-class class obj s)))
   18.58+                (if nullp
   18.59+                    `(,ns ,v)
   18.60+                    (unless (null v)
   18.61+                      `(,ns ,v))))
   18.62+              (when unboundp (list ns))))))
   18.63+    slots)))
    19.1--- a/lisp/std/named-readtables.lisp	Sun Apr 21 22:38:49 2024 -0400
    19.2+++ b/lisp/std/named-readtables.lisp	Mon Apr 22 23:14:47 2024 -0400
    19.3@@ -12,30 +12,6 @@
    19.4 ;; behavior (using standard) versus your source code (custom).
    19.5 
    19.6 ;;; Code:
    19.7-(uiop:define-package :std/named-readtables
    19.8-  (:use :cl)
    19.9-  (:export
   19.10-   #:defreadtable
   19.11-   #:in-readtable
   19.12-   #:make-readtable
   19.13-   #:merge-readtables-into
   19.14-   #:find-readtable
   19.15-   #:ensure-readtable
   19.16-   #:rename-readtable
   19.17-   #:readtable-name
   19.18-   #:register-readtable
   19.19-   #:unregister-readtable
   19.20-   #:copy-named-readtable
   19.21-   #:list-all-named-readtables
   19.22-   ;; Types
   19.23-   #:named-readtable-designator
   19.24-   ;; Conditions
   19.25-   #:readtable-error
   19.26-   #:reader-macro-conflict
   19.27-   #:readtable-does-already-exist
   19.28-   #:readtable-does-not-exist
   19.29-   #:parse-body))
   19.30-
   19.31 (in-package :std/named-readtables)
   19.32 (pushnew :named-readtables *features*)
   19.33 
    20.1--- a/lisp/std/num/float.lisp	Sun Apr 21 22:38:49 2024 -0400
    20.2+++ b/lisp/std/num/float.lisp	Mon Apr 22 23:14:47 2024 -0400
    20.3@@ -9,7 +9,7 @@
    20.4 ;;;
    20.5 ;;; See http://common-lisp.net/project/ieee-floats/
    20.6 
    20.7-(in-package :std)
    20.8+(in-package :std/num)
    20.9 
   20.10 ;; The following macro may look a bit overcomplicated to the casual
   20.11 ;; reader. The main culprit is the fact that NaN and infinity can be
    21.1--- a/lisp/std/num/parse.lisp	Sun Apr 21 22:38:49 2024 -0400
    21.2+++ b/lisp/std/num/parse.lisp	Mon Apr 22 23:14:47 2024 -0400
    21.3@@ -3,7 +3,7 @@
    21.4 ;;
    21.5 
    21.6 ;;; Code:
    21.7-(in-package :std)
    21.8+(in-package :std/num)
    21.9 
   21.10 (define-condition invalid-number (parse-error)
   21.11   ((value :reader invalid-number-value
    22.1--- a/lisp/std/os.lisp	Sun Apr 21 22:38:49 2024 -0400
    22.2+++ b/lisp/std/os.lisp	Mon Apr 22 23:14:47 2024 -0400
    22.3@@ -3,7 +3,7 @@
    22.4 ;; UNIX only.
    22.5 
    22.6 ;;; Code:
    22.7-(in-package :std)
    22.8+(in-package :std/os)
    22.9 (require 'sb-posix)
   22.10 
   22.11 (defun list-all-users ()
    23.1--- a/lisp/std/pan.lisp	Sun Apr 21 22:38:49 2024 -0400
    23.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3@@ -1,84 +0,0 @@
    23.4-;;; pan.lisp --- Pandoric macros
    23.5-
    23.6-;;; Code:
    23.7-(in-package :std)
    23.8-(in-readtable :std)
    23.9-
   23.10-(defun pandoriclet-get (letargs)
   23.11-  `(case sym
   23.12-     ,@(mapcar #`(((car a1)) (car a1))
   23.13-               letargs)
   23.14-     (t (error
   23.15-          "Unknown pandoric get: ~a"
   23.16-          sym))))
   23.17-
   23.18-(defun pandoriclet-set (letargs)
   23.19-  `(case sym
   23.20-     ,@(mapcar #`(((car a1))
   23.21-                   (setq (car a1) val))
   23.22-               letargs)
   23.23-     (t (error
   23.24-          "Unknown pandoric set: ~a"
   23.25-          sym))))
   23.26-
   23.27-(defmacro pandoriclet (letargs &rest body)
   23.28-  (let ((letargs (cons
   23.29-                   '(this)
   23.30-                   (let-binding-transform
   23.31-                     letargs))))
   23.32-    `(let (,@letargs)
   23.33-       (setq this ,@(last body))
   23.34-       ,@(butlast body)
   23.35-       (dlambda
   23.36-         (:pandoric-get (sym)
   23.37-           ,(pandoriclet-get letargs))
   23.38-         (:pandoric-set (sym val)
   23.39-           ,(pandoriclet-set letargs))
   23.40-         (t (&rest args)
   23.41-           (apply this args))))))
   23.42-
   23.43-(declaim (inline get-pandoric))
   23.44-
   23.45-(defun get-pandoric (box sym)
   23.46-  (funcall box :pandoric-get sym))
   23.47-
   23.48-(defsetf get-pandoric (box sym) (val)
   23.49-  `(progn
   23.50-     (funcall ,box :pandoric-set ,sym ,val)
   23.51-     ,val))
   23.52-
   23.53-(defmacro! with-pandoric (syms o!box &rest body)
   23.54-       `(symbol-macrolet
   23.55-         (,@(mapcar #`(a1 (get-pandoric ,g!box a1))
   23.56-                    syms))
   23.57-         ,@body))
   23.58-
   23.59-;; (defun pandoric-hotpatch (box new)
   23.60-;;   (with-pandoric (this) box
   23.61-;;     (setq this new)))
   23.62-
   23.63-(defmacro pandoric-recode (vars box new)
   23.64-  `(with-pandoric (this ,@vars) ,box
   23.65-     (setq this ,new)))
   23.66-
   23.67-(defmacro plambda (largs pargs &rest body)
   23.68-  (let ((pargs (mapcar #'list pargs)))
   23.69-    `(let (this self)
   23.70-       (setq
   23.71-         this (lambda ,largs ,@body)
   23.72-         self (dlambda
   23.73-                (:pandoric-get (sym)
   23.74-                  ,(pandoriclet-get pargs))
   23.75-                (:pandoric-set (sym val)
   23.76-                  ,(pandoriclet-set pargs))
   23.77-                (t (&rest args)
   23.78-                  (apply this args)))))))
   23.79-
   23.80-(defvar pandoric-eval-tunnel)
   23.81-
   23.82-(defmacro pandoric-eval (vars expr)
   23.83-  `(let ((pandoric-eval-tunnel
   23.84-           (plambda () ,vars t)))
   23.85-     (eval `(with-pandoric
   23.86-              ,',vars pandoric-eval-tunnel
   23.87-              ,,expr))))
    24.1--- a/lisp/std/path.lisp	Sun Apr 21 22:38:49 2024 -0400
    24.2+++ b/lisp/std/path.lisp	Mon Apr 22 23:14:47 2024 -0400
    24.3@@ -3,7 +3,7 @@
    24.4 ;;
    24.5 
    24.6 ;;; Code:
    24.7-(in-package :std)
    24.8+(in-package :std/path)
    24.9 
   24.10 (deftype wild-pathname ()
   24.11   "A pathname with wild components."
    25.1--- a/lisp/std/pkg.lisp	Sun Apr 21 22:38:49 2024 -0400
    25.2+++ b/lisp/std/pkg.lisp	Mon Apr 22 23:14:47 2024 -0400
    25.3@@ -1,17 +1,56 @@
    25.4 (pushnew :std *features*)
    25.5 (pushnew "STD" *modules* :test 'equal)
    25.6-(uiop:define-package :std
    25.7-  (:use :cl :sb-unicode :cl-ppcre :sb-mop :sb-c :sb-thread :sb-alien :sb-gray :sb-concurrency)
    25.8-  (:use-reexport :std/named-readtables)
    25.9-  (:shadowing-import-from :uiop :println)
   25.10-  (:shadowing-import-from
   25.11-   :sb-int 
   25.12-   :ensure-list :recons :memq :assq :ensure-list 
   25.13-   :proper-list-of-length-p :proper-list-p :singleton-p
   25.14-   :with-unique-names :symbolicate :package-symbolicate :keywordicate :gensymify*)
   25.15+
   25.16+(defpackage :std/named-readtables
   25.17+  (:use :cl)
   25.18   (:export
   25.19-   ;; types
   25.20-   ;; err
   25.21+   :defreadtable
   25.22+   :in-readtable
   25.23+   :make-readtable
   25.24+   :merge-readtables-into
   25.25+   :find-readtable
   25.26+   :ensure-readtable
   25.27+   :rename-readtable
   25.28+   :readtable-name
   25.29+   :register-readtable
   25.30+   :unregister-readtable
   25.31+   :copy-named-readtable
   25.32+   :list-all-named-readtables
   25.33+   ;; Types
   25.34+   :named-readtable-designator
   25.35+   ;; Conditions
   25.36+   :readtable-error
   25.37+   :reader-macro-conflict
   25.38+   :readtable-does-already-exist
   25.39+   :readtable-does-not-exist
   25.40+   :parse-body))
   25.41+
   25.42+(defpackage :std/defpkg
   25.43+  (:use :cl)
   25.44+  (:nicknames :pkg)
   25.45+  (:export :defpkg
   25.46+   :find-package* :find-symbol* :symbol-call
   25.47+           :intern* :export* :import* :shadowing-import* 
   25.48+           :shadow* :make-symbol* :unintern*
   25.49+   :symbol-shadowing-p :home-package-p
   25.50+   :symbol-package-name :standard-common-lisp-symbol-p
   25.51+   :reify-package :unreify-package :reify-symbol :unreify-symbol
   25.52+   :nuke-symbol-in-package :nuke-symbol :rehome-symbol
   25.53+           :ensure-package-unused :delete-package*
   25.54+           :package-names :packages-from-names :fresh-package-name 
   25.55+   :rename-package-away :package-definition-form :parse-defpkg-form
   25.56+           :ensure-package))
   25.57+
   25.58+(defpackage :std-user
   25.59+  (:use :cl :std/named-readtables :std/defpkg)
   25.60+  (:shadowing-import-from :std/defpkg :defpkg)
   25.61+  (:export :defpkg :in-readtable))
   25.62+
   25.63+(in-package :std-user)
   25.64+
   25.65+(defpkg :std/err
   25.66+  (:use :cl)
   25.67+  (:export    ;; err
   25.68    :std-error :std-error-message
   25.69    :define-error-reporter
   25.70    :deferror
   25.71@@ -35,7 +74,60 @@
   25.72    :invalid-argument-item
   25.73    :invalid-argument-reason
   25.74    :invalid-argument-p
   25.75-   :unwind-protect-case
   25.76+   :unwind-protect-case))
   25.77+
   25.78+(defpkg :std/sym
   25.79+  (:use :cl)
   25.80+  (:shadowing-import-from :sb-int
   25.81+   :with-unique-names :symbolicate :package-symbolicate :keywordicate :gensymify*
   25.82+   :gensymify)
   25.83+  (:export
   25.84+   :ensure-symbol
   25.85+   :format-symbol
   25.86+   :make-keyword
   25.87+   :make-slot-name
   25.88+   :make-gensym
   25.89+   :make-gensym-list
   25.90+   :with-gensyms
   25.91+   :with-unique-names
   25.92+   :symbolicate
   25.93+   :keywordicate
   25.94+   :gensymify
   25.95+   :gensymify*))
   25.96+
   25.97+(defpkg :std/list
   25.98+  (:use :cl)
   25.99+  (:shadowing-import-from :sb-int 
  25.100+   :ensure-list :recons :memq :assq
  25.101+   :ensure-list :proper-list-of-length-p :proper-list-p :singleton-p)
  25.102+  (:export
  25.103+   :ensure-car
  25.104+   :ensure-cons
  25.105+   :appendf
  25.106+   :nconcf
  25.107+   :unionf
  25.108+   :nunionf
  25.109+   :reversef
  25.110+   :nreversef
  25.111+   :deletef
  25.112+   :flatten
  25.113+   :group
  25.114+   :let-binding-transform
  25.115+   :ensure-list :recons :memq :assq
  25.116+   :circular-list :circular-list-p :circular-tree-p :merge!
  25.117+   :sort!))
  25.118+
  25.119+(defpkg :std/type
  25.120+  (:use :cl)
  25.121+  (:import-from :std/sym :format-symbol)
  25.122+  (:import-from :std/list :ensure-car)
  25.123+  (:export :+default-element-type+
  25.124+   :array-index :array-length
  25.125+   :negative-integer :non-negative-integer :positive-integer))
  25.126+
  25.127+(defpkg :std/num
  25.128+  (:use :cl)
  25.129+  (:export
  25.130    ;; num/parse
  25.131    :parse-number
  25.132    :parse-real-number
  25.133@@ -48,7 +140,12 @@
  25.134    :encode-float32
  25.135    :decode-float32
  25.136    :encode-float64
  25.137-   :decode-float64
  25.138+   :decode-float64))
  25.139+
  25.140+(defpkg :std/stream
  25.141+  (:use :cl)
  25.142+  (:import-from :std/type :non-negative-integer :positive-integer)
  25.143+  (:export
  25.144    ;; stream
  25.145    :copy-stream
  25.146    :wrapped-stream
  25.147@@ -58,66 +155,53 @@
  25.148    :prefixed-character-output-stream
  25.149    :stream-of :char-count-of :line-count-of :col-count-of
  25.150    :prev-col-count-of :col-index-of :write-prefix
  25.151-   :prefix-of
  25.152-   ;; path
  25.153-   #:wild-pathname
  25.154-   #:non-wild-pathname
  25.155-   #:absolute-pathname
  25.156-   #:relative-pathname
  25.157-   #:directory-pathname
  25.158-   #:absolute-directory-pathname
  25.159-   ;; file
  25.160-   #:file-pathname
  25.161-   #:with-open-files
  25.162-   #:write-stream-into-file
  25.163-   #:write-file-into-stream
  25.164-   #:file=
  25.165-   #:file-size
  25.166-   :file-size-in-octets
  25.167-   :+pathsep+
  25.168-   :octet-vector=
  25.169-   :file-date
  25.170-   :file-timestamp
  25.171-   :directory-path-p
  25.172-   :hidden-path-p
  25.173-   :directory-path :find-files
  25.174-   :count-file-lines
  25.175-   ;; string
  25.176-   :*omit-nulls*
  25.177-   :*whitespaces*
  25.178-   :string-designator
  25.179-   :split
  25.180-   :trim
  25.181-   :collapse-whitespaces
  25.182-   :make-template-parser
  25.183-   :string-case
  25.184-   ;; fmt
  25.185-   :printer-status :fmt-row :format-sxhash :iprintln :fmt-tree :println
  25.186-   ;; sym
  25.187-   :ensure-symbol
  25.188-   :format-symbol
  25.189-   :make-keyword
  25.190-   :make-slot-name
  25.191-   :make-gensym
  25.192-   :make-gensym-list
  25.193-   :with-gensyms
  25.194-   :with-unique-names
  25.195-   :symbolicate
  25.196-   ;; list
  25.197-   :ensure-car
  25.198-   :ensure-cons
  25.199-   :appendf
  25.200-   :nconcf
  25.201-   :unionf
  25.202-   :nunionf
  25.203-   :reversef
  25.204-   :nreversef
  25.205-   :deletef
  25.206-   :let-binding-transform
  25.207-   :ensure-list :recons :memq :assq
  25.208-   :circular-list :circular-list-p :circular-tree-p
  25.209-   ;; :proper-list-of-length-p :proper-list-p :singleton-p
  25.210-   ;; thread
  25.211+   :prefix-of))
  25.212+
  25.213+(defpkg :std/fu
  25.214+  (:use :cl)
  25.215+  (:export
  25.216+   :ensure-function
  25.217+   :ensure-functionf
  25.218+   :disjoin
  25.219+   :conjoin
  25.220+   :compose
  25.221+   :multiple-value-compose
  25.222+   :curry
  25.223+   :rcurry))
  25.224+
  25.225+(defpkg :std/array
  25.226+  (:use :cl)
  25.227+  (:export :copy-array :signed-array-length))
  25.228+
  25.229+(defpkg :std/hash-table
  25.230+  (:use :cl)
  25.231+  (:nicknames :std/ht)
  25.232+  (:export :hash-table-alist
  25.233+   :maphash-keys :hash-table-keys
  25.234+   :maphash-values :hash-table-values))
  25.235+
  25.236+(defpkg :std/alien
  25.237+  (:use :cl :sb-alien)
  25.238+  (:import-from :std/sym :symbolicate)
  25.239+  (:export
  25.240+   :shared-object-name
  25.241+   :define-alien-loader
  25.242+   :c-string-to-string-list
  25.243+   :list-all-shared-objects
  25.244+   :num-cpus
  25.245+   :*cpus*
  25.246+   :loff-t
  25.247+   :memset))
  25.248+
  25.249+(defpkg :std/mop
  25.250+  (:use :cl)
  25.251+  (:export :list-slot-values-using-class
  25.252+   :list-class-methods :list-class-slots :list-indirect-slot-methods))
  25.253+   
  25.254+(defpkg :std/thread
  25.255+  (:use :cl :sb-thread :sb-concurrency)
  25.256+  (:import-from :std/list :flatten)
  25.257+  (:export
  25.258    :print-thread-message-top-level :thread-support-p
  25.259    :find-thread-by-id :thread-id-list
  25.260    :make-threads :with-threads :finish-threads
  25.261@@ -135,53 +219,15 @@
  25.262    :job-tasks :make-job :job-p :task-object
  25.263    :make-task :task-p :task :wait-for-threads
  25.264    :task-pool-oracle :task-pool-jobs :task-pool-stages
  25.265-   :task-pool-workers :task-pool-results
  25.266-   ;; util
  25.267-   :find-package* #:find-symbol* #:symbol-call
  25.268-   :intern* #:export* #:import* #:shadowing-import* 
  25.269-   :shadow* #:make-symbol* #:unintern*
  25.270-   :symbol-shadowing-p #:home-package-p
  25.271-   :symbol-package-name #:standard-common-lisp-symbol-p
  25.272-   :reify-package #:unreify-package #:reify-symbol #:unreify-symbol
  25.273-   :nuke-symbol-in-package #:nuke-symbol #:rehome-symbol
  25.274-   :ensure-package-unused #:delete-package*
  25.275-   :package-names #:packages-from-names #:fresh-package-name 
  25.276-   :rename-package-away #:package-definition-form #:parse-defpkg-form
  25.277-   :ensure-package :defpkg
  25.278-   :save-lisp-tree-shake-and-die
  25.279-   :save-lisp-and-live
  25.280-   ;; ana
  25.281-   :awhen
  25.282-   :acond
  25.283-   :alambda
  25.284-   :nlet-tail
  25.285-   :alet%
  25.286-   :alet
  25.287-   :acond2
  25.288-   :it
  25.289-   :aif
  25.290-   :this
  25.291-   :self
  25.292-   ;; pan
  25.293-   :pandoriclet
  25.294-   :pandoriclet-get
  25.295-   :pandoriclet-set
  25.296-   :get-pandoric
  25.297-   :with-pandoric
  25.298-   :pandoric-hotpatch
  25.299-   :pandoric-recode
  25.300-   :plambda
  25.301-   :pandoric-eval
  25.302-   ;; fu
  25.303-   :copy-array
  25.304-   :hash-table-alist
  25.305-   :until
  25.306-   :mkstr
  25.307-   :symb
  25.308-   :group
  25.309-   :flatten
  25.310-   :fact
  25.311-   :choose
  25.312+   :task-pool-workers :task-pool-results))
  25.313+
  25.314+(defpkg :std/macs
  25.315+  (:use :cl)
  25.316+  (:import-from :std/sym :symb :mkstr :make-gensym-list :once-only)
  25.317+  (:import-from :std/named-readtables :in-readtable :parse-body)
  25.318+  (:import-from :std/list :flatten)
  25.319+  (:export
  25.320+   :named-lambda
  25.321    :g!-symbol-p
  25.322    :defmacro/g!
  25.323    :o!-symbol-p
  25.324@@ -189,6 +235,9 @@
  25.325    :defmacro!
  25.326    :defun!
  25.327    :dlambda
  25.328+   :until
  25.329+   :fact
  25.330+   :choose
  25.331    :make-tlist
  25.332    :tlist-left
  25.333    :tlist-right
  25.334@@ -214,38 +263,32 @@
  25.335    :define-constant
  25.336    :def!
  25.337    :eval-always
  25.338-   :merge! :sort!
  25.339-   :list-slot-values-using-class :list-class-methods :list-class-slots :list-indirect-slot-methods
  25.340-   :signed-array-length
  25.341-   :take
  25.342-   :maphash-keys
  25.343-   :hash-table-keys
  25.344-   :maphash-values
  25.345-   :hash-table-values
  25.346-   :current-lisp-implementation
  25.347-   :tmpfile
  25.348-   :ensure-function
  25.349-   :ensure-functionf
  25.350-   :disjoin
  25.351-   :conjoin
  25.352-   :compose
  25.353-   :multiple-value-compose
  25.354-   :curry
  25.355-   :rcurry
  25.356-   :named-lambda
  25.357-   ;; alien
  25.358-   :shared-object-name
  25.359-   :define-alien-loader
  25.360-   :c-string-to-string-list
  25.361-   :list-all-shared-objects
  25.362-   :num-cpus
  25.363-   :*cpus*
  25.364-   :loff-t
  25.365-   :memset
  25.366-   ;; os
  25.367-   :list-all-users
  25.368-   :list-all-groups
  25.369-   ;; bits
  25.370+   ;; ana
  25.371+   :awhen
  25.372+   :acond
  25.373+   :alambda
  25.374+   :nlet-tail
  25.375+   :alet%
  25.376+   :alet
  25.377+   :acond2
  25.378+   :it
  25.379+   :aif
  25.380+   :this
  25.381+   :self
  25.382+   ;; pan
  25.383+   :pandoriclet
  25.384+   :pandoriclet-get
  25.385+   :pandoriclet-set
  25.386+   :get-pandoric
  25.387+   :with-pandoric
  25.388+   :pandoric-hotpatch
  25.389+   :pandoric-recode
  25.390+   :plambda
  25.391+   :pandoric-eval))
  25.392+
  25.393+(defpkg :std/bit
  25.394+  (:use :cl)
  25.395+  (:export
  25.396    :make-bits
  25.397    :sign-bit
  25.398    :different-signs-p
  25.399@@ -262,7 +305,9 @@
  25.400    :clone-strings
  25.401    :clone-octets-to-alien
  25.402    :clone-octets-from-alien
  25.403-   :foreign-int-to-integer :foreign-int-to-bool :bool-to-foreign-int
  25.404+   :foreign-int-to-integer
  25.405+   :foreign-int-to-bool
  25.406+   :bool-to-foreign-int
  25.407    :bitfield
  25.408    :bitfield-slot-name
  25.409    :bitfield-slot-start
  25.410@@ -283,7 +328,81 @@
  25.411    :octet-vector-to-hex-string
  25.412    :octets-to-integer
  25.413    :integer-to-octets
  25.414-   :hexchar-to-int
  25.415+   :hexchar-to-int))
  25.416+
  25.417+(defpkg :std/fmt
  25.418+  (:use :cl)
  25.419+  (:import-from :std/list :group :ensure-cons)
  25.420+  (:shadowing-import-from :uiop :println)
  25.421+  (:export :printer-status :fmt-row :format-sxhash :iprintln :fmt-tree :println))
  25.422+
  25.423+(defpkg :std/path
  25.424+  (:use :cl)
  25.425+  (:export
  25.426+   :wild-pathname
  25.427+   :non-wild-pathname
  25.428+   :absolute-pathname
  25.429+   :relative-pathname
  25.430+   :directory-pathname
  25.431+   :absolute-directory-pathname))
  25.432+
  25.433+(defpkg :std/os
  25.434+  (:use :cl)
  25.435+  (:export
  25.436+   :list-all-users
  25.437+   :list-all-groups))
  25.438+
  25.439+(defpkg :std/file
  25.440+  (:use :cl)
  25.441+  (:export
  25.442+   :tmpfile
  25.443+   :file-pathname
  25.444+   :with-open-files
  25.445+   :write-stream-into-file
  25.446+   :write-file-into-stream
  25.447+   :file=
  25.448+   :file-size
  25.449+   :file-size-in-octets
  25.450+   :+pathsep+
  25.451+   :octet-vector=
  25.452+   :file-date
  25.453+   :file-timestamp
  25.454+   :directory-path-p
  25.455+   :hidden-path-p
  25.456+   :directory-path
  25.457+   :find-files
  25.458+   :count-file-lines))
  25.459+
  25.460+(defpkg :std/string
  25.461+  (:use :cl)
  25.462+  (:export
  25.463+   :*omit-nulls*
  25.464+   :*whitespaces*
  25.465+   :string-designator
  25.466+   :ssplit
  25.467+   :trim
  25.468+   :collapse-whitespaces
  25.469+   :make-template-parser
  25.470+   :string-case))
  25.471+
  25.472+(defpkg :std/seq
  25.473+  (:use :cl)
  25.474+  (:import-from :std/array :signed-array-length)
  25.475+  (:export :take))
  25.476+
  25.477+(defpkg :std/sys
  25.478+  (:use :cl)
  25.479+  (:export
  25.480+   :current-lisp-implementation
  25.481+   :save-lisp-tree-shake-and-die
  25.482+   :save-lisp-and-live))
  25.483+
  25.484+(defpkg :std/readtable
  25.485+  (:use :cl)
  25.486+  (:import-from :std/named-readtables :defreadtable)
  25.487+  (:import-from :std/sym :symb)
  25.488+  (:import-from :std/macs :defmacro!)
  25.489+  (:export
  25.490    ;; readtable
  25.491    :|#"-reader|
  25.492    :|#`-reader|
  25.493@@ -295,5 +414,8 @@
  25.494    :|#~-reader|
  25.495    :_))
  25.496 
  25.497-(defpackage :std-user
  25.498-  (:use :cl :cl-user :std))
  25.499+(defpkg :std
  25.500+  (:use :cl :sb-unicode :cl-ppcre :sb-mop :sb-c :sb-thread :sb-alien :sb-gray :sb-concurrency)
  25.501+  (:use-reexport :std/named-readtables :std/defpkg :std/err :std/sym :std/list :std/type :std/num
  25.502+   :std/stream :std/fu :std/array :std/hash-table :std/alien :std/mop :std/thread
  25.503+   :std/macs :std/bit :std/fmt :std/path :std/os :std/file :std/string :std/seq :std/sys :std/readtable))
    26.1--- a/lisp/std/readtable.lisp	Sun Apr 21 22:38:49 2024 -0400
    26.2+++ b/lisp/std/readtable.lisp	Mon Apr 22 23:14:47 2024 -0400
    26.3@@ -6,7 +6,7 @@
    26.4 ;;; Usage: (in-readtable :std)
    26.5 
    26.6 ;;; Code:
    26.7-(in-package :std)
    26.8+(in-package :std/readtable)
    26.9 
   26.10 (eval-when (:compile-toplevel :execute :load-toplevel)
   26.11   (defun |#`-reader| (stream sub-char numarg)
    27.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2+++ b/lisp/std/seq.lisp	Mon Apr 22 23:14:47 2024 -0400
    27.3@@ -0,0 +1,24 @@
    27.4+;;; std/seq.lisp --- Standard Sequences
    27.5+
    27.6+;;
    27.7+
    27.8+;;; Code:
    27.9+(in-package :std/seq)
   27.10+
   27.11+(defun take (n seq)
   27.12+  "Return, at most, the first N elements of SEQ, as a *new* sequence
   27.13+of the same type as SEQ.
   27.14+
   27.15+If N is longer than SEQ, SEQ is simply copied.
   27.16+
   27.17+If N is negative, then |N| elements are taken (in their original
   27.18+order) from the end of SEQ."
   27.19+  #+sbcl (declare (sb-ext:muffle-conditions style-warning))
   27.20+  (declare (type signed-array-length n))
   27.21+  (seq-dispatch seq
   27.22+    (if (minusp n)
   27.23+        (last seq (abs n))
   27.24+        (firstn n seq))
   27.25+    (if (minusp n)
   27.26+        (subseq seq (max 0 (+ (length seq) n)))
   27.27+        (subseq seq 0 (min n (length seq))))))
    28.1--- a/lisp/std/std.asd	Sun Apr 21 22:38:49 2024 -0400
    28.2+++ b/lisp/std/std.asd	Mon Apr 22 23:14:47 2024 -0400
    28.3@@ -1,7 +1,7 @@
    28.4 ;;; std.asd --- standard library
    28.5 (defsystem :std/named-readtables
    28.6   :version "0.1.0"
    28.7-  :components ((:file "named-readtables"))
    28.8+  :components ((:file "pkg") (:file "named-readtables"))
    28.9   :in-order-to ((test-op (test-op "std/tests"))))
   28.10 
   28.11 (register-system-packages "std/named-readtables" '(:std))
   28.12@@ -11,27 +11,38 @@
   28.13   :depends-on (:std/named-readtables :cl-ppcre :sb-concurrency)
   28.14   :serial t
   28.15   :components ((:file "pkg")
   28.16+               (:file "defpkg")
   28.17                (:file "err")
   28.18-               (:file "bits")
   28.19-               (:module "num"
   28.20-                :components ((:file "float")
   28.21-                             (:file "parse")))
   28.22-               (:file "string")
   28.23-               (:file "fmt")
   28.24                (:file "sym")
   28.25                (:file "list")
   28.26-               (:file "util")
   28.27-               (:file "readtable")
   28.28-               (:file "ana")
   28.29-               (:file "pan")
   28.30-               (:file "fu")
   28.31-               (:file "types")
   28.32+               (:file "type")
   28.33+               (:module "num"
   28.34+                :components
   28.35+                ((:file "float")
   28.36+                 (:file "parse")))
   28.37+               (:file "stream")
   28.38+               (:module "fu"
   28.39+                :components
   28.40+                ((:file "curry")))
   28.41+               (:file "array")
   28.42+               (:file "hash-table")
   28.43+               (:file "alien")
   28.44+               (:file "mop")
   28.45+               (:file "thread")
   28.46+               (:module "macs"
   28.47+                :components
   28.48+                ((:file "ana")
   28.49+                 (:file "pan")
   28.50+                 (:file "const")))
   28.51+               (:file "bit")
   28.52+               (:file "fmt")
   28.53                (:file "path")
   28.54-               (:file "stream")
   28.55+               (:file "os")
   28.56                (:file "file")
   28.57-               (:file "thread")
   28.58-               (:file "defpkg")               
   28.59-               (:file "alien"))
   28.60+               (:file "string")
   28.61+               (:file "seq")
   28.62+               (:file "sys")
   28.63+               (:file "readtable"))
   28.64   :in-order-to ((test-op (test-op "std/tests"))))
   28.65 
   28.66 (register-system-packages "std" '(:std))
    29.1--- a/lisp/std/stream.lisp	Sun Apr 21 22:38:49 2024 -0400
    29.2+++ b/lisp/std/stream.lisp	Mon Apr 22 23:14:47 2024 -0400
    29.3@@ -3,7 +3,7 @@
    29.4 ;;
    29.5 
    29.6 ;;; Code:
    29.7-(in-package :std)
    29.8+(in-package :std/stream)
    29.9 
   29.10 (defun copy-stream (input output &key (element-type (stream-element-type input))
   29.11                     (buffer-size 4096)
    30.1--- a/lisp/std/string.lisp	Sun Apr 21 22:38:49 2024 -0400
    30.2+++ b/lisp/std/string.lisp	Mon Apr 22 23:14:47 2024 -0400
    30.3@@ -13,7 +13,7 @@
    30.4 ;;     decimal-value digit-value
    30.5 ;;     unicode< unicode> unicode= unicode-equal
    30.6 ;;     unicode<= unicode>=))
    30.7-(in-package :std)
    30.8+(in-package :std/string)
    30.9 
   30.10 ;; (mapc (lambda (s) (export s)) sb-unicode-syms)
   30.11 ;; (reexport-from 
    31.1--- a/lisp/std/sym.lisp	Sun Apr 21 22:38:49 2024 -0400
    31.2+++ b/lisp/std/sym.lisp	Mon Apr 22 23:14:47 2024 -0400
    31.3@@ -3,7 +3,7 @@
    31.4 ;; inspired by alexandria/symbols.lisp
    31.5 
    31.6 ;;; Code:
    31.7-(in-package :std)
    31.8+(in-package :std/sym)
    31.9 
   31.10 ;;(std::reexport-from 
   31.11 ;; :sb-int
   31.12@@ -12,7 +12,8 @@
   31.13 ;; On SBCL, `with-unique-names' is defined under
   31.14 ;; src/code/primordial-extensions.lisp. We use that instead of
   31.15 ;; defining our own.
   31.16-(setf (macro-function 'with-gensyms) (macro-function 'with-unique-names))
   31.17+(eval-when (:compile-toplevel :load-toplevel :execute)
   31.18+  (setf (macro-function 'with-gensyms) (macro-function 'with-unique-names)))
   31.19 
   31.20 (declaim (inline ensure-symbol))
   31.21 (defun ensure-symbol (name &optional (package *package*))
   31.22@@ -69,26 +70,6 @@
   31.23 (defun symb (&rest args)
   31.24   (values (intern (apply #'mkstr args))))
   31.25 
   31.26-(defun g!-symbol-p (s)
   31.27-  (and (symbolp s)
   31.28-       (> (length (symbol-name s)) 2)
   31.29-       (string= (symbol-name s)
   31.30-                "G!"
   31.31-                :start1 0
   31.32-                :end1 2)))
   31.33-
   31.34-(defun o!-symbol-p (s)
   31.35-  (and (symbolp s)
   31.36-       (> (length (symbol-name s)) 2)
   31.37-       (string= (symbol-name s)
   31.38-                "O!"
   31.39-                :start1 0
   31.40-                :end1 2)))
   31.41-
   31.42-(defun o!-symbol-to-g!-symbol (s)
   31.43-  (symb "G!"
   31.44-        (subseq (symbol-name s) 2)))
   31.45-
   31.46 (sb-ext:with-unlocked-packages (:sb-int)
   31.47   (handler-bind
   31.48       ((sb-kernel:redefinition-warning #'muffle-warning))
    32.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2+++ b/lisp/std/sys.lisp	Mon Apr 22 23:14:47 2024 -0400
    32.3@@ -0,0 +1,56 @@
    32.4+;;; std/sys.lisp @ 2023-10-14.03:28:40 -*- mode: lisp; -*-
    32.5+
    32.6+;;
    32.7+
    32.8+;;; Code:
    32.9+(in-package :std/sys)
   32.10+
   32.11+;;; Introspection
   32.12+;; (reexport-from :sb-introspect
   32.13+;; 	       :include '(:function-lambda-list :lambda-list-keywords :lambda-parameters-limit
   32.14+;; 			  :method-combination-lambda-list :deftype-lambda-list
   32.15+;; 			  :primitive-object-size :allocation-information
   32.16+;; 			  :function-type
   32.17+;; 			  :who-specializes-directly :who-specializes-generally
   32.18+;; 			  :find-function-callees :find-function-callers))
   32.19+
   32.20+(defun current-lisp-implementation ()
   32.21+  "Return the current lisp implemenation as a cons: (TYPE VERSION)"
   32.22+  (list 
   32.23+   (lisp-implementation-type) 
   32.24+   (lisp-implementation-version)
   32.25+   *features*))
   32.26+
   32.27+;; TODO
   32.28+(defun save-lisp-tree-shake-and-die (path &rest args)
   32.29+  "A naive tree-shaker for lisp."
   32.30+  (sb-ext:gc :full t)
   32.31+  (apply #'sb-ext:save-lisp-and-die path args))
   32.32+
   32.33+(defun save-lisp-and-live (filename completion-function restart &rest args)
   32.34+  (flet ((restart-sbcl ()
   32.35+           (sb-debug::enable-debugger)
   32.36+           (setf sb-impl::*descriptor-handlers* nil)
   32.37+           (funcall restart)))
   32.38+    ;; fork it - assumes only one thread is running
   32.39+    (multiple-value-bind (pipe-in pipe-out) (sb-posix:pipe)
   32.40+      (let ((pid (sb-posix:fork)))
   32.41+        (cond ((= pid 0) ;; make simple-restart core
   32.42+               (sb-posix:close pipe-in)
   32.43+               (sb-debug::disable-debugger)
   32.44+               (apply #'sb-ext:save-lisp-and-die filename
   32.45+                      (append
   32.46+                       (list :toplevel #'restart-sbcl)
   32.47+                       args)))
   32.48+              (t
   32.49+               (sb-posix:close pipe-out)
   32.50+               (sb-sys:add-fd-handler
   32.51+                pipe-in :input
   32.52+                (lambda (fd)
   32.53+                  (sb-sys:invalidate-descriptor fd)
   32.54+                  (sb-posix:close fd)
   32.55+                  (multiple-value-bind (rpid status) (sb-posix:waitpid pid 0) ;; wait for master
   32.56+                    (assert (= pid rpid))
   32.57+                    (assert (sb-posix:wifexited status))
   32.58+                    (funcall completion-function
   32.59+                             (zerop (sb-posix:wexitstatus status))))))))))))
    33.1--- a/lisp/std/thread.lisp	Sun Apr 21 22:38:49 2024 -0400
    33.2+++ b/lisp/std/thread.lisp	Mon Apr 22 23:14:47 2024 -0400
    33.3@@ -7,7 +7,7 @@
    33.4 ;; mostly yoinked from sb-thread and friends
    33.5 
    33.6 ;;; Code:
    33.7-(in-package :std)
    33.8+(in-package :std/thread)
    33.9 
   33.10 ;; (sb-thread:thread-os-tid sb-thread:*current-thread*)
   33.11 ;; sb-thread:interrupt-thread
   33.12@@ -203,26 +203,41 @@
   33.13     (declare (ignore pool))
   33.14     (make-threads count function :name *default-worker-name*)))
   33.15 
   33.16-(defmacro define-task-kernel (name (&rest opts) &body body)
   33.17-  "Define a kernel function for tasks."
   33.18-  `(defun ,name (,@opts) 
   33.19+(defmacro define-task-kernel (name (&key args accessors) &body body)
   33.20+  "Define a task kernel.
   33.21+
   33.22+(define-task-kernel NAME (&key ARGS MAX MIN ACCESSORS)
   33.23+
   33.24+The kernel should process all options and return a function - the
   33.25+'kernel function'.
   33.26+
   33.27+The kernel function is installed in worker threads by passing it to
   33.28+SB-THREAD:MAKE-THREAD. It may accept a varying number of arguments
   33.29+specified by ARGS.
   33.30+
   33.31+ACCESSORS is a list of pandoric accessors which can be called on the
   33.32+kernel via an ORACLE. 
   33.33+
   33.34+This interface is experimental and subject to change."
   33.35+  `(defun ,name (,@args) 
   33.36      ,@body))
   33.37 
   33.38-(define-task-kernel default-task-kernel ()
   33.39+(define-task-kernel default-task-kernel (:args () )
   33.40   "The default task kernel used to initialize the KERNEL slot of
   33.41-task-pools. Currently, the kernel is used to initialize every worker
   33.42-in the pool when it is spawned starts running immediately."
   33.43+task-pools.
   33.44+
   33.45+"
   33.46   nil)
   33.47 
   33.48 (defgeneric spawn-worker (pool)
   33.49   (:method ((pool null))
   33.50     (declare (ignore pool))
   33.51-    (make-thread *default-task-kernel*)))
   33.52+    (make-thread (default-task-kernel))))
   33.53 
   33.54 (defgeneric spawn-workers (pool count)
   33.55   (:method ((pool null) (count fixnum))
   33.56     (declare (ignore pool))
   33.57-    (make-threads count *default-task-kernel* :name *default-worker-name*)))
   33.58+    (make-threads count (default-task-kernel) :name *default-worker-name*)))
   33.59 
   33.60 (defstruct task-pool
   33.61   (oracle-id nil :type (or null (unsigned-byte 32)))
   33.62@@ -325,7 +340,7 @@
   33.63 
   33.64 ;; TODO..
   33.65 (defmethod run-job ((self task-pool) (job job))
   33.66-  (log:trace! "running remote job...")
   33.67+  #+log (log:trace! "running remote job...")
   33.68   (push-job job self))
   33.69 
   33.70 (defclass stage ()
    34.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2+++ b/lisp/std/type.lisp	Mon Apr 22 23:14:47 2024 -0400
    34.3@@ -0,0 +1,157 @@
    34.4+;;; std/types.lisp --- Standard Types
    34.5+
    34.6+;;
    34.7+
    34.8+;;; Code:
    34.9+(in-package :std/type)
   34.10+
   34.11+(defconstant +default-element-type+ 'character)
   34.12+
   34.13+(deftype array-index (&optional (length (1- array-dimension-limit)))
   34.14+  "Type designator for an index into array of LENGTH: an integer between
   34.15+0 (inclusive) and LENGTH (exclusive). LENGTH defaults to one less than
   34.16+ARRAY-DIMENSION-LIMIT."
   34.17+  `(integer 0 (,length)))
   34.18+
   34.19+(deftype array-length (&optional (length (1- array-dimension-limit)))
   34.20+  "Type designator for a dimension of an array of LENGTH: an integer between
   34.21+0 (inclusive) and LENGTH (inclusive). LENGTH defaults to one less than
   34.22+ARRAY-DIMENSION-LIMIT."
   34.23+  `(integer 0 ,length))
   34.24+
   34.25+;; This MACROLET will generate most of CDR5 (http://cdr.eurolisp.org/document/5/)
   34.26+;; except the RATIO related definitions and ARRAY-INDEX.
   34.27+(macrolet
   34.28+    ((frob (type &optional (base-type type))
   34.29+       (let ((subtype-names (list))
   34.30+             (predicate-names (list)))
   34.31+         (flet ((make-subtype-name (format-control)
   34.32+                  (let ((result (format-symbol :std format-control
   34.33+                                               (symbol-name type))))
   34.34+                    (push result subtype-names)
   34.35+                    result))
   34.36+                (make-predicate-name (sybtype-name)
   34.37+                  (let ((result (format-symbol :std '#:~A-p
   34.38+                                               (symbol-name sybtype-name))))
   34.39+                    (push result predicate-names)
   34.40+                    result))
   34.41+                (make-docstring (range-beg range-end range-type)
   34.42+                  (let ((inf (ecase range-type (:negative "-inf") (:positive "+inf"))))
   34.43+                    (format nil "Type specifier denoting the ~(~A~) range from ~A to ~A."
   34.44+                            type
   34.45+                            (if (equal range-beg ''*) inf (ensure-car range-beg))
   34.46+                            (if (equal range-end ''*) inf (ensure-car range-end))))))
   34.47+           (let* ((negative-name     (make-subtype-name '#:negative-~a))
   34.48+                  (non-positive-name (make-subtype-name '#:non-positive-~a))
   34.49+                  (non-negative-name (make-subtype-name '#:non-negative-~a))
   34.50+                  (positive-name     (make-subtype-name '#:positive-~a))
   34.51+                  (negative-p-name     (make-predicate-name negative-name))
   34.52+                  (non-positive-p-name (make-predicate-name non-positive-name))
   34.53+                  (non-negative-p-name (make-predicate-name non-negative-name))
   34.54+                  (positive-p-name     (make-predicate-name positive-name))
   34.55+                  (negative-extremum)
   34.56+                  (positive-extremum)
   34.57+                  (below-zero)
   34.58+                  (above-zero)
   34.59+                  (zero))
   34.60+             (setf (values negative-extremum below-zero
   34.61+                           above-zero positive-extremum zero)
   34.62+                   (ecase type
   34.63+                     (fixnum       (values 'most-negative-fixnum -1 1 'most-positive-fixnum 0))
   34.64+                     (integer      (values ''* -1       1        ''* 0))
   34.65+                     (rational     (values ''* '(0)     '(0)     ''* 0))
   34.66+                     (real         (values ''* '(0)     '(0)     ''* 0))
   34.67+                     (float        (values ''* '(0.0E0) '(0.0E0) ''* 0.0E0))
   34.68+                     (short-float  (values ''* '(0.0S0) '(0.0S0) ''* 0.0S0))
   34.69+                     (single-float (values ''* '(0.0F0) '(0.0F0) ''* 0.0F0))
   34.70+                     (double-float (values ''* '(0.0D0) '(0.0D0) ''* 0.0D0))
   34.71+                     (long-float   (values ''* '(0.0L0) '(0.0L0) ''* 0.0L0))))
   34.72+             `(progn
   34.73+                (deftype ,negative-name ()
   34.74+                  ,(make-docstring negative-extremum below-zero :negative)
   34.75+                  `(,',base-type ,,negative-extremum ,',below-zero))
   34.76+
   34.77+                (deftype ,non-positive-name ()
   34.78+                  ,(make-docstring negative-extremum zero :negative)
   34.79+                  `(,',base-type ,,negative-extremum ,',zero))
   34.80+
   34.81+                (deftype ,non-negative-name ()
   34.82+                  ,(make-docstring zero positive-extremum :positive)
   34.83+                  `(,',base-type ,',zero ,,positive-extremum))
   34.84+
   34.85+                (deftype ,positive-name ()
   34.86+                  ,(make-docstring above-zero positive-extremum :positive)
   34.87+                  `(,',base-type ,',above-zero ,,positive-extremum))
   34.88+
   34.89+                (declaim (inline ,@predicate-names))
   34.90+
   34.91+                (defun ,negative-p-name (n)
   34.92+                  (and (typep n ',type)
   34.93+                       (< n ,zero)))
   34.94+
   34.95+                (defun ,non-positive-p-name (n)
   34.96+                  (and (typep n ',type)
   34.97+                       (<= n ,zero)))
   34.98+
   34.99+                (defun ,non-negative-p-name (n)
  34.100+                  (and (typep n ',type)
  34.101+                       (<= ,zero n)))
  34.102+
  34.103+                (defun ,positive-p-name (n)
  34.104+                  (and (typep n ',type)
  34.105+                       (< ,zero n)))))))))
  34.106+  (frob fixnum integer)
  34.107+  (frob integer)
  34.108+  (frob rational)
  34.109+  (frob real)
  34.110+  (frob float)
  34.111+  (frob short-float)
  34.112+  (frob single-float)
  34.113+  (frob double-float)
  34.114+  (frob long-float))
  34.115+
  34.116+(defun of-type (type)
  34.117+  "Returns a function of one argument, which returns true when its argument is
  34.118+of TYPE."
  34.119+  (lambda (thing) (typep thing type)))
  34.120+
  34.121+(define-compiler-macro of-type (&whole form type &environment env)
  34.122+  ;; This can yeild a big benefit, but no point inlining the function
  34.123+  ;; all over the place if TYPE is not constant.
  34.124+  (if (constantp type env)
  34.125+      (with-gensyms (thing)
  34.126+        `(lambda (,thing)
  34.127+           (typep ,thing ,type)))
  34.128+      form))
  34.129+
  34.130+(declaim (inline type=))
  34.131+(defun type= (type1 type2)
  34.132+  "Returns a primary value of T if TYPE1 and TYPE2 are the same type,
  34.133+and a secondary value that is true is the type equality could be reliably
  34.134+determined: primary value of NIL and secondary value of T indicates that the
  34.135+types are not equivalent."
  34.136+  (multiple-value-bind (sub ok) (subtypep type1 type2)
  34.137+    (cond ((and ok sub) ; type1 is known to be a subtype of type 2
  34.138+           ; so type= return values come from the second invocation of subtypep
  34.139+           (subtypep type2 type1))
  34.140+          ;; type1 is assuredly NOT a subtype of type2,
  34.141+          ;; so assuredly type1 and type2 cannot be type=
  34.142+          (ok
  34.143+           (values nil t))
  34.144+          ;; our first result is uncertain ( ok == nil ) and it follows
  34.145+          ;; from specification of SUBTYPEP that sub = ok = NIL
  34.146+          (t
  34.147+           (assert (not sub))           ; is the implementation correct?
  34.148+           (multiple-value-bind (sub2 ok2)
  34.149+               (subtypep type2 type1)
  34.150+             (if  (and (not sub2) ok2)  ; we KNOW type2 is not a subtype of type1
  34.151+                  ;; so our results are certain...
  34.152+                  (values nil t)
  34.153+                  ;; otherwise, either type2 is surely a subtype of type1 (t t)
  34.154+                  ;; or type2 is not a subtype of type1, but we don't
  34.155+                  ;; know that for sure (nil nil)
  34.156+                  ;; In either case our result is negative but unsure
  34.157+                  (values nil nil)))))))
  34.158+
  34.159+(define-modify-macro coercef (type-spec) coerce
  34.160+  "Modify-macro for COERCE.")
    35.1--- a/lisp/std/types.lisp	Sun Apr 21 22:38:49 2024 -0400
    35.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3@@ -1,157 +0,0 @@
    35.4-;;; std/types.lisp --- Standard Types
    35.5-
    35.6-;;
    35.7-
    35.8-;;; Code:
    35.9-(in-package :std)
   35.10-
   35.11-(defconstant +default-element-type+ 'character)
   35.12-
   35.13-(deftype array-index (&optional (length (1- array-dimension-limit)))
   35.14-  "Type designator for an index into array of LENGTH: an integer between
   35.15-0 (inclusive) and LENGTH (exclusive). LENGTH defaults to one less than
   35.16-ARRAY-DIMENSION-LIMIT."
   35.17-  `(integer 0 (,length)))
   35.18-
   35.19-(deftype array-length (&optional (length (1- array-dimension-limit)))
   35.20-  "Type designator for a dimension of an array of LENGTH: an integer between
   35.21-0 (inclusive) and LENGTH (inclusive). LENGTH defaults to one less than
   35.22-ARRAY-DIMENSION-LIMIT."
   35.23-  `(integer 0 ,length))
   35.24-
   35.25-;; This MACROLET will generate most of CDR5 (http://cdr.eurolisp.org/document/5/)
   35.26-;; except the RATIO related definitions and ARRAY-INDEX.
   35.27-(macrolet
   35.28-    ((frob (type &optional (base-type type))
   35.29-       (let ((subtype-names (list))
   35.30-             (predicate-names (list)))
   35.31-         (flet ((make-subtype-name (format-control)
   35.32-                  (let ((result (format-symbol :std format-control
   35.33-                                               (symbol-name type))))
   35.34-                    (push result subtype-names)
   35.35-                    result))
   35.36-                (make-predicate-name (sybtype-name)
   35.37-                  (let ((result (format-symbol :std '#:~A-p
   35.38-                                               (symbol-name sybtype-name))))
   35.39-                    (push result predicate-names)
   35.40-                    result))
   35.41-                (make-docstring (range-beg range-end range-type)
   35.42-                  (let ((inf (ecase range-type (:negative "-inf") (:positive "+inf"))))
   35.43-                    (format nil "Type specifier denoting the ~(~A~) range from ~A to ~A."
   35.44-                            type
   35.45-                            (if (equal range-beg ''*) inf (ensure-car range-beg))
   35.46-                            (if (equal range-end ''*) inf (ensure-car range-end))))))
   35.47-           (let* ((negative-name     (make-subtype-name '#:negative-~a))
   35.48-                  (non-positive-name (make-subtype-name '#:non-positive-~a))
   35.49-                  (non-negative-name (make-subtype-name '#:non-negative-~a))
   35.50-                  (positive-name     (make-subtype-name '#:positive-~a))
   35.51-                  (negative-p-name     (make-predicate-name negative-name))
   35.52-                  (non-positive-p-name (make-predicate-name non-positive-name))
   35.53-                  (non-negative-p-name (make-predicate-name non-negative-name))
   35.54-                  (positive-p-name     (make-predicate-name positive-name))
   35.55-                  (negative-extremum)
   35.56-                  (positive-extremum)
   35.57-                  (below-zero)
   35.58-                  (above-zero)
   35.59-                  (zero))
   35.60-             (setf (values negative-extremum below-zero
   35.61-                           above-zero positive-extremum zero)
   35.62-                   (ecase type
   35.63-                     (fixnum       (values 'most-negative-fixnum -1 1 'most-positive-fixnum 0))
   35.64-                     (integer      (values ''* -1       1        ''* 0))
   35.65-                     (rational     (values ''* '(0)     '(0)     ''* 0))
   35.66-                     (real         (values ''* '(0)     '(0)     ''* 0))
   35.67-                     (float        (values ''* '(0.0E0) '(0.0E0) ''* 0.0E0))
   35.68-                     (short-float  (values ''* '(0.0S0) '(0.0S0) ''* 0.0S0))
   35.69-                     (single-float (values ''* '(0.0F0) '(0.0F0) ''* 0.0F0))
   35.70-                     (double-float (values ''* '(0.0D0) '(0.0D0) ''* 0.0D0))
   35.71-                     (long-float   (values ''* '(0.0L0) '(0.0L0) ''* 0.0L0))))
   35.72-             `(progn
   35.73-                (deftype ,negative-name ()
   35.74-                  ,(make-docstring negative-extremum below-zero :negative)
   35.75-                  `(,',base-type ,,negative-extremum ,',below-zero))
   35.76-
   35.77-                (deftype ,non-positive-name ()
   35.78-                  ,(make-docstring negative-extremum zero :negative)
   35.79-                  `(,',base-type ,,negative-extremum ,',zero))
   35.80-
   35.81-                (deftype ,non-negative-name ()
   35.82-                  ,(make-docstring zero positive-extremum :positive)
   35.83-                  `(,',base-type ,',zero ,,positive-extremum))
   35.84-
   35.85-                (deftype ,positive-name ()
   35.86-                  ,(make-docstring above-zero positive-extremum :positive)
   35.87-                  `(,',base-type ,',above-zero ,,positive-extremum))
   35.88-
   35.89-                (declaim (inline ,@predicate-names))
   35.90-
   35.91-                (defun ,negative-p-name (n)
   35.92-                  (and (typep n ',type)
   35.93-                       (< n ,zero)))
   35.94-
   35.95-                (defun ,non-positive-p-name (n)
   35.96-                  (and (typep n ',type)
   35.97-                       (<= n ,zero)))
   35.98-
   35.99-                (defun ,non-negative-p-name (n)
  35.100-                  (and (typep n ',type)
  35.101-                       (<= ,zero n)))
  35.102-
  35.103-                (defun ,positive-p-name (n)
  35.104-                  (and (typep n ',type)
  35.105-                       (< ,zero n)))))))))
  35.106-  (frob fixnum integer)
  35.107-  (frob integer)
  35.108-  (frob rational)
  35.109-  (frob real)
  35.110-  (frob float)
  35.111-  (frob short-float)
  35.112-  (frob single-float)
  35.113-  (frob double-float)
  35.114-  (frob long-float))
  35.115-
  35.116-(defun of-type (type)
  35.117-  "Returns a function of one argument, which returns true when its argument is
  35.118-of TYPE."
  35.119-  (lambda (thing) (typep thing type)))
  35.120-
  35.121-(define-compiler-macro of-type (&whole form type &environment env)
  35.122-  ;; This can yeild a big benefit, but no point inlining the function
  35.123-  ;; all over the place if TYPE is not constant.
  35.124-  (if (constantp type env)
  35.125-      (with-gensyms (thing)
  35.126-        `(lambda (,thing)
  35.127-           (typep ,thing ,type)))
  35.128-      form))
  35.129-
  35.130-(declaim (inline type=))
  35.131-(defun type= (type1 type2)
  35.132-  "Returns a primary value of T if TYPE1 and TYPE2 are the same type,
  35.133-and a secondary value that is true is the type equality could be reliably
  35.134-determined: primary value of NIL and secondary value of T indicates that the
  35.135-types are not equivalent."
  35.136-  (multiple-value-bind (sub ok) (subtypep type1 type2)
  35.137-    (cond ((and ok sub) ; type1 is known to be a subtype of type 2
  35.138-           ; so type= return values come from the second invocation of subtypep
  35.139-           (subtypep type2 type1))
  35.140-          ;; type1 is assuredly NOT a subtype of type2,
  35.141-          ;; so assuredly type1 and type2 cannot be type=
  35.142-          (ok
  35.143-           (values nil t))
  35.144-          ;; our first result is uncertain ( ok == nil ) and it follows
  35.145-          ;; from specification of SUBTYPEP that sub = ok = NIL
  35.146-          (t
  35.147-           (assert (not sub))           ; is the implementation correct?
  35.148-           (multiple-value-bind (sub2 ok2)
  35.149-               (subtypep type2 type1)
  35.150-             (if  (and (not sub2) ok2)  ; we KNOW type2 is not a subtype of type1
  35.151-                  ;; so our results are certain...
  35.152-                  (values nil t)
  35.153-                  ;; otherwise, either type2 is surely a subtype of type1 (t t)
  35.154-                  ;; or type2 is not a subtype of type1, but we don't
  35.155-                  ;; know that for sure (nil nil)
  35.156-                  ;; In either case our result is negative but unsure
  35.157-                  (values nil nil)))))))
  35.158-
  35.159-(define-modify-macro coercef (type-spec) coerce
  35.160-  "Modify-macro for COERCE.")
    36.1--- a/lisp/std/util.lisp	Sun Apr 21 22:38:49 2024 -0400
    36.2+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3@@ -1,167 +0,0 @@
    36.4-;;; std/util.lisp @ 2023-10-14.03:28:40 -*- mode: lisp; -*-
    36.5-;;; Code:
    36.6-(in-package :std)
    36.7-
    36.8-;;; Misc
    36.9-(defmacro until (condition &body body)
   36.10-  (let ((block-name (gensym)))
   36.11-    `(block ,block-name
   36.12-       (loop
   36.13-	 (if ,condition
   36.14-	     (return-from ,block-name nil)
   36.15-	     (progn ,@body))))))
   36.16-
   36.17-(defmacro defmacro/g! (name args &rest body)
   36.18-  (let ((syms (remove-duplicates
   36.19-               (remove-if-not #'g!-symbol-p
   36.20-                              (flatten body)))))
   36.21-    (multiple-value-bind (body declarations docstring)
   36.22-        (parse-body body :documentation t)
   36.23-      `(defmacro ,name ,args
   36.24-         ,@(when docstring
   36.25-             (list docstring))
   36.26-         ,@declarations
   36.27-         (let ,(mapcar
   36.28-                (lambda (s)
   36.29-                  `(,s (gensym ,(subseq
   36.30-                                 (symbol-name s)
   36.31-                                 2))))
   36.32-                syms)
   36.33-           ,@body)))))
   36.34-
   36.35-(defmacro defmacro! (name args &rest body)
   36.36-  (let* ((os (remove-if-not #'o!-symbol-p (flatten args)))
   36.37-         (gs (mapcar #'o!-symbol-to-g!-symbol os)))
   36.38-    (multiple-value-bind (body declarations docstring)
   36.39-        (parse-body body :documentation t)
   36.40-      `(defmacro/g! ,name ,args
   36.41-         ,@(when docstring
   36.42-             (list docstring))
   36.43-         ,@declarations
   36.44-         `(let ,(mapcar #'list (list ,@gs) (list ,@os))
   36.45-            ,(progn ,@body))))))
   36.46-
   36.47-(defmacro defun! (name args &body body)
   36.48-  (let ((syms (remove-duplicates
   36.49-               (remove-if-not #'g!-symbol-p
   36.50-                              (flatten body)))))
   36.51-    (multiple-value-bind (body declarations docstring)
   36.52-        (parse-body body :documentation t)
   36.53-      `(defun ,name ,args
   36.54-         ,@(when docstring
   36.55-             (list docstring))
   36.56-         ,@declarations
   36.57-         (let ,(mapcar (lambda (s)
   36.58-                         `(,s (gensym ,(subseq (symbol-name s)
   36.59-                                               2))))
   36.60-                syms)
   36.61-           ,@body)))))
   36.62-
   36.63-(defmacro! dlambda (&rest ds)
   36.64-  "Dynamic dispatch lambda."
   36.65-  `(lambda (&rest ,g!args)
   36.66-     (case (car ,g!args)
   36.67-       ,@(mapcar
   36.68-          (lambda (d)
   36.69-            `(,(if (eq t (car d))
   36.70-                   t
   36.71-                   (list (car d)))
   36.72-              (apply (lambda ,@(cdr d))
   36.73-                     ,(if (eq t (car d))
   36.74-                          g!args
   36.75-                          `(cdr ,g!args)))))
   36.76-          ds))))
   36.77-
   36.78-;; LoL tlist
   36.79-;; (declaim (inline make-tlist tlist-left
   36.80-;;                  tlist-right tlist-empty-p))
   36.81-
   36.82-;; (defun make-tlist () (cons nil nil))
   36.83-;; (defun tlist-left (tl) (caar tl))
   36.84-;; (defun tlist-right (tl) (cadr tl))
   36.85-;; (defun tlist-empty-p (tl) (null (car tl)))
   36.86-
   36.87-;; (declaim (inline tlist-add-left
   36.88-;;                  tlist-add-right))
   36.89-
   36.90-;; (defun tlist-add-left (tl it)
   36.91-;;   (let ((x (cons it (car tl))))
   36.92-;;     (if (tlist-empty-p tl)
   36.93-;;         (setf (cdr tl) x))
   36.94-;;     (setf (car tl) x)))
   36.95-
   36.96-;; (defun tlist-add-right (tl it)
   36.97-;;   (let ((x (cons it nil)))
   36.98-;;     (if (tlist-empty-p tl)
   36.99-;;         (setf (car tl) x)
  36.100-;;         (setf (cddr tl) x))
  36.101-;;     (setf (cdr tl) x)))
  36.102-
  36.103-;; (declaim (inline tlist-rem-left))
  36.104-
  36.105-;; (defun tlist-rem-left (tl)
  36.106-;;   (if (tlist-empty-p tl)
  36.107-;;       (error "Remove from empty tlist")
  36.108-;;       (let ((x (car tl)))
  36.109-;;         (setf (car tl) (cdar tl))
  36.110-;;         (if (tlist-empty-p tl)
  36.111-;;             (setf (cdr tl) nil)) ;; For gc
  36.112-;;         (car x))))
  36.113-
  36.114-;; (declaim (inline tlist-update))
  36.115-
  36.116-;; (defun tlist-update (tl)
  36.117-;;   (setf (cdr tl) (last (car tl))))
  36.118-
  36.119-(defun build-batcher-sn (n)
  36.120-  (let* (network
  36.121-         (tee (ceiling (log n 2)))
  36.122-         (p (ash 1 (- tee 1))))
  36.123-    (loop while (> p 0) do
  36.124-      (let ((q (ash 1 (- tee 1)))
  36.125-            (r 0)
  36.126-            (d p))
  36.127-        (loop while (> d 0) do
  36.128-          (loop for i from 0 to (- n d 1) do
  36.129-            (if (= (logand i p) r)
  36.130-                (push (list i (+ i d))
  36.131-                      network)))
  36.132-          (setf d (- q p)
  36.133-                q (ash q -1)
  36.134-                r p)))
  36.135-      (setf p (ash p -1)))
  36.136-    (nreverse network)))
  36.137-
  36.138-;; TODO
  36.139-(defun save-lisp-tree-shake-and-die (path &rest args)
  36.140-  "A naive tree-shaker for lisp."
  36.141-  (sb-ext:gc :full t)
  36.142-  (apply #'sb-ext:save-lisp-and-die path args))
  36.143-
  36.144-(defun save-lisp-and-live (filename completion-function restart &rest args)
  36.145-  (flet ((restart-sbcl ()
  36.146-           (sb-debug::enable-debugger)
  36.147-           (setf sb-impl::*descriptor-handlers* nil)
  36.148-           (funcall restart)))
  36.149-    ;; fork it - assumes only one thread is running
  36.150-    (multiple-value-bind (pipe-in pipe-out) (sb-posix:pipe)
  36.151-      (let ((pid (sb-posix:fork)))
  36.152-        (cond ((= pid 0) ;; make simple-restart core
  36.153-               (sb-posix:close pipe-in)
  36.154-               (sb-debug::disable-debugger)
  36.155-               (apply #'sb-ext:save-lisp-and-die filename
  36.156-                      (append
  36.157-                       (list :toplevel #'restart-sbcl)
  36.158-                       args)))
  36.159-              (t
  36.160-               (sb-posix:close pipe-out)
  36.161-               (sb-sys:add-fd-handler
  36.162-                pipe-in :input
  36.163-                (lambda (fd)
  36.164-                  (sb-sys:invalidate-descriptor fd)
  36.165-                  (sb-posix:close fd)
  36.166-                  (multiple-value-bind (rpid status) (sb-posix:waitpid pid 0) ;; wait for master
  36.167-                    (assert (= pid rpid))
  36.168-                    (assert (sb-posix:wifexited status))
  36.169-                    (funcall completion-function
  36.170-                             (zerop (sb-posix:wexitstatus status))))))))))))