diff --git a/src/clos/boot.lsp b/src/clos/boot.lsp index 11d085987..791137807 100644 --- a/src/clos/boot.lsp +++ b/src/clos/boot.lsp @@ -41,7 +41,11 @@ ;; itself as metaclass. MAKE-EMPTY-CLASS takes care of that. ;; (let* ((standard-class (make-empty-standard-class 'STANDARD-CLASS nil)) + (std-class (make-empty-standard-class 'STD-CLASS standard-class)) (standard-object (make-empty-standard-class 'STANDARD-OBJECT standard-class)) + (funcallable-standard-class + (make-empty-standard-class 'FUNCALLABLE-STANDARD-CLASS + standard-class)) (the-class (make-empty-standard-class 'CLASS standard-class)) (the-t (make-empty-standard-class 'T the-class)) ;; It does not matter that we pass NIL instead of a class object, @@ -52,7 +56,7 @@ collect (canonical-slot-to-direct-slot nil s))) (hash-table (make-hash-table :size 24))) - ;; 2) STANDARD-CLASS and CLASS are the only classes with slots. Create a + ;; 2) STANDARD-CLASS and CLASS and others are classes with slots. Create a ;; hash table for them, so that SLOT-VALUE works. Notice that we ;; make a intentional mistake: CLASS and STANDARD-CLASS share the same ;; hashtable!! @@ -68,11 +72,22 @@ (setf (class-slots the-class) (copy-list class-slots) (class-size the-class) (length class-slots) (slot-table the-class) hash-table - (class-direct-slots the-class) class-slots - (class-slots standard-class) standard-slots + (class-direct-slots the-class) class-slots) + (setf (class-slots standard-class) standard-slots (class-size standard-class) (length standard-slots) (slot-table standard-class) hash-table - (class-direct-slots standard-class) (set-difference standard-slots class-slots)) + (class-direct-slots standard-class) + (set-difference standard-slots class-slots)) + (setf (class-slots funcallable-standard-class) standard-slots + (class-size funcallable-standard-class) (length standard-slots) + (slot-table funcallable-standard-class) hash-table + (class-direct-slots funcallable-standard-class) + (class-direct-slots standard-class)) + (setf (class-slots std-class) standard-slots + (class-size std-class) (length standard-slots) + (slot-table std-class) hash-table + (class-direct-slots std-class) + (class-direct-slots standard-class)) ;; 3) Fix the class hierarchy (setf (class-direct-superclasses the-t) nil @@ -81,16 +96,22 @@ (class-direct-subclasses standard-object) (list the-class) (class-direct-superclasses the-class) (list standard-object) (class-direct-subclasses the-class) (list standard-class) - (class-direct-superclasses standard-class) (list the-class)) + (class-direct-superclasses std-class) (list the-class) + (class-direct-superclasses standard-class) (list std-class) + (class-direct-superclasses funcallable-standard-class) (list std-class)) (si::instance-sig-set the-class) + (si::instance-sig-set std-class) (si::instance-sig-set standard-class) (si::instance-sig-set standard-object) + (si::instance-sig-set funcallable-standard-class) (si::instance-sig-set the-t) ;; 4) Fix the class precedence list - (let ((cpl (list standard-class the-class standard-object the-t))) - (setf (class-precedence-list standard-class) cpl + (let ((cpl (list std-class the-class standard-object the-t))) + (setf (class-precedence-list std-class) cpl + (class-precedence-list standard-class) (list* standard-class cpl) + (class-precedence-list funcallable-standard-class) (list* funcallable-standard-class cpl) (class-precedence-list the-class) (cdr cpl) (class-precedence-list standard-object) (cddr cpl) (class-precedence-list the-t) (cdddr cpl))) @@ -99,6 +120,8 @@ ) (defconstant +the-standard-class+ (find-class 'standard-class nil)) +(defconstant +the-funcallable-standard-class+ + (find-class 'funcallable-standard-class nil)) (defmethod class-prototype ((class class)) (unless (slot-boundp class 'prototype) @@ -114,8 +137,8 @@ (defun find-slot-definition (class slot-name) (declare (si::c-local)) - (if nil #+nil ; TODO: fix - (eq (si:instance-class class) +the-standard-class+) + (if (or (eq (si:instance-class class) +the-standard-class+) + (eq (si:instance-class class) +the-funcallable-standard-class+)) (gethash slot-name (slot-table class) nil) (find slot-name (class-slots class) :key #'slot-definition-name))) diff --git a/src/clos/change.lsp b/src/clos/change.lsp index 782de4337..3d1bb83cf 100644 --- a/src/clos/change.lsp +++ b/src/clos/change.lsp @@ -50,7 +50,7 @@ #'shared-initialize (list new-data added-slots)))) (apply #'shared-initialize new-data added-slots initargs))) -(defmethod change-class ((instance standard-object) (new-class standard-class) +(defmethod change-class ((instance standard-object) (new-class std-class) &rest initargs) (let* ((old-instance (si::copy-instance instance)) (new-size (class-size new-class)) diff --git a/src/clos/fixup.lsp b/src/clos/fixup.lsp index fbcfd2f51..5c219b93a 100644 --- a/src/clos/fixup.lsp +++ b/src/clos/fixup.lsp @@ -43,7 +43,7 @@ x)))) (map-into direct-slots #'identity new-direct-slots) (map-into effective-slots #'identity new-effective-slots) - (when (typep class 'standard-class) + (when (typep class 'std-class) (std-create-slots-table class))) (mapc #'convert-one-class (class-direct-subclasses class))) @@ -65,12 +65,12 @@ (make-instances-obsolete (find-class 't)) (convert-one-class (find-class 't))) -(defmethod reader-method-class ((class standard-class) +(defmethod reader-method-class ((class std-class) (direct-slot direct-slot-definition) &rest initargs) (find-class 'standard-reader-method)) -(defmethod writer-method-class ((class standard-class) +(defmethod writer-method-class ((class std-class) (direct-slot direct-slot-definition) &rest initargs) (find-class 'standard-writer-method)) diff --git a/src/clos/inspect.lsp b/src/clos/inspect.lsp index 49fad1041..fe9f0fedf 100644 --- a/src/clos/inspect.lsp +++ b/src/clos/inspect.lsp @@ -58,7 +58,7 @@ (si::inspect-indent) (format t "It has no class slots.~%"))))) -(defmethod select-clos-N ((instance standard-class)) +(defun select-clos-N-inner-class (instance) (let* ((class (si:instance-class instance)) (local-slotds (slot-value class 'CLOS::SLOTS))) (if local-slotds @@ -83,30 +83,11 @@ (si::inspect-indent) (format t "It has no (local) slots.~%"))))) +(defmethod select-clos-N ((instance std-class)) + (select-clos-N-inner-class instance)) + (defmethod select-clos-N ((instance t)) - (let* ((class (si:instance-class instance)) - (local-slotds (slot-value class 'CLOS::SLOTS))) - (if local-slotds - (progn - (si::inspect-indent) - (format t "The (local) slots are:~%") - (incf si::*inspect-level*) - (dolist (slotd local-slotds) - (si::inspect-indent-1) - (format t "name : ~S" (clos::slot-definition-name slotd)) - (if (slot-boundp instance (clos::slot-definition-name slotd)) - (si::inspect-recursively "value:" - (slot-value instance (clos::slot-definition-name slotd)) -; (slot-value instance (clos::slot-definition-name slotd)) - ) - (si::inspect-print "value: Unbound" - nil -; (slot-value instance (clos::slot-definition-name slotd)) - ))) - (decf si::*inspect-level*)) - (progn - (si::inspect-indent) - (format t "It has no (local) slots.~%"))))) + (select-clos-N-inner-class instance)) (defmethod select-clos-L ((instance standard-object)) (let* ((class (si:instance-class instance)) @@ -130,7 +111,7 @@ (format t "It has no class slots.~%"))) (terpri))) -(defmethod select-clos-L ((instance standard-class)) +(defun select-clos-L-inner-class (instance) (let* ((class (si:instance-class instance)) (local-slotds (slot-value class 'CLOS::SLOTS))) (terpri) @@ -143,18 +124,11 @@ (format t "It has no (local) slots.~%"))) (terpri))) +(defmethod select-clos-L ((instance std-class)) + (select-clos-L-inner-class instance)) + (defmethod select-clos-L ((instance t)) - (let* ((class (si:instance-class instance)) - (local-slotds (slot-value class 'CLOS::SLOTS))) - (terpri) - (if local-slotds - (progn - (format t "The names of the (local) slots are:~%") - (dolist (slotd local-slotds) - (format t " ~S~%" (clos::slot-definition-name slotd)))) - (progn - (format t "It has no (local) slots.~%"))) - (terpri))) + (select-clos-L-inner-class instance)) (defmethod select-clos-J ((instance standard-object)) (let* ((class (si:instance-class instance)) @@ -185,7 +159,7 @@ (terpri) (terpri))))) -(defmethod select-clos-J ((instance standard-class)) +(defun select-clos-J-inner-class (instance) (let* ((class (si:instance-class instance)) (local-slotds (slot-value class 'CLOS::SLOTS)) (slotd (car (member (prog1 @@ -215,35 +189,11 @@ (terpri) (terpri))))) +(defmethod select-clos-J ((instance std-class)) + (select-clos-J-inner-class instance)) + (defmethod select-clos-J ((instance t)) - (let* ((class (si:instance-class instance)) - (local-slotds (slot-value class 'CLOS::SLOTS)) - (slotd (car (member (prog1 - (read-preserving-whitespace *query-io*) - (si::inspect-read-line)) - local-slotds - :key #'clos::slot-definition-name - :test #'eq)))) - (if slotd - (progn - (incf si::*inspect-level*) - (si::inspect-indent-1) - (format t "name : ~S" (clos::slot-definition-name slotd)) - (if (slot-boundp instance (clos::slot-definition-name slotd)) - (si::inspect-recursively "value:" - (slot-value instance (clos::slot-definition-name slotd)) -; (slot-value instance (clos::slot-definition-name slotd)) - ) - (si::inspect-print "value: Unbound" - nil -; (slot-value instance (clos::slot-definition-name slotd)) - )) - (decf si::*inspect-level*)) - (progn - (terpri) - (format t "~S is not a slot of the instance." (slot-definition-name slotd)) - (terpri) - (terpri))))) + (select-clos-J-inner-class instance)) (defun select-clos-? () (declare (si::c-local)) @@ -262,8 +212,9 @@ q (or Q): quits the inspection.~%~ )) (defmethod inspect-obj ((instance standard-object)) - (unless (eq (si:instance-class (si:instance-class instance)) - (find-class 'STANDARD-CLASS)) + (unless (let ((metaclass (si:instance-class (si:instance-class instance)))) + (or (eq metaclass (find-class 'STANDARD-CLASS)) + (eq metaclass (find-class 'FUNCALLABLE-STANDARD-CLASS)))) (terpri) (format t "No applicable method CLOS::INSPECT-OBJ for an instance~%") (format t "of class ~S" (si:instance-class instance)) @@ -320,7 +271,7 @@ q (or Q): quits the inspection.~%~ (si::inspect-indent))) (incf si::*inspect-level*)) -(defmethod inspect-obj ((instance standard-class)) +(defun inspect-obj-inner-class (instance) (decf si::*inspect-level*) (let* ((class (si:instance-class instance)) (local-slotds (slot-value class 'CLOS::SLOTS))) @@ -371,56 +322,11 @@ q (or Q): quits the inspection.~%~ (si::inspect-indent))) (incf si::*inspect-level*)) +(defmethod inspect-obj ((instance std-class)) + (inspect-obj-inner-class instance)) + (defmethod inspect-obj ((instance t)) - (decf si::*inspect-level*) - (let* ((class (si:instance-class instance)) - (local-slotds (slot-value class 'CLOS::SLOTS))) - (declare (type class)) - (loop - (format t "~S - clos object:" instance) - (incf si::*inspect-level*) - (si::inspect-indent) - (format t "- it is an instance of class named ~S," - (class-name class)) - (si::inspect-indent) - (format t "- it has ~A local slots: " (length local-slotds)) - (force-output) - (case (do ((char (read-char *query-io*) (read-char *query-io*))) - ((and (char/= char #\Space) (char/= #\Tab)) char)) - ((#\Newline #\Return) - (select-clos-N instance) - (return nil)) - ((#\n #\N) - (si::inspect-read-line) - (select-clos-N instance) - (return nil)) - ((#\s #\S) - (si::inspect-read-line) - (return nil)) - ((#\p #\P) - (si::inspect-read-line) - (si::select-P instance)) - ((#\a #\A) - (si::inspect-read-line) - (throw 'SI::ABORT-INSPECT nil)) - ((#\e #\E) - (si::select-E)) - ((#\q #\Q) - (si::inspect-read-line) - (throw 'SI::QUIT-INSPECT nil)) - ((#\l #\L) - (si::inspect-read-line) - (select-clos-L instance)) - ((#\j #\J) - (select-clos-J instance)) - ((#\?) - (si::inspect-read-line) - (select-clos-?)) - (t - (si::inspect-read-line))) - (decf si::*inspect-level*) - (si::inspect-indent))) - (incf si::*inspect-level*)) + (inspect-obj-inner-class instance)) ;;; ------------------------------------------------------------------------- ;;; diff --git a/src/clos/standard.lsp b/src/clos/standard.lsp index 994fb9fb3..ce0aa002e 100644 --- a/src/clos/standard.lsp +++ b/src/clos/standard.lsp @@ -167,7 +167,7 @@ class) -(defmethod shared-initialize :after ((class standard-class) slot-names &rest initargs &key +(defmethod shared-initialize :after ((class std-class) slot-names &rest initargs &key (optimize-slot-access (list *optimize-slot-access*)) sealedp) (setf (slot-value class 'optimize-slot-access) (first optimize-slot-access) @@ -186,6 +186,7 @@ (list (find-class (typecase class (STANDARD-CLASS 'STANDARD-OBJECT) (STRUCTURE-CLASS 'STRUCTURE-OBJECT) + (FUNCALLABLE-STANDARD-CLASS 'FUNCALLABLE-STANDARD-OBJECT) (otherwise (error "No :DIRECT-SUPERCLASS ~ argument was supplied for metaclass ~S." (class-of class)))))))) ;; FIXME!!! Here should come the invocation of VALIDATE-SUPERCLASS! @@ -203,10 +204,12 @@ argument was supplied for metaclass ~S." (class-of class)))))))) (defun find-slot-definition (class slot-name) (declare (si::c-local)) - (if nil #+nil ; TODO: fix - (eq (si:instance-class class) +the-standard-class+) - (gethash slot-name (slot-table class) nil) - (find slot-name (class-slots class) :key #'slot-definition-name))) + (let (table) + (if (and (or (eq (si:instance-class class) +the-standard-class+) + (eq (si:instance-class class) +the-funcallable-standard-class+)) + (not (eq (setf table (slot-table class)) 'SI::UNBOUND))) + (gethash slot-name table nil) + (find slot-name (class-slots class) :key #'slot-definition-name)))) (defmethod finalize-inheritance ((class class)) ;; FINALIZE-INHERITANCE computes the guts of what defines a class: the @@ -301,7 +304,7 @@ because it contains a reference to the undefined class~% ~A" (setf (gethash (slot-definition-name slotd) table) slotd)) (setf (slot-table class) table))) -(defmethod finalize-inheritance ((class standard-class)) +(defmethod finalize-inheritance ((class std-class)) (call-next-method) (std-create-slots-table class) (std-class-generate-accessors class)) @@ -496,7 +499,7 @@ because it contains a reference to the undefined class~% ~A" (return))))))))) slots)) -(defmethod compute-slots :around ((class standard-class)) +(defmethod compute-slots :around ((class std-class)) (std-class-compute-slots class (call-next-method))) ;;; ---------------------------------------------------------------------- @@ -586,8 +589,6 @@ because it contains a reference to the undefined class~% ~A" ;; the instance. ;; (dolist (slotd (class-direct-slots standard-class)) - #+(or) - (print (slot-definition-name slotd)) (multiple-value-bind (reader writer) (let ((name (slot-definition-name slotd)) (allocation (slot-definition-allocation slotd)) @@ -723,7 +724,7 @@ because it contains a reference to the undefined class~% ~A" ;;; ---------------------------------------------------------------------- ;;; Methods -(defmethod describe-object ((obj standard-class) (stream t)) +(defmethod describe-object ((obj std-class) (stream t)) (let ((slotds (class-slots (si:instance-class obj)))) (format t "~%~A is an instance of class ~A" obj (class-name (si:instance-class obj))) diff --git a/src/clos/stdmethod.lsp b/src/clos/stdmethod.lsp index 5fadf4e0d..98c40933c 100644 --- a/src/clos/stdmethod.lsp +++ b/src/clos/stdmethod.lsp @@ -11,15 +11,22 @@ (in-package "CLOS") +;;; ---------------------------------------------------------------------- +;;; Funcallable object +;;; ---------------------------------------------------------------------- + +(defclass funcallable-standard-object (standard-object function) ()) ;;; ---------------------------------------------------------------------- ;;; Generic Functions ;;; ---------------------------------------------------------------------- -(defclass generic-function (standard-object function) ()) +(defclass generic-function (standard-object function) () + (:metaclass 'funcallable-standard-class)) (defclass standard-generic-function (generic-function) - #.+standard-generic-function-slots+) + #.+standard-generic-function-slots+ + (:metaclass 'funcallable-standard-class)) ;;;---------------------------------------------------------------------- ;;; Method