(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:" #