8baa554470fd

Fix direct-superclasses patching in CCL/ECL
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 29 Aug 2020 23:48:49 -0400
parents a7ad406182d8
children b148ffd26464
branches/tags (none)
files src/mop.lisp

Changes

--- a/src/mop.lisp	Sat Aug 29 19:46:58 2020 -0400
+++ b/src/mop.lisp	Sat Aug 29 23:48:49 2020 -0400
@@ -122,6 +122,23 @@
                         (before-print slot))))
           (json-slots class)))
 
+
+(defmethod shared-initialize :around
+  ((class json-class) slot-names
+   &rest initargs
+   &key slot-name-to-json-name unknown-slots allow-print allow-read
+   &allow-other-keys)
+  (flet ((arg (initarg args)
+           (when args ; todo assert length = 1
+             (list initarg (first args)))))
+    (apply #'call-next-method class slot-names
+           (append (arg :slot-name-to-json-name slot-name-to-json-name)
+                   (arg :unknown-slots unknown-slots)
+                   (arg :allow-read (or allow-read '(t)))
+                   (arg :allow-print (or allow-print '(t)))
+                   initargs))))
+
+
 (defun patch-direct-superclasses (direct-superclasses)
   "Patch `direct-superclasses` to ensure `json-object` will be a superclass.
 
@@ -136,21 +153,25 @@
       direct-superclasses
       (append direct-superclasses (list super)))))
 
-(defmethod shared-initialize :around
-  ((class json-class) slot-names
-   &rest initargs
-   &key slot-name-to-json-name unknown-slots allow-print allow-read direct-superclasses
-   &allow-other-keys)
-  (flet ((arg (initarg args)
-           (when args ; todo assert length = 1
-             (list initarg (first args)))))
-    (apply #'call-next-method class slot-names
+(defmethod initialize-instance :around
+    ((class json-class) &rest initargs
+     &key direct-superclasses &allow-other-keys)
+  ;;; I have no idea why doing this once in shared-initialize works in SBCL but
+  ;;; not in CCL/ECL.  Oh well.  This solution from https://www.cliki.net/MOP%20design%20patterns
+  ;;; seems to work everywhere.
+  (apply #'call-next-method class
+         :direct-superclasses (patch-direct-superclasses direct-superclasses)
+         initargs))
+
+(defmethod reinitialize-instance :around
+    ((class json-class) &rest initargs
+     &key (direct-superclasses nil direct-superclasses?) &allow-other-keys)
+  (if direct-superclasses?
+    (apply #'call-next-method class
            :direct-superclasses (patch-direct-superclasses direct-superclasses)
-           (append (arg :slot-name-to-json-name slot-name-to-json-name)
-                   (arg :unknown-slots unknown-slots)
-                   (arg :allow-read (or allow-read '(t)))
-                   (arg :allow-print (or allow-print '(t)))
-                   initargs))))
+           initargs)
+    (call-next-method)))
+
 
 (defmethod c2mop:finalize-inheritance :after ((class json-class))
   (setf (slot-map class) (make-slot-map class)
@@ -176,9 +197,9 @@
       :with map = (slot-map class)
       :with init = (list)
       :for name = (read% 'string nil input)
-      :for sep = (parse-kv-separator class-name input)
       :for (initarg c cc after-read) = (gethash name map)
       :do (progn
+            (parse-kv-separator class-name input)
             (if (null initarg)
               (ecase unknown
                 (:preserve (setf (gethash name (or preserved (setf preserved (make-hash-table :test #'equal))))