🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.clos
Article #21

Re: Portability: Adding a slot to a class

#21
From: Gary Hooyman
Date: Mon, 03 Aug 1992 05:22
340 lines
14188 bytes

In response to a previous post by Nicholas Roquette, I am posting this
clip of code for my solution to the problem of providing dynamic
extension of class definitions.

The code is in two parts: design-object-class and dynamic-design-object-class.


Some of the code specifically mentions objects of the class 'data-item. 
These are the domain specific objects that I put into the initforms of
the classes.  Their definitions exist elsewhere, but are not needed
here.  The code can be easily modified to accomodate other types of
objects.  The lisp-script methods referred to are methods for printing
an evaluatable representation of an object - f.i. '(make-instance
'data-item...).'


The :after methods on the dynamic-design-object-class may seem a bit
confusing.  These are needed because overridden slots do not get updated
by update-instance-for-redefined-class (possibly an error in CLOS).



Any questions or comments are eagerly sought.



Gary Hooyman
Department of Civil Engineering
Carnegie Mellon University
Pittsburgh, PA 15201




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;                                                                         
;;;                                                                          
;;;                       CARNEGIE MELLON UNIVERSITY                         
;;;                                                                        
;;;                   DEPARTMENT  OF  CIVIL  ENGINEERING                  
;;;                                                                          
;;;                    COMPUTER-AIDED ENGINEERING GROUP                   
;;;                                                                         
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;                                                                         
;;;   FILE.... : DESIGN-OBJECT-CLASS.LISP                                   
;;;                                                                         
;;;   AUTHOR.. : MAHER HAKIM & GARY HOOYMAN                             
    ;;;
