(require :asdf)
(require :alexandria)
(require :trivial-garbage)
(require :closer-mop)
(in-package :cl-user)
(defmacro capture-read (&body body)
`(with-input-from-string
(*standard-input* (with-output-to-string
(*standard-output*) ,@body))
(read)))
(defgeneric (setf form) (obj val))
(defgeneric (setf state-alist) (obj val))
(defclass eve () (form))
(defmethod make-load-form
((obj eve) &optional env
&aux (class (class-name (class-of obj))))
(declare (ignore env))
(eval
`(defmethod make-load-form
:around ((obj ,class) &optional env)
(declare (ignore env))
(capture-read
(format t "
(let
((form
'~s))
(let ((particular-quine (eval form)))
(setf (form particular-quine) form)
(values particular-quine)))
"
(form obj)))))
(make-load-form obj))
(defun form-eve (&rest other-classes)
(let
((form
`(macrolet
((ana-quine-class
((&rest class-paraphernalia) &body body)
(alexandria:with-gensyms (classname)
`(let ((quine
(defclass ,classname
,@class-paraphernalia)))
,@body))))
(ana-quine-class
((,@other-classes eve) ((form :accessor form))
(:documentation " . . . "))
(values (make-instance quine))))))
(let ((particular-quine (eval form)))
(setf (form particular-quine) form)
(values particular-quine))))
(defclass stately (eve)
((state-alist :initform (list) :accessor state-alist)))
(defmethod make-load-form
((obj stately) &optional env
&aux (class (class-name (class-of obj))))
(declare (ignore env))
(capture-read (format t "
(let* ((parent-quine (eval '~s))
(stately (eval parent-quine)))
(setf (state-alist stately) '~s)
(values stately))" (call-next-method) (state-alist obj))))
(defclass heritable (eve) ())
(defmethod make-load-form
((obj heritable) &optional env
&aux (class (class-of obj))) "
"
(declare (ignore env))
(alexandria:with-gensyms (form classer)
`(let ((,form ,(call-next-method)))
(change-class (eval ,form) ,class))))
(defclass mempubsub (eve)
((peers :initform (tg:make-weak-hash-table :weakness :value)
:allocation :class :reader peers)))
(defmethod shared-initialize :after ((obj mempubsub) names
&rest rest)
(declare (ignore names rest))
(setf (gethash obj (peers obj)) obj))
(defmethod bread-massage ((obj mempubsub) (lambda function)) "
When you knead assistants
" (with-hash-table-iterator (iter (peers obj))
(loop initially (tg:gc)
for k = (nth-value 1 (funcall iter)) while k
when (and (member (class-of obj)
(clos:class-direct-superclasses
(class-of k))))
do (funcall lambda k)
finally (unless (next-method-p) (return))
(call-next-method))))
#|----AD-HOC-EXAMPLES----------------------------------------------
(load #p"eve-quine.lisp")
(print "Eve quines:")
(let* ((eve-1 (print (form-eve)))
(eve-2 (print (form-eve 'mempubsub)))
(eve-3 (print (form-eve (class-name (class-of eve-2)))))
(fun (lambda (x) (print x))))
(terpri)
(print "eve-2 calls fun on her child, eve-3")
(bread-massage eve-2 fun)
(terpri)
(print "eve-3 has no children")
(bread-massage eve-3 fun)
(terpri)
(print "eve-3 directly adopts eve-2")
(push (class-of eve-3)
(clos:class-direct-superclasses (class-of eve-2)))
(bread-massage eve-3 fun)
(terpri)
(print "eve-2 calls fun on her child, eve-3")
(bread-massage eve-2 fun)
(terpri)
(print "Now badly named 'heritable class instance and their clone")
(let* ((heri-1 (print (form-eve 'heritable 'mempubsub)))
(heri-2 (print (eval (make-load-form heri-1))))
(tage-1 (print (form-eve (class-name (class-of heri-1))))))
(terpri)
(print "heri-1 has one child")
(bread-massage heri-1 fun)
(terpri)
(print "hence so too heri-2")
(bread-massage heri-2 fun)
(terpri)
(print "eve-2 adopts heri-1 (and hence her clone heri-2)")
(push (class-of eve-2)
(clos:class-direct-superclasses (class-of heri-2)))
(bread-massage eve-2 fun)))
(terpri)
(si:quit)
|#
#|----AD-HOC-OUTPUTS-----------------------------------------------
;;; Loading #P"path/to/asdf.fas"
;;; Loading #P"path/to/common-lisp/eve-quine/test-eve-quines.lisp"
"Eve quines:"
#<a #:CLASSNAME98 ; eve-1
#<a #:CLASSNAME104 ; eve-2
#<a #:CLASSNAME110 ; eve-3
"eve-2 calls fun on her child, eve-3"
#<a #:CLASSNAME110
"eve-3 has no children"
"eve-3 directly adopts eve-2"
#<a #:CLASSNAME104
"eve-2 calls fun on her child, eve-3"
#<a #:CLASSNAME110
"Now badly named 'heritable class instance and their clone"
#<a #:CLASSNAME116 0x1 ; heri-1
#<a #:CLASSNAME116 0x2 ; heri-2
#<a #:CLASSNAME132 ; tage-1
"heri-1 has one child"
#<a #:CLASSNAME132
"hence so too heri-2"
#<a #:CLASSNAME132
"eve-2 adopts heri-1 (and hence her clone heri-2)"
#<a #:CLASSNAME116
#<a #:CLASSNAME110
#<a #:CLASSNAME116
|#