PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/src/clos-class1.lisp

https://github.com/ynd/clisp-branch--ynd-devel
Lisp | 743 lines | 487 code | 78 blank | 178 comment | 8 complexity | 706413c6a58af6b50747ab3abc9e9cbb MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, BSD-3-Clause
  1. ;;;; Common Lisp Object System for CLISP
  2. ;;;; Class metaobjects
  3. ;;;; Part 1: Class definitions, preliminary accessors.
  4. ;;;; Bruno Haible 2004-05-25
  5. ;;;; Sam Steingold 2005-2006
  6. (in-package "CLOS")
  7. ;;; Low-level representation:
  8. ;; In the runtime-system, the type "CLOS instance" exists.
  9. ;; The first component is the class-version, the rest are the local slot
  10. ;; values.
  11. ;; Classes are instances of type CLASS,
  12. ;; The "value" of a slot that is unbound, is #<UNBOUND> - what else?
  13. ;;; see RECORD.D :
  14. ;; (STD-INSTANCE-P obj) tests, if an object is a CLOS-instance.
  15. ;; (ALLOCATE-STD-INSTANCE class n) returns a non-funcallable CLOS-instance
  16. ;; with Class class and n-1 additional slots.
  17. ;; (ALLOCATE-FUNCALLABLE-INSTANCE class n) returns a funcallable CLOS-instance
  18. ;; with Class class and n-3 additional slots.
  19. ;;; see IO.D :
  20. ;; CLOS-instances are printed via (PRINT-OBJECT object stream).
  21. ;; (CLASS-OF object) see PREDTYPE.D, uses property CLOSCLASS.
  22. ;;; ===========================================================================
  23. ;;; Auxiliary stuff.
  24. ;; An empty hash table.
  25. (defconstant empty-ht
  26. (make-hash-table :key-type 'symbol :value-type 't
  27. :test 'eq :warn-if-needs-rehash-after-gc t
  28. :size 0))
  29. ;;; ===========================================================================
  30. ;;; The abstract class <super-class> allows defined classes and
  31. ;;; forward-references to classes to be treated in a homogenous way.
  32. (defvar *<super-class>-defclass*
  33. '(defclass super-class (standard-stablehash metaobject)
  34. (($classname ; (class-name class) = (class-classname class),
  35. ; a symbol
  36. :type symbol
  37. :initarg :name)
  38. ($direct-subclasses ; set of all direct subclasses, as a weak-list or
  39. ; weak-hash-table or NIL
  40. :type (or hash-table weak-list null)
  41. :initform nil))
  42. (:fixed-slot-locations nil)))
  43. ;;; ===========================================================================
  44. ;;; The abstract class <potential-class> is the abstract base class of all
  45. ;;; classes.
  46. (defvar *<potential-class>-defclass*
  47. '(defclass potential-class (specializer super-class)
  48. ()
  49. (:fixed-slot-locations t)))
  50. ;; Fixed slot locations.
  51. (defconstant *<potential-class>-classname-location* 3)
  52. (defconstant *<potential-class>-direct-subclasses-location* 4)
  53. ;; Preliminary accessors.
  54. (predefun class-classname (object)
  55. (sys::%record-ref object *<potential-class>-classname-location*))
  56. (predefun (setf class-classname) (new-value object)
  57. (setf (sys::%record-ref object *<potential-class>-classname-location*) new-value))
  58. (predefun class-direct-subclasses-table (object)
  59. (if (potential-class-p object)
  60. (sys::%record-ref object *<potential-class>-direct-subclasses-location*)
  61. (slot-value object '$direct-subclasses)))
  62. (predefun (setf class-direct-subclasses-table) (new-value object)
  63. (if (potential-class-p object)
  64. (setf (sys::%record-ref object *<potential-class>-direct-subclasses-location*) new-value)
  65. (setf (slot-value object '$direct-subclasses) new-value)))
  66. ;; Initialization of a <potential-class> instance.
  67. (defun shared-initialize-<potential-class> (class situation &rest args
  68. &key (name nil name-p)
  69. &allow-other-keys)
  70. (apply #'shared-initialize-<specializer> class situation args)
  71. (unless *classes-finished*
  72. ; Bootstrapping: Simulate the effect of #'%shared-initialize.
  73. (when (eq situation 't) ; called from initialize-instance?
  74. (setf (class-direct-subclasses-table class) nil)))
  75. (when (or (eq situation 't) name-p)
  76. (setf (class-classname class) (check-symbol name '(setf class-name))))
  77. class)
  78. ;;; ===========================================================================
  79. ;;; The class <forward-referenced-class> allows forward-references to classes
  80. ;;; to collect their direct subclasses already before they are defined:
  81. ;;; (defclass b (a) ())
  82. ;;; (defclass a () ())
  83. ;;; (class-direct-subclasses (find-class 'a)) => (#<STANDARD-CLASS B>)
  84. ;;; A forward-referenced-class's name is always a symbol that cannot be
  85. ;;; changed, and the forward-referenced-class is available as
  86. ;;; (get name 'CLOSCLASS), until it is replaced with the defined class.
  87. ;;; The MOP specification regarding <forward-referenced-class> is severely
  88. ;;; misdesigned. The actual meaning of a <forward-referenced-class> is a
  89. ;;; forward-reference to (= placeholder for) a not yet defined class. The only
  90. ;;; place where it is used is in the direct-superclasses list of some classes
  91. ;;; that are not yet finalized.
  92. ;;;
  93. ;;; Putting it under <class> is a mistake because:
  94. ;;; 1. Classes fundamentally describe the slots and operations available
  95. ;;; on its (direct and indirect) instances. But a forward-referenced
  96. ;;; class can never have (direct and indirect) instances, since the
  97. ;;; slots and operations are not yet known.
  98. ;;; 2. All the generic functions on <class>, such as class-precedence-list
  99. ;;; or class-direct-default-initargs, make no sense on a
  100. ;;; <forward-referenced-class> - since the real information is not yet
  101. ;;; available.
  102. ;;; 3. <class> inherits from <specializer>, but it makes no sense to use
  103. ;;; a <forward-referenced-class> as a specializer in a method or as a
  104. ;;; type in TYPEP or SUBTYPEP.
  105. ;;;
  106. ;;; This is also backed by the fact that this MOP implementation has three
  107. ;;; times more tests for <defined-class> (i.e. for <class> without
  108. ;;; <forward-referenced-class>) than for <potential-class>.
  109. ;;;
  110. ;;; A better design would be to define an abstract class <superclass> and
  111. ;;; let <forward-referenced-class> inherit from it:
  112. ;;; (defclass super-class () ...)
  113. ;;; (defclass class (super-class specializer) ...)
  114. ;;; (defclass forward-referenced-class (super-class) ...)
  115. ;;; and (class-direct-superclasses class) would simply be a list of
  116. ;;; <super-class> instances.
  117. ;; The proper <forward-referenced-class> inherits from <super-class> but
  118. ;; not from <specializer>.
  119. (defvar *<forward-reference-to-class>-defclass*
  120. '(defclass forward-reference-to-class (super-class)
  121. ()
  122. (:fixed-slot-locations nil)))
  123. ;; The crappy <forward-referenced-class> from the MOP is subclass of
  124. ;; <potential-class> and thus also of <specializer>.
  125. (defvar *<misdesigned-forward-referenced-class>-defclass*
  126. '(defclass misdesigned-forward-referenced-class (forward-reference-to-class potential-class)
  127. ()
  128. (:fixed-slot-locations nil)))
  129. ;;; ===========================================================================
  130. ;;; The abstract class <defined-class> allows built-in objects, user-defined
  131. ;;; objects and proxies to external worlds to be treated in a homogenous way.
  132. (defvar *<defined-class>-defclass*
  133. '(defclass defined-class (potential-class)
  134. (($direct-superclasses ; list of all direct superclasses (or their names,
  135. ; while the class is waiting to be finalized)
  136. :type list
  137. :initarg :direct-superclasses)
  138. ($all-superclasses ; hash table of all superclasses (including
  139. ; the class itself)
  140. :type hash-table)
  141. ($precedence-list ; ordered list of all superclasses (with the class
  142. ; itself first), or NIL while the class is waiting
  143. ; to be finalized
  144. :type list)
  145. ($direct-slots ; list of all freshly added slots (as
  146. ; direct-slot-definition instances)
  147. :type list
  148. :initarg :direct-slots)
  149. ($slots ; list of all slots (as effective-slot-definition
  150. ; instances)
  151. :type list)
  152. ($slot-location-table ; hash table slotname -> descriptor
  153. ; where the descriptor is either
  154. ; - the location of the slot (a fixnum or cons), or
  155. ; - its effective slot definition
  156. :type hash-table
  157. :initform empty-ht)
  158. ($direct-default-initargs ; freshly added default-initargs
  159. ; (as alist initarg -> (form function))
  160. :type list
  161. :initarg :direct-default-initargs)
  162. ($default-initargs ; default-initargs
  163. ; (as alist initarg -> (form function))
  164. )
  165. ($documentation ; string or NIL
  166. :type (or string null)
  167. :initarg :documentation)
  168. ($listeners ; list of objects to be notified upon a change
  169. :type list
  170. :initform nil)
  171. ($initialized ; describes which parts of the class are initialized
  172. :type (integer 0 6) ; 0 = nothing
  173. ; 1 = name
  174. ; 2 = likewise, plus direct-... info
  175. ; 3 = likewise, plus class-precedence-list
  176. ; 4 = likewise, plus class-all-superclasses
  177. ; 5 = likewise, plus class-slots
  178. ; 6 = likewise, plus slot-location-table, default-initargs
  179. :initform 0))
  180. (:fixed-slot-locations t)))
  181. ;; Fixed slot locations.
  182. (defconstant *<defined-class>-direct-superclasses-location* 5)
  183. (defconstant *<defined-class>-all-superclasses-location* 6)
  184. (defconstant *<defined-class>-precedence-list-location* 7)
  185. (defconstant *<defined-class>-direct-slots-location* 8)
  186. (defconstant *<defined-class>-slots-location* 9)
  187. (defconstant *<defined-class>-slot-location-table-location* 10)
  188. (defconstant *<defined-class>-direct-default-initargs-location* 11)
  189. (defconstant *<defined-class>-default-initargs-location* 12)
  190. (defconstant *<defined-class>-documentation-location* 13)
  191. (defconstant *<defined-class>-listeners-location* 14)
  192. (defconstant *<defined-class>-initialized-location* 15)
  193. ;; Preliminary accessors.
  194. (predefun class-direct-superclasses (object)
  195. (sys::%record-ref object *<defined-class>-direct-superclasses-location*))
  196. (predefun (setf class-direct-superclasses) (new-value object)
  197. (setf (sys::%record-ref object *<defined-class>-direct-superclasses-location*) new-value))
  198. (predefun class-all-superclasses (object)
  199. (sys::%record-ref object *<defined-class>-all-superclasses-location*))
  200. (predefun (setf class-all-superclasses) (new-value object)
  201. (setf (sys::%record-ref object *<defined-class>-all-superclasses-location*) new-value))
  202. (predefun class-precedence-list (object)
  203. (sys::%record-ref object *<defined-class>-precedence-list-location*))
  204. (predefun (setf class-precedence-list) (new-value object)
  205. (setf (sys::%record-ref object *<defined-class>-precedence-list-location*) new-value))
  206. (predefun class-direct-slots (object)
  207. (sys::%record-ref object *<defined-class>-direct-slots-location*))
  208. (predefun (setf class-direct-slots) (new-value object)
  209. (setf (sys::%record-ref object *<defined-class>-direct-slots-location*) new-value))
  210. (predefun class-slots (object)
  211. (sys::%record-ref object *<defined-class>-slots-location*))
  212. (predefun (setf class-slots) (new-value object)
  213. (setf (sys::%record-ref object *<defined-class>-slots-location*) new-value))
  214. (predefun class-slot-location-table (object)
  215. (sys::%record-ref object *<defined-class>-slot-location-table-location*))
  216. (predefun (setf class-slot-location-table) (new-value object)
  217. (setf (sys::%record-ref object *<defined-class>-slot-location-table-location*) new-value))
  218. (predefun class-direct-default-initargs (object)
  219. (sys::%record-ref object *<defined-class>-direct-default-initargs-location*))
  220. (predefun (setf class-direct-default-initargs) (new-value object)
  221. (setf (sys::%record-ref object *<defined-class>-direct-default-initargs-location*) new-value))
  222. (predefun class-default-initargs (object)
  223. (sys::%record-ref object *<defined-class>-default-initargs-location*))
  224. (predefun (setf class-default-initargs) (new-value object)
  225. (setf (sys::%record-ref object *<defined-class>-default-initargs-location*) new-value))
  226. (predefun class-documentation (object)
  227. (sys::%record-ref object *<defined-class>-documentation-location*))
  228. (predefun (setf class-documentation) (new-value object)
  229. (setf (sys::%record-ref object *<defined-class>-documentation-location*) new-value))
  230. (predefun class-listeners (object)
  231. (sys::%record-ref object *<defined-class>-listeners-location*))
  232. (predefun (setf class-listeners) (new-value object)
  233. (setf (sys::%record-ref object *<defined-class>-listeners-location*) new-value))
  234. (predefun class-initialized (object)
  235. (sys::%record-ref object *<defined-class>-initialized-location*))
  236. (predefun (setf class-initialized) (new-value object)
  237. (setf (sys::%record-ref object *<defined-class>-initialized-location*) new-value))
  238. (defun canonicalized-slot-p (x)
  239. ; A "canonicalized slot specification" is a special kind of property list.
  240. ; See MOP p. 13-15.
  241. (and (proper-list-p x)
  242. (evenp (length x))
  243. (let ((default '#:default))
  244. (not (eq (getf x ':name default) default)))))
  245. (defun canonicalized-default-initarg-p (x)
  246. ; A "canonicalized default initarg" is an element of an alist mapping
  247. ; a slot name (a symbol) to a list of the form (form function).
  248. ; See MOP p. 16.
  249. (and (consp x) (symbolp (first x))
  250. (consp (cdr x)) (consp (cddr x)) (functionp (third x))
  251. (null (cdddr x))))
  252. ;; Initialization of a <defined-class> instance.
  253. (defun shared-initialize-<defined-class> (class situation &rest args
  254. &key (name nil)
  255. (direct-superclasses nil direct-superclasses-p)
  256. ((:direct-slots direct-slots-as-lists) '() direct-slots-as-lists-p)
  257. ((direct-slots direct-slots-as-metaobjects) '() direct-slots-as-metaobjects-p)
  258. (direct-default-initargs nil direct-default-initargs-p)
  259. (documentation nil documentation-p)
  260. &allow-other-keys
  261. &aux old-direct-superclasses)
  262. (setq old-direct-superclasses
  263. (if (eq situation 't) ; called from initialize-instance?
  264. '()
  265. (sys::%record-ref class *<defined-class>-direct-superclasses-location*)))
  266. (apply #'shared-initialize-<potential-class> class situation args)
  267. (unless *classes-finished*
  268. ; Bootstrapping: Simulate the effect of #'%shared-initialize.
  269. (when (eq situation 't) ; called from initialize-instance?
  270. (setf (class-slot-location-table class) empty-ht)
  271. (setf (class-listeners class) nil)
  272. (setf (class-initialized class) 0)))
  273. (when (eq situation 't)
  274. ; shared-initialize-<potential-class> has initialized the name.
  275. (setf (class-initialized class) 1))
  276. ; Get the name, for error message purposes.
  277. (setq name (class-classname class))
  278. (when (or (eq situation 't) direct-superclasses-p)
  279. ; Check the direct-superclasses.
  280. (unless (proper-list-p direct-superclasses)
  281. (error (TEXT "(~S ~S) for class ~S: The ~S argument should be a proper list, not ~S")
  282. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  283. 'class name ':direct-superclasses direct-superclasses))
  284. (unless (every #'(lambda (x)
  285. (or (defined-class-p x)
  286. (forward-reference-to-class-p x)))
  287. direct-superclasses)
  288. (error (TEXT "(~S ~S) for class ~S: The direct-superclasses list should consist of classes, not ~S")
  289. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  290. 'class name direct-superclasses))
  291. (when (and (> (length direct-superclasses) 1)
  292. (typep class <structure-class>))
  293. (error (TEXT "(~S ~S) for class ~S: The metaclass ~S forbids more than one direct superclass: It does not support multiple inheritance.")
  294. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  295. 'class name (class-of class)))
  296. (dolist (sc direct-superclasses)
  297. (when (defined-class-p sc)
  298. (check-allowed-superclass class sc)))
  299. (when (null direct-superclasses)
  300. (setq direct-superclasses (default-direct-superclasses class))))
  301. (when (or (eq situation 't) direct-slots-as-lists-p)
  302. ; Check the direct-slots.
  303. (unless (proper-list-p direct-slots-as-lists)
  304. (error (TEXT "(~S ~S) for class ~S: The ~S argument should be a proper list, not ~S")
  305. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  306. 'class name ':direct-slots direct-slots-as-lists))
  307. (dolist (sl direct-slots-as-lists)
  308. (unless (canonicalized-slot-p sl)
  309. (error (TEXT "(~S ~S) for class ~S: The direct slot specification ~S is not in the canonicalized form (slot-name initform initfunction).")
  310. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  311. 'class name sl))))
  312. (when (or (eq situation 't) direct-default-initargs-p)
  313. ; Check the direct-default-initargs.
  314. (unless (proper-list-p direct-default-initargs)
  315. (error (TEXT "(~S ~S) for class ~S: The ~S argument should be a proper list, not ~S")
  316. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  317. 'class name ':direct-default-initargs direct-default-initargs))
  318. (dolist (definitarg direct-default-initargs)
  319. (unless (canonicalized-default-initarg-p definitarg)
  320. (error (TEXT "(~S ~S) for class ~S: The direct default initarg ~S is not in canonicalized form (a property list).")
  321. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  322. 'class name definitarg))))
  323. (when (or (eq situation 't) documentation-p)
  324. ; Check the documentation.
  325. (unless (or (null documentation) (stringp documentation))
  326. (error (TEXT "(~S ~S) for class ~S: The ~S argument should be a string or NIL, not ~S")
  327. (if (eq situation 't) 'initialize-instance 'shared-initialize)
  328. 'class name :documentation documentation)))
  329. ; Fill the slots.
  330. (when (or (eq situation 't) direct-superclasses-p)
  331. (setf (class-direct-superclasses class) (copy-list direct-superclasses))
  332. (update-subclasses-sets class old-direct-superclasses direct-superclasses))
  333. (when (or (eq situation 't) direct-slots-as-lists-p direct-slots-as-metaobjects-p)
  334. (setf (class-direct-slots class)
  335. (if direct-slots-as-metaobjects-p
  336. direct-slots-as-metaobjects
  337. (convert-direct-slots class direct-slots-as-lists))))
  338. (when (or (eq situation 't) direct-default-initargs-p)
  339. (setf (class-direct-default-initargs class) direct-default-initargs))
  340. (when (or (eq situation 't) documentation-p)
  341. (setf (class-documentation class) documentation))
  342. ; The following slots are initialized by the subclass' shared-initialize:
  343. ; all-superclasses
  344. ; precedence-list
  345. ; slots
  346. ; slot-location-table
  347. ; default-initargs
  348. ; Now allow the user to call some class-xxx accessor functions.
  349. (when (eq situation 't)
  350. (setf (class-initialized class) 2))
  351. class)
  352. ;;; ===========================================================================
  353. ;;; The class <built-in-class> represents those classes for which the user
  354. ;;; cannot create subclasses.
  355. (defvar <built-in-class> 'built-in-class)
  356. (defvar *<built-in-class>-defclass*
  357. '(defclass built-in-class (defined-class)
  358. (($prototype ; class prototype - an instance
  359. :type t))
  360. (:fixed-slot-locations t)))
  361. (defvar *<built-in-class>-class-version* (make-class-version))
  362. ;; Fixed slot locations.
  363. (defconstant *<built-in-class>-prototype-location* 16)
  364. (defconstant *<built-in-class>-instance-size* 17)
  365. ;;; ===========================================================================
  366. ;;; The class <slotted-class> represents those classes for which the local
  367. ;;; slot values are stored in the instance. It also represents common
  368. ;;; behaviour of <standard-class> and <structure-class>.
  369. (defvar *<slotted-class>-defclass*
  370. '(defclass slotted-class (defined-class)
  371. (($subclass-of-stablehash-p ; true if <standard-stablehash> or
  372. ; <structure-stablehash> is among the superclasses
  373. :type boolean)
  374. ($generic-accessors ; flag whether to create the accessors as methods;
  375. ; if false, regular functions are used
  376. :initform t)
  377. ($direct-accessors ; automatically generated accessor methods
  378. ; (as plist)
  379. :type list
  380. :initform '())
  381. ($valid-initargs-from-slots ; list of valid initargs, computed from slots
  382. :type list) ; (not including those declared valid by methods!)
  383. ($instance-size ; number of local slots of the direct instances + 1
  384. :type (integer 1 *)))
  385. (:fixed-slot-locations t)))
  386. ;; Fixed slot locations.
  387. (defconstant *<slotted-class>-subclass-of-stablehash-p-location* 16)
  388. (defconstant *<slotted-class>-generic-accessors-location* 17)
  389. (defconstant *<slotted-class>-direct-accessors-location* 18)
  390. (defconstant *<slotted-class>-valid-initargs-from-slots-location* 19)
  391. (defconstant *<slotted-class>-instance-size-location* 20)
  392. ;; Preliminary accessors.
  393. (predefun class-subclass-of-stablehash-p (object)
  394. (sys::%record-ref object *<slotted-class>-subclass-of-stablehash-p-location*))
  395. (predefun (setf class-subclass-of-stablehash-p) (new-value object)
  396. (setf (sys::%record-ref object *<slotted-class>-subclass-of-stablehash-p-location*) new-value))
  397. (predefun class-generic-accessors (object)
  398. (sys::%record-ref object *<slotted-class>-generic-accessors-location*))
  399. (predefun (setf class-generic-accessors) (new-value object)
  400. (setf (sys::%record-ref object *<slotted-class>-generic-accessors-location*) new-value))
  401. (predefun class-direct-accessors (object)
  402. (sys::%record-ref object *<slotted-class>-direct-accessors-location*))
  403. (predefun (setf class-direct-accessors) (new-value object)
  404. (setf (sys::%record-ref object *<slotted-class>-direct-accessors-location*) new-value))
  405. (predefun class-valid-initargs-from-slots (object)
  406. (sys::%record-ref object *<slotted-class>-valid-initargs-from-slots-location*))
  407. (predefun (setf class-valid-initargs-from-slots) (new-value object)
  408. (setf (sys::%record-ref object *<slotted-class>-valid-initargs-from-slots-location*) new-value))
  409. (predefun class-instance-size (object)
  410. (sys::%record-ref object *<slotted-class>-instance-size-location*))
  411. (predefun (setf class-instance-size) (new-value object)
  412. (setf (sys::%record-ref object *<slotted-class>-instance-size-location*) new-value))
  413. ;; Initialization of a <slotted-class> instance.
  414. (defun shared-initialize-<slotted-class> (class situation &rest args
  415. &key (generic-accessors t generic-accessors-p)
  416. &allow-other-keys)
  417. (apply #'shared-initialize-<defined-class> class situation args)
  418. (unless *classes-finished*
  419. ; Bootstrapping: Simulate the effect of #'%shared-initialize.
  420. (when (eq situation 't) ; called from initialize-instance?
  421. (setf (class-direct-accessors class) '())))
  422. (when (or (eq situation 't) generic-accessors-p)
  423. (setf (class-generic-accessors class) generic-accessors))
  424. ; The following slots are initialized by the subclass' shared-initialize:
  425. ; subclass-of-stablehash-p
  426. ; valid-initargs-from-slots
  427. ; instance-size
  428. class)
  429. ;;; ===========================================================================
  430. ;;; The class <structure-class> represents classes like those defined through
  431. ;;; DEFSTRUCT.
  432. (defvar <structure-class> 'structure-class)
  433. (defvar *<structure-class>-defclass*
  434. '(defclass structure-class (slotted-class)
  435. (($names ; encoding of the include-nesting, a list
  436. ; (name_1 ... name_i-1 name_i) with name=name_1,
  437. :type cons) ; name_1 contains name_2, ..., name_i-1 contains name_i.
  438. ($kconstructor ; name of keyword constructor function
  439. :type symbol)
  440. ($boa-constructors ; list of all BOA constructor function names
  441. :type list)
  442. ($copier ; name of the copier function
  443. :type symbol)
  444. ($predicate ; name of the predicate function
  445. :type symbol)
  446. ($prototype ; class prototype - an instance or NIL
  447. :type (or structure-object null)))
  448. (:fixed-slot-locations t)))
  449. (defvar *<structure-class>-class-version* (make-class-version))
  450. ;; Fixed slot locations.
  451. (defconstant *<structure-class>-names-location* 21)
  452. (defconstant *<structure-class>-kconstructor-location* 22)
  453. (defconstant *<structure-class>-boa-constructors-location* 23)
  454. (defconstant *<structure-class>-copier-location* 24)
  455. (defconstant *<structure-class>-predicate-location* 25)
  456. (defconstant *<structure-class>-prototype-location* 26)
  457. ;; Preliminary accessors.
  458. (predefun class-names (object)
  459. (sys::%record-ref object *<structure-class>-names-location*))
  460. (predefun (setf class-names) (new-value object)
  461. (setf (sys::%record-ref object *<structure-class>-names-location*) new-value))
  462. (predefun class-kconstructor (object)
  463. (sys::%record-ref object *<structure-class>-kconstructor-location*))
  464. (predefun (setf class-kconstructor) (new-value object)
  465. (setf (sys::%record-ref object *<structure-class>-kconstructor-location*) new-value))
  466. (predefun class-boa-constructors (object)
  467. (sys::%record-ref object *<structure-class>-boa-constructors-location*))
  468. (predefun (setf class-boa-constructors) (new-value object)
  469. (setf (sys::%record-ref object *<structure-class>-boa-constructors-location*) new-value))
  470. (predefun class-copier (object)
  471. (sys::%record-ref object *<structure-class>-copier-location*))
  472. (predefun (setf class-copier) (new-value object)
  473. (setf (sys::%record-ref object *<structure-class>-copier-location*) new-value))
  474. (predefun class-predicate (object)
  475. (sys::%record-ref object *<structure-class>-predicate-location*))
  476. (predefun (setf class-predicate) (new-value object)
  477. (setf (sys::%record-ref object *<structure-class>-predicate-location*) new-value))
  478. (defconstant *<structure-class>-instance-size* 27)
  479. ;;; ===========================================================================
  480. ;;; The class <semi-standard-class> is a common superclass of <standard-class>
  481. ;;; and <funcallable-standard-class>. Both implement the "default" CLOS
  482. ;;; behaviour.
  483. (defvar <semi-standard-class> 'semi-standard-class)
  484. (defvar *<semi-standard-class>-defclass*
  485. '(defclass semi-standard-class (slotted-class)
  486. (($current-version ; most recent class-version, points back to this
  487. ; class
  488. :type simple-vector)
  489. ($funcallablep ; flag whether direct instances are funcallable
  490. :type boolean)
  491. ($fixed-slot-locations ; flag whether to guarantee same slot locations
  492. ; in all subclasses
  493. :initarg :fixed-slot-locations
  494. )
  495. ($instantiated ; true if an instance has already been created
  496. :type boolean
  497. :initform nil)
  498. ($direct-instance-specializers ; set of all eql-specializers of direct
  499. ; instances that may be used in methods, as a
  500. ; weak-list or weak-hash-table or NIL
  501. :type (or hash-table weak-list null)
  502. :initform nil)
  503. ($finalized-direct-subclasses ; set of all finalized direct subclasses,
  504. ; as a weak-list or weak-hash-table or NIL
  505. :type (or hash-table weak-list null)
  506. :initform '())
  507. ($prototype ; class prototype - an instance or NIL
  508. :type (or standard-object null)))
  509. (:default-initargs :fixed-slot-locations nil)
  510. (:fixed-slot-locations t)))
  511. ;; Fixed slot locations.
  512. (defconstant *<semi-standard-class>-current-version-location* 21)
  513. (defconstant *<semi-standard-class>-funcallablep-location* 22)
  514. (defconstant *<semi-standard-class>-fixed-slot-locations-location* 23)
  515. (defconstant *<semi-standard-class>-instantiated-location* 24)
  516. (defconstant *<semi-standard-class>-direct-instance-specializers-location* 25)
  517. (defconstant *<semi-standard-class>-finalized-direct-subclasses-location* 26)
  518. (defconstant *<semi-standard-class>-prototype-location* 27)
  519. ;; Preliminary accessors.
  520. (predefun class-current-version (object)
  521. (sys::%record-ref object *<semi-standard-class>-current-version-location*))
  522. (predefun (setf class-current-version) (new-value object)
  523. (setf (sys::%record-ref object *<semi-standard-class>-current-version-location*) new-value))
  524. (predefun class-funcallablep (object)
  525. (sys::%record-ref object *<semi-standard-class>-funcallablep-location*))
  526. (predefun (setf class-funcallablep) (new-value object)
  527. (setf (sys::%record-ref object *<semi-standard-class>-funcallablep-location*) new-value))
  528. (predefun class-fixed-slot-locations (object)
  529. (sys::%record-ref object *<semi-standard-class>-fixed-slot-locations-location*))
  530. (predefun (setf class-fixed-slot-locations) (new-value object)
  531. (setf (sys::%record-ref object *<semi-standard-class>-fixed-slot-locations-location*) new-value))
  532. (predefun class-instantiated (object)
  533. (sys::%record-ref object *<semi-standard-class>-instantiated-location*))
  534. (predefun (setf class-instantiated) (new-value object)
  535. (setf (sys::%record-ref object *<semi-standard-class>-instantiated-location*) new-value))
  536. (predefun class-direct-instance-specializers-table (object)
  537. (sys::%record-ref object *<semi-standard-class>-direct-instance-specializers-location*))
  538. (predefun (setf class-direct-instance-specializers-table) (new-value object)
  539. (setf (sys::%record-ref object *<semi-standard-class>-direct-instance-specializers-location*) new-value))
  540. (predefun class-finalized-direct-subclasses-table (object)
  541. (sys::%record-ref object *<semi-standard-class>-finalized-direct-subclasses-location*))
  542. (predefun (setf class-finalized-direct-subclasses-table) (new-value object)
  543. (setf (sys::%record-ref object *<semi-standard-class>-finalized-direct-subclasses-location*) new-value))
  544. (predefun class-prototype (object)
  545. (sys::%record-ref object *<semi-standard-class>-prototype-location*))
  546. (predefun (setf class-prototype) (new-value object)
  547. (setf (sys::%record-ref object *<semi-standard-class>-prototype-location*) new-value))
  548. ;;; ===========================================================================
  549. ;;; The class <standard-class> represents classes with the "default" CLOS
  550. ;;; behaviour.
  551. (defvar <standard-class> 'standard-class) ; ABI
  552. (defvar *<standard-class>-defclass*
  553. '(defclass standard-class (semi-standard-class)
  554. ()
  555. (:fixed-slot-locations t)))
  556. (defvar *<standard-class>-class-version* (make-class-version))
  557. (defconstant *<standard-class>-instance-size* 28)
  558. ;; For DEFCLASS macro expansions.
  559. (defconstant *<standard-class>-valid-initialization-keywords* ; ABI
  560. '(:name :direct-superclasses :direct-slots :direct-default-initargs
  561. :documentation :generic-accessors :fixed-slot-locations))
  562. (defconstant *<standard-class>-default-initargs* '(:fixed-slot-locations nil))
  563. ;;; ===========================================================================
  564. ;;; The classes <funcallable-standard-class> and <funcallable-standard-object>
  565. ;;; can be defined later.
  566. (defvar <funcallable-standard-class> nil)
  567. (defvar *<funcallable-standard-class>-class-version* nil)
  568. (defvar <funcallable-standard-object> nil)
  569. ;;; ===========================================================================
  570. ;;; Type tests.
  571. (defun built-in-class-p (object) ; ABI
  572. (and (std-instance-p object)
  573. (let ((cv (sys::%record-ref object 0)))
  574. ; Treat the most frequent cases first, for speed and bootstrapping.
  575. (cond ((eq cv *<standard-class>-class-version*) nil)
  576. ((eq cv *<structure-class>-class-version*) nil)
  577. ((eq cv *<built-in-class>-class-version*) t)
  578. (t ; Now a slow, but general instanceof test.
  579. (gethash <built-in-class>
  580. (class-all-superclasses (class-of object))))))))
  581. (defun structure-class-p (object) ; ABI
  582. (and (std-instance-p object)
  583. (let ((cv (sys::%record-ref object 0)))
  584. ; Treat the most frequent cases first, for speed and bootstrapping.
  585. (cond ((eq cv *<standard-class>-class-version*) nil)
  586. ((eq cv *<structure-class>-class-version*) t)
  587. ((eq cv *<built-in-class>-class-version*) nil)
  588. (t ; Now a slow, but general instanceof test.
  589. (gethash <structure-class>
  590. (class-all-superclasses (class-of object))))))))
  591. (defun semi-standard-class-p (object)
  592. (and (std-instance-p object)
  593. (let ((cv (sys::%record-ref object 0)))
  594. ; Treat the most frequent cases first, for speed and bootstrapping.
  595. (cond ((eq cv *<standard-class>-class-version*) t)
  596. ((eq cv *<structure-class>-class-version*) nil)
  597. ((eq cv *<built-in-class>-class-version*) nil)
  598. (t ; Now a slow, but general instanceof test.
  599. (gethash <semi-standard-class>
  600. (class-all-superclasses (class-of object))))))))
  601. (defun standard-class-p (object) ; ABI
  602. (and (std-instance-p object)
  603. (let ((cv (sys::%record-ref object 0)))
  604. ; Treat the most frequent cases first, for speed and bootstrapping.
  605. (cond ((eq cv *<standard-class>-class-version*) t)
  606. ((eq cv *<structure-class>-class-version*) nil)
  607. ((eq cv *<built-in-class>-class-version*) nil)
  608. (t ; Now a slow, but general instanceof test.
  609. (gethash <standard-class>
  610. (class-all-superclasses (class-of object))))))))
  611. (sys::def-atomic-type potential-class potential-class-p)
  612. (sys::def-atomic-type defined-class defined-class-p)
  613. (sys::def-atomic-type built-in-class built-in-class-p)
  614. (sys::def-atomic-type structure-class structure-class-p)
  615. (sys::def-atomic-type standard-class standard-class-p)
  616. (defun forward-reference-to-class-p (object)
  617. (and (std-instance-p object)
  618. (gethash <forward-reference-to-class>
  619. (class-all-superclasses (class-of object)))))
  620. ;;; ===========================================================================
  621. ;;; Copying.
  622. (defun copy-standard-class (class)
  623. (let* ((n (sys::%record-length class))
  624. (copy (allocate-metaobject-instance (sys::%record-ref class 0) n)))
  625. (dotimes (i n) (setf (sys::%record-ref copy i) (sys::%record-ref class i)))
  626. copy))
  627. (defun print-object-<potential-class> (object stream)
  628. (if (and *print-readably* (defined-class-p object))
  629. ; Only defined-class instances can be restored through FIND-CLASS.
  630. (write (sys::make-load-time-eval `(FIND-CLASS ',(class-classname object)))
  631. :stream stream)
  632. (print-unreadable-object (object stream :type t)
  633. (let ((name (class-classname object)))
  634. ;; The class <string> has two names: cl:string and cs-cl:string.
  635. ;; Which one we show, depends on *package*.
  636. (when (and (eq name 'string)
  637. (eq (find-symbol "STRING" *package*) 'cs-cl:string))
  638. (setq name 'cs-cl:string))
  639. (write name :stream stream))
  640. (when (semi-standard-class-p object)
  641. (if (and (slot-boundp object '$current-version)
  642. (class-version-p (class-current-version object))
  643. (slot-boundp object '$precedence-list))
  644. (progn
  645. (when (< (class-initialized object) 3) ; not yet finalized?
  646. (write-string " " stream)
  647. (write :incomplete :stream stream))
  648. ;; FIXME: Overhaul this questionable and confusing feature.
  649. (let ((serial (cv-serial (class-current-version object))))
  650. (unless (eql serial 0)
  651. (write-string " " stream)
  652. (write :version :stream stream)
  653. (write-string " " stream)
  654. (write serial :stream stream))))
  655. (progn
  656. (write-string " " stream)
  657. (write :uninitialized :stream stream)))))))
  658. (defun print-object-<forward-reference-to-class> (object stream)
  659. (print-unreadable-object (object stream :type t)
  660. (write (slot-value object '$classname) :stream stream)))
  661. ;; Preliminary.
  662. ;; Now we can at least print classes.
  663. (predefun print-object (object stream)
  664. (cond ((potential-class-p object) (format stream "#<CLASS ~S>" (class-classname object)))
  665. (t (write-string "#<UNKNOWN>" stream))))