;;;                                                                         
;;;   CREATED. : JULY 1992                                                  
;;;                                                                         
;;;   ABSTRACT : This file contains the design object class definition for  
;;;              the STandards REPresentation and Processing ENvironment    
;;;              "STREPPEN"                                                 
;;;                                                                         
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defclass design-object-class ()
  ((satisfied          :accessor satisfied
		       :allocation :instance
		       :initform
		       (make-instance 'constant :name
				      'satisfied :value 'satisfied
				      :defined-in-class 'design-object-class))
   (not-satisfied      :accessor not-satisfied
		       :allocation :instance
		       :initform
		       (make-instance 'constant :name
				      'not-satisfied :value 'not-satisfied
				      :defined-in-class 'design-object-class))
   (not-applicable     :accessor not-applicable
		       :allocation :instance
		       :initform
		       (make-instance 'constant :name
				      'not-applicable :value 'not-applicable
				      :defined-in-class 'design-object-class)))
  (:documentation "the root class for all static design object classes in
STREPPEN"))

;================================================

(defmethod class-name ((self design-object-class))
  "return the class name symbol"
  (clos:class-name (class-of self)))

;==============================================================================
==

(defmethod initialize-instance :after
                   ((self design-object-class) &rest initargs)
  "point each slot object to the new instance"
  (loop for slot-name in (mapcar #'clos:slot-definition-name
				 (clos:class-slots (class-of self)))
	do (eval (list 'setf (list 'parent-object (list slot-name self))
		       self))))

;================================================

(defmethod defclass-form-slot-definitions ((self design-object-class))
  "write the defclass form of the slot definitions"
  (mapcar #'(lambda (x-slot-def) 
	      (append
	       (list (clos:slot-definition-name x-slot-def))

	       (list :allocation
		     (clos:slot-definition-allocation x-slot-def))

	       (mapcan #'(lambda (x-slot-initarg)
			   (list :initarg x-slot-initarg))
		       (clos:slot-definition-initargs x-slot-def))

	       
	       (list :initform
		     (if (typep   ; if the initform evaluates to a data-item
			  (eval  
			   (list (clos:slot-definition-name x-slot-def)
				 self))
			  'data-item)
			 
			 (lisp-script   ; then make clos printed form of the
			  (eval (list   ; object in the slot
				        ; (assures an updated version)
				 (clos:slot-definition-name x-slot-def)
				 self)))
		       
		       (clos:slot-definition-initform x-slot-def)))
	                                ; else, reassert the previous initform
		       
	       (mapcan #'(lambda (x-slot-reader)
			   (list :reader x-slot-reader))
		       (clos:slot-definition-readers x-slot-def))

	       (mapcan #'(lambda (x-slot-writer-method)
			   (list :writer x-slot-writer-method))
		       (clos:slot-definition-writers x-slot-def))))

	  (clos:class-direct-slots (class-of self))))

;===============================================

(defmethod lisp-script-defclass-form ((self design-object-class))
  "returns a written representation of the defclass form of the instance"
  (list 'defclass (clos:class-name (class-of self))
	(mapcar #'clos:class-name
		(clos:class-direct-superclasses
		 (class-of self)))
	(defclass-form-slot-definitions self)
	(list ':documentation (documentation (class-of self)))))

;===============================================

(defmethod list-all-di-names ((self design-object-class))
  "returns a list of all the slot names of the instance"
  (mapcar #'clos:slot-definition-name
	  (clos:class-slots (class-of self))))

;==============================================================================
=

(defmethod list-all-di-objects ((self design-object-class))
  "returns a list of all the slot objects of the instance"
  (mapcar #'(lambda (x-di-name)
	      (eval (list x-di-name self)))
	  (list-all-di-names self)))

;===============================================

(defmethod list-local-di-names ((self design-object-class))
  "returns a list of the locally defined slot names of the instance"
  (mapcar #'clos:slot-definition-name
	  (clos:class-direct-slots (class-of self))))

;==============================================

(defmethod list-local-di-objects ((self design-object-class))
  "returns a list of the locally defined slot objects of the instance"
  (mapcar #'(lambda (x-di-name)
	      (eval (list x-di-name self)))
	  (list-local-di-names self)))

;=============================================





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;                                                                          
;;;                                                                          
;;;                       CARNEGIE MELLON UNIVERSITY                         
;;;                                                                          
;;;                   DEPARTMENT  OF  CIVIL  ENGINEERING                     
;;;                                                                          
;;;                    COMPUTER-AIDED ENGINEERING GROUP                      
;;;                                                                          
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;                                                                          
;;;   FILE.... : DYNAMIC-DESIGN-OBJECT-CLASS.LISP                       
    ;;;
;;;                                                                          
;;;   AUTHOR.. : MAHER HAKIM & GARY HOOYMAN                             
    ;;;
;;;                                                                          
;;;   CREATED. : JULY 1992                                                   
;;;                                                                          
;;;   ABSTRACT : This file contains the dynamic design object class          
;;;              definition for the STandards REPresentation and Processing  
;;;              ENvironment "STREPPEN"                                      
;;;                                                                          
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;




(defclass dynamic-design-object-class (design-object-class)
  ()
  (:documentation "a mixin for design object class to support the dynamic
class definition in STREPPEN"))

;===============================================

;; this function asserts a class definition of a class that is
;; in the design-object-class-hierarchy

(defun make-dynamic-design-object-class (name &key
				     (parents '(dynamic-design-object-class))
				     (slot-definitions '())
				     (documentation "nil"))
  (eval
   (list 'defclass name
	 parents
	 slot-definitions
	 (list :documentation documentation))))

;===============================================

(defmethod add-di (name type (self dynamic-design-object-class))
  "add a slot filled with a data item of the name and type specified"
  (eval
   (list 'defclass (class-name (class-of self))
	 (mapcar #'clos:class-name
		 (clos:class-direct-superclasses
		  (class-of self)))
	 (append (defclass-form-slot-definitions self)
		 (list (list name
		       :initarg
		       (read-from-string
			(concatenate 'string
			    ":" (write-to-string name)))
		       :accessor name
		       :initform  (make-instance type
				       :name name :defined-in-class
				       (class-name (class-of self))))))
	 (list :documentation (documentation (class-of self))))))

; will signal an error if the slot name is already in use locally

;===============================================

; sets the parent object of the newly added data-item and
; writes an :after method for (setf slot-name) that assures that
; any data-item put into the slot maintains the appropriate name,
; parent object, and the name of the class defined in

(defmethod add-di :after (name type (self dynamic-design-object-class))
  "for the new slot, insert the new initform into the prototype instance
and define a setf method to assure the slot object maintains the proper name,
parent-object, and class-defined-in"
  (eval (list 'defmethod  (list 'setf name) :after
	      (list 'arg (list 'self (class-name self)))
	      (list 'if (list 'typep 'arg (quote 'data-item))
		    (list 'progn
			  (list 'setf (list 'slot-value
			       (list name 'self) (quote 'name))
				(list 'quote name))
			  (list 'setf (list 'parent-object 'arg) 'self)
			  (list 'setf (list 'defined-in-class 'arg)
				        (list 'quote (class-name self)))))))
  (eval (list 'setf (list name self)
	      (list name (list 'make-instance
			       (list 'quote (class-name self)))))))

;===============================================

(defmethod remove-di (name (self dynamic-design-object-class))
  "reassert the defclass without the specified slot"
  (eval
   (list 'defclass (class-name (class-of self))
	(mapcar #'clos:class-name
		(clos:class-direct-superclasses
		 (class-of self)))
	(remove-if #'(lambda (x-slot-def)
		       (equal (first x-slot-def) name))
		   (defclass-form-slot-definitions self))
	(list :documentation (documentation (class-of self))))))

(defmethod remove-di :after (name (self dynamic-design-object-class))
  "for an overridden slot, remove the local setf method and retrieve the
   inherited slot initform"
  (if (member name (list-all-di-names self))
      (progn
	(eval
	 (list 'defmethod  (list 'setf name) :after
	       (list 'arg (list 'self (class-name self)))))
	(eval (list 'setf (list name self)
		    (list name (list 'make-instance
				     (list 'quote (class-name self)))))))))
      
;===============================================

(defmethod set-class-parents
             (parents-list (self dynamic-design-object-class))
  "redefine the class with a new set of parents"
  (if (null parents-list)
      (setq parents-list (list 'dynamic-design-object-class)))
  (eval (list 'defclass (class-name (class-of self))
	      parents-list
	      (defclass-form-slot-definitions self)
	      (list :documentation (documentation (class-of self))))))

;===============================================

(defmethod set-class-documentation
              (documentation-string (self dynamic-design-object-class))
  "set the documentation string of the class"
  (setf (documentation (class-of self)) documentation-string))

;===============================================

(defmethod class-documentation ((self dynamic-design-object-class))
  "return the documentation string of the class"
  (documentation (class-of self)))
Technical Details
Message-ID: <seTHA0O00iQQ8F3kcv@andrew.cmu.edu>
Path: arc1-ca.pugleaf.net!sparky!uunet!ogicse!das-news.harvard.edu!cantaloupe.srv.cs.cmu.edu!crabapple.srv.cs.cmu.edu!andrew.cmu.edu!gh1h+
References: <1992Jul30.234218.28623@jpl-devvax.jpl.nasa.gov> <keSKjBC00iQQ0AHUcK@andrew.cmu.edu> <1992Jul31.224711.25800@jpl-devvax.jpl.nasa.gov>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!ogicse!das-news.harvard.edu!cantaloupe.srv.cs.cmu.edu!crabapple.srv.cs.cmu.edu!andrew.cmu.edu!gh1h+
From: gh1h+@andrew.cmu.edu (Gary Hooyman)
Newsgroups: comp.lang.clos
Subject: Re: Portability: Adding a slot to a class
Message-ID: <seTHA0O00iQQ8F3kcv@andrew.cmu.edu>
Date: 3 Aug 92 05:22:08 GMT
Article-I.D.: andrew.seTHA0O00iQQ8F3kcv
References: <1992Jul30.234218.28623@jpl-devvax.jpl.nasa.gov> <keSKjBC00iQQ0AHUcK@andrew.cmu.edu>
 <1992Jul31.224711.25800@jpl-devvax.jpl.nasa.gov>
Organization: Masters student, Civil Engineering, Carnegie Mellon, Pittsburgh, PA
Lines: 340
In-Reply-To: <1992Jul31.224711.25800@jpl-devvax.jpl.nasa.gov>