;;; -*- Mode:LISP; Package:SYSTEM-INTERNALS; Base:8; Readtable: ZL -*- ; ** (c) Copyright 1980 Massachusetts Institute of Technology ** ;a CLASS-SYMBOL is the name by which the user refers to the class. It usually ; has a -CLASS suffix. Its value is ; a DTP-ENTITY which is an instance of CLASS-CLASS. Instances of CLASS-CLASS ; contain a NAME, a CLASS-SYMBOL, and a CLASS-METHOD-SYMBOL (and some others ; as well). The NAME is used for printing out, and usually does not contain ; the -CLASS suffix. ;an INSTANCE is a closure of some INSTANCE-VARIABLES and whose functional ; component is a CLASS-METHOD-SYMBOL. ;a CLASS-METHOD-SYMBOL is usually a gensym created at class definition time. ; The value of the CLASS-METHOD-SYMBOL is a DTP-ENTITY which is an instance of ; CLASS-CLASS. This is initially the identical instance which is in the ; value cell of the CLASS-SYMBOL, however, if the class is redefined ; (ie a new DEFCLASS done), the CLASS-SYMBOL will change, while the ; current CLASS-METHOD-SYMBOL will not change, and instead a new one will be made. ; The function cell of the CLASS-METHOD-SYMBOL is a DTP-SELECT-METHOD which holds ; the methods of the class. ; The CLASS-METHOD-SYMBOL has an SI:ENTITY-TYPEP property whose value ; is the class-symbol. ;When DEFCLASS is done, a new CLASS-METHOD-SYMBOL is always created. Any instances ;of the old class will be unaffected since they close over the old CLASS-METHOD-SYMBOL. ;The system attempts to alter the NAME of the old class so the user will ;be warned if he has one of these floating around. ; Methods can be defined local to a particular instance (as opposed to its class) ;by DEFMETHOD-INSTANCE. However, it is assumed to be fairly rare to want to do this, ;and we dont want to garbage up all instances on this account. ; Accordingly, the first time this is ;done for a particular instance, a phantom CLASS is created which is a subclass ;of the original class. The instance is then transmuted to the phantom class. ;Phantom classes have the :PHANTOM-CLASS property on the property list of the ;CLASS-METHOD-SYMBOL (for extra connectedness, the value of this property is the ;instance). ;With this new scheme, LISP-OBJECT-CLASS can eventually be flushed in favor of ; regular instances of CLASS-CLASS with special NEW methods. ;A CLASS is held on a lisp symbol, specially created for the purpose. ; The function cell of the symbol contains the DTP-SELECT-METHOD for the class. (DECLARE (SPECIAL CLASS-CLASS OBJECT-CLASS SELF)) (DECLARE (SPECIAL PRINT-ENTITY-ADDRESSES-FLAG)) (SETQ PRINT-ENTITY-ADDRESSES-FLAG T) (DEFMACRO ENTITY (CLOSED-VARS-LIST FCTN) "Returns a newly created entity, which is like a closure except in the way some system functions work on it. Entities are mostly obsolete; use flavors." `(%MAKE-POINTER DTP-ENTITY (CLOSURE ,CLOSED-VARS-LIST ,FCTN))) ;;;; Various functions for sending messages to an instance. (DEFUN <- (LOCAL-SELF MSG-KEY &REST REST) "Sends LOCAL-SELF the message MSG-KEY and REST." (typecase local-self (ENTITY (LEXPR-SEND LOCAL-SELF MSG-KEY REST)) (instance (LEXPR-SEND LOCAL-SELF MSG-KEY REST)) (T (LET ((SELF LOCAL-SELF)) ;Avoid binding special var unless necessary. (LEXPR-FUNCALL (CLASS-METHOD-SYMBOL SELF) MSG-KEY REST))))) ;slight speed bum. ;<<-- sends an object several messages in succession, as in ;(<<-- TVOB (:EDGES<- LEFT TOP RIGHT BOTTOM) (:CLOBBER) (:UPDATE)) (DEFMACRO <<-- (OBJ . MESSAGES) "Sends the object OBJ the messages MESSAGES in succession, as in /(<<-- TVOB (:EDGES<- LEFT TOP RIGHT BOTTOM) (:CLOBBER) (:UPDATE))." `(PROGN . ,(MAPCAR 'APPEND (CIRCULAR-LIST `(<- ,OBJ)) MESSAGES))) ;(<-AS TVOB ':UPDATE) sends SELF the message ':UPDATE but handles it ;as if SELF were of class TVOB instead of its actual class. ;It is useful in definitions of methods of subclasses of TVOB. ;It is also useful in methods of TVOB, since SELF is not rebound. ;The specified class must be a constant. ;Caveat: Doesn't check to see if TVOB is a superclass of SELF's class. ;Other Caveat: always refers to the most recent class definition of TVOB. (DEFMACRO <-AS (CLASS-SYMBOL . MESSAGE) "Sends SELF the message MESSAGE but handles it as if SELF were of class CLASS-SYMBOL instead of its actual class. It is useful in definitions of methods of subclasses of CLASS-SYMBOL and in methods of CLASS-SYMBOL, since SELF is not rebound. CLASS-SYMBOL must be a constant." `(FUNCALL (SYMEVAL-IN-CLOSURE ,CLASS-SYMBOL 'CLASS-METHOD-SYMBOL) . ,MESSAGE)) ;(DEFUN <-AS (CLASS-SYMBOL &REST MESSAGE) ; (LEXPR-FUNCALL (SYMEVAL-IN-CLOSURE CLASS-SYMBOL 'CLASS-METHOD-SYMBOL) MESSAGE)) ;; GET TO HERE VIA TAIL POINTER ON OBJECT-CLASS ;; Flavors now use FLAVOR-UNCLAIMED-MESSAGE by default instead. (DEFUN UNCLAIMED-MESSAGE (KEY &REST REST) "Signals KEY as an unclaimed message to SELF. Includes the rest of the message." (SIGNAL-PROCEED-CASE ((NEW-OPERATION) 'SYS:UNCLAIMED-MESSAGE :OBJECT SELF :MESSAGE KEY :ARGUMENTS (COPY-LIST REST)) (:NEW-OPERATION (LEXPR-SEND SELF NEW-OPERATION REST)))) ;CLASS of any object returns the actual class of that object, an instance of class CLASS. ; It gets this by SYMEVALing the CLASS-METHOD-SYMBOL. ;CLASS-SYMBOL of an object returns the class-symbol. It pulls this out of the CLASS. ; This function should rarely be used. ;CLASS-METHOD-SYMBOL returns a symbol whose function cell holds the select-method. ; If an entity, the CLASS-METHOD-SYMBOL is its storage-wise CAR. ; this is always different from CLASS-SYMBOL. (DEFUN CLASS (OBJ) "Returns the actual class of OBJ" (SYMEVAL (CLASS-METHOD-SYMBOL OBJ))) (DEFUN CLASS-METHOD-SYMBOL (OBJ) "If OBJ is an entity, returns its storage-wise CAR." (COND ((ENTITYP OBJ) (CAR (%MAKE-POINTER DTP-LIST OBJ))) ((FIXP OBJ) (SYMEVAL-IN-CLOSURE FIXNUM-CLASS 'CLASS-METHOD-SYMBOL)) ((SYMBOLP OBJ) (SYMEVAL-IN-CLOSURE SYMBOL-CLASS 'CLASS-METHOD-SYMBOL)) ((FLOATP OBJ) (SYMEVAL-IN-CLOSURE FLONUM-CLASS 'CLASS-METHOD-SYMBOL)) ((AND (NAMED-STRUCTURE-P OBJ) (OR (LET ((C (IF (ARRAY-HAS-LEADER-P OBJ) (ARRAY-LEADER OBJ 1) (AREF OBJ 0)))) (AND (TYPEP C :CLOSURE) C)) (GET (NAMED-STRUCTURE-P OBJ) 'CLASS-METHOD-SYMBOL)))) ((ARRAYP OBJ) (SYMEVAL-IN-CLOSURE ARRAY-CLASS 'CLASS-METHOD-SYMBOL)) ((NOT (ATOM OBJ)) (SYMEVAL-IN-CLOSURE CONS-CLASS 'CLASS-METHOD-SYMBOL)) (T (FERROR NIL "NO CLASS-METHOD-SYMBOL APPLIES ~S" OBJ)))) (DEFUN CLASS-SYMBOL (OBJ) "Returns the class-symbol of OBJ. This should be used rarely." (LET ((CMS (CLASS-METHOD-SYMBOL OBJ))) (OR (GET CMS 'ENTITY-TYPEP) (SYMEVAL CMS)))) (DEFUN CLASS-NAME (OBJ) "Returns the class-name of OBJ." (PROG (CSM) (SETQ CSM (CLASS-METHOD-SYMBOL OBJ)) L (COND ((GET CSM ':PHANTOM-CLASS) (SETQ CSM (<- (<- (SYMEVAL CSM) ':SUPERCLASS) ':CLASS-METHOD-SYMBOL)) (GO L))) (RETURN (SYMEVAL-IN-CLOSURE (SYMEVAL CSM) 'NAME)))) (DEFUN IMMEDIATE-CLASS-NAME (OBJ) "Returns the immediate-class-name of OBJ." (SYMEVAL-IN-CLOSURE (SYMEVAL (CLASS-METHOD-SYMBOL OBJ)) 'NAME)) ;CLASS-SYMBOLP moved to QMISC (DEFUN SUBCLASS-OF-CLASS-SYMBOL-P (SUBCLASS CLASS-SYMBOL) "Returns T if SUBCLASS is a subclass of any class whose class symbol is CLASS-SYMBOL. Otherwise returns NIL." (OR (EQ (<- SUBCLASS ':CLASS-SYMBOL) CLASS-SYMBOL) (LET ((SC (<- SUBCLASS ':SUPERCLASS))) (COND ((OR (NULL SC) (EQ SC SUBCLASS)) NIL) ((ENTITYP SC) (SUBCLASS-OF-CLASS-SYMBOL-P SC CLASS-SYMBOL)) (T (DOLIST (SC1 SC) (COND ((SUBCLASS-OF-CLASS-SYMBOL-P SC1 CLASS-SYMBOL) (RETURN T))))))))) (DEFUN SUBCLASS-OF-CLASSP (SUBCLASS CLASS) "Returns T if SUBCLASS is a subclass of CLASS. Otherwise returns NIL." (OR (EQ SUBCLASS CLASS) (LET ((SC (<- SUBCLASS ':SUPERCLASS))) (COND ((OR (NULL SC) (EQ SC SUBCLASS)) NIL) ((ENTITYP SC) (SUBCLASS-OF-CLASSP SC CLASS)) (T (DOLIST (SC1 SC) (COND ((SUBCLASS-OF-CLASSP SC1 CLASS) (RETURN T))))))))) (DEFUN SUBINSTANCE-OF-CLASSP (ENT CLASS) "Returns T if ENT is a subinstance of CLASS. Otherwise returns NIL." (AND (ENTITYP ENT) (SUBCLASS-OF-CLASSP (CLASS ENT) CLASS))) (DEFUN SUBINSTANCE-OF-CLASS-SYMBOL-P (ENT CLASS-SYMBOL) "Returns T if ENT is a subinstance of CLASS-SYMBOL. Otherwise returns NIL." (AND (ENTITYP ENT) (SUBCLASS-OF-CLASS-SYMBOL-P (CLASS ENT) CLASS-SYMBOL))) (DEFUN ALL-SUBCLASSES-OF-CLASS (CLASS &OPTIONAL SO-FAR) "Lists the subclasses of CLASS." (DOLIST (CL (<- CLASS ':IMMEDIATE-SUBCLASS-LIST)) (COND ((NOT (MEMQ CL SO-FAR)) (SETQ SO-FAR (CONS CL SO-FAR)) (SETQ SO-FAR (ALL-SUBCLASSES-OF-CLASS CL SO-FAR))))) SO-FAR) (DEFUN MAP-CLASS-HIERARCHY (FCTN &OPTIONAL (CLASS OBJECT-CLASS)) "Lists the class hierarchy of FCTN." (FUNCALL FCTN CLASS) (DOLIST (CL (<- CLASS ':IMMEDIATE-SUBCLASS-LIST)) (MAP-CLASS-HIERARCHY FCTN CL))) ;Macros for defining classes. ;Define a class of named structures. ;You must give the class name sans "-CLASS", since that will be used ;as the named-structure-symbol. (DEFMACRO DEFSTRUCTCLASS (CL SUPERCLASS-SYMBOL) "Defines a class of named structures. You must give the class name sans /"-CLASS/", since that will be used as the named-structure-symbol." (LET ((CLASS-SYMBOL (CLASS-HOLDER CL))) `(PROGN 'COMPILE (DECLARE (SPECIAL ,CLASS-SYMBOL)) (DEFCLASS-1 ,CLASS-SYMBOL ,SUPERCLASS-SYMBOL NIL) (DEFMETHOD-INSTANCE (,CLASS-SYMBOL :NEW) (&REST IGNORE) (FERROR NIL "The class ~S does not handle NEW messages" ,CLASS-SYMBOL)) (PUTPROP ',CL (SYMEVAL-IN-CLOSURE ,CLASS-SYMBOL 'CLASS-METHOD-SYMBOL) 'CLASS-METHOD-SYMBOL)))) ;Should be flushed ... (DEFUN CLASS-HOLDER (CL) (COND ((ATOM CL) (INTERN (STRING-APPEND CL "-CLASS"))) (T (MAPCAR (FUNCTION CLASS-HOLDER) CL)))) ;Define a class of ENTITYs. The superclass must be specified. ;Also, you must specify the names of the instance-variables ;(in addition to those which are inherited from the superclass, ;which you should not mention again). (DEFMACRO DEFCLASS (CLASS-SYMBOL SUPERCLASS-SYMBOL INSTANCE-PATTERN &OPTIONAL (ACCESSOR-METHODS T)) "Defines a class of ENTITYs under SUPERCLASS-SYMBOL. INSTANCE PATTERN contains only the instance varibles not contained in the superclass." `(PROGN 'COMPILE (SPECIAL ,CLASS-SYMBOL) (EVAL-WHEN (COMPILE) (PUSH ',*MACROARG* FILE-LOCAL-DECLARATIONS)) (DEFCLASS-1 ,CLASS-SYMBOL ,SUPERCLASS-SYMBOL ,INSTANCE-PATTERN) . ,(COND (ACCESSOR-METHODS (MAKE-ACCESSOR-METHODS CLASS-SYMBOL INSTANCE-PATTERN))))) ;Should only be called from above macro. (DEFUN MAKE-ACCESSOR-METHODS (CLASS-SYMBOL INSTANCE-PATTERN &AUX RES) (DOLIST (L INSTANCE-PATTERN) (SETQ RES (NCONC RES `((DEFMETHOD (,CLASS-SYMBOL ,(INTERN (STRING-APPEND L "<-") PKG-KEYWORD-PACKAGE)) (A) (SETQ ,L A)))))) (DOLIST (L INSTANCE-PATTERN) (SETQ RES (NCONC RES `((DEFMETHOD (,CLASS-SYMBOL ,(INTERN (STRING L) PKG-KEYWORD-PACKAGE)) () ,L))))) RES) ;Should only be called from above macros. ; Makes an instance of CLASS-CLASS (DEFUN DEFCLASS-1 ("E CLASS-SYMBOL SUPERCLASS-SYMBOL INSTANCE-PATTERN) (LET ((SUPERCLASS (COND ((ATOM SUPERCLASS-SYMBOL) (SYMEVAL SUPERCLASS-SYMBOL)) (T (MAPCAR (FUNCTION SYMEVAL) SUPERCLASS-SYMBOL))))) ;Dont redefine class if it is already defined with same instance variables. (COND ((OR (NOT (BOUNDP CLASS-SYMBOL)) (NOT (ENTITYP (SYMEVAL CLASS-SYMBOL))) (NOT (EQUAL (<- (SYMEVAL CLASS-SYMBOL) ':INSTANCE-PATTERN) (UNION INSTANCE-PATTERN (COND ((ENTITYP SUPERCLASS) (<- SUPERCLASS ':INSTANCE-PATTERN)) (T (APPLY 'UNION (MAPCAR (FUNCTION (LAMBDA (SC) (<- SC ':INSTANCE-PATTERN))) SUPERCLASS)))))))) (<- CLASS-CLASS ':NEW 'CLASS-SYMBOL CLASS-SYMBOL ;NAME is set in the :BORN method now 'INSTANCE-PATTERN INSTANCE-PATTERN 'SUPERCLASS SUPERCLASS 'CLASS-VERSION-NUMBER (COND ((CLASS-SYMBOLP CLASS-SYMBOL) (1+ (<- (SYMEVAL CLASS-SYMBOL) ':CLASS-VERSION-NUMBER))) (T 0))))))) ;Funny form of DEFCLASS. Used only to bootstrap classes CLASS-CLASS and OBJECT-CLASS before ; mechanism necessary to make NEW message work is set up. Does not set up the ; value of SUPERCLASS because that cant be done until CLASS-CLASS and OBJECT-CLASS exist. (DEFUN DEFCLASS-BOOTSTRAP ("E NM C-S METHOD-TAIL VARIABLES) (IF (BOUNDP C-S) NIL (LET ((NAME NM) (CLASS-SYMBOL C-S) (CLASS-METHOD-SYMBOL (GENSYM)) (INSTANCE-PATTERN VARIABLES) (SUPERCLASS NIL) (CLASS-VERSION-NUMBER 0) (IMMEDIATE-SUBCLASS-LIST NIL)) (DECLARE (SPECIAL NAME CLASS-SYMBOL CLASS-METHOD-SYMBOL INSTANCE-PATTERN SUPERCLASS CLASS-VERSION-NUMBER IMMEDIATE-SUBCLASS-LIST)) (FSET CLASS-METHOD-SYMBOL METHOD-TAIL) (PUTPROP CLASS-METHOD-SYMBOL CLASS-SYMBOL 'ENTITY-TYPEP) (SET CLASS-METHOD-SYMBOL (SET CLASS-SYMBOL (ENTITY '(NAME CLASS-SYMBOL CLASS-METHOD-SYMBOL SUPERCLASS INSTANCE-PATTERN CLASS-VERSION-NUMBER IMMEDIATE-SUBCLASS-LIST) (COND ((EQ CLASS-SYMBOL 'CLASS-CLASS) CLASS-METHOD-SYMBOL) (T (SYMEVAL-IN-CLOSURE CLASS-CLASS 'CLASS-METHOD-SYMBOL)))))) (DEFINE-ACCESSOR-METHODS CLASS-SYMBOL CLASS-METHOD-SYMBOL VARIABLES)))) ;Define for a class of named structures a method which ;simply returns the value of a particular component. (DEFMACRO TRIVIAL-ACCESS (CLASS COMPONENT) `(DEFMETHOD (,CLASS ,(INTERN (STRING COMPONENT) PKG-KEYWORD-PACKAGE)) () (,(INTERN (STRING-APPEND CLASS "-" COMPONENT)) SELF))) (PROGN 'COMPILE ;Dont return any ENTITIES to READ-EVAL-PRINT loop until object printer ; in place to handle them. ;CLASS must be first use of DEFCLASS, since that uses the value of CLASS-CLASS, ;and magically wins if it is setting that value, but loses if it is simply unbound. ; METHOD-TAIL is to be the CLASS-METHOD-SYMBOL for OBJECT-CLASS, which doesnt ;exist yet. (DEFCLASS-BOOTSTRAP CLASS CLASS-CLASS NIL (NAME CLASS-SYMBOL CLASS-METHOD-SYMBOL INSTANCE-PATTERN SUPERCLASS CLASS-VERSION-NUMBER IMMEDIATE-SUBCLASS-LIST)) ;Now that CLASS-CLASS is bound, we can create the class OBJECT. ;It is funny, because if you ask for its superclass, you get it itself; ;but in fact the superclass in the select-method is UNCLAIMED-MESSAGE. (DEFCLASS-BOOTSTRAP OBJECT OBJECT-CLASS UNCLAIMED-MESSAGE ()) (SET-IN-CLOSURE OBJECT-CLASS 'SUPERCLASS OBJECT-CLASS) (SET-IN-CLOSURE CLASS-CLASS 'SUPERCLASS OBJECT-CLASS) ;finish linking up. (SET-METHOD-SUPERCLASS (<- CLASS-CLASS ':CLASS-METHOD-SYMBOL) OBJECT-CLASS) ;FILL IN WHERE LEFT BLANK. (COND ((NULL (SYMEVAL-IN-CLOSURE OBJECT-CLASS 'IMMEDIATE-SUBCLASS-LIST)) (SET-IN-CLOSURE OBJECT-CLASS 'IMMEDIATE-SUBCLASS-LIST (LIST CLASS-CLASS)))) (EVAL-WHEN (COMPILE) (PUSH '(DEFCLASS CLASS-CLASS OBJECT-CLASS (NAME CLASS-SYMBOL CLASS-METHOD-SYMBOL INSTANCE-PATTERN SUPERCLASS CLASS-VERSION-NUMBER IMMEDIATE-SUBCLASS-LIST)) LOCAL-DECLARATIONS) (PUSH '(DEFCLASS OBJECT-CLASS OBJECT-CLASS ()) LOCAL-DECLARATIONS)) ;;; Now define the method for NEW, for creating instances of ENTITY classes, ;;; and related methods. (DEFMETHOD (CLASS-CLASS :NEW) (&REST REST) (LET ((NEWGUY (LET ((CMS CLASS-METHOD-SYMBOL) ;AVOID SCREW WHEN MAKING INSTANCES OF CLASS-CLASS (**VN** INSTANCE-PATTERN)) (PROGV **VN** (MAKE-LIST (LENGTH **VN**)) (DO ((R REST (CDDR R)) (V)) ((NULL R)) (COND ((SETQ V (CAR (MEM #'STRING-EQUAL (CAR R) **VN**))) (SET V (CADR R))) (T (FERROR NIL "The class ~S has no variable ~A" SELF (CAR R))))) (ENTITY **VN** CMS))))) (<- NEWGUY ':BORN) NEWGUY)) (DEFMETHOD (OBJECT-CLASS :BORN) () NIL) ;Now define appropriate methods for creating a new class using a NEW message. (DEFMETHOD (CLASS-CLASS :BORN) () (OR CLASS-SYMBOL (FERROR NIL "CLASS-SYMBOL must be specified when creating a class")) (SET CLASS-SYMBOL SELF) (OR CLASS-METHOD-SYMBOL (SETQ CLASS-METHOD-SYMBOL (GENSYM))) (PUTPROP CLASS-METHOD-SYMBOL CLASS-SYMBOL 'ENTITY-TYPEP) (SET CLASS-METHOD-SYMBOL SELF) (COND ((NULL NAME) (SETQ NAME (MAKE-CLASS-NAME CLASS-SYMBOL)))) ;SUPERCLASS IS AN ENTITY OR LIST OF ENTITIES. (SET-METHOD-SUPERCLASS CLASS-METHOD-SYMBOL SUPERCLASS) (SETQ INSTANCE-PATTERN (UNION INSTANCE-PATTERN (COND ((ENTITYP SUPERCLASS) (<- SUPERCLASS ':INSTANCE-PATTERN)) (T (APPLY 'UNION (MAPCAR (FUNCTION (LAMBDA (SC) (<- SC ':INSTANCE-PATTERN))) SUPERCLASS)))))) (COND ((ENTITYP SUPERCLASS) (<- SUPERCLASS ':ADD-IMMEDIATE-SUBCLASS SELF)) (T (MAPC (FUNCTION (LAMBDA (SC) (<- SC ':ADD-IMMEDIATE-SUBCLASS SELF))) SUPERCLASS))) SELF) (DEFMETHOD (CLASS-CLASS :ADD-IMMEDIATE-SUBCLASS) (CLASS) (COND ((NULL (MEMQ CLASS IMMEDIATE-SUBCLASS-LIST)) (SETQ IMMEDIATE-SUBCLASS-LIST (CONS CLASS IMMEDIATE-SUBCLASS-LIST))))) (DEFMETHOD (CLASS-CLASS :CLASS-SYMBOL<-) (IGNORE) (FERROR NIL "Attempt to change CLASS-SYMBOL of ~S" SELF)) (DEFMETHOD (CLASS-CLASS :INSTANCE-PATTERN<-) (&REST IGNORE) (FERROR NIL "Attempt to change INSTANCE-PATTERN of ~S" SELF)) (DEFMETHOD (CLASS-CLASS :SUPERCLASS<-) (IGNORE) (FERROR NIL "Attempt to change SUPERCLASS of ~S" SELF)) ;This can be used only to add a class without instance variables. ; To add one that has instance variables, you must create a new ;subclass (which can be a phantom subclass if desired). (DEFMETHOD (CLASS-CLASS :ADD-SUPERCLASS) (SC) (COND ((NOT (NULL (<- SC ':INSTANCE-PATTERN))) (FERROR NIL "You can't add a superclass that has instance variables ~S" SC)) (T (SETQ SUPERCLASS (CONS SC (COND ((ENTITYP SUPERCLASS) (LIST SUPERCLASS)) (T SUPERCLASS)))) (SET-METHOD-SUPERCLASS CLASS-METHOD-SYMBOL SUPERCLASS)))) ;Returns a tree whose leaves are instances of CLASS-CLASS (DEFMETHOD (CLASS-CLASS :CLASS-CLASS-HIERARCHY) () (CONS SELF (COND ((EQ CLASS-SYMBOL 'OBJECT-CLASS) NIL) ((ENTITYP SUPERCLASS) (<- SUPERCLASS ':CLASS-CLASS-HIERARCHY)) (T (MAPCAR (FUNCTION (LAMBDA (X) (<- X ':CLASS-CLASS-HIERARCHY))) SUPERCLASS))))) (DEFMETHOD (OBJECT-CLASS :CLASS-HIERARCHY) () (<- (CLASS SELF) ':CLASS-CLASS-HIERARCHY)) (DEFMETHOD (CLASS-CLASS :CLASS-SYMBOL-HIERARCHY) () (CONS CLASS-SYMBOL (COND ((EQ CLASS-SYMBOL 'OBJECT-CLASS) NIL) ((ENTITYP SUPERCLASS) (<- SUPERCLASS ':CLASS-SYMBOL-HIERARCHY)) (T (MAPCAR (FUNCTION (LAMBDA (X) (<- X ':CLASS-SYMBOL-HIERARCHY))) SUPERCLASS))))) (DEFMETHOD (OBJECT-CLASS :SYMBOL-HIERARCHY) () (<- (CLASS SELF) ':CLASS-SYMBOL-HIERARCHY)) (DEFMETHOD (OBJECT-CLASS :PRINT-SELF) (&OPTIONAL (STREAM T) &REST IGNORE &AUX TEM) (COND ((NOT (ENTITYP SELF)) (PRIN1 SELF STREAM)) (T (PRINC "#<" STREAM) (PRIN1 (CLASS-NAME SELF) STREAM) (COND ((SETQ TEM (ASS (FUNCTION STRING-EQUAL) "NAME" (CLOSURE-ALIST SELF))) (TYO #/ STREAM) (PRINC (CDR TEM) STREAM) (AND PRINT-ENTITY-ADDRESSES-FLAG (FORMAT STREAM " ~O" (%POINTER SELF))) (TYO #/> STREAM)) (T ;Unfortunately, this gets rid of self recursions but not mutual recursions ;This is rather a crock anyway, comment it out. ; (MAPC #'(LAMBDA (E) ; (FORMAT STREAM " ~S: ~S" (CAR E) ;Don't recurse infinitely! ; (IF (EQ (CDR E) SELF) 'SELF ; (CDR E)))) ; (CLOSURE-ALIST SELF)) (FORMAT STREAM " ~O" (%POINTER SELF)) (TYO #/> STREAM))))) SELF) (DEFMETHOD (OBJECT-CLASS :DESCRIBE) (&OPTIONAL (STREAM STANDARD-OUTPUT) &REST IGNORE) (COND ((NOT (ENTITYP SELF)) (LET ((STANDARD-OUTPUT STREAM)) (DESCRIBE SELF))) (T (FORMAT STREAM "~%~S is an instance of ~S.~%Its components are:~%" SELF (CLASS SELF)) (MAPC (FUNCTION (LAMBDA (E) (FORMAT STREAM "~S: ~S~%" (CAR E) (CDR E)))) (CLOSURE-ALIST SELF)) (TERPRI STREAM))) SELF) ) ;This closes the PROGN far above. OK to generate ENTITIES since PRINT of them should ; work now ;; Ask a class which operations its instances handle. (DEFMETHOD (CLASS-CLASS :CLASS-OPERATIONS) (&OPTIONAL (SUPERIORS-FLAG T)) (DO ((ACCUM) (L (METHOD-LIST CLASS-METHOD-SYMBOL) (CDR L))) ((ATOM L) (AND L SUPERIORS-FLAG (BOUNDP L) (NEQ (SYMEVAL L) SELF) (SETQ ACCUM (UNION ACCUM (<- (SYMEVAL L) ':CLASS-OPERATIONS)))) ACCUM) (COND ((CONSP (CAR L)) (SETQ ACCUM (UNION ACCUM (COND ((ATOM (CAAR L)) (LIST (CAAR L))) (T (CAAR L)))))) (SUPERIORS-FLAG (SETQ ACCUM (UNION ACCUM (<- (SYMEVAL (CAR L)) ':CLASS-OPERATIONS NIL))))))) ;; Ask an object which operations it handles. ;; This definition is sufficient except for objects with ideosyncratic handlers, ;; which don't exist yet. (DEFMETHOD (OBJECT-CLASS :WHICH-OPERATIONS) (&OPTIONAL (SUPERIORS-FLAG T)) (<- (CLASS SELF) ':CLASS-OPERATIONS SUPERIORS-FLAG)) (defmethod (object-class :operation-handled-p) (operation) (memq operation (<- self :which-operations))) ;; This message sent to a class returns the method used by that class ;; to handle the specified operation. If there is none, NIL is returned. ;; If SUPERIORS-FLAG is NIL, then inherited methods are not searched. ;; This can be used to tell whether a class handles a certain operation at all, ;; or to get the handler once and call it many times, for efficiency. ;**can't use OPERATION as name of lambda variable, because that is used ; to receive the message key!! crock** (DEFMETHOD (CLASS-CLASS :METHOD-FOR) (OP &OPTIONAL (SUPERIORS-FLAG T)) (DO ((L (METHOD-LIST CLASS-METHOD-SYMBOL) (CDR L)) (TEM)) ((ATOM L) (AND L SUPERIORS-FLAG (BOUNDP L) (NEQ (SYMEVAL L) SELF) (<- (SYMEVAL L) ':METHOD-FOR OP))) (COND ((CONSP (CAR L)) (AND (COND ((CONSP (CAAR L)) (MEMQ OP (CAAR L))) (T (EQ OP (CAAR L)))) (RETURN (CDAR L)))) (SUPERIORS-FLAG (AND (SETQ TEM (<- (SYMEVAL (CAR L)) ':METHOD-FOR OP NIL)) (RETURN TEM)))))) ;; Ask an object how it will handle a given operation. (DEFMETHOD (OBJECT-CLASS :HANDLER-FOR) (OP) ;**likewise, dont call this OPERATION** (<- (CLASS SELF) ':METHOD-FOR OP)) ;;; No documentation for default (DEFMETHOD (OBJECT-CLASS :DOCUMENTATION) () NIL) (DEFCLASS NUMBER-CLASS OBJECT-CLASS ()) (DEFMETHOD-INSTANCE (NUMBER-CLASS :NEW) (&REST ARGS) (COND ((GETF ARGS ':VALUE)) (T 0))) (DEFCLASS SYMBOL-CLASS OBJECT-CLASS ()) ;I hope no one uses this method, since it doesn't work (DEFMETHOD-INSTANCE (SYMBOL-CLASS :NEW) (&REST ARGS) (APPLY 'MAKE-SYMBOL (GETF ARGS ':PNAME) ARGS)) (DEFCLASS FIXNUM-CLASS NUMBER-CLASS ()) ;GETS :NEW MESSAGE FROM NUMBER-CLASS (DEFCLASS FLONUM-CLASS NUMBER-CLASS ()) (DEFMETHOD-INSTANCE (FLONUM-CLASS :NEW) (&REST ARGS) (+ 0.0 (COND ((GETF ARGS ':VALUE)) (T 0.0)))) (DEFCLASS ARRAY-CLASS OBJECT-CLASS ()) (DEFMETHOD-INSTANCE (ARRAY-CLASS :NEW) (&REST ARGS) (APPLY 'MAKE-ARRAY ARGS)) (DEFCLASS CONS-CLASS OBJECT-CLASS ()) (DEFMETHOD-INSTANCE (CONS-CLASS :NEW) (&REST ARGS) (CONS (GETF ARGS ':CAR) (GETF ARGS ':CDR)